From 1bd26338b7a5eba5e99023ddf971b5b96c86e3a7 Mon Sep 17 00:00:00 2001 From: Leon Chan Date: Tue, 10 Aug 2021 18:51:51 +0800 Subject: [PATCH] feat: page cache backed by vnode instead of filep 1, change the owner of page to the vnode instead of filep 2, store the file path in struct Vnode close: #I44TBS Signed-off-by: Leon Chan --- fs/dirent/fs_opendir.c | 30 ++-- fs/driver/fs_blockproxy.c | 5 - fs/inode/fs_files.c | 163 +++++++---------- fs/mount/fs_mount.c | 1 + fs/nfs/nfs_adapter.c | 356 ++++++++++++++++++++++++++++++++++++++ fs/romfs/fs_romfs.c | 59 +++++++ fs/vfs/fs_dupfd.c | 53 +----- fs/vfs/fs_mkdir.c | 1 + fs/vfs/fs_open.c | 35 ++-- fs/vfs/fs_rename.c | 9 +- fs/vfs/fs_unlink.c | 4 +- fs/vfs/include/file.h | 48 +++-- 12 files changed, 526 insertions(+), 238 deletions(-) diff --git a/fs/dirent/fs_opendir.c b/fs/dirent/fs_opendir.c index cd0c7bd..55efbba 100644 --- a/fs/dirent/fs_opendir.c +++ b/fs/dirent/fs_opendir.c @@ -150,7 +150,6 @@ errout: int do_opendir(const char *path, int oflags) { int ret; - int fd; struct Vnode *vp = NULL; struct file *filep = NULL; @@ -197,30 +196,19 @@ int do_opendir(const char *path, int oflags) vp->useCount++; VnodeDrop(); - /* Associate the vnode with a file structure */ - fd = files_allocate(vp, oflags, 0, NULL, 3); /* 3: file start fd */ - if (fd < 0) + filep = files_allocate(vp, oflags, 0, NULL, FILE_START_FD); + if (filep == NULL) { ret = -EMFILE; goto errout_with_vnode; } - /* Get the file structure corresponding to the file descriptor. */ - ret = fs_getfilep(fd, &filep); - if (ret < 0) - { - ret = -EPERM; - goto errout_with_fd; - } - - filep->f_path = (char *)fullpath; /* The mem will free in close(fd); */ - /* Allocate a type DIR -- which is little more than an vnode container. */ dir = (struct fs_dirent_s *)zalloc(sizeof(struct fs_dirent_s)); if (dir == NULL) { ret = -ENOMEM; - goto errout_with_fd; + goto errout_with_file; } dir->fd_position = 0; /* This is the position in the read stream */ @@ -237,17 +225,21 @@ int do_opendir(const char *path, int oflags) if (ret < 0) { free(dir); - goto errout_with_fd; + goto errout_with_file; } dir->fd_root = vp; dir->fd_status = DIRENT_MAGIC; filep->f_dir = dir; + if (fullpath) + { + free(fullpath); + } - return fd; + return filep->fd; -errout_with_fd: - files_release(fd); +errout_with_file: + files_release(filep->fd); errout_with_vnode: VnodeHold(); vp->useCount--; diff --git a/fs/driver/fs_blockproxy.c b/fs/driver/fs_blockproxy.c index 918374b..b0da61a 100755 --- a/fs/driver/fs_blockproxy.c +++ b/fs/driver/fs_blockproxy.c @@ -223,11 +223,6 @@ int block_proxy(const char *blkdev, int oflags) vnode->type = VNODE_TYPE_BCHR; VnodeDrop(); - /* Block char device is no need for file mapping */ -#ifdef LOSCFG_KERNEL_VM - (void)remove_mapping(chardev); -#endif - /* Free the allocate character driver name and return the open file * descriptor. */ diff --git a/fs/inode/fs_files.c b/fs/inode/fs_files.c index 4aa9e30..2d4cba3 100644 --- a/fs/inode/fs_files.c +++ b/fs/inode/fs_files.c @@ -111,7 +111,6 @@ bool get_bit(int i) return false; } - /**************************************************************************** * Private Functions ****************************************************************************/ @@ -140,6 +139,40 @@ static void _files_semtake(struct filelist *list) #define _files_semgive(list) (void)sem_post(&list->fl_sem) +void file_hold(struct file *filep) +{ + struct filelist *list = sched_getfiles(); + if (!list) + { + return; + } + + _files_semtake(list); + if (filep != NULL) + { + assert(filep->f_refcount > 0); + filep->f_refcount++; + } + _files_semgive(list); +} + +void file_release(struct file *filep) +{ + struct filelist *list = sched_getfiles(); + if (!list) + { + return; + } + + _files_semtake(list); + if (filep != NULL) + { + assert(filep->f_refcount > 0); + filep->f_refcount--; + } + _files_semgive(list); +} + /**************************************************************************** * Name: _files_close * @@ -192,21 +225,10 @@ static int _files_close(struct file *filep) VnodeDrop(); } - /* Release the path of file */ - - free(filep->f_path); - /* Release the file descriptor */ - filep->f_magicnum = 0; - filep->f_oflags = 0; - filep->f_pos = 0; - filep->f_path = NULL; - filep->f_priv = NULL; - filep->f_vnode = NULL; - filep->f_refcount = 0; - filep->f_mapping = NULL; - filep->f_dir = NULL; + memset(filep, 0, sizeof(struct file)); + filep->fd = -1; return ret; } @@ -293,10 +315,7 @@ int file_dup2(struct file *filep1, struct file *filep2) { struct filelist *list = NULL; struct Vnode *vnode_ptr = NULL; - char *fullpath = NULL; - const char *relpath = NULL; int err; - int len; int ret; if (!filep1 || !filep1->f_vnode || !filep2) @@ -331,20 +350,6 @@ int file_dup2(struct file *filep1, struct file *filep2) goto errout_with_ret; } - len = strlen(filep1->f_path); - if ((len == 0) || (len >= PATH_MAX)) - { - ret = -EINVAL; - goto errout_with_ret; - } - - fullpath = (char *)zalloc(len + 1); - if (fullpath == NULL) - { - ret = -ENOMEM; - goto errout_with_ret; - } - /* Increment the reference count on the contained vnode */ vnode_ptr = filep1->f_vnode; @@ -353,12 +358,11 @@ int file_dup2(struct file *filep1, struct file *filep2) filep2->f_oflags = filep1->f_oflags; filep2->f_pos = filep1->f_pos; - filep2->f_vnode = vnode_ptr; + filep2->f_vnode = filep1->f_vnode; filep2->f_priv = filep1->f_priv; - - (void)strncpy_s(fullpath, len + 1, filep1->f_path, len); - filep2->f_path = fullpath; - filep2->f_relpath = relpath; + filep2->f_path = filep1->f_path; + filep2->ops = filep1->ops; + filep2->f_refcount = filep1->f_refcount; /* Call the open method on the file, driver, mountpoint so that it * can maintain the correct open counts. @@ -400,14 +404,8 @@ int file_dup2(struct file *filep1, struct file *filep2) /* Handle various error conditions */ errout_with_vnode: - - free(filep2->f_path); - filep2->f_oflags = 0; - filep2->f_pos = 0; - filep2->f_vnode = NULL; - filep2->f_priv = NULL; - filep2->f_path = NULL; - filep2->f_relpath = NULL; + memset(filep2, 0, sizeof(struct file)); + filep2->fd = -1; errout_with_ret: err = -ret; @@ -418,32 +416,13 @@ errout: return VFS_ERROR; } -#define FILE_START_FD 3 - -static inline unsigned int files_magic_generate(void) -{ - static unsigned int files_magic = 0; - return files_magic++; -} - -/**************************************************************************** - * Name: files_allocate - * - * Description: - * Allocate a struct files instance and associate it with an inode instance. - * Returns the file descriptor == index into the files array. - * - ****************************************************************************/ - -int files_allocate(struct Vnode *vnode_ptr, int oflags, off_t pos, void *priv, int minfd) +struct file *files_allocate(const struct Vnode *vnode_ptr, int oflags, off_t pos, const void *priv, int minfd) { struct filelist *list = NULL; unsigned int *p = NULL; unsigned int mask; unsigned int i; - struct files_struct *process_files = NULL; - - /* minfd should be a positive number,and 0,1,2 had be distributed to stdin,stdout,stderr */ + struct file *filep = NULL; if (minfd < FILE_START_FD) { @@ -463,29 +442,25 @@ int files_allocate(struct Vnode *vnode_ptr, int oflags, off_t pos, void *priv, i if ((~(*p) & mask)) { set_bit(i, bitmap); - list->fl_files[i].f_oflags = oflags; - list->fl_files[i].f_pos = pos; - list->fl_files[i].f_vnode = vnode_ptr; - list->fl_files[i].f_priv = priv; - list->fl_files[i].f_refcount = 1; - list->fl_files[i].f_mapping = NULL; - list->fl_files[i].f_dir = NULL; - list->fl_files[i].f_magicnum = files_magic_generate(); - process_files = OsCurrProcessGet()->files; - if (process_files == NULL) - { - PRINT_ERR("process files is NULL, %s %d\n", __FUNCTION__ ,__LINE__); - _files_semgive(list); - return VFS_ERROR; - } + filep = &list->fl_files[i]; + filep->f_oflags = oflags; + filep->f_pos = pos; + filep->f_vnode = (struct Vnode *)vnode_ptr; + filep->f_priv = (void *)priv; + filep->f_refcount = 1; + filep->f_mapping = (struct page_mapping *)&vnode_ptr->mapping; + filep->f_dir = NULL; + filep->f_path = vnode_ptr->filePath; + filep->fd = i; + filep->ops = vnode_ptr->fop; _files_semgive(list); - return (int)i; + return filep; } i++; } _files_semgive(list); - return VFS_ERROR; + return NULL; } int files_close_internal(int fd, LosProcessCB *processCB) @@ -525,20 +500,9 @@ int files_close_internal(int fd, LosProcessCB *processCB) return -EINVAL; } - /* The filep->f_refcount may not be zero here, when the filep is shared in parent-child processes. - so, upon closing the filep in current process, relevant region must be released immediately */ -#ifdef LOSCFG_KERNEL_VM - struct file *filep = &list->fl_files[fd]; - - OsVmmFileRegionFree(filep, processCB); -#endif - list->fl_files[fd].f_refcount--; if (list->fl_files[fd].f_refcount == 0) { -#ifdef LOSCFG_KERNEL_VM - dec_mapping_nolock(filep->f_mapping); -#endif ret = _files_close(&list->fl_files[fd]); if (ret == OK) { @@ -585,17 +549,10 @@ void files_release(int fd) if (fd >=0 && fd < CONFIG_NFILE_DESCRIPTORS) { _files_semtake(list); + struct file *filep = &list->fl_files[fd]; - list->fl_files[fd].f_magicnum = 0; - list->fl_files[fd].f_oflags = 0; - list->fl_files[fd].f_vnode = NULL; - list->fl_files[fd].f_pos = 0; - list->fl_files[fd].f_refcount = 0; - list->fl_files[fd].f_path = NULL; - list->fl_files[fd].f_relpath = NULL; - list->fl_files[fd].f_priv = NULL; - list->fl_files[fd].f_mapping = NULL; - list->fl_files[fd].f_dir = NULL; + memset(filep, 0, sizeof(struct file)); + filep->fd = -1; clear_bit(fd, bitmap); _files_semgive(list); } diff --git a/fs/mount/fs_mount.c b/fs/mount/fs_mount.c index 7326441..225a77c 100755 --- a/fs/mount/fs_mount.c +++ b/fs/mount/fs_mount.c @@ -296,6 +296,7 @@ int mount(const char *source, const char *target, } mnt->vnodeBeCovered->flag |= VNODE_FLAG_MOUNT_ORIGIN; mnt->vnodeCovered->flag |= VNODE_FLAG_MOUNT_NEW; + mnt->vnodeCovered->filePath = strdup(target); mnt->vnodeDev = device; mnt->ops = mops; if (target && (strlen(target) != 0)) diff --git a/fs/nfs/nfs_adapter.c b/fs/nfs/nfs_adapter.c index 0f729b4..2ca1aca 100644 --- a/fs/nfs/nfs_adapter.c +++ b/fs/nfs/nfs_adapter.c @@ -1764,6 +1764,210 @@ errout_with_mutex: return -error; } +ssize_t vfs_nfs_writepage(struct Vnode *node, char *buffer, off_t pos, size_t buflen) +{ + struct nfsmount *nmp; + struct nfsnode *np; + loff_t f_pos = pos; + size_t writesize; + size_t bufsize; + size_t byteswritten; + size_t reqlen; + uint32_t *ptr = NULL; + uint32_t tmp; + int committed = NFSV3WRITE_UNSTABLE; + int error; + char *temp_buffer = NULL; + struct file_handle parent_fhandle; + + nmp = (struct nfsmount *)(node->originMount->data); + DEBUGASSERT(nmp != NULL); + + /* Make sure that the mount is still healthy */ + + nfs_mux_take(nmp); + np = (struct nfsnode *)node->data; + error = nfs_checkmount(nmp); + if (error != OK) + { + nfs_debug_error("nfs_checkmount failed: %d\n", error); + goto errout_with_mutex; + } + + parent_fhandle.length = ((struct nfsnode *)node->parent->data)->n_fhsize; + memcpy_s(&(parent_fhandle.handle), parent_fhandle.length, + &(((struct nfsnode *)node->parent->data)->n_fhandle), + ((struct nfsnode *)node->parent->data)->n_fhsize); + + /* Check if the file size would exceed the range of off_t */ + + if (np->n_size + buflen < np->n_size) + { + error = EFBIG; + goto errout_with_mutex; + } + + /* writepage cannot exceed the file range */ + + if (f_pos >= np->n_size) + { + error = ERANGE; + goto errout_with_mutex; + } + + buflen = min(buflen, np->n_size - f_pos); + + /* Allocate memory for data */ + + bufsize = (buflen < nmp->nm_wsize) ? buflen : nmp->nm_wsize; + temp_buffer = malloc(bufsize); + if (temp_buffer == NULL) + { + error = ENOMEM; + goto errout_with_mutex; + } + + /* Now loop until we send the entire user buffer */ + + writesize = 0; + for (byteswritten = 0; byteswritten < buflen; ) + { + /* Make sure that the attempted write size does not exceed the RPC + * maximum. + */ + + writesize = buflen - byteswritten; + if (writesize > nmp->nm_wsize) + { + writesize = nmp->nm_wsize; + } + + /* Make sure that the attempted read size does not exceed the IO + * buffer size. + */ + + bufsize = SIZEOF_rpc_call_write(writesize); + if (bufsize > nmp->nm_buflen) + { + writesize -= (bufsize - nmp->nm_buflen); + } + + /* Copy a chunk of the user data into the temporary buffer */ + + if (LOS_CopyToKernel(temp_buffer, writesize, buffer, writesize) != 0) + { + error = EINVAL; + goto errout_with_memfree; + } + + /* Initialize the request. Here we need an offset pointer to the write + * arguments, skipping over the RPC header. Write is unique among the + * RPC calls in that the entry RPC calls messasge lies in the I/O buffer + */ + + ptr = (uint32_t *)&((struct rpc_call_write *) + nmp->nm_iobuffer)->write; + reqlen = 0; + + /* Copy the variable length, file handle */ + + *ptr++ = txdr_unsigned((uint32_t)np->n_fhsize); + reqlen += sizeof(uint32_t); + + (void)memcpy_s(ptr, np->n_fhsize, &np->n_fhandle, np->n_fhsize); + reqlen += (int)np->n_fhsize; + ptr += uint32_increment((int)np->n_fhsize); + + /* Copy the file offset */ + + txdr_hyper((uint64_t)f_pos, ptr); + ptr += 2; + reqlen += 2*sizeof(uint32_t); + + /* Copy the count and stable values */ + + *ptr++ = txdr_unsigned(writesize); + *ptr++ = txdr_unsigned((uint32_t)committed); + reqlen += 2*sizeof(uint32_t); + + /* Copy a chunk of the user data into the I/O buffer from temporary buffer */ + + *ptr++ = txdr_unsigned(writesize); + reqlen += sizeof(uint32_t); + error = memcpy_s(ptr, writesize, temp_buffer, writesize); + if (error != EOK) + { + error = ENOBUFS; + goto errout_with_memfree; + } + reqlen += uint32_alignup(writesize); + + /* Perform the write */ + + nfs_statistics(NFSPROC_WRITE); + error = nfs_request(nmp, NFSPROC_WRITE, + (void *)nmp->nm_iobuffer, reqlen, + (void *)&nmp->nm_msgbuffer.write, + sizeof(struct rpc_reply_write)); + if (error) + { + goto errout_with_memfree; + } + + /* Get a pointer to the WRITE reply data */ + + ptr = (uint32_t *)&nmp->nm_msgbuffer.write.write; + + /* Parse file_wcc. First, check if WCC attributes follow. */ + + tmp = *ptr++; + if (tmp != 0) + { + /* Yes.. WCC attributes follow. But we just skip over them. */ + + ptr += uint32_increment(sizeof(struct wcc_attr)); + } + + /* Check if normal file attributes follow */ + + tmp = *ptr++; + if (tmp != 0) + { + /* Yes.. Update the cached file status in the file structure. */ + + nfs_attrupdate(np, (struct nfs_fattr *)ptr); + ptr += uint32_increment(sizeof(struct nfs_fattr)); + } + + /* Get the count of bytes actually written */ + + tmp = fxdr_unsigned(uint32_t, *ptr); + ptr++; + + if (tmp < 1 || tmp > writesize) + { + error = EIO; + goto errout_with_memfree; + } + + writesize = tmp; + f_pos += writesize; + np->n_fpos = f_pos; + + byteswritten += writesize; + buffer += writesize; + } + + free(temp_buffer); + nfs_mux_release(nmp); + return byteswritten; +errout_with_memfree: + free(temp_buffer); +errout_with_mutex: + nfs_mux_release(nmp); + return -error; +} + off_t vfs_nfs_seek(struct file *filep, off_t offset, int whence) { struct Vnode *node = filep->f_vnode; @@ -1834,6 +2038,156 @@ errout_with_mutex: return -error; } +ssize_t vfs_nfs_readpage(struct Vnode *node, char *buffer, off_t pos) +{ + struct nfsnode *np; + struct rpc_reply_read *read_response = NULL; + size_t readsize; + size_t tmp; + size_t bytesread; + size_t reqlen; + uint32_t *ptr = NULL; + int error = 0; + struct file_handle parent_fhandle; + int buflen = PAGE_SIZE; + struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data); + + DEBUGASSERT(nmp != NULL); + + /* Make sure that the mount is still healthy */ + + nfs_mux_take(nmp); + np = (struct nfsnode *)node->data; + error = nfs_checkmount(nmp); + if (error != OK) + { + nfs_debug_error("nfs_checkmount failed: %d\n", error); + goto errout_with_mutex; + } + + + parent_fhandle.length = ((struct nfsnode *)node->parent->data)->n_fhsize; + memcpy_s(&(parent_fhandle.handle), parent_fhandle.length, + &(((struct nfsnode *)node->parent->data)->n_fhandle), + ((struct nfsnode *)node->parent->data)->n_fhsize); + error = nfs_fileupdate(nmp, np->n_name, &parent_fhandle, np); + if (error != OK) + { + nfs_debug_info("nfs_fileupdate failed: %d\n", error); + goto errout_with_mutex; + } + + /* Get the number of bytes left in the file and truncate read count so that + * it does not exceed the number of bytes left in the file. + */ + + if (pos >= np->n_size) { + error = EFAULT; + nfs_debug_info("readpage out of file range: %d\n", error); + goto errout_with_mutex; + } + + tmp = np->n_size - pos; + if (buflen > tmp) + { + buflen = tmp; + } + + /* Now loop until we fill the user buffer (or hit the end of the file) */ + + for (bytesread = 0; bytesread < buflen; ) + { + /* Make sure that the attempted read size does not exceed the RPC maximum */ + + readsize = buflen - bytesread; + if (readsize > nmp->nm_rsize) + { + readsize = nmp->nm_rsize; + } + + /* Make sure that the attempted read size does not exceed the IO buffer size */ + + tmp = SIZEOF_rpc_reply_read(readsize); + if (tmp > nmp->nm_buflen) + { + readsize -= (tmp - nmp->nm_buflen); + } + + /* Initialize the request */ + + ptr = (uint32_t *)&nmp->nm_msgbuffer.read.read; + reqlen = 0; + + /* Copy the variable length, file handle */ + + *ptr++ = txdr_unsigned((uint32_t)np->n_fhsize); + reqlen += sizeof(uint32_t); + + memcpy_s(ptr, np->n_fhsize, &np->n_fhandle, np->n_fhsize); + reqlen += (int)np->n_fhsize; + ptr += uint32_increment((int)np->n_fhsize); + + /* Copy the file offset */ + + txdr_hyper((uint64_t)pos, ptr); + ptr += 2; + reqlen += 2*sizeof(uint32_t); + + /* Set the readsize */ + + *ptr = txdr_unsigned(readsize); + reqlen += sizeof(uint32_t); + + /* Perform the read */ + + nfs_statistics(NFSPROC_READ); + error = nfs_request(nmp, NFSPROC_READ, + (void *)&nmp->nm_msgbuffer.read, reqlen, + (void *)nmp->nm_iobuffer, nmp->nm_buflen); + if (error) + { + nfs_debug_error("nfs_request failed: %d\n", error); + goto errout_with_mutex; + } + + /* The read was successful. Get a pointer to the beginning of the NFS + * response data. + */ + + read_response = (struct rpc_reply_read *)nmp->nm_iobuffer; + readsize = fxdr_unsigned(uint32_t, read_response->read.hdr.count); + + /* Copy the read data into the user buffer */ + + if (LOS_CopyFromKernel(buffer, buflen, (const void *)read_response->read.data, readsize) != 0) + { + error = EINVAL; + goto errout_with_mutex; + } + + /* Update the read state data */ + + pos += readsize; + np->n_fpos += readsize; + bytesread += readsize; + buffer += readsize; + + /* Check if we hit the end of file */ + + if (read_response->read.hdr.eof != 0) + { + break; + } + } + + nfs_mux_release(nmp); + return bytesread; + +errout_with_mutex: + nfs_mux_release(nmp); + return -error; +} + ssize_t vfs_nfs_read(struct file *filep, char *buffer, size_t buflen) { struct nfsnode *np; @@ -2725,6 +3079,8 @@ struct VnodeOps nfs_vops = .Rename = vfs_nfs_rename, .Mkdir = vfs_nfs_mkdir, .Create = vfs_nfs_create, + .ReadPage = vfs_nfs_readpage, + .WritePage = vfs_nfs_writepage, .Unlink = vfs_nfs_unlink, .Rmdir = vfs_nfs_rmdir, .Reclaim = vfs_nfs_reclaim, diff --git a/fs/romfs/fs_romfs.c b/fs/romfs/fs_romfs.c index 26b72d2..be3c494 100644 --- a/fs/romfs/fs_romfs.c +++ b/fs/romfs/fs_romfs.c @@ -303,6 +303,63 @@ errout_with_semaphore: return ret; } +/**************************************************************************** + * Name: romfs_readpage + ****************************************************************************/ + +static ssize_t romfs_readpage(struct Vnode *vnode, char *buffer, off_t off) +{ + size_t bytesleft; + int ret = 0; + int buflen = PAGE_SIZE; + struct romfs_mountpt_s *rm = NULL; + struct romfs_file_s *rf = NULL; + + /* Recover our private data from the struct file instance */ + + rf = (struct romfs_file_s *)vnode->data; + rm = (struct romfs_mountpt_s *)vnode->originMount->data; + + /* Make sure that the mount is still healthy */ + + romfs_semtake(rm); + ret = romfs_checkmount(rm); + if (ret != OK) + { + PRINTK("ERROR: romfs_checkmount failed: %d\n", ret); + goto errout_with_semaphore; + } + + if (off >= rf->rf_size) + { + ret = -ERANGE; + PRINTK("ERROR: readpage out of range, ret: %d.\n", ret); + goto errout_with_semaphore; + } + + /* Get the number of bytes left in the file */ + + bytesleft = rf->rf_size - off; + + /* Truncate read count so that it does not exceed the number + * of bytes left in the file. + */ + + if (buflen > bytesleft) + { + buflen = bytesleft; + } + + LOS_CopyFromKernel(buffer, buflen, &rm->rm_buffer[off], buflen); + + romfs_semgive(rm); + return buflen; + +errout_with_semaphore: + romfs_semgive(rm); + return ret; +} + /**************************************************************************** * Name: romfs_seek ****************************************************************************/ @@ -830,6 +887,8 @@ struct VnodeOps g_romfsVops = { .Lookup = romfs_lookup, .Create = NULL, + .ReadPage = romfs_readpage, + .WritePage = NULL, .Rename = NULL, .Mkdir = NULL, .Getattr = romfs_stat, diff --git a/fs/vfs/fs_dupfd.c b/fs/vfs/fs_dupfd.c index dfef05b..9f0c8d6 100644 --- a/fs/vfs/fs_dupfd.c +++ b/fs/vfs/fs_dupfd.c @@ -75,12 +75,7 @@ int file_dup(struct file *filep, int minfd) { - int fd2; - int ret; - int err,len,rellen; struct file *filep2 = NULL; - char *fullpath = NULL; - char *relpath = NULL; /* Verify that fd is a valid, open file descriptor */ @@ -90,57 +85,17 @@ int file_dup(struct file *filep, int minfd) return VFS_ERROR; } - len = strlen(filep->f_path); - fullpath = (char *)zalloc(len + 1); - if (fullpath == NULL) - { - set_errno(ENOMEM); - return VFS_ERROR; - } - /* Then allocate a new file descriptor for the vnode */ - fd2 = files_allocate(filep->f_vnode, filep->f_oflags, filep->f_pos, filep->f_priv, minfd); - if (fd2 < 0) + filep2 = files_allocate(filep->f_vnode, filep->f_oflags, filep->f_pos, filep->f_priv, minfd); + if (filep2 == NULL) { - free(fullpath); set_errno(EMFILE); return VFS_ERROR; } + filep2->f_refcount = filep->f_refcount; - ret = fs_getfilep(fd2, &filep2); - - (void)strncpy_s(fullpath, len + 1, filep->f_path, len); - if (filep->f_relpath != NULL) - { - rellen = strlen(filep->f_relpath); - relpath = (char *)zalloc(rellen + 1); - (void)strncpy_s(relpath, rellen + 1, filep->f_relpath, rellen); - } - filep2->f_path = fullpath; - filep2->f_relpath = relpath; - filep2->f_priv = filep->f_priv; - - if (ret < 0) - { - goto errout_with_vnode; - } - - return fd2; - -errout_with_vnode: - clear_fd(fd2); - free(fullpath); - filep2->f_oflags = 0; - filep2->f_pos = 0; - filep2->f_vnode = NULL; - filep2->f_priv = NULL; - filep2->f_path = NULL; - filep2->f_relpath = NULL; - filep2->f_mapping = NULL; - err = -ret; - set_errno(err); - return VFS_ERROR; + return filep2->fd; } /**************************************************************************** diff --git a/fs/vfs/fs_mkdir.c b/fs/vfs/fs_mkdir.c index 427647c..209babf 100644 --- a/fs/vfs/fs_mkdir.c +++ b/fs/vfs/fs_mkdir.c @@ -144,6 +144,7 @@ int do_mkdir(int dirfd, const char *pathname, mode_t mode) // alloc name cache failed is not a critical problem, let it go. PRINT_ERR("alloc path cache %s failed\n", dirname); } + vnode->filePath = strdup(fullpath); parentVnode->useCount--; VnodeDrop(); out: diff --git a/fs/vfs/fs_open.c b/fs/vfs/fs_open.c index 8e3b851..cab92d4 100755 --- a/fs/vfs/fs_open.c +++ b/fs/vfs/fs_open.c @@ -158,7 +158,6 @@ static int do_creat(struct Vnode *parentNode, char *fullpath, mode_t mode, struc int fp_open(int dirfd, const char *path, int oflags, mode_t mode) { int ret; - int fd; int accmode; struct file *filep = NULL; struct Vnode *vnode = NULL; @@ -180,7 +179,7 @@ int fp_open(int dirfd, const char *path, int oflags, mode_t mode) if (vnode->type == VNODE_TYPE_BLK) { VnodeDrop(); - fd = block_proxy(fullpath, oflags); + int fd = block_proxy(fullpath, oflags); if (fd < 0) { ret = fd; @@ -239,6 +238,7 @@ int fp_open(int dirfd, const char *path, int oflags, mode_t mode) VnodeDrop(); goto errout; } + vnode->filePath = strdup(fullpath); } if (ret != OK) @@ -273,26 +273,13 @@ int fp_open(int dirfd, const char *path, int oflags, mode_t mode) } } - fd = files_allocate(vnode, oflags, 0, NULL, 3); /* 3: file start fd */ - if (fd < 0) + filep = files_allocate(vnode, oflags, 0, NULL, FILE_START_FD); + if (filep == NULL) { ret = -EMFILE; goto errout_with_count; } - /* Get the file structure corresponding to the file descriptor. */ - ret = fs_getfilep(fd, &filep); - if (ret < 0) - { - files_release(fd); - ret = -get_errno(); - goto errout_with_count; - } - - filep->f_vnode = vnode; - filep->ops = vnode->fop; - filep->f_path = fullpath; - if (filep->ops && filep->ops->open) { ret = filep->ops->open(filep); @@ -300,17 +287,15 @@ int fp_open(int dirfd, const char *path, int oflags, mode_t mode) if (ret < 0) { - files_release(fd); + files_release(filep->fd); goto errout_with_count; } - /* we do not bother to handle the NULL scenario, if so, page-cache feature will not be used - * when we do the file fault */ -#ifdef LOSCFG_KERNEL_VM - add_mapping(filep, fullpath); -#endif - - return fd; + if (fullpath) + { + free(fullpath); + } + return filep->fd; errout_with_count: VnodeHold(); diff --git a/fs/vfs/fs_rename.c b/fs/vfs/fs_rename.c index 4cb84ab..6cf5292 100644 --- a/fs/vfs/fs_rename.c +++ b/fs/vfs/fs_rename.c @@ -208,16 +208,9 @@ int do_rename(int oldfd, const char *oldpath, int newfd, const char *newpath) } VnodeFree(new_vnode); VnodePathCacheFree(old_vnode); + old_vnode->filePath = strdup(fullnewpath); PathCacheAlloc(new_parent_vnode, old_vnode, newname, strlen(newname)); VnodeDrop(); - ret = update_file_path(fulloldpath, fullnewpath); - if (ret != OK) - { - PRINT_ERR("rename change file path failed, something bad might happped.\n"); - } - /* Successfully renamed */ - - rename_mapping(fulloldpath, fullnewpath); free(fulloldpath); free(fullnewpath); diff --git a/fs/vfs/fs_unlink.c b/fs/vfs/fs_unlink.c index d1947a7..61127f0 100644 --- a/fs/vfs/fs_unlink.c +++ b/fs/vfs/fs_unlink.c @@ -149,9 +149,7 @@ int do_unlink(int dirfd, const char *pathname) done: VnodeDrop(); -#ifdef LOSCFG_KERNEL_VM - (void)remove_mapping(fullpath); -#endif + /* Successfully unlinked */ free(fullpath); diff --git a/fs/vfs/include/file.h b/fs/vfs/include/file.h index 8e645cd..cdfc5a5 100644 --- a/fs/vfs/include/file.h +++ b/fs/vfs/include/file.h @@ -64,23 +64,37 @@ extern "C" { #define OK 0 #endif +/* minimal fd allocated for file */ +#define FILE_START_FD 3 + +struct Vnode; + +/* file mapped in VMM pages */ +struct page_mapping { + LOS_DL_LIST page_list; /* all pages */ + SPIN_LOCK_S list_lock; /* lock protecting it */ + LosMux mux_lock; /* mutex lock */ + unsigned long nrpages; /* number of total pages */ + unsigned long flags; + Atomic ref; /* reference counting */ + struct Vnode *host; /* owner of this mapping */ +}; + /* This is the underlying representation of an open file. A file * descriptor is an index into an array of such types. The type associates * the file descriptor to the file state and to a set of vnode operations. */ -struct Vnode; - struct file { - unsigned int f_magicnum; /* file magic number */ + unsigned int f_magicnum; /* file magic number. -- to be deleted */ int f_oflags; /* Open mode flags */ struct Vnode *f_vnode; /* Driver interface */ loff_t f_pos; /* File position */ unsigned long f_refcount; /* reference count */ char *f_path; /* File fullpath */ void *f_priv; /* Per file driver private data */ - const char *f_relpath; /* realpath */ + const char *f_relpath; /* realpath. -- to be deleted */ struct page_mapping *f_mapping; /* mapping file to memory */ void *f_dir; /* DIR struct for iterate the directory if open a directory */ const struct file_operations_vfs *ops; @@ -131,26 +145,8 @@ struct file_operations_vfs int (*unlink)(struct Vnode *vnode); }; -/* file mapped in VMM pages */ -struct page_mapping { - LOS_DL_LIST page_list; /* all pages */ - SPIN_LOCK_S list_lock; /* lock protecting it */ - LosMux mux_lock; /* mutex lock */ - unsigned long nrpages; /* number of total pages */ - unsigned long flags; - Atomic ref; /* reference counting */ - struct file *host; /* owner of this mapping */ -}; - -/* map: full_path(owner) <-> mapping */ -struct file_map { - LOS_DL_LIST head; - LosMux lock; /* lock to protect this mapping */ - struct page_mapping mapping; - int name_len; - char *rename; - char owner[0]; /* owner: full path of file */ -}; +void file_hold(struct file *filep); +void file_release(struct file *filep); /**************************************************************************** * Name: files_initlist @@ -467,11 +463,11 @@ off64_t file_seek64(struct file *filep, off64_t offset, int whence); * * Description: * Allocate a struct files instance and associate it with an vnode instance. - * Returns the file descriptor == index into the files array. + * Returns the file descriptor pointer. * ****************************************************************************/ -int files_allocate(struct Vnode *vnode, int oflags, off_t pos, void *priv, int minfd); +struct file *files_allocate(const struct Vnode *vnode_ptr, int oflags, off_t pos, const void *priv, int minfd); /**************************************************************************** * Name: files_close -- Gitee