diff --git a/fs/proc/os_adapt/proc_vfs.c b/fs/proc/os_adapt/proc_vfs.c index fb40407346c4e3a1bab7ff422a878a28cbaea874..dd467b3a77e94ed5fc5f1cde626ca1c222a6e101 100644 --- a/fs/proc/os_adapt/proc_vfs.c +++ b/fs/proc/os_adapt/proc_vfs.c @@ -125,10 +125,18 @@ int VfsProcfsRead(struct file *filep, char *buffer, size_t buflen) return -EINVAL; } + VnodeHold(); entry = VnodeToEntry(filep->f_vnode); + if (entry == NULL) { + VnodeDrop(); + return -EPERM; + } + + spin_lock(&entry->pdeUnloadLock); size = (ssize_t)ReadProcFile(entry, (void *)buffer, buflen); filep->f_pos = entry->pf->fPos; - + spin_unlock(&entry->pdeUnloadLock); + VnodeDrop(); return size; } @@ -140,10 +148,18 @@ int VfsProcfsWrite(struct file *filep, const char *buffer, size_t buflen) return -EINVAL; } + VnodeHold(); entry = VnodeToEntry(filep->f_vnode); + if (entry == NULL) { + VnodeDrop(); + return -EPERM; + } + + spin_lock(&entry->pdeUnloadLock); size = (ssize_t)WriteProcFile(entry, (void *)buffer, buflen); filep->f_pos = entry->pf->fPos; - + spin_unlock(&entry->pdeUnloadLock); + VnodeDrop(); return size; } @@ -156,9 +172,12 @@ int VfsProcfsLookup(struct Vnode *parent, const char *name, int len, struct Vnod if (entry == NULL) { return -ENODATA; } + + spin_lock(&procfsLock); entry = entry->subdir; while (1) { if (entry == NULL) { + spin_unlock(&procfsLock); return -ENOENT; } if (EntryMatch(name, len, entry)) { @@ -166,6 +185,7 @@ int VfsProcfsLookup(struct Vnode *parent, const char *name, int len, struct Vnod } entry = entry->next; } + spin_unlock(&procfsLock); *vpp = EntryToVnode(entry); if ((*vpp) == NULL) { @@ -214,11 +234,17 @@ int VfsProcfsUnmount(void *handle, struct Vnode **blkdriver) int VfsProcfsStat(struct Vnode *node, struct stat *buf) { + VnodeHold(); struct ProcDirEntry *entry = VnodeToEntry(node); - + if (entry == NULL) { + VnodeDrop(); + return -EPERM; + } (void)memset_s(buf, sizeof(struct stat), 0, sizeof(struct stat)); + spin_lock(&entry->pdeUnloadLock); buf->st_mode = entry->mode; - + spin_unlock(&entry->pdeUnloadLock); + VnodeDrop(); return LOS_OK; } @@ -226,9 +252,7 @@ int VfsProcfsReaddir(struct Vnode *node, struct fs_dirent_s *dir) { int result; char *buffer = NULL; - int buflen = NAME_MAX; - unsigned int min_size; - unsigned int dst_name_size; + unsigned int minSize, dstNameSize; struct ProcDirEntry *pde = NULL; int i = 0; @@ -238,28 +262,38 @@ int VfsProcfsReaddir(struct Vnode *node, struct fs_dirent_s *dir) if (node->type != VNODE_TYPE_DIR) { return -ENOTDIR; } + VnodeHold(); pde = VnodeToEntry(node); + if (pde == NULL) { + VnodeDrop(); + return -EPERM; + } + spin_lock(&pde->pdeUnloadLock); while (i < dir->read_cnt) { buffer = (char *)zalloc(sizeof(char) * NAME_MAX); if (buffer == NULL) { + spin_unlock(&pde->pdeUnloadLock); + VnodeDrop(); PRINT_ERR("malloc failed\n"); return -ENOMEM; } - result = ReadProcFile(pde, (void *)buffer, buflen); + result = ReadProcFile(pde, (void *)buffer, NAME_MAX); if (result != ENOERR) { free(buffer); break; } - dst_name_size = sizeof(dir->fd_dir[i].d_name); - min_size = (dst_name_size < NAME_MAX) ? dst_name_size : NAME_MAX; - result = strncpy_s(dir->fd_dir[i].d_name, dst_name_size, buffer, min_size); + dstNameSize = sizeof(dir->fd_dir[i].d_name); + minSize = (dstNameSize < NAME_MAX) ? dstNameSize : NAME_MAX; + result = strncpy_s(dir->fd_dir[i].d_name, dstNameSize, buffer, minSize); if (result != EOK) { + spin_unlock(&pde->pdeUnloadLock); + VnodeDrop(); free(buffer); return -ENAMETOOLONG; } - dir->fd_dir[i].d_name[dst_name_size - 1] = '\0'; + dir->fd_dir[i].d_name[dstNameSize - 1] = '\0'; dir->fd_position++; dir->fd_dir[i].d_off = dir->fd_position; dir->fd_dir[i].d_reclen = (uint16_t)sizeof(struct dirent); @@ -267,21 +301,30 @@ int VfsProcfsReaddir(struct Vnode *node, struct fs_dirent_s *dir) i++; free(buffer); } - + spin_unlock(&pde->pdeUnloadLock); + VnodeDrop(); return i; } int VfsProcfsOpendir(struct Vnode *node, struct fs_dirent_s *dir) { + VnodeHold(); struct ProcDirEntry *pde = VnodeToEntry(node); if (pde == NULL) { + VnodeDrop(); return -EINVAL; } + + spin_lock(&pde->pdeUnloadLock); pde->pdirCurrent = pde->subdir; if (pde->pf == NULL) { + spin_unlock(&pde->pdeUnloadLock); + VnodeDrop(); return -EINVAL; } pde->pf->fPos = 0; + spin_unlock(&pde->pdeUnloadLock); + VnodeDrop(); return LOS_OK; } @@ -290,9 +333,17 @@ int VfsProcfsOpen(struct file *filep) if (filep == NULL) { return -EINVAL; } + VnodeHold(); struct Vnode *node = filep->f_vnode; struct ProcDirEntry *pde = VnodeToEntry(node); + if (pde == NULL) { + VnodeDrop(); + return -EPERM; + } + + spin_lock(&pde->pdeUnloadLock); if (ProcOpen(pde->pf) != OK) { + spin_unlock(&pde->pdeUnloadLock); return -ENOMEM; } if (S_ISREG(pde->mode) && (pde->procFileOps != NULL) && (pde->procFileOps->open != NULL)) { @@ -303,6 +354,8 @@ int VfsProcfsOpen(struct file *filep) pde->pf->fPos = 0; } filep->f_priv = (void *)pde; + spin_unlock(&pde->pdeUnloadLock); + VnodeDrop(); return LOS_OK; } @@ -312,15 +365,24 @@ int VfsProcfsClose(struct file *filep) if (filep == NULL) { return -EINVAL; } + + VnodeHold(); struct Vnode *node = filep->f_vnode; struct ProcDirEntry *pde = VnodeToEntry(node); + if (pde == NULL) { + VnodeDrop(); + return -EPERM; + } + + spin_lock(&pde->pdeUnloadLock); pde->pf->fPos = 0; if ((pde->procFileOps != NULL) && (pde->procFileOps->release != NULL)) { result = pde->procFileOps->release((struct Vnode *)pde, pde->pf); } LosBufRelease(pde->pf->sbuf); pde->pf->sbuf = NULL; - + spin_unlock(&pde->pdeUnloadLock); + VnodeDrop(); return result; } @@ -345,9 +407,15 @@ ssize_t VfsProcfsReadlink(struct Vnode *vnode, char *buffer, size_t bufLen) } struct ProcDirEntry *pde = VnodeToEntry(vnode); + if (pde == NULL) { + return -EPERM; + } + + spin_lock(&pde->pdeUnloadLock); if ((pde->procFileOps != NULL) && (pde->procFileOps->readLink != NULL)) { result = pde->procFileOps->readLink(pde, buffer, bufLen); } + spin_unlock(&pde->pdeUnloadLock); return result; } diff --git a/fs/proc/src/proc_file.c b/fs/proc/src/proc_file.c index 750616a1d71220be17190e15f54e7b70818566bb..739365b6136da61b60d156b367b1b638dba818d5 100644 --- a/fs/proc/src/proc_file.c +++ b/fs/proc/src/proc_file.c @@ -378,11 +378,34 @@ struct ProcDirEntry *CreateProcEntry(const char *name, mode_t mode, struct ProcD return pde; } +static void ProcEntryClearVnode(struct ProcDirEntry *entry) +{ + struct Vnode *item = NULL; + struct Vnode *nextItem = NULL; + + VnodeHold(); + LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, GetVnodeActiveList(), struct Vnode, actFreeEntry) { + if ((struct ProcDirEntry *)item->data != entry) { + continue; + } + + if (VnodeFree(item) != LOS_OK) { + PRINT_ERR("ProcEntryClearVnode free failed, entry: %s : 0x%x \n", entry->name, item); + } + } + VnodeDrop(); + return; +} + static void FreeProcEntry(struct ProcDirEntry *entry) { if (entry == NULL) { return; } + + ProcEntryClearVnode(entry); + + spin_lock(&entry->pdeUnloadLock); if (entry->pf != NULL) { free(entry->pf); entry->pf = NULL; @@ -391,6 +414,7 @@ static void FreeProcEntry(struct ProcDirEntry *entry) free(entry->data); entry->data = NULL; } + spin_unlock(&entry->pdeUnloadLock); free(entry); } @@ -562,22 +586,21 @@ static int ProcRead(struct ProcDirEntry *pde, char *buf, size_t len) struct ProcDirEntry *OpenProcFile(const char *fileName, int flags, ...) { - unsigned int intSave; struct ProcDirEntry *pn = ProcFindEntry(fileName); if (pn == NULL) { return NULL; } - SCHEDULER_LOCK(intSave); + spin_lock(&pn->pdeUnloadLock); if (S_ISREG(pn->mode) && (pn->count != 1)) { - SCHEDULER_UNLOCK(intSave); + spin_unlock(&pn->pdeUnloadLock); return NULL; } pn->flags = (unsigned int)(pn->flags) | (unsigned int)flags; atomic_set(&pn->count, PROC_INUSE); - SCHEDULER_UNLOCK(intSave); if (ProcOpen(pn->pf) != OK) { + spin_unlock(&pn->pdeUnloadLock); return NULL; } if (S_ISREG(pn->mode) && (pn->procFileOps != NULL) && (pn->procFileOps->open != NULL)) { @@ -587,6 +610,7 @@ struct ProcDirEntry *OpenProcFile(const char *fileName, int flags, ...) pn->pdirCurrent = pn->subdir; pn->pf->fPos = 0; } + spin_unlock(&pn->pdeUnloadLock); return pn; }