From 70bdb2590c57c4645dffb3fe1d752f73fe79f705 Mon Sep 17 00:00:00 2001 From: wangchenyang Date: Fri, 15 Jan 2021 05:26:30 +0800 Subject: [PATCH 1/2] Description:vfs refactoring Feature or Bugfix:Feature Binary Source:Huawei PrivateCode(Yes/No):Yes Change-Id: I175d2648bc6f9078c34de2c0a5c93fda10b86c47 ChangeID:13306420 --- drivers/bch/bch.h | 2 +- drivers/bch/bchdev_driver.c | 98 +- drivers/bch/bchlib_setup.c | 22 +- drivers/bch/bchlib_teardown.c | 7 +- drivers/pipes/fifo.c | 26 +- drivers/pipes/pipe.c | 55 +- drivers/pipes/pipe_common.c | 102 +- drivers/pipes/pipe_common.h | 2 +- drivers/video/fb.c | 92 +- fs/dirent/fs_closedir.c | 79 +- fs/dirent/fs_opendir.c | 459 +-- fs/dirent/fs_readdir.c | 264 +- fs/dirent/fs_rewinddir.c | 84 +- fs/dirent/fs_seekdir.c | 103 +- fs/dirent/fs_telldir.c | 1 - fs/driver/fs_blockproxy.c | 31 +- fs/driver/fs_closeblockdriver.c | 47 +- fs/driver/fs_devsyslog.c | 0 fs/driver/fs_findblockdriver.c | 50 +- fs/driver/fs_openblockdriver.c | 54 +- fs/driver/fs_registerblockdriver.c | 61 +- fs/driver/fs_registerdriver.c | 66 +- fs/driver/fs_unregisterblockdriver.c | 7 +- fs/driver/fs_unregisterdriver.c | 19 +- fs/inode/fs_files.c | 214 +- fs/inode/inode.h | 48 - fs/mount/fs_foreachmountpoint.c | 37 +- fs/mount/fs_mount.c | 217 +- fs/mount/fs_umount.c | 184 +- fs/nfs/{nfs_vfsops.c => nfs_adapter.c} | 4554 ++++++++++-------------- fs/nfs/nfs_mount.h | 3 + fs/nfs/nfs_node.h | 2 + fs/nfs/nfs_util.c | 55 +- fs/nfs/rpc_clnt.c | 70 +- fs/tmpfs/fs_tmpfs.c | 1184 +++--- fs/tmpfs/fs_tmpfs.h | 4 +- fs/vfs/fs_close.c | 1 - fs/vfs/fs_dup.c | 2 +- fs/vfs/fs_dup2.c | 3 +- fs/vfs/fs_dupfd.c | 44 +- fs/vfs/fs_dupfd2.c | 8 +- fs/vfs/fs_fcntl.c | 10 +- fs/vfs/fs_fsync.c | 20 +- fs/vfs/fs_getfilep.c | 14 +- fs/vfs/fs_ioctl.c | 14 +- fs/vfs/fs_lseek.c | 45 +- fs/vfs/fs_lseek64.c | 42 +- fs/vfs/fs_mkdir.c | 217 +- fs/vfs/fs_open.c | 322 +- fs/vfs/fs_poll.c | 9 +- fs/vfs/fs_read.c | 19 +- fs/vfs/fs_rename.c | 356 +- fs/vfs/fs_rmdir.c | 215 +- fs/vfs/fs_select.c | 1 - fs/vfs/fs_stat.c | 193 +- fs/vfs/fs_statfs.c | 121 +- fs/vfs/fs_truncate.c | 16 +- fs/vfs/fs_truncate64.c | 106 +- fs/vfs/fs_unlink.c | 210 +- fs/vfs/fs_write.c | 19 +- include/nuttx/fs/dirent_fs.h | 31 +- include/nuttx/fs/file.h | 46 +- include/nuttx/fs/fs.h | 445 ++- 63 files changed, 4381 insertions(+), 6451 deletions(-) mode change 100755 => 100644 drivers/bch/bchdev_driver.c mode change 100755 => 100644 drivers/bch/bchlib_setup.c mode change 100755 => 100644 drivers/bch/bchlib_teardown.c mode change 100755 => 100644 drivers/pipes/fifo.c mode change 100755 => 100644 drivers/pipes/pipe.c mode change 100755 => 100644 drivers/pipes/pipe_common.c mode change 100755 => 100644 drivers/video/fb.c mode change 100755 => 100644 fs/dirent/fs_closedir.c mode change 100755 => 100644 fs/dirent/fs_opendir.c mode change 100755 => 100644 fs/dirent/fs_readdir.c mode change 100755 => 100644 fs/dirent/fs_rewinddir.c mode change 100755 => 100644 fs/dirent/fs_seekdir.c mode change 100755 => 100644 fs/dirent/fs_telldir.c mode change 100755 => 100644 fs/driver/fs_closeblockdriver.c mode change 100755 => 100644 fs/driver/fs_devsyslog.c mode change 100755 => 100644 fs/driver/fs_findblockdriver.c mode change 100755 => 100644 fs/driver/fs_openblockdriver.c mode change 100755 => 100644 fs/driver/fs_registerblockdriver.c mode change 100755 => 100644 fs/driver/fs_registerdriver.c mode change 100755 => 100644 fs/driver/fs_unregisterblockdriver.c mode change 100755 => 100644 fs/driver/fs_unregisterdriver.c mode change 100755 => 100644 fs/inode/fs_files.c mode change 100755 => 100644 fs/inode/inode.h mode change 100755 => 100644 fs/mount/fs_foreachmountpoint.c mode change 100644 => 100755 fs/mount/fs_umount.c rename fs/nfs/{nfs_vfsops.c => nfs_adapter.c} (43%) mode change 100755 => 100644 mode change 100755 => 100644 fs/nfs/nfs_mount.h mode change 100755 => 100644 fs/nfs/nfs_node.h mode change 100755 => 100644 fs/nfs/nfs_util.c mode change 100755 => 100644 fs/nfs/rpc_clnt.c mode change 100755 => 100644 fs/vfs/fs_close.c mode change 100755 => 100644 fs/vfs/fs_dupfd.c mode change 100755 => 100644 fs/vfs/fs_dupfd2.c mode change 100755 => 100644 fs/vfs/fs_fcntl.c mode change 100755 => 100644 fs/vfs/fs_fsync.c mode change 100755 => 100644 fs/vfs/fs_getfilep.c mode change 100755 => 100644 fs/vfs/fs_ioctl.c mode change 100755 => 100644 fs/vfs/fs_lseek.c mode change 100755 => 100644 fs/vfs/fs_lseek64.c mode change 100755 => 100644 fs/vfs/fs_mkdir.c mode change 100755 => 100644 fs/vfs/fs_poll.c mode change 100755 => 100644 fs/vfs/fs_read.c mode change 100755 => 100644 fs/vfs/fs_rename.c mode change 100755 => 100644 fs/vfs/fs_rmdir.c mode change 100755 => 100644 fs/vfs/fs_select.c mode change 100755 => 100644 fs/vfs/fs_stat.c mode change 100755 => 100644 fs/vfs/fs_statfs.c mode change 100755 => 100644 fs/vfs/fs_truncate.c mode change 100755 => 100644 fs/vfs/fs_truncate64.c mode change 100755 => 100644 fs/vfs/fs_unlink.c mode change 100755 => 100644 fs/vfs/fs_write.c mode change 100755 => 100644 include/nuttx/fs/dirent_fs.h mode change 100755 => 100644 include/nuttx/fs/file.h mode change 100755 => 100644 include/nuttx/fs/fs.h diff --git a/drivers/bch/bch.h b/drivers/bch/bch.h index e1e0685..eeaad6d 100755 --- a/drivers/bch/bch.h +++ b/drivers/bch/bch.h @@ -62,7 +62,7 @@ struct bchlib_s { - struct inode *inode; /* I-node of the block driver */ + struct Vnode *vnode; /* I-node of the block driver */ uint32_t sectsize; /* The size of one sector on the device */ unsigned long long nsectors; /* Number of sectors supported by the device */ unsigned long long sector; /* The current sector in the buffer */ diff --git a/drivers/bch/bchdev_driver.c b/drivers/bch/bchdev_driver.c old mode 100755 new mode 100644 index 2da55e6..6de6b74 --- a/drivers/bch/bchdev_driver.c +++ b/drivers/bch/bchdev_driver.c @@ -68,7 +68,7 @@ static ssize_t bch_write(struct file *filep, const char *buffer, static int bch_ioctl(struct file *filep, int cmd, unsigned long arg); #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS -static int bch_unlink(struct inode *inode); +static int bch_unlink(struct Vnode *vnode); #endif /**************************************************************************** @@ -77,17 +77,13 @@ static int bch_unlink(struct inode *inode); const struct file_operations_vfs bch_fops = { - bch_open, /* open */ - bch_close, /* close */ - bch_read, /* read */ - bch_write, /* write */ - bch_seek, /* seek */ - bch_ioctl, /* ioctl */ - NULL, /* mmap */ -#ifndef CONFIG_DISABLE_POLL - NULL, /* poll */ -#endif - bch_unlink, /* unlink */ + .open = bch_open, /* open */ + .close = bch_close, /* close */ + .read = bch_read, /* read */ + .write = bch_write, /* write */ + .seek = bch_seek, /* seek */ + .ioctl = bch_ioctl, /* ioctl */ + .unlink = bch_unlink, /* unlink */ }; /**************************************************************************** @@ -101,14 +97,13 @@ const struct file_operations_vfs bch_fops = * ****************************************************************************/ -static int bch_open(FAR struct file *filep) +static int bch_open(struct file *filep) { - FAR struct inode *inode = filep->f_inode; - FAR struct bchlib_s *bch; + struct Vnode *vnode = filep->f_vnode; + struct bchlib_s *bch; int ret = OK; - DEBUGASSERT(inode && inode->i_private); - bch = (FAR struct bchlib_s *)inode->i_private; + bch = (struct bchlib_s *)((struct drv_data *)vnode->data)->priv; /* Increment the reference count */ @@ -133,14 +128,13 @@ static int bch_open(FAR struct file *filep) * ****************************************************************************/ -static int bch_close(FAR struct file *filep) +static int bch_close(struct file *filep) { - FAR struct inode *inode = filep->f_inode; - FAR struct bchlib_s *bch; + struct Vnode *vnode = filep->f_vnode; + struct bchlib_s *bch; int ret = OK; - DEBUGASSERT(inode && inode->i_private); - bch = (FAR struct bchlib_s *)inode->i_private; + bch = (struct bchlib_s *)((struct drv_data *)vnode->data)->priv; /* Flush any dirty pages remaining in the cache */ @@ -168,7 +162,7 @@ static int bch_close(FAR struct file *filep) { /* Tear the driver down now. */ - ret = bchlib_teardown((FAR void *)bch); + ret = bchlib_teardown((void *)bch); /* bchlib_teardown() would only fail if there are outstanding * references on the device. Since we know that is not true, it @@ -193,16 +187,14 @@ static int bch_close(FAR struct file *filep) * Name: bch_seek ****************************************************************************/ -static off_t bch_seek(FAR struct file *filep, off_t offset, int whence) +static off_t bch_seek(struct file *filep, off_t offset, int whence) { - FAR struct inode *inode = filep->f_inode; - FAR struct bchlib_s *bch; + struct Vnode *vnode = filep->f_vnode; + struct bchlib_s *bch; loff_t newpos; int ret; - DEBUGASSERT(inode && inode->i_private); - - bch = (FAR struct bchlib_s *)inode->i_private; + bch = (struct bchlib_s *)((struct drv_data *)vnode->data)->priv; bchlib_semtake(bch); /* Determine the new, requested file position */ @@ -259,14 +251,13 @@ static off_t bch_seek(FAR struct file *filep, off_t offset, int whence) * Name: bch_read ****************************************************************************/ -static ssize_t bch_read(FAR struct file *filep, FAR char *buffer, size_t len) +static ssize_t bch_read(struct file *filep, char *buffer, size_t len) { - FAR struct inode *inode = filep->f_inode; - FAR struct bchlib_s *bch; + struct Vnode *vnode = filep->f_vnode; + struct bchlib_s *bch; int ret; - DEBUGASSERT(inode && inode->i_private); - bch = (FAR struct bchlib_s *)inode->i_private; + bch = (struct bchlib_s *)((struct drv_data *)vnode->data)->priv; bchlib_semtake(bch); ret = bchlib_read(bch, buffer, filep->f_pos, len); @@ -283,14 +274,13 @@ static ssize_t bch_read(FAR struct file *filep, FAR char *buffer, size_t len) * Name: bch_write ****************************************************************************/ -static ssize_t bch_write(FAR struct file *filep, FAR const char *buffer, size_t len) +static ssize_t bch_write(struct file *filep, const char *buffer, size_t len) { - FAR struct inode *inode = filep->f_inode; - FAR struct bchlib_s *bch; + struct Vnode *vnode = filep->f_vnode; + struct bchlib_s *bch; int ret = -EACCES; - DEBUGASSERT(inode && inode->i_private); - bch = (FAR struct bchlib_s *)inode->i_private; + bch = (struct bchlib_s *)((struct drv_data *)vnode->data)->priv; if (!bch->readonly) { @@ -315,14 +305,14 @@ static ssize_t bch_write(FAR struct file *filep, FAR const char *buffer, size_t * ****************************************************************************/ -static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +static int bch_ioctl(struct file *filep, int cmd, unsigned long arg) { - FAR struct inode *inode = filep->f_inode; - FAR struct bchlib_s *bch; + struct Vnode *vnode = filep->f_vnode; + struct bchlib_s *bch; + struct block_operations *bop = NULL; int ret = -ENOTTY; - DEBUGASSERT(inode && inode->i_private); - bch = (FAR struct bchlib_s *)inode->i_private; + bch = (struct bchlib_s *)((struct drv_data *)vnode->data)->priv; /* Process the call according to the command */ @@ -332,8 +322,8 @@ static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg) case DIOC_GETPRIV: { - FAR struct bchlib_s **bchr = - (FAR struct bchlib_s **)((uintptr_t)arg); + struct bchlib_s **bchr = + (struct bchlib_s **)((uintptr_t)arg); bchlib_semtake(bch); if (!bchr || bch->refs == MAX_OPENCNT) @@ -362,8 +352,6 @@ static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg) default: { - struct inode *bchinode = bch->inode; - /* Does the block driver support the ioctl method? */ los_disk *disk = bch->disk; @@ -380,9 +368,10 @@ static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg) } if (disk->disk_status == STAT_INUSED) { - if (bchinode->u.i_bops->ioctl != NULL) + bop = (struct block_operations *)(((struct drv_data *)vnode->data)->ops); + if (bop != NULL && bop->ioctl != NULL) { - ret = bchinode->u.i_bops->ioctl(bchinode, cmd, arg); + ret = bop->ioctl(bch->vnode, cmd, arg); } } @@ -405,13 +394,12 @@ static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg) * ****************************************************************************/ -static int bch_unlink(FAR struct inode *inode) +int bch_unlink(struct Vnode *vnode) { - FAR struct bchlib_s *bch; + struct bchlib_s *bch; int ret = OK; - DEBUGASSERT(inode && inode->i_private); - bch = (FAR struct bchlib_s *)inode->i_private; + bch = (struct bchlib_s *)((struct drv_data *)vnode->data)->priv; /* Get exclusive access to the BCH device */ @@ -429,7 +417,7 @@ static int bch_unlink(FAR struct inode *inode) { /* Tear the driver down now. */ - ret = bchlib_teardown((FAR void *)bch); + ret = bchlib_teardown((void *)bch); /* bchlib_teardown() would only fail if there are outstanding * references on the device. Since we know that is not true, it diff --git a/drivers/bch/bchlib_setup.c b/drivers/bch/bchlib_setup.c old mode 100755 new mode 100644 index 720c8fd..24bb1c7 --- a/drivers/bch/bchlib_setup.c +++ b/drivers/bch/bchlib_setup.c @@ -60,9 +60,9 @@ * ****************************************************************************/ -int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle) +int bchlib_setup(const char *blkdev, bool readonly, void **handle) { - FAR struct bchlib_s *bch; + struct bchlib_s *bch; struct geometry geo; los_part *part; int ret; @@ -71,26 +71,28 @@ int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle) /* Allocate the BCH state structure */ - bch = (FAR struct bchlib_s *)zalloc(sizeof(struct bchlib_s)); + bch = (struct bchlib_s *)zalloc(sizeof(struct bchlib_s)); if (!bch) { PRINTK("ERROR: Failed to allocate BCH structure\n"); return -ENOMEM; } - /* Open the block driver */ - ret = open_blockdriver(blkdev, readonly ? MS_RDONLY : 0, &bch->inode); + ret = open_blockdriver(blkdev, readonly ? MS_RDONLY : 0, &bch->vnode); if (ret < 0) { PRINTK("ERROR: Failed to open driver %s: %d\n", blkdev, -ret); goto errout_with_bch; } - DEBUGASSERT(bch->inode && bch->inode->u.i_bops && bch->inode->u.i_bops->geometry); + struct drv_data *drv = (struct drv_data *)bch->vnode->data; + struct block_operations *bops = (struct block_operations *)drv->ops; + + DEBUGASSERT(bch->vnode && bops && bops->geometry); - ret = bch->inode->u.i_bops->geometry(bch->inode, &geo); + ret = bops->geometry(bch->vnode, &geo); if (ret < 0) { PRINTK("ERROR: geometry failed: %d\n", -ret); @@ -104,7 +106,7 @@ int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle) goto errout_with_bch; } - if (!readonly && (!bch->inode->u.i_bops->write || !geo.geo_writeenabled)) + if (!readonly && (!bops->write || !geo.geo_writeenabled)) { PRINTK("ERROR: write access not supported\n"); ret = -EACCES; @@ -121,7 +123,7 @@ int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle) bch->dirty = false; bch->unlinked = false; - part = los_part_find(bch->inode); + part = los_part_find(bch->vnode); if (part != NULL) { bch->sectstart = part->sector_start; @@ -137,7 +139,7 @@ int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle) /* Allocate the sector I/O buffer */ - bch->buffer = (FAR uint8_t *)malloc(bch->sectsize); + bch->buffer = (uint8_t *)malloc(bch->sectsize); if (!bch->buffer) { PRINTK("ERROR: Failed to allocate sector buffer\n"); diff --git a/drivers/bch/bchlib_teardown.c b/drivers/bch/bchlib_teardown.c old mode 100755 new mode 100644 index 47425c0..8564d81 --- a/drivers/bch/bchlib_teardown.c +++ b/drivers/bch/bchlib_teardown.c @@ -40,6 +40,7 @@ #include #include #include +#include "fs/fs.h" #include "bch.h" /**************************************************************************** @@ -55,9 +56,9 @@ * ****************************************************************************/ -int bchlib_teardown(FAR void *handle) +int bchlib_teardown(void *handle) { - FAR struct bchlib_s *bch = (FAR struct bchlib_s *)handle; + struct bchlib_s *bch = (struct bchlib_s *)handle; DEBUGASSERT(handle); @@ -74,7 +75,7 @@ int bchlib_teardown(FAR void *handle) /* Close the block driver */ - (void)close_blockdriver(bch->inode); + (void)close_blockdriver(bch->vnode); /* Free the BCH state structure */ diff --git a/drivers/pipes/fifo.c b/drivers/pipes/fifo.c old mode 100755 new mode 100644 index fd4b33f..c489853 --- a/drivers/pipes/fifo.c +++ b/drivers/pipes/fifo.c @@ -51,7 +51,7 @@ * Private Data ****************************************************************************/ -static ssize_t fifo_map(FAR struct file* filep, FAR LosVmMapRegion *region) +static ssize_t fifo_map(struct file* filep, LosVmMapRegion *region) { PRINTK("%s %d, mmap is not support\n", __FUNCTION__, __LINE__); return 0; @@ -59,16 +59,16 @@ static ssize_t fifo_map(FAR struct file* filep, FAR LosVmMapRegion *region) static const struct file_operations_vfs fifo_fops = { - pipecommon_open, /* open */ - pipecommon_close, /* close */ - pipecommon_read, /* read */ - pipecommon_write, /* write */ - NULL, /* seek */ - NULL, /* ioctl */ - fifo_map, /* mmap */ - NULL, /* poll */ + .open = pipecommon_open, /* open */ + .close = pipecommon_close, /* close */ + .read = pipecommon_read, /* read */ + .write = pipecommon_write, /* write */ + .seek = NULL, /* seek */ + .ioctl = NULL, /* ioctl */ + .mmap = fifo_map, /* mmap */ + .poll = NULL, /* poll */ #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS - pipecommon_unlink, /* unlink */ + .unlink = pipecommon_unlink, /* unlink */ #endif }; @@ -110,9 +110,9 @@ static const struct file_operations_vfs fifo_fops = * ****************************************************************************/ -int mkfifo(FAR const char *pathname, mode_t mode) +int mkfifo(const char *pathname, mode_t mode) { - FAR struct pipe_dev_s *dev; + struct pipe_dev_s *dev = NULL; int ret; size_t bufsize = 1024; @@ -139,7 +139,7 @@ int mkfifo(FAR const char *pathname, mode_t mode) return -ENOMEM; } - ret = register_driver(pathname, &fifo_fops, mode, (FAR void *)dev); + ret = register_driver(pathname, &fifo_fops, mode, (void *)dev); if (ret != 0) { pipecommon_freedev(dev); diff --git a/drivers/pipes/pipe.c b/drivers/pipes/pipe.c old mode 100755 new mode 100644 index 96ed3a2..cf876e1 --- a/drivers/pipes/pipe.c +++ b/drivers/pipes/pipe.c @@ -47,6 +47,7 @@ #include +#include "fs/vnode.h" #include "pipe_common.h" #include "stdio.h" #if CONFIG_DEV_PIPE_SIZE > 0 @@ -65,16 +66,16 @@ * Private Function Prototypes ****************************************************************************/ -static int pipe_close(FAR struct file *filep); +static int pipe_close(struct file *filep); #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS -static int pipe_unlink(FAR struct inode *priv); +int pipe_unlink(struct Vnode *priv); #endif /**************************************************************************** * Private Data ****************************************************************************/ -static ssize_t pipe_map(FAR struct file* filep, FAR LosVmMapRegion *region) +static ssize_t pipe_map(struct file* filep, LosVmMapRegion *region) { PRINTK("%s %d, mmap is not support\n", __FUNCTION__, __LINE__); return 0; @@ -82,16 +83,16 @@ static ssize_t pipe_map(FAR struct file* filep, FAR LosVmMapRegion *region) static const struct file_operations_vfs pipe_fops = { - pipecommon_open, /* open */ - pipe_close, /* close */ - pipecommon_read, /* read */ - pipecommon_write, /* write */ - NULL, /* seek */ - NULL, /* ioctl */ - pipe_map, /* mmap */ - pipecommon_poll, /* poll */ + .open = pipecommon_open, /* open */ + .close = pipe_close, /* close */ + .read = pipecommon_read, /* read */ + .write = pipecommon_write, /* write */ + .seek = NULL, /* seek */ + .ioctl = NULL, /* ioctl */ + .mmap = pipe_map, /* mmap */ + .poll = pipecommon_poll, /* poll */ #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS - pipe_unlink, /* unlink */ + .unlink = pipe_unlink, /* unlink */ #endif }; @@ -145,10 +146,10 @@ static inline void pipe_free(int pipeno) * Name: pipe_close ****************************************************************************/ -static int pipe_close(FAR struct file *filep) +static int pipe_close(struct file *filep) { - FAR struct inode *inode = filep->f_inode; - FAR struct pipe_dev_s *dev = inode->i_private; + struct Vnode *vnode = filep->f_vnode; + struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv; int ret; if (dev == NULL) @@ -159,7 +160,7 @@ static int pipe_close(FAR struct file *filep) /* Perform common close operations */ ret = pipecommon_close(filep); - if (ret == 0 && inode->i_crefs == 1) + if (ret == 0 && vnode->useCount <= 1) { /* Release the pipe when there are no further open references to it. */ @@ -174,9 +175,9 @@ static int pipe_close(FAR struct file *filep) ****************************************************************************/ #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS -static int pipe_unlink(FAR struct inode *priv) + int pipe_unlink(struct Vnode *vnode) { - FAR struct pipe_dev_s *dev = priv->i_private; + struct pipe_dev_s *dev = ((struct drv_data *)vnode->data)->priv; uint8_t pipeno = 0; int ret; @@ -185,8 +186,8 @@ static int pipe_unlink(FAR struct inode *priv) pipeno = dev->d_pipeno; } /* Perform common close operations */ - ret = pipecommon_unlink(priv); - if (ret == 0 && priv->i_crefs == 1) + ret = pipecommon_unlink(vnode); + if (ret == 0) { (void)sem_wait(&g_pipesem); g_pipecreated &= ~(1 << pipeno); @@ -198,7 +199,6 @@ static int pipe_unlink(FAR struct inode *priv) } #endif - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -207,7 +207,7 @@ static int pipe_unlink(FAR struct inode *priv) * Name: pipe2 * * Description: - * pipe() creates a pair of file descriptors, pointing to a pipe inode, + * pipe() creates a pair of file descriptors, pointing to a pipe vnode, * and places them in the array pointed to by 'fd'. fd[0] is for reading, * fd[1] is for writing. * @@ -228,11 +228,12 @@ static int pipe_unlink(FAR struct inode *priv) int pipe(int fd[2]) { - FAR struct pipe_dev_s *dev = NULL; + struct pipe_dev_s *dev = NULL; char devname[16]; int pipeno; int errcode; int ret; + struct file *filep = NULL; size_t bufsize = 1024; /* Get exclusive access to the pipe allocation data */ @@ -276,7 +277,7 @@ int pipe(int fd[2]) /* Register the pipe device */ - ret = register_driver(devname, &pipe_fops, 0660, (FAR void *)dev); + ret = register_driver(devname, &pipe_fops, 0660, (void *)dev); if (ret != 0) { (void)sem_post(&g_pipesem); @@ -309,6 +310,12 @@ int pipe(int fd[2]) goto errout_with_wrfd; } + ret = fs_getfilep(fd[0], &filep); + filep->ops = &pipe_fops; + + ret = fs_getfilep(fd[1], &filep); + filep->ops = &pipe_fops; + return OK; errout_with_wrfd: diff --git a/drivers/pipes/pipe_common.c b/drivers/pipes/pipe_common.c old mode 100755 new mode 100644 index 0b3a53c..e57dbc8 --- a/drivers/pipes/pipe_common.c +++ b/drivers/pipes/pipe_common.c @@ -66,6 +66,8 @@ #include "user_copy.h" #ifdef LOSCFG_KERNEL_PIPE +#include "fs/vnode.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -94,7 +96,7 @@ static void pipecommon_semtake(sem_t *sem); * Name: pipecommon_semtake ****************************************************************************/ -static void pipecommon_semtake(FAR sem_t *sem) +static void pipecommon_semtake(sem_t *sem) { int ret; @@ -112,7 +114,7 @@ static void pipecommon_semtake(FAR sem_t *sem) * Name: pipecommon_pollnotify ****************************************************************************/ -static void pipecommon_pollnotify(FAR struct pipe_dev_s *dev, +static void pipecommon_pollnotify(struct pipe_dev_s *dev, pollevent_t eventset) { if (eventset & POLLERR) @@ -131,9 +133,9 @@ static void pipecommon_pollnotify(FAR struct pipe_dev_s *dev, * Name: pipecommon_allocdev ****************************************************************************/ -FAR struct pipe_dev_s *pipecommon_allocdev(size_t bufsize, const char *name) +struct pipe_dev_s *pipecommon_allocdev(size_t bufsize, const char *name) { - FAR struct pipe_dev_s *dev; + struct pipe_dev_s *dev = NULL; int ret; if (bufsize > CONFIG_DEV_PIPE_MAXSIZE) @@ -143,7 +145,7 @@ FAR struct pipe_dev_s *pipecommon_allocdev(size_t bufsize, const char *name) /* Allocate a private structure to manage the pipe */ - dev = (FAR struct pipe_dev_s *)malloc(sizeof(struct pipe_dev_s)); + dev = (struct pipe_dev_s *)malloc(sizeof(struct pipe_dev_s)); if (dev) { /* Initialize the private structure */ @@ -173,7 +175,7 @@ FAR struct pipe_dev_s *pipecommon_allocdev(size_t bufsize, const char *name) * Name: pipecommon_freedev ****************************************************************************/ -void pipecommon_freedev(FAR struct pipe_dev_s *dev) +void pipecommon_freedev(struct pipe_dev_s *dev) { sem_destroy(&dev->d_bfsem); sem_destroy(&dev->d_rdsem); @@ -185,10 +187,10 @@ void pipecommon_freedev(FAR struct pipe_dev_s *dev) * Name: pipecommon_open ****************************************************************************/ -int pipecommon_open(FAR struct file *filep) +int pipecommon_open(struct file *filep) { - FAR struct inode *inode = filep->f_inode; - FAR struct pipe_dev_s *dev = inode->i_private; + struct Vnode *vnode = filep->f_vnode; + struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv; int sval; int ret; @@ -213,9 +215,9 @@ int pipecommon_open(FAR struct file *filep) * is first opened. */ - if (inode->i_crefs == 1 && dev->d_buffer == NULL) + if (vnode->useCount == 1 && dev->d_buffer == NULL) { - dev->d_buffer = (FAR uint8_t *)malloc(dev->d_bufsize); + dev->d_buffer = (uint8_t *)malloc(dev->d_bufsize); if (!dev->d_buffer) { (void)sem_post(&dev->d_bfsem); @@ -285,6 +287,8 @@ int pipecommon_open(FAR struct file *filep) } } + vnode->useCount++; + return ret; } @@ -292,13 +296,13 @@ int pipecommon_open(FAR struct file *filep) * Name: pipecommon_close ****************************************************************************/ -int pipecommon_close(FAR struct file *filep) +int pipecommon_close(struct file *filep) { - FAR struct inode *inode = filep->f_inode; - FAR struct pipe_dev_s *dev = inode->i_private; + struct Vnode *vnode = filep->f_vnode; + struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv; int sval; - if (dev == NULL || filep->f_inode->i_crefs <= 0) + if (dev == NULL || filep->f_vnode->useCount <= 1) { return -EINVAL; } @@ -314,9 +318,9 @@ int pipecommon_close(FAR struct file *filep) * still outstanding references to the pipe. */ - /* Check if the decremented inode reference count would go to zero */ + /* Check if the decremented vnode reference count would go to zero */ - if (inode->i_crefs > 1) + if (vnode->useCount > 1) { /* More references.. If opened for writing, decrement the count of * writers on the pipe instance. @@ -380,6 +384,8 @@ int pipecommon_close(FAR struct file *filep) dev->d_nreaders = 0; } + vnode->useCount--; + sem_post(&dev->d_bfsem); return OK; } @@ -388,11 +394,11 @@ int pipecommon_close(FAR struct file *filep) * Name: pipecommon_read ****************************************************************************/ -ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len) +ssize_t pipecommon_read(struct file *filep, char *buffer, size_t len) { - FAR struct inode *inode = filep->f_inode; - FAR struct pipe_dev_s *dev = inode->i_private; - ssize_t nread = 0; + struct Vnode *vnode = filep->f_vnode; + struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv; + ssize_t nread; int sval; int ret; volatile int num; @@ -548,11 +554,11 @@ ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len) * Name: pipecommon_write ****************************************************************************/ -ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer, +ssize_t pipecommon_write(struct file *filep, const char *buffer, size_t len) { - FAR struct inode *inode = filep->f_inode; - FAR struct pipe_dev_s *dev = inode->i_private; + struct Vnode *vnode = filep->f_vnode; + struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv; ssize_t nwritten = 0; ssize_t last; int nxtwrndx; @@ -710,13 +716,13 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer, * Name: pipecommon_poll ****************************************************************************/ -int pipecommon_poll(FAR struct file *filep, poll_table *table) +int pipecommon_poll(struct file *filep, poll_table *table) { - FAR struct inode *inode = filep->f_inode; - FAR struct pipe_dev_s *dev = inode->i_private; + struct Vnode *vnode = filep->f_vnode; + struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv; pollevent_t eventset; pipe_ndx_t nbytes; - int ret = OK; + int ret; if (dev == NULL || table == NULL) { @@ -787,7 +793,7 @@ int pipecommon_poll(FAR struct file *filep, poll_table *table) * Name: pipecommon_ioctl ****************************************************************************/ -int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +int pipecommon_ioctl(struct file *filep, int cmd, unsigned long arg) { return -ENOSYS; } @@ -797,38 +803,30 @@ int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg) ****************************************************************************/ #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS -int pipecommon_unlink(FAR struct inode *inode) +int pipecommon_unlink(struct Vnode *vnode) { - FAR struct pipe_dev_s *dev; + struct pipe_dev_s *dev = NULL; - if (inode == NULL || inode->i_private == NULL) - { + if (vnode == NULL || vnode->data == NULL) + { return -EINVAL; - } - - dev = (FAR struct pipe_dev_s *)inode->i_private; + } - /* Are the any open references to the driver? */ - - if (inode->i_crefs == 1) + dev = ((struct drv_data *)vnode->data)->priv; + if (dev == NULL) { - /* No.. free the buffer (if there is one) */ - - if (dev->d_buffer) - { - free(dev->d_buffer); - } - - /* And free the device structure. */ - unregister_driver(dev->name); - pipecommon_freedev(dev); + return -EINVAL; } - else + + if (dev->d_buffer) { - PRINTK("Device busy!\n"); - return -EBUSY; + free(dev->d_buffer); } + /* And free the device structure. */ + unregister_driver(dev->name); + pipecommon_freedev(dev); + return OK; } #endif diff --git a/drivers/pipes/pipe_common.h b/drivers/pipes/pipe_common.h index 3574103..b5984d9 100755 --- a/drivers/pipes/pipe_common.h +++ b/drivers/pipes/pipe_common.h @@ -161,7 +161,7 @@ ssize_t pipecommon_write(FAR struct file *, FAR const char *, size_t); int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg); int pipecommon_poll(FAR struct file *filep, poll_table *fds); #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS -int pipecommon_unlink(FAR struct inode *priv); +int pipecommon_unlink(struct Vnode *vnode); #endif int pipe_init(void); diff --git a/drivers/video/fb.c b/drivers/video/fb.c old mode 100755 new mode 100644 index 86eb106..985b928 --- a/drivers/video/fb.c +++ b/drivers/video/fb.c @@ -61,8 +61,8 @@ struct fb_chardev_s { - FAR struct fb_vtable_s *vtable; /* Framebuffer interface */ - FAR void *fbmem; /* Start of frame buffer memory */ + struct fb_vtable_s *vtable; /* Framebuffer interface */ + void *fbmem; /* Start of frame buffer memory */ size_t fblen; /* Size of the framebuffer */ uint8_t plane; /* Video plan number */ uint8_t bpp; /* Bits per pixel */ @@ -75,15 +75,13 @@ static struct fb_chardev_s *g_fb_dev[FB_DEV_MAXNUM] = {NULL}; * Private Function Prototypes ****************************************************************************/ -static int fb_open(FAR struct file *filep); -static int fb_close(FAR struct file *filep); -static ssize_t fb_read(FAR struct file *filep, FAR char *buffer, - size_t buflen); -static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer, - size_t buflen); -static off_t fb_seek(FAR struct file *filep, off_t offset, int whence); -static int fb_ioctl(FAR struct file *filep, int cmd, unsigned long arg); -static ssize_t fb_mmap(FAR struct file* filep, FAR LosVmMapRegion *region); +static int fb_open(struct file *filep); +static int fb_close(struct file *filep); +static ssize_t fb_read(struct file *filep, char *buffer, size_t buflen); +static ssize_t fb_write(struct file *filep, const char *buffer, size_t buflen); +static off_t fb_seek(struct file *filep, off_t offset, int whence); +static int fb_ioctl(struct file *filep, int cmd, unsigned long arg); +static ssize_t fb_mmap(struct file* filep, LosVmMapRegion *region); /**************************************************************************** * Private Data @@ -110,13 +108,13 @@ static const struct file_operations_vfs fb_fops = * Private Functions ****************************************************************************/ -static ssize_t fb_mmap(FAR struct file *filep, FAR LosVmMapRegion *region) +static ssize_t fb_mmap(struct file *filep, LosVmMapRegion *region) { int ret = -EINVAL; struct fb_chardev_s *fb; struct fb_vtable_s *vtable; - fb = (struct fb_chardev_s *)filep->f_inode->i_private; + fb = (struct fb_chardev_s *)((struct drv_data *)filep->f_vnode->data)->priv; if (fb == NULL) { return -ENODEV; @@ -144,14 +142,14 @@ static ssize_t fb_mmap(FAR struct file *filep, FAR LosVmMapRegion *region) * ****************************************************************************/ -static int fb_open(FAR struct file *filep) +static int fb_open(struct file *filep) { - DEBUGASSERT(filep != NULL && filep->f_inode != NULL); + DEBUGASSERT(filep != NULL && filep->f_vnode != NULL); struct fb_chardev_s *fb; struct fb_vtable_s *vtable; int ret = -EINVAL; - fb = (struct fb_chardev_s *)filep->f_inode->i_private; + fb = (struct fb_chardev_s *)((struct drv_data *)filep->f_vnode->data)->priv; if (fb == NULL) { return -ENODEV; @@ -179,14 +177,14 @@ static int fb_open(FAR struct file *filep) * ****************************************************************************/ -static int fb_close(FAR struct file *filep) +static int fb_close(struct file *filep) { - DEBUGASSERT(filep != NULL && filep->f_inode != NULL); + DEBUGASSERT(filep != NULL && filep->f_vnode != NULL); struct fb_chardev_s *fb; struct fb_vtable_s *vtable; int ret = -EINVAL; - fb = (struct fb_chardev_s *)filep->f_inode->i_private; + fb = (struct fb_chardev_s *)((struct drv_data *)filep->f_vnode->data)->priv; if (fb == NULL) { return -ENODEV; @@ -210,10 +208,9 @@ static int fb_close(FAR struct file *filep) * Name: fb_read ****************************************************************************/ -static ssize_t fb_read(FAR struct file *filep, FAR char *buffer, size_t len) +static ssize_t fb_read(struct file *filep, char *buffer, size_t len) { - FAR struct inode *inode; - FAR struct fb_chardev_s *fb; + struct fb_chardev_s *fb = NULL; size_t start; size_t end; size_t size; @@ -221,10 +218,8 @@ static ssize_t fb_read(FAR struct file *filep, FAR char *buffer, size_t len) /* Get the framebuffer instance */ - DEBUGASSERT(filep != NULL && filep->f_inode != NULL); - inode = filep->f_inode; - fb = (FAR struct fb_chardev_s *)inode->i_private; - + DEBUGASSERT(filep != NULL && filep->f_vnode != NULL); + fb = (struct fb_chardev_s *)((struct drv_data *)filep->f_vnode->data)->priv; /* Get the start and size of the transfer */ start = filep->f_pos; @@ -256,11 +251,10 @@ static ssize_t fb_read(FAR struct file *filep, FAR char *buffer, size_t len) * Name: fb_write ****************************************************************************/ -static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer, +static ssize_t fb_write(struct file *filep, const char *buffer, size_t len) { - FAR struct inode *inode; - FAR struct fb_chardev_s *fb; + struct fb_chardev_s *fb = NULL; size_t start; size_t end; size_t size; @@ -268,10 +262,8 @@ static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer, /* Get the framebuffer instance */ - DEBUGASSERT(filep != NULL && filep->f_inode != NULL); - inode = filep->f_inode; - fb = (FAR struct fb_chardev_s *)inode->i_private; - + DEBUGASSERT(filep != NULL && filep->f_vnode != NULL); + fb = (struct fb_chardev_s *)((struct drv_data *)filep->f_vnode->data)->priv; /* Get the start and size of the transfer */ start = filep->f_pos; @@ -309,19 +301,16 @@ static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer, * ****************************************************************************/ -static off_t fb_seek(FAR struct file *filep, off_t offset, int whence) +static off_t fb_seek(struct file *filep, off_t offset, int whence) { - FAR struct inode *inode; - FAR struct fb_chardev_s *fb; + struct fb_chardev_s *fb = NULL; off_t newpos; int ret; /* Get the framebuffer instance */ - DEBUGASSERT(filep != NULL && filep->f_inode != NULL); - inode = filep->f_inode; - fb = (FAR struct fb_chardev_s *)inode->i_private; - + DEBUGASSERT(filep != NULL && filep->f_vnode != NULL); + fb = (struct fb_chardev_s *)((struct drv_data *)filep->f_vnode->data)->priv; /* Determine the new, requested file position */ switch (whence) @@ -378,25 +367,22 @@ static off_t fb_seek(FAR struct file *filep, off_t offset, int whence) * ****************************************************************************/ -static int fb_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +static int fb_ioctl(struct file *filep, int cmd, unsigned long arg) { - FAR struct inode *inode; - FAR struct fb_chardev_s *fb; + struct fb_chardev_s *fb = NULL; int ret; /* Get the framebuffer instance */ - DEBUGASSERT(filep != NULL && filep->f_inode != NULL); - inode = filep->f_inode; - fb = (FAR struct fb_chardev_s *)inode->i_private; - + DEBUGASSERT(filep != NULL && filep->f_vnode != NULL); + fb = (struct fb_chardev_s *)((struct drv_data *)filep->f_vnode->data)->priv; /* Process the IOCTL command */ switch (cmd) { case FIOC_MMAP: /* Get color plane info */ { - FAR void **ppv = (FAR void **)((uintptr_t)arg); + void **ppv = (void **)((uintptr_t)arg); uintptr_t fbmem = (uintptr_t)fb->fbmem; /* Return the address corresponding to the start of frame buffer. */ @@ -532,7 +518,7 @@ static int fb_ioctl(FAR struct file *filep, int cmd, unsigned long arg) ret = fb->vtable->getplaneinfo(fb->vtable, fb->plane, &pinfo); if (ret >= 0) { - nx_notify_rectangle((FAR NX_PLANEINFOTYPE *)&pinfo, &rect); + nx_notify_rectangle((NX_PLANEINFOTYPE *)&pinfo, &rect); } } break; @@ -739,7 +725,7 @@ static int fb_ioctl(FAR struct file *filep, int cmd, unsigned long arg) int fb_register(int display, int plane) { - FAR struct fb_chardev_s *fb; + struct fb_chardev_s *fb = NULL; struct fb_videoinfo_s vinfo; struct fb_planeinfo_s pinfo; #ifdef CONFIG_FB_OVERLAY @@ -754,7 +740,7 @@ int fb_register(int display, int plane) /* Allocate a framebuffer state instance */ - fb = (FAR struct fb_chardev_s *)malloc(sizeof(struct fb_chardev_s)); + fb = (struct fb_chardev_s *)malloc(sizeof(struct fb_chardev_s)); if (fb == NULL) { return -ENOMEM; @@ -837,7 +823,7 @@ int fb_register(int display, int plane) (void)snprintf(devname, 16, "/dev/fb%d.%d", display, plane); } - ret = register_driver(devname, &fb_fops, 0666, (FAR void *)fb); + ret = register_driver(devname, &fb_fops, 0666, (void *)fb); if (ret < 0) { gerr("ERROR: register_driver() failed: %d\n", ret); @@ -855,7 +841,7 @@ errout_with_fb: int fb_unregister(int display) { - FAR struct fb_chardev_s *fb; + struct fb_chardev_s *fb = NULL; if (display < 0 || display >= FB_DEV_MAXNUM) return -EINVAL; diff --git a/fs/dirent/fs_closedir.c b/fs/dirent/fs_closedir.c old mode 100755 new mode 100644 index cd733c2..5c9c2ad --- a/fs/dirent/fs_closedir.c +++ b/fs/dirent/fs_closedir.c @@ -38,19 +38,12 @@ ****************************************************************************/ #include "vfs_config.h" - #include "dirent.h" #include "errno.h" - #include "stdlib.h" #include "fs/fs.h" #include "fs/dirent_fs.h" - -#include "inode/inode.h" - -/**************************************************************************** - * Private Functions - ****************************************************************************/ +#include "fs/vnode.h" /**************************************************************************** * Public Functions @@ -73,90 +66,56 @@ * ****************************************************************************/ -int closedir(FAR DIR *dirp) +int closedir(DIR *dirp) { struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp; -#ifndef CONFIG_DISABLE_MOUNTPOINT - struct inode *inode; -#endif + struct Vnode *vnode = NULL; int ret; /* Verify that we were provided with a valid directory structure */ if (!idir || idir->fd_status != DIRENT_MAGIC) { - ret = EBADF; + ret = -EBADF; goto errout; } - /* A special case is when we enumerate an "empty", unused inode. That is - * an inode in the pseudo-filesystem that has no operations and no children. - * This is a "dangling" directory entry that has lost its childre. - */ - if (idir->fd_root) { - /* This is the 'root' inode of the directory. This means different + /* This is the 'root' vnode of the directory. This means different * things wih different filesystems. */ - -#ifndef CONFIG_DISABLE_MOUNTPOINT - inode = idir->fd_root; - - /* The way that we handle the close operation depends on what kind of - * root inode we have open. - */ - - if (INODE_IS_MOUNTPT(inode) && !DIRENT_ISPSEUDONODE(idir->fd_flags)) + vnode = idir->fd_root; + /* Perform the closedir() operation */ + if (vnode->vop && vnode->vop->Closedir) { - /* The node is a file system mointpoint. Verify that the - * mountpoint supports the closedir() method (not an error if it - * does not) - */ - - if (inode->u.i_mops && inode->u.i_mops->closedir) + ret = vnode->vop->Closedir(vnode, idir); + if (ret < 0) { - /* Perform the closedir() operation */ - - ret = inode->u.i_mops->closedir(inode, idir); - if (ret < 0) - { - ret = -ret; - goto errout_with_inode; - } + goto errout_with_vnode; } } else -#endif { - /* The node is part of the root pseudo file system, release - * our contained reference to the 'next' inode. - */ - - if (idir->u.pseudo.fd_next) - { - inode_release(idir->u.pseudo.fd_next); - } + ret = -ENOSYS; + goto errout_with_vnode; } - - /* Release our references on the contained 'root' inode */ - - inode_release(idir->fd_root); + VnodeHold(); + vnode->useCount--; + VnodeDrop(); } /* Then release the container */ idir->fd_status = 0; free(idir); + return OK; -#ifndef CONFIG_DISABLE_MOUNTPOINT -errout_with_inode: - inode_release(inode); +errout_with_vnode: free(idir); -#endif errout: - set_errno(ret); + set_errno(-ret); return VFS_ERROR; } diff --git a/fs/dirent/fs_opendir.c b/fs/dirent/fs_opendir.c old mode 100755 new mode 100644 index 44b0186..3f6c12c --- a/fs/dirent/fs_opendir.c +++ b/fs/dirent/fs_opendir.c @@ -39,153 +39,15 @@ ****************************************************************************/ #include "vfs_config.h" - #include "dirent.h" #include "string.h" #include "assert.h" #include "errno.h" - #include "stdlib.h" #include "fs/fs.h" #include "fs/dirent_fs.h" - -#include "inode/inode.h" - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: open_mountpoint - * - * Description: - * Handle the case where the inode to be opened is within a mountpoint. - * - * Input Parameters: - * inode -- the inode of the mountpoint to open - * relpath -- the relative path within the mountpoint to open - * dir -- the dirent structure to be initialized - * - * Returned Value: - * On success, OK is returned; Otherwise, a positive errno is returned. - * - ****************************************************************************/ - -#ifndef CONFIG_DISABLE_MOUNTPOINT -static inline int open_mountpoint(FAR struct inode *inode, - FAR const char *relpath, - FAR struct fs_dirent_s *dir) -{ - int ret; - - /* The inode itself as the 'root' of mounted volume. The actually - * directory is at relpath into the* mounted filesystem. - * - * Verify that the mountpoint inode supports the opendir() method - */ - - if (!inode->u.i_mops || !inode->u.i_mops->opendir) - { - return ENOSYS; - } - - /* Take reference to the mountpoint inode. Note that we do not use - * inode_addref() because we already hold the tree semaphore. - */ - - inode->i_crefs++; - - /* Perform the opendir() operation */ - - ret = inode->u.i_mops->opendir(inode, relpath, dir); - if (ret < 0) - { - /* We now need to back off our reference to the inode. We can't - * call inode_release() to do that unless we release the tree - * semaphore. The following should be safe because: (1) after the - * reference count was incremented above it should be >=1 so it should - * not decrement below zero, and (2) we hold the tree semaphore so no - * other thread should be able to change the reference count. - */ - - inode->i_crefs--; - DEBUGASSERT(inode->i_crefs >= 0); - - /* Negate the error value so that it can be used to set errno */ - - return -ret; - } - - return OK; -} -#endif - -/**************************************************************************** - * Name: open_pseudodir - * - * Description: - * Handle the case where the inode to be opened is within the top-level - * pseudo-file system. - * - * Input Parameters: - * inode -- the inode of the mountpoint to open - * dir -- the dirent structure to be initialized - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void open_pseudodir(FAR struct inode *inode, FAR struct fs_dirent_s *dir) -{ - /* We have a valid pseudo-filesystem node. Take two references on the - * inode -- one for the parent (fd_root) and one for the child (fd_next). - * Note that we do not call inode_addref because we are holding the tree - * semaphore and that would result in deadlock. - */ - - inode->i_crefs++; - inode->i_child->i_crefs++; - dir->fd_root = inode; /* Save the inode where we start */ - dir->u.pseudo.fd_next = inode->i_child; /* This is the next node to use for readdir() */ - - /* Flag the inode as belonging to the pseudo-filesystem */ - -#ifndef CONFIG_DISABLE_MOUNTPOINT - DIRENT_SETPSEUDONODE(dir->fd_flags); -#endif -} - -/**************************************************************************** - * Name: open_emptydir - * - * Description: - * Handle the case where the inode to be opened is an empty, directory node - * within the top-level pseudo-file system. That is, it has no operations - * and, therefore, it must be a directory node. But is has no children - * to be enumerated either. - * - * Input Parameters: - * dir -- the dirent structure to be initialized - * - * Returned Value: - * None - * - ****************************************************************************/ - -static inline void open_emptydir(FAR struct fs_dirent_s *dir) -{ - /* We have a valid, but empty pseudo-filesystem node. fd_next is NULL - * meaning that we are already at the end of the list of its children. - * fd_root is NULL so that if the directory is rewound, it will still be - * at the end of the list. - */ - /* Flag the inode as belonging to the pseudo-filesystem */ - -#ifndef CONFIG_DISABLE_MOUNTPOINT - DIRENT_SETPSEUDONODE(dir->fd_flags); -#endif -} +#include "fs/vnode.h" +#include "fs/path_cache.h" /**************************************************************************** * Public Functions @@ -217,141 +79,72 @@ static inline void open_emptydir(FAR struct fs_dirent_s *dir) * ****************************************************************************/ -FAR DIR *opendir(FAR const char *path) +DIR *opendir(const char *path) { - FAR struct inode *inode; - FAR struct fs_dirent_s *dir; - FAR const char *relpath; + struct Vnode *vp = NULL; + struct fs_dirent_s *dir = NULL; int ret; - char *fullpath; - char *fullpath_bak; - /* If we are given 'nothing' then we will interpret this as - * request for the root inode. - */ - - ret = vfs_normalize_path((const char *)NULL, path, &fullpath); - if (ret < 0) + /* Find the node matching the path. */ + VnodeHold(); + ret = VnodeLookup(path, &vp, 0); + if (vp == NULL || ret != OK) { - ret = -ret; + VnodeDrop(); goto errout; } - fullpath_bak = fullpath; - - inode_semtake(); - - /* We don't know what to do with relative pathes */ - - if (*fullpath != '/') - { - ret = ENOTDIR; - goto errout_with_semaphore; - } - - /* Find the node matching the path. */ - - inode = inode_search((FAR const char **)&fullpath, (FAR struct inode**)NULL, - (FAR struct inode**)NULL, &relpath); - - /* Did we get an inode? */ - - if (inode == NULL) + if (vp->type != VNODE_TYPE_DIR) { - /* 'path' does not exist. */ - - ret = ENOTDIR; - goto errout_with_semaphore; + ret = -ENOTDIR; + PRINT_ERR("opendir (%s) failed, err=%d\n", path, ret); + VnodeDrop(); + goto errout; } - /* Allocate a type DIR -- which is little more than an inode - * container. - */ + vp->useCount++; + VnodeDrop(); - dir = (FAR struct fs_dirent_s *)zalloc(sizeof(struct fs_dirent_s)); + /* Allocate a type DIR -- which is little more than an vp container. */ + dir = (struct fs_dirent_s *)calloc(1, sizeof(struct fs_dirent_s)); if (!dir) { /* Insufficient memory to complete the operation. */ - - ret = ENOMEM; - goto errout_with_semaphore; + ret = -ENOMEM; + goto errout_with_count; } /* Populate the DIR structure and return it to the caller. The way that * we do this depends on whenever this is a "normal" pseudo-file-system - * inode or a file system mountpoint. + * vp or a file system mountpoint. */ dir->fd_position = 0; /* This is the position in the read stream */ - /* The node is part of the root pseudo file system. Does the inode - * have a child? If so that the child would be the 'root' of a list - * of nodes under the directory. - */ - - FAR struct inode *child = inode->i_child; - if (!*relpath && child) + if (vp->vop != NULL && vp->vop->Opendir != NULL) { - /* It looks we have a valid pseudo-filesystem directory node. */ - - open_pseudodir(inode, dir); - } - -#ifndef CONFIG_DISABLE_MOUNTPOINT - if (INODE_IS_MOUNTPT(inode)) - { - /* Yes, the node is a file system mountpoint */ - - dir->fd_root = inode; /* Save the inode where we start */ - - /* Open the directory at the relative path */ - - ret = open_mountpoint(inode, relpath, dir); - if (ret != OK) - { - goto errout_with_direntry; - } + ret = vp->vop->Opendir(vp, dir); } else -#endif - - if (!*relpath && child == NULL) { - if (inode->u.i_ops == NULL) - { - /* This is a dangling node with no children and no operations. Set - * up to enumerate an empty directory. - */ - - open_emptydir(dir); - } - else - { - ret = ENOTDIR; - goto errout_with_direntry; - } + ret = -ENOSYS; } - else if (*relpath) + if (ret < 0) { - ret = ENOENT; - goto errout_with_direntry; + goto errout; } - dir->fd_status = DIRENT_MAGIC; - inode_semgive(); - free(fullpath_bak); + dir->fd_root = vp; + return ((DIR *)dir); /* Nasty goto's make error handling simpler */ -errout_with_direntry: - free(dir); - -errout_with_semaphore: - inode_semgive(); - free(fullpath_bak); - +errout_with_count: + VnodeHold(); + vp->useCount--; + VnodeDrop(); errout: - set_errno(ret); + set_errno(-ret); return NULL; } @@ -359,170 +152,114 @@ int do_opendir(const char *path, int oflags) { int ret; int fd; - FAR struct inode *inode = NULL; - FAR struct fs_dirent_s *dir = NULL; - FAR const char *relpath = NULL; + + struct Vnode *vp = NULL; + struct file *filep = NULL; + struct fs_dirent_s *dir = NULL; char *fullpath = NULL; - FAR struct file *filep = NULL; - FAR struct inode *child = NULL; - struct inode_search_s desc; + char *relativepath = NULL; - /* If we are given 'nothing' then we will interpret this as - * request for the root inode. - */ + if (path == NULL || *path == 0) + { + ret = -EINVAL; + goto errout; + } - ret = vfs_normalize_path((const char *)NULL, path, &fullpath); + ret = get_path_from_fd(AT_FDCWD, &relativepath); if (ret < 0) { - ret = -ret; goto errout; } - /* We don't know what to do with relative pathes */ - - if (*fullpath != '/') + ret = vfs_normalize_path((const char *)relativepath, path, &fullpath); + if (relativepath) { - ret = ENOTDIR; - goto errout_with_path; + free(relativepath); } - - /* Get an inode for this file */ - - SETUP_SEARCH(&desc, fullpath, false); - ret = inode_find(&desc); if (ret < 0) { - PRINTK("ERROR: Failed to find %s\n", fullpath); - - /* 'path' does not exist. */ - - ret = ENOTDIR; - goto errout_with_path; + goto errout; } - inode = desc.node; - relpath = desc.relpath; - /* Associate the inode with a file structure */ + VnodeHold(); + /* Get an vnode for this file */ + ret = VnodeLookup(path, &vp, 0); + if (ret < 0) + { + PRINT_ERR("Failed to find vnode %s\n", path); + VnodeDrop(); + goto errout; + } + if (vp->type != VNODE_TYPE_DIR) + { + ret = -ENOTDIR; + PRINT_ERR("opendir (%s) failed, err=%d\n", path, ret); + VnodeDrop(); + goto errout; + } + vp->useCount++; + VnodeDrop(); - fd = files_allocate(inode, oflags, 0, NULL, 3); /* 3: file start fd */ + /* Associate the vnode with a file structure */ + fd = files_allocate(vp, oflags, 0, NULL, 3); /* 3: file start fd */ if (fd < 0) { - ret = EMFILE; - goto errout_with_inode; + 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; - - /* The errno value has already been set */ + ret = -EPERM; goto errout_with_fd; } - /* Perform the driver open operation. NOTE that the open method may be - * called many times. The driver/mountpoint logic should handled this - * because it may also be closed that many times. - */ - - ret = OK; - filep->f_path = fullpath; /* The mem will free in close(fd); */ - filep->f_relpath = relpath; + filep->f_path = (char *)fullpath; /* The mem will free in close(fd); */ - /* Allocate a type DIR -- which is little more than an inode - * container. - */ - - dir = (FAR struct fs_dirent_s *)zalloc(sizeof(struct fs_dirent_s)); - if (!dir) + /* 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) { - /* Insufficient memory to complete the operation. */ - - ret = ENOMEM; + ret = -ENOMEM; goto errout_with_fd; } - - /* Populate the DIR structure and return it to the caller. The way that - * we do this depends on whenever this is a "normal" pseudo-file-system - * inode or a file system mountpoint. - */ - dir->fd_position = 0; /* This is the position in the read stream */ - /* The node is part of the root pseudo file system. Does the inode - * have a child? If so that the child would be the 'root' of a list - * of nodes under the directory. - */ - - child = inode->i_child; - if (!*relpath && child) + /* Open the directory at the relative path */ + if (vp->vop != NULL && vp->vop->Opendir != NULL) { - /* It looks we have a valid pseudo-filesystem directory node. */ - - open_pseudodir(inode, dir); - } - -#ifndef CONFIG_DISABLE_MOUNTPOINT - if (INODE_IS_MOUNTPT(inode)) - { - /* Yes, the node is a file system mountpoint */ - - dir->fd_root = inode; /* Save the inode where we start */ - - /* Open the directory at the relative path */ - - ret = open_mountpoint(inode, relpath, dir); - if (ret != OK) - { - goto errout_with_direntry; - } + ret = vp->vop->Opendir(vp, dir); } else -#endif - - if (!*relpath && child == NULL) { - if (inode->u.i_ops == NULL) - { - /* This is a dangling node with no children and no operations. Set - * up to enumerate an empty directory. - */ - - open_emptydir(dir); - } - else - { - ret = ENOTDIR; - goto errout_with_direntry; - } + ret = -ENOSYS; } - else if (*relpath) + + if (ret < 0) { - ret = ENOENT; - goto errout_with_direntry; + free(dir); + goto errout_with_fd; } + dir->fd_root = vp; dir->fd_status = DIRENT_MAGIC; - filep->f_dir = (struct fs_dirent_s *)dir; - return fd; - - /* Nasty goto's make error handling simpler */ + filep->f_dir = dir; -errout_with_direntry: - free(dir); + return fd; errout_with_fd: files_release(fd); - -errout_with_inode: - inode_release(inode); - -errout_with_path: - free(fullpath); - +errout_with_vnode: + VnodeHold(); + vp->useCount--; + VnodeDrop(); errout: - set_errno(ret); - return -1; + if (fullpath) + { + free(fullpath); + } + set_errno(-ret); + return VFS_ERROR; } diff --git a/fs/dirent/fs_readdir.c b/fs/dirent/fs_readdir.c old mode 100755 new mode 100644 index 3f0fd37..81fd09e --- a/fs/dirent/fs_readdir.c +++ b/fs/dirent/fs_readdir.c @@ -39,151 +39,14 @@ ****************************************************************************/ #include "vfs_config.h" - #include "string.h" #include "dirent.h" #include "errno.h" #include "unistd.h" - #include "fs/fs.h" #include "fs/dirent_fs.h" - -#include "inode/inode.h" -#include "sys/statfs.h" #include "user_copy.h" -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: readpseudodir - ****************************************************************************/ - -static inline int readpseudodir(struct fs_dirent_s *idir) -{ - FAR struct inode *prev; - int ret; - - /* Check if we are at the end of the list */ - - if (!idir->u.pseudo.fd_next) - { - /* End of file and error conditions are not distinguishable with - * readdir. Here we return -ENOENT to signal the end of the - * directory. - */ - - return -ENOENT; - } - - /* Copy the inode name into the dirent structure */ - ret = strncpy_s(idir->fd_dir[0].d_name, NAME_MAX + 1, idir->u.pseudo.fd_next->i_name, NAME_MAX); - if (ret != EOK) - { - return -ENAMETOOLONG; - } - - /* If the node has file operations, we will say that it is a file. */ - - idir->fd_dir[0].d_type = 0; - if (idir->u.pseudo.fd_next->u.i_ops) - { -#ifndef CONFIG_DISABLE_MOUNTPOINT - if (INODE_IS_BLOCK(idir->u.pseudo.fd_next)) - { - idir->fd_dir[0].d_type |= DT_BLK; - } - if (INODE_IS_MOUNTPT(idir->u.pseudo.fd_next)) - { - idir->fd_dir[0].d_type |= DT_DIR; - } - else -#endif - { - idir->fd_dir[0].d_type |= DT_CHR; - } - } - - /* If the node has child node(s) or no operations, then we will say that - * it is a directory rather than a special file. NOTE: that the node can - * be both! - */ - - if (idir->u.pseudo.fd_next->i_child || !idir->u.pseudo.fd_next->u.i_ops) - { - idir->fd_dir[0].d_type |= DT_DIR; - } - - /* Now get the inode to vist next time that readdir() is called */ - - inode_semtake(); - - prev = idir->u.pseudo.fd_next; - idir->u.pseudo.fd_next = prev->i_peer; /* The next node to visit */ - - if (idir->u.pseudo.fd_next) - { - /* Increment the reference count on this next node */ - - idir->u.pseudo.fd_next->i_crefs++; - } - - inode_semgive(); - - if (prev) - { - inode_release(prev); - } - - return OK; -} - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: handlezpfsdir - * Description: - * The handlezpfsdir() function handle with the inode with zpfs magic - * - * Input Parameters: - * idir -- the pointer of one dir - * - * Returned Value: - * none - ****************************************************************************/ -#ifdef LOSCFG_FS_ZPFS -static inline void handlezpfsdir(struct fs_dirent_s *idir) -{ - struct statfs buf; - int ret; - /* Maybe there are two or more zpfs nodes together, so we need one loop */ - do - { - if (!idir->u.pseudo.fd_next || !INODE_IS_MOUNTPT(idir->u.pseudo.fd_next) || - !idir->u.pseudo.fd_next->u.i_mops || !idir->u.pseudo.fd_next->u.i_mops->statfs) - { - return; - } - ret = idir->u.pseudo.fd_next->u.i_mops->statfs(idir->u.pseudo.fd_next, &buf); - if (ret != OK || buf.f_type != ZPFS_MAGIC) - { - return; - } - if (readpseudodir(idir) == OK) - { - idir->fd_position++; - } - } while (1); -} -#endif - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - /**************************************************************************** * Name: do_readdir * @@ -206,96 +69,63 @@ static inline void handlezpfsdir(struct fs_dirent_s *idir) ****************************************************************************/ static struct dirent *__readdir(DIR *dirp, int *lencnt) { - FAR struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp; - struct inode *inode_ptr = NULL; + struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp; + struct Vnode *vnode_ptr = NULL; int ret = 0; int file_cnt = 0; + /* Verify that we were provided with a valid directory structure */ - if (!idir || idir->fd_status != DIRENT_MAGIC) + if (!idir) { - ret = EBADF; + ret = -EBADF; goto errout; } - /* A special case is when we enumerate an "empty", unused inode. That is - * an inode in the pseudo-filesystem that has no operations and no children. - * This is a "dangling" directory entry that has lost its children. - */ - - inode_ptr = idir->fd_root; - if (inode_ptr == NULL) + vnode_ptr = idir->fd_root; + if (vnode_ptr == NULL) { /* End of file and error conditions are not distinguishable * with readdir. We return NULL to signal either case. */ - ret = ENOENT; + ret = -ENOENT; goto errout; } - /* The way we handle the readdir depends on the type of inode - * that we are dealing with. - */ - if (DIRENT_ISPSEUDONODE(idir->fd_flags)) - { -#ifdef LOSCFG_FS_ZPFS - /* if the current node has the zpfs magic, we continue to skip the node */ - handlezpfsdir(idir); + /* Perform the readdir() operation */ +#ifdef LOSCFG_ENABLE_READ_BUFFER + idir->read_cnt = MAX_DIRENT_NUM; +#else + idir->read_cnt = 1; #endif - /* The node is part of the root pseudo file system */ - ret = readpseudodir(idir); - if (ret == OK) - { - idir->fd_position++; - idir->fd_dir[0].d_off = idir->fd_position; - idir->fd_dir[0].d_reclen = (uint16_t)sizeof(struct dirent); - *lencnt = sizeof(struct dirent); - return &(idir->fd_dir[0]); - } + if (vnode_ptr->vop != NULL && vnode_ptr->vop->Readdir != NULL) + { + file_cnt = vnode_ptr->vop->Readdir(vnode_ptr, idir); } - -#ifndef CONFIG_DISABLE_MOUNTPOINT - if (INODE_IS_MOUNTPT(inode_ptr)) + else { - /* The node is a file system mointpoint. Verify that the mountpoint - * supports the readdir() method - */ - if (!inode_ptr->u.i_mops || !inode_ptr->u.i_mops->readdir) - { - ret = EACCES; - goto errout; - } + ret = -ENOSYS; + goto errout; + } - /* Perform the readdir() operation */ -#ifdef LOSCFG_ENABLE_READ_BUFFER - idir->read_cnt = MAX_DIRENT_NUM; -#else - idir->read_cnt = 1; -#endif - file_cnt = inode_ptr->u.i_mops->readdir(inode_ptr, idir); - if (file_cnt > 0) - { - *lencnt = file_cnt * sizeof(struct dirent); - return &(idir->fd_dir[0]); - } + if (file_cnt > 0) + { + *lencnt = file_cnt * sizeof(struct dirent); + return &(idir->fd_dir[0]); } -#endif errout: - if (ret != OK) + if (ret < 0) { - if (ret < 0) - { - ret = -ret; - } set_errno(ret); } else if (file_cnt <= 0) { set_errno(ENOENT); } + return (struct dirent *)NULL; } @@ -323,33 +153,30 @@ errout: * EBADF - Invalid directory stream descriptor dir * ****************************************************************************/ - -FAR struct dirent *readdir(DIR *dirp) +struct dirent *readdir(DIR *dirp) { int ret; int old_err = get_errno(); - int lencnt = 0; + int dirent_len = 0; struct dirent *de = NULL; - FAR struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp; - int dirlen; + struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp; -#ifdef LOSCFG_ENABLE_READ_BUFFER - dirlen = MAX_DIRENT_NUM; -#else - dirlen = 1; -#endif - if (idir->cur_pos != 0 && idir->cur_pos < dirlen && idir->cur_pos < idir->end_pos) + if (idir->cur_pos != 0 && idir->cur_pos < MAX_DIRENT_NUM && idir->cur_pos < idir->end_pos) { de = &(idir->fd_dir[idir->cur_pos]); - if (idir->cur_pos == dirlen) + + if (idir->cur_pos == MAX_DIRENT_NUM) { idir->cur_pos = 0; } idir->cur_pos++; + return de; - } else { - de = __readdir(dirp, &lencnt); - idir->end_pos = lencnt / sizeof(struct dirent); + } + else + { + de = __readdir(dirp, &dirent_len); + idir->end_pos = dirent_len / sizeof(struct dirent); idir->cur_pos = 1; if (de == NULL) @@ -372,18 +199,18 @@ FAR struct dirent *readdir(DIR *dirp) int do_readdir(int fd, struct dirent **de, unsigned int count) { struct dirent *de_src = NULL; - int lencnt = 0; + int de_len = 0; /* Did we get a valid file descriptor? */ #if CONFIG_NFILE_DESCRIPTORS > 0 - FAR struct file *filep = NULL; + struct file *filep = NULL; if (de == NULL) { return -EINVAL; } - if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) + if ((fd < 3) || (unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) { return -EBADF; } @@ -401,7 +228,8 @@ int do_readdir(int fd, struct dirent **de, unsigned int count) } /* Then let do_readdir do all of the work */ - de_src = __readdir(filep->f_dir, &lencnt); + + de_src = __readdir(filep->f_dir, &de_len); if (de_src == NULL) { /* Special case: ret = -ENOENT is end of file */ @@ -409,10 +237,8 @@ int do_readdir(int fd, struct dirent **de, unsigned int count) } *de = de_src; - lencnt = (lencnt != 0) ? lencnt : sizeof(*de_src); - return lencnt; + return de_len; } #endif - - return 0; + return OK; } diff --git a/fs/dirent/fs_rewinddir.c b/fs/dirent/fs_rewinddir.c old mode 100755 new mode 100644 index 4fad333..e2c5f3b --- a/fs/dirent/fs_rewinddir.c +++ b/fs/dirent/fs_rewinddir.c @@ -38,49 +38,11 @@ ****************************************************************************/ #include "vfs_config.h" - #include "dirent.h" #include "errno.h" - #include "fs/fs.h" #include "fs/dirent_fs.h" - -#include "inode/inode.h" - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: rewindpseudodir - ****************************************************************************/ - -static inline void rewindpseudodir(struct fs_dirent_s *idir) -{ - struct inode *prev; - - inode_semtake(); - - /* Reset the position to the beginning */ - - prev = idir->u.pseudo.fd_next; /* (Save to delete later) */ - idir->u.pseudo.fd_next = idir->fd_root->i_child; /* The next node to visit */ - idir->fd_position = 0; /* Reset position */ - - /* Increment the reference count on the root=next node. We - * should now have two references on the inode. - */ - - idir->fd_root->i_child->i_crefs++; - inode_semgive(); - - /* Then release the reference to the old next inode */ - - if (prev != NULL) - { - inode_release(prev); - } -} +#include "fs/vnode.h" /**************************************************************************** * Public Functions @@ -102,19 +64,10 @@ static inline void rewindpseudodir(struct fs_dirent_s *idir) * ****************************************************************************/ -void rewinddir(FAR DIR *dirp) +void rewinddir(DIR *dirp) { struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp; -#ifndef CONFIG_DISABLE_MOUNTPOINT - struct inode *inode_ptr; -#endif - - /* Verify that we were provided with a valid directory structure, - * A special case is when we enumerate an "empty", unused inode (fd_root - * == 0). That is an inode in the pseudo-filesystem that has no - * operations and no children. This is a "dangling" directory entry that - * has lost its children. - */ + struct Vnode *vnode_ptr = NULL; if (!idir || !idir->fd_root || idir->fd_status != DIRENT_MAGIC) { @@ -122,34 +75,23 @@ void rewinddir(FAR DIR *dirp) return; } - /* The way we handle the readdir depends on the type of inode + /* The way we handle the readdir depends on the type of vnode * that we are dealing with. */ -#ifndef CONFIG_DISABLE_MOUNTPOINT - inode_ptr = idir->fd_root; - if (INODE_IS_MOUNTPT(inode_ptr)) + vnode_ptr = idir->fd_root; + if (vnode_ptr->vop != NULL && vnode_ptr->vop->Rewinddir != NULL) { - /* The node is a file system mointpoint. Verify that the mountpoint - * supports the rewinddir() method - */ - - if (inode_ptr->u.i_mops && inode_ptr->u.i_mops->rewinddir) - { - /* Perform the rewinddir() operation */ - - (void)inode_ptr->u.i_mops->rewinddir(inode_ptr, idir); - } - - /* Reset position for telldir() */ + /* Perform the rewinddir() operation */ - idir->fd_position = 0; + vnode_ptr->vop->Rewinddir(vnode_ptr, idir); } else -#endif { - /* The node is part of the root pseudo file system */ - - rewindpseudodir(idir); + set_errno(ENOSYS); } + + /* Reset position for telldir() */ + + idir->fd_position = 0; } diff --git a/fs/dirent/fs_seekdir.c b/fs/dirent/fs_seekdir.c old mode 100755 new mode 100644 index f9621d7..4154aa6 --- a/fs/dirent/fs_seekdir.c +++ b/fs/dirent/fs_seekdir.c @@ -38,85 +38,23 @@ ****************************************************************************/ #include "vfs_config.h" - #include "sys/types.h" #include "dirent.h" #include "errno.h" - #include "fs/fs.h" #include "fs/dirent_fs.h" - -#include "inode/inode.h" +#include "fs/vnode.h" /**************************************************************************** * Private Functions ****************************************************************************/ - -/**************************************************************************** - * Name: seekpseudodir - ****************************************************************************/ - -static inline void seekpseudodir(struct fs_dirent_s *idir, off_t offset) -{ - struct inode *curr; - struct inode *prev; - off_t pos; - - /* Determine a starting point for the seek. If the seek - * is "forward" from the current position, then we will - * start at the current poisition. Otherwise, we will - * "rewind" to the root dir. - */ - - if (offset < idir->fd_position) - { - pos = 0; - curr = idir->fd_root->i_child; - } - else - { - pos = idir->fd_position; - curr = idir->u.pseudo.fd_next; - } - - /* Traverse the peer list starting at the 'root' of the - * the list until we find the node at 'offset". If devices - * are being registered and unregistered, then this can - * be a very unpredictable operation. - */ - - inode_semtake(); - for (; curr && pos != offset; pos++, curr = curr->i_peer); - - /* Now get the inode to vist next time that readdir() is called */ - - prev = idir->u.pseudo.fd_next; - idir->u.pseudo.fd_next = curr; /* The next node to visit (might be null) */ - idir->fd_position = pos; /* Might be beyond the last dirent */ - - if (curr) - { - /* Increment the reference count on this next node */ - - curr->i_crefs++; - } - - inode_semgive(); - - if (prev) - { - inode_release(prev); - } -} - /**************************************************************************** * Name: seekmountptdir ****************************************************************************/ -#ifndef CONFIG_DISABLE_MOUNTPOINT static inline void seekmountptdir(struct fs_dirent_s *idir, off_t offset) { - struct inode *inode; + struct Vnode *vnode; off_t pos; /* Determine a starting point for the seek. If the seek @@ -125,14 +63,14 @@ static inline void seekmountptdir(struct fs_dirent_s *idir, off_t offset) * "rewind" to the root dir. */ - inode = idir->fd_root; + vnode = idir->fd_root; if (offset < idir->fd_position) { - if (inode->u.i_mops && inode->u.i_mops->rewinddir) + if (vnode->vop != NULL && vnode->vop->Rewinddir != NULL) { /* Perform the rewinddir() operation */ - inode->u.i_mops->rewinddir(inode, idir); + vnode->vop->Rewinddir(vnode, idir); pos = 0; } else @@ -157,8 +95,8 @@ static inline void seekmountptdir(struct fs_dirent_s *idir, off_t offset) while (pos < offset) { - if (!inode->u.i_mops || !inode->u.i_mops->readdir || - inode->u.i_mops->readdir(inode, idir) <= 0) + if (!vnode->vop || !vnode->vop->Readdir || + vnode->vop->Readdir(vnode, idir) <= 0) { /* We can't read the next entry and there is no way to return * an error indication. @@ -175,7 +113,6 @@ static inline void seekmountptdir(struct fs_dirent_s *idir, off_t offset) /* If we get here the directory position has been successfully set */ idir->fd_position = pos; } -#endif /**************************************************************************** * Public Functions @@ -203,13 +140,6 @@ void seekdir(DIR *dirp, long offset) { struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp; - /* Verify that we were provided with a valid directory structure, - * A special case is when we enumerate an "empty", unused inode (fd_root - * == 0). That is an inode in the pseudo-filesystem that has no - * operations and no children. This is a "dangling" directory entry that - * has lost its children. - */ - if (!idir || !idir->fd_root || idir->fd_status != DIRENT_MAGIC) { set_errno(EBADF); @@ -222,22 +152,5 @@ void seekdir(DIR *dirp, long offset) return; } - /* The way we handle the readdir depends on the type of inode - * that we are dealing with. - */ - -#ifndef CONFIG_DISABLE_MOUNTPOINT - if (INODE_IS_MOUNTPT(idir->fd_root)) - { - /* The node is a file system mointpoint */ - - seekmountptdir(idir, offset); - } - else -#endif - { - /* The node is part of the root pseudo file system */ - - seekpseudodir(idir, offset); - } + seekmountptdir(idir, offset); } diff --git a/fs/dirent/fs_telldir.c b/fs/dirent/fs_telldir.c old mode 100755 new mode 100644 index 4ed2419..f82bd01 --- a/fs/dirent/fs_telldir.c +++ b/fs/dirent/fs_telldir.c @@ -45,7 +45,6 @@ #include "fs/fs.h" #include "fs/dirent_fs.h" -#include "inode/inode.h" /**************************************************************************** * Public Functions diff --git a/fs/driver/fs_blockproxy.c b/fs/driver/fs_blockproxy.c index f95431a..2950a5f 100755 --- a/fs/driver/fs_blockproxy.c +++ b/fs/driver/fs_blockproxy.c @@ -169,7 +169,9 @@ static char *unique_chardev(void) int block_proxy(FAR const char *blkdev, int oflags) { - FAR char *chardev; + struct file *filep = NULL; + struct Vnode *vnode = NULL; + char *chardev; bool readonly; int ret; int fd; @@ -211,23 +213,21 @@ int block_proxy(FAR const char *blkdev, int oflags) goto errout_with_bchdev; } - /* Unlink the character device name. The driver instance will persist, - * provided that CONFIG_DISABLE_PSEUDOFS_OPERATIONS=y (otherwise, we have - * a problem here!) - */ - - ret = unlink(chardev); + ret = fs_getfilep(fd, &filep); if (ret < 0) { - ret = -errno; - PRINTK("ERROR: Failed to unlink %s: %d\n", chardev, ret); + files_release(fd); + ret = -get_errno(); + goto errout_with_bchdev; } - ret = unregister_driver(chardev); - if (ret < 0 && ret != -EBUSY) - { - PRINTK("ERROR: Failed to unregister %s: %d\n", chardev, ret); - } + vnode = filep->f_vnode; + VnodeHold(); + vnode->type = VNODE_TYPE_BCHR; + VnodeDrop(); + + /* Block char device is no need for file mapping */ + (void)remove_mapping(chardev); /* Free the allocate character driver name and return the open file * descriptor. @@ -238,10 +238,7 @@ int block_proxy(FAR const char *blkdev, int oflags) return fd; errout_with_bchdev: - (void)bchdev_unregister(chardev); - (void)unlink(chardev); (void)unregister_driver(chardev); - errout_with_chardev: (void)free(chardev); (void)sem_destroy(&g_devno_sem); diff --git a/fs/driver/fs_closeblockdriver.c b/fs/driver/fs_closeblockdriver.c old mode 100755 new mode 100644 index 768fffc..f159a73 --- a/fs/driver/fs_closeblockdriver.c +++ b/fs/driver/fs_closeblockdriver.c @@ -39,11 +39,9 @@ #include "fs/fs.h" #include "vfs_config.h" - #include "debug.h" #include "errno.h" - -#include "inode/inode.h" +#include "fs/vnode.h" #include "disk.h" /**************************************************************************** @@ -54,56 +52,57 @@ * Name: close_blockdriver * * Description: - * Call the close method and release the inode + * Call the close method and release the vnode * * Input Parameters: - * inode - reference to the inode of a block driver opened by open_blockdriver + * vnode - reference to the vnode of a block driver opened by open_blockdriver * * Returned Value: * Returns zero on success or a negated errno on failure: * - * EINVAL - inode is NULL - * ENOTBLK - The inode is not a block driver + * EINVAL - vnode is NULL + * ENOTBLK - The vnode is not a block driver * ****************************************************************************/ -int close_blockdriver(FAR struct inode *inode_ptr) +int close_blockdriver(struct Vnode *vnode_ptr) { +#ifdef VFS_IMPL_LATER int ret = 0; /* Assume success */ los_part *part = NULL; los_disk *disk = NULL; /* Sanity checks */ - if (!inode_ptr || !inode_ptr->u.i_bops) + if (!vnode_ptr || !vnode_ptr->u.i_bops) { ret = -EINVAL; goto errout; } - /* Verify that the inode is a block driver. */ + /* Verify that the vnode is a block driver. */ - if (!INODE_IS_BLOCK(inode_ptr)) + if (!INODE_IS_BLOCK(vnode_ptr)) { - fdbg("inode is not a block driver\n"); + fdbg("vnode is not a block driver\n"); ret = -ENOTBLK; goto errout; } - part = los_part_find(inode_ptr); + part = los_part_find(vnode_ptr); if (part != NULL) { disk = get_disk(part->disk_id); if (disk == NULL) { ret = -EINVAL; - goto errout_with_inode; + goto errout_with_vnode; } if (pthread_mutex_lock(&disk->disk_mutex) != ENOERR) { PRINT_ERR("%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__); - inode_release(inode_ptr); + vnode_release(vnode_ptr); return -1; } if (disk->disk_status == STAT_INUSED) @@ -113,34 +112,36 @@ int close_blockdriver(FAR struct inode *inode_ptr) * if needed. */ - if (inode_ptr->u.i_bops->close != NULL) + if (vnode_ptr->u.i_bops->close != NULL) { - ret = inode_ptr->u.i_bops->close(inode_ptr); + ret = vnode_ptr->u.i_bops->close(vnode_ptr); } } if (pthread_mutex_unlock(&disk->disk_mutex) != ENOERR) { PRINT_ERR("%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__); - inode_release(inode_ptr); + vnode_release(vnode_ptr); return -1; } } else { - if ((inode_ptr->i_flags & FSNODEFLAG_DELETED) == 0 && inode_ptr->u.i_bops->close != NULL) + if ((vnode_ptr->i_flags & FSNODEFLAG_DELETED) == 0 && vnode_ptr->u.i_bops->close != NULL) { - ret = inode_ptr->u.i_bops->close(inode_ptr); + ret = vnode_ptr->u.i_bops->close(vnode_ptr); } } -errout_with_inode: +errout_with_vnode: - /* Then release the reference on the inode */ + /* Then release the reference on the vnode */ - inode_release(inode_ptr); + vnode_release(vnode_ptr); errout: return ret; +#endif + return 0; } diff --git a/fs/driver/fs_devsyslog.c b/fs/driver/fs_devsyslog.c old mode 100755 new mode 100644 diff --git a/fs/driver/fs_findblockdriver.c b/fs/driver/fs_findblockdriver.c old mode 100755 new mode 100644 index 166c991..9e92e45 --- a/fs/driver/fs_findblockdriver.c +++ b/fs/driver/fs_findblockdriver.c @@ -39,15 +39,12 @@ #include "vfs_config.h" +#include "driver/driver.h" #include "sys/types.h" #include "sys/mount.h" #include "debug.h" #include "errno.h" - #include "fs/fs.h" - -#include "inode/inode.h" -#include "driver/driver.h" #include "string.h" /**************************************************************************** @@ -75,7 +72,51 @@ * support write access * ****************************************************************************/ +int find_blockdriver(const char *pathname, int mountflags, struct Vnode **vpp) +{ + int ret; + struct Vnode *vp = NULL; + + /* Sanity checks */ + + /* Find the vnode registered with this pathname */ + VnodeHold(); + ret = VnodeLookup(pathname, &vp, V_DUMMY); + if (ret < 0) + { + ret = -EACCES; + goto errout; + } + + /* Verify that the vnode is a block driver. */ + if (vp->type != VNODE_TYPE_BLK) + { + fdbg("%s is not a block driver\n", pathname); + ret = -ENOTBLK; + goto errout; + } + + /* Make sure that the vnode supports the requested access */ + struct block_operations *i_bops = (struct block_operations *)((struct drv_data *)vp->data)->ops; + + if (i_bops == NULL || i_bops->read == NULL || (i_bops->write == NULL && (mountflags & MS_RDONLY) == 0)) + { + fdbg("%s does not support requested access\n", pathname); + ret = -EACCES; + goto errout; + } + + *vpp = vp; + VnodeDrop(); + return OK; + +errout: + VnodeDrop(); + return ret; +} + +#ifdef VFS_IMPL_LATER int find_blockdriver(FAR const char *pathname, int mountflags, FAR struct inode **ppinode) { @@ -132,3 +173,4 @@ errout_with_inode: errout: return ret; } +#endif diff --git a/fs/driver/fs_openblockdriver.c b/fs/driver/fs_openblockdriver.c old mode 100755 new mode 100644 index d263f04..b363ae3 --- a/fs/driver/fs_openblockdriver.c +++ b/fs/driver/fs_openblockdriver.c @@ -38,14 +38,13 @@ ****************************************************************************/ #include "vfs_config.h" - #include "debug.h" #include "errno.h" #include "fs/fs.h" - -#include "inode/inode.h" +#include "fs/vnode.h" #include "driver/driver.h" #include "disk.h" +#include /**************************************************************************** * Public Functions @@ -55,29 +54,32 @@ * Name: open_blockdriver * * Description: - * Return the inode of the block driver specified by 'pathname' + * Return the vnode of the block driver specified by 'pathname' * * Input Parameters: * pathname - the full path to the block driver to be opened * mountflags - if MS_RDONLY is not set, then driver must support write * operations (see include/sys/mount.h) - * ppinode - address of the location to return the inode reference + * ppvnode - address of the location to return the vnode reference * * Returned Value: * Returns zero on success or a negated errno on failure: * - * EINVAL - pathname or pinode is NULL + * EINVAL - pathname or pvnode is NULL * ENOENT - No block driver of this name is registered - * ENOTBLK - The inode associated with the pathname is not a block driver + * ENOTBLK - The vnode associated with the pathname is not a block driver * EACCESS - The MS_RDONLY option was not set but this driver does not * support write access * ****************************************************************************/ -int open_blockdriver(FAR const char *pathname, int mountflags, - FAR struct inode **ppinode) + +extern int find_blockdriver(const char *pathname, int mountflags, struct Vnode **vpp); + +int open_blockdriver(const char *pathname, int mountflags, + struct Vnode **ppvnode) { - FAR struct inode *inode_ptr = NULL; + struct Vnode *vnode_ptr = NULL; los_part *part = NULL; los_disk *disk = NULL; int ret; @@ -85,18 +87,18 @@ int open_blockdriver(FAR const char *pathname, int mountflags, /* Minimal sanity checks */ #ifdef CONFIG_DEBUG - if (ppinode == NULL) + if (ppvnode == NULL) { ret = -EINVAL; goto errout; } #endif - /* Find the inode associated with this block driver name. find_blockdriver + /* Find the vnode associated with this block driver name. find_blockdriver * will perform all additional error checking. */ - ret = find_blockdriver(pathname, mountflags, &inode_ptr); + ret = find_blockdriver(pathname, mountflags, &vnode_ptr); if (ret < 0) { fdbg("Failed to file %s block driver\n", pathname); @@ -108,33 +110,35 @@ int open_blockdriver(FAR const char *pathname, int mountflags, * if needed. */ - part = los_part_find(inode_ptr); + struct drv_data* drv = (struct drv_data*)vnode_ptr->data; + struct block_operations *ops = (struct block_operations *)drv->ops; + + part = los_part_find(vnode_ptr); if (part != NULL) { disk = get_disk(part->disk_id); if (disk == NULL) { ret = -EINVAL; - goto errout_with_inode; + goto errout_with_vnode; } if (pthread_mutex_lock(&disk->disk_mutex) != ENOERR) { PRINT_ERR("%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__); - inode_release(inode_ptr); return -1; } if (disk->disk_status == STAT_INUSED) { - if (inode_ptr->u.i_bops->open != NULL) + if (ops->open != NULL) { - ret = inode_ptr->u.i_bops->open(inode_ptr); + ret = ops->open(vnode_ptr); if (ret < 0) { fdbg("%s driver open failed\n", pathname); (void)pthread_mutex_unlock(&disk->disk_mutex); - goto errout_with_inode; + goto errout_with_vnode; } } } @@ -142,29 +146,27 @@ int open_blockdriver(FAR const char *pathname, int mountflags, if (pthread_mutex_unlock(&disk->disk_mutex) != ENOERR) { PRINT_ERR("%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__); - inode_release(inode_ptr); return -1; } } else { - if ((inode_ptr->i_flags & FSNODEFLAG_DELETED) == 0 && inode_ptr->u.i_bops->open != NULL) + if (ops->open != NULL) { - ret = inode_ptr->u.i_bops->open(inode_ptr); + ret = ops->open(vnode_ptr); if (ret < 0) { fdbg("%s driver open failed\n", pathname); - goto errout_with_inode; + goto errout_with_vnode; } } } - *ppinode = inode_ptr; + *ppvnode = vnode_ptr; return OK; -errout_with_inode: - inode_release(inode_ptr); +errout_with_vnode: errout: return ret; } diff --git a/fs/driver/fs_registerblockdriver.c b/fs/driver/fs_registerblockdriver.c old mode 100755 new mode 100644 index 864d9d1..47bbe31 --- a/fs/driver/fs_registerblockdriver.c +++ b/fs/driver/fs_registerblockdriver.c @@ -38,14 +38,16 @@ ****************************************************************************/ #include "vfs_config.h" - #include "sys/types.h" #include "errno.h" - #include "fs/fs.h" - -#include "inode/inode.h" +#include "fs/vnode.h" #include "string.h" +#include "fs/vfs_util.h" +#include "fs/path_cache.h" +#include "fs/vnode.h" +#include "limits.h" + #ifndef CONFIG_DISABLE_MOUNTPOINT @@ -57,62 +59,63 @@ * Name: register_blockdriver * * Description: - * Register a block driver inode the pseudo file system. + * Register a block driver vnode the pseudo file system. * * Input parameters: - * path - The path to the inode to create + * path - The path to the vnode to create * bops - The block driver operations structure * mode - inmode priviledges (not used) - * priv - Private, user data that will be associated with the inode. + * priv - Private, user data that will be associated with the vnode. * * Returned Value: - * Zero on success (with the inode point in 'inode'); A negated errno + * Zero on success (with the vnode point in 'vnode'); A negated errno * value is returned on a failure (all error values returned by - * inode_reserve): + * vnode_reserve): * * EINVAL - 'path' is invalid for this operation - * EEXIST - An inode already exists at 'path' + * EEXIST - An vnode already exists at 'path' * ENOMEM - Failed to allocate in-memory resources for the operation * ****************************************************************************/ -int register_blockdriver(FAR const char *path, - FAR const struct block_operations *bops, - mode_t mode, FAR void *priv) +int register_blockdriver(const char *path, + const struct block_operations *bops, + mode_t mode, void *priv) { - FAR struct inode *node; + struct Vnode *vp = NULL; int ret; if (path == NULL || strlen(path) >= PATH_MAX || strncmp("/dev/", path, DEV_PATH_LEN) != 0) { - return EINVAL; + return -EINVAL; } - /* Insert an inode for the device driver -- we need to hold the inode + /* Insert an vnode for the device driver -- we need to hold the vnode * semaphore to prevent access to the tree while we this. This is because - * we will have a momentarily bad true until we populate the inode with + * we will have a momentarily bad true until we populate the vnode with * valid data. */ - inode_semtake(); - ret = inode_reserve(path, &node); + struct drv_data *data = (struct drv_data *)zalloc(sizeof(struct drv_data)); + + data->ops = (void *)bops; + data->mode = mode; + data->priv = priv; + + VnodeHold(); + ret = VnodeLookup(path, &vp, V_CREATE | V_CACHE | V_DUMMY); if (ret >= 0) { /* We have it, now populate it with block driver specific information. */ - INODE_SET_BLOCK(node); - - node->u.i_bops = bops; -#ifdef LOSCFG_FILE_MODE - node->i_mode = mode; -#endif - node->i_private = priv; - ret = OK; + vp->type = VNODE_TYPE_BLK; + vp->data = data; + vp->mode = mode; + ret = OK; } - inode_semgive(); + VnodeDrop(); return ret; } #endif /* !CONFIG_DISABLE_MOUNTPOINT */ - diff --git a/fs/driver/fs_registerdriver.c b/fs/driver/fs_registerdriver.c old mode 100755 new mode 100644 index f2f907d..cc78959 --- a/fs/driver/fs_registerdriver.c +++ b/fs/driver/fs_registerdriver.c @@ -38,14 +38,14 @@ ****************************************************************************/ #include "vfs_config.h" - #include "sys/types.h" #include "errno.h" - #include "fs/fs.h" - -#include "inode/inode.h" +#include "fs/vnode.h" #include "string.h" +#include "fs/vfs_util.h" +#include "fs/path_cache.h" +#include "limits.h" /**************************************************************************** * Public Functions @@ -55,29 +55,29 @@ * Name: register_driver * * Description: - * Register a character driver inode the pseudo file system. + * Register a character driver vnode the pseudo file system. * * Input Parameters: - * path - The path to the inode to create + * path - The path to the vnode to create * fops - The file operations structure * mode - inmode priviledges (not used) - * priv - Private, user data that will be associated with the inode. + * priv - Private, user data that will be associated with the vnode. * * Returned Value: - * Zero on success (with the inode point in 'inode'); A negated errno + * Zero on success (with the vnode point in 'vnode'); A negated errno * value is returned on a failure (all error values returned by - * inode_reserve): + * vnode_reserve): * * EINVAL - 'path' is invalid for this operation - * EEXIST - An inode already exists at 'path' + * EEXIST - An vnode already exists at 'path' * ENOMEM - Failed to allocate in-memory resources for the operation * ****************************************************************************/ -int register_driver(FAR const char *path, FAR const struct file_operations_vfs *fops, - mode_t mode, FAR void *priv) +int register_driver(const char *path, const struct file_operations_vfs *fops, + mode_t mode, void *priv) { - FAR struct inode *node; + struct Vnode *vnode = NULL; int ret; if (path == NULL || strlen(path) >= PATH_MAX || strncmp("/dev/", path, DEV_PATH_LEN) != 0) @@ -85,28 +85,38 @@ int register_driver(FAR const char *path, FAR const struct file_operations_vfs * return -EINVAL; } - /* Insert a dummy node -- we need to hold the inode semaphore because we + VnodeHold(); + ret = VnodeLookup(path, &vnode, 0); + if (ret == 0) + { + VnodeDrop(); + return -EEXIST; + } + + /* Insert a dummy node -- we need to hold the vnode semaphore because we * will have a momentarily bad structure. */ - inode_semtake(); - ret = inode_reserve(path, &node); - if (ret >= 0) + struct drv_data *data = (struct drv_data *)zalloc(sizeof(struct drv_data)); + + data->ops = (void *)fops; + data->mode = mode; + data->priv = priv; + + ret = VnodeLookup(path, &vnode, V_CREATE | V_CACHE | V_DUMMY); + if (ret == OK) { /* We have it, now populate it with driver specific information. - * NOTE that the initial reference count on the new inode is zero. + * NOTE that the initial reference count on the new vnode is zero. */ - - INODE_SET_DRIVER(node); - - node->u.i_ops = fops; -#ifdef LOSCFG_FILE_MODE - node->i_mode = mode & (S_IRWXU|S_IRWXG|S_IRWXO); -#endif - node->i_private = priv; - ret = OK; + vnode->type = VNODE_TYPE_CHR; + vnode->data = data; + vnode->mode = mode; + vnode->fop = (struct file_operations_vfs *)fops; + ret = OK; } - inode_semgive(); + VnodeDrop(); + return ret; } diff --git a/fs/driver/fs_unregisterblockdriver.c b/fs/driver/fs_unregisterblockdriver.c old mode 100755 new mode 100644 index 27a9110..cb1d456 --- a/fs/driver/fs_unregisterblockdriver.c +++ b/fs/driver/fs_unregisterblockdriver.c @@ -59,15 +59,10 @@ int unregister_blockdriver(const char *path) { - int ret; - if (path == NULL || strlen(path) >= PATH_MAX || strncmp("/dev/", path, DEV_PATH_LEN) != 0) { return EINVAL; } - inode_semtake(); - ret = inode_remove(path); - inode_semgive(); - return ret; + return -ENOSYS; } diff --git a/fs/driver/fs_unregisterdriver.c b/fs/driver/fs_unregisterdriver.c old mode 100755 new mode 100644 index 2870efa..ef2df33 --- a/fs/driver/fs_unregisterdriver.c +++ b/fs/driver/fs_unregisterdriver.c @@ -41,7 +41,7 @@ #include "fs/fs.h" -#include "inode/inode.h" +#include "fs/vnode.h" #include "string.h" #include "errno.h" @@ -53,21 +53,12 @@ * Name: unregister_driver * * Description: - * Remove the character driver inode at 'path' from the pseudo-file system + * Remove the character driver vnode at 'path' from the pseudo-file system * ****************************************************************************/ -int unregister_driver(FAR const char *path) +int unregister_driver(const char *path) { - int ret; - - if (path == NULL || strlen(path) >= PATH_MAX || strncmp("/dev/", path, DEV_PATH_LEN) != 0) - { - return -EINVAL; - } - - inode_semtake(); - ret = inode_remove(path); - inode_semgive(); - return ret; + (void)path; + return 0; } diff --git a/fs/inode/fs_files.c b/fs/inode/fs_files.c old mode 100755 new mode 100644 index 7c2e34e..35164a4 --- a/fs/inode/fs_files.c +++ b/fs/inode/fs_files.c @@ -39,18 +39,17 @@ ****************************************************************************/ #include "unistd.h" #include "vfs_config.h" - #include "sys/types.h" #include "string.h" +#include "dirent.h" #include "semaphore.h" #include "assert.h" #include "errno.h" - #include "fs/fs.h" #include "fs/file.h" #include "stdio.h" #include "stdlib.h" -#include "inode/inode.h" +#include "fs/vnode.h" #include "los_mux.h" #include "fs/fd_table.h" #ifdef LOSCFG_NET_LWIP_SACK @@ -105,6 +104,20 @@ static void clear_bit(int i, void *addr) *addri = old; } +bool get_bit(int i) +{ + unsigned int *p = NULL; + unsigned int mask; + + p = ((unsigned int *)bitmap) + (i >> 5); /* Gets the location in the bitmap */ + mask = 1 << (i & 0x1f); /* Gets the mask for the current bit int bitmap */ + if (!(~(*p) & mask)){ + return true; + } + return false; +} + + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -113,7 +126,7 @@ static void clear_bit(int i, void *addr) * Name: _files_semtake ****************************************************************************/ -static void _files_semtake(FAR struct filelist *list) +static void _files_semtake(struct filelist *list) { /* Take the semaphore (perhaps waiting) */ @@ -137,70 +150,71 @@ static void _files_semtake(FAR struct filelist *list) * Name: _files_close * * Description: - * Close an inode (if open) + * Close an vnode (if open) * * Assumuptions: * Caller holds the list semaphore because the file descriptor will be freed. * ****************************************************************************/ -static int _files_close(FAR struct file *filep) +static int _files_close(struct file *filep) { - struct inode *inode = filep->f_inode; + struct Vnode *vnode = filep->f_vnode; int ret = OK; - /* Check if the struct file is open (i.e., assigned an inode) */ - - if (inode) + /* Check if the struct file is open (i.e., assigned an vnode) */ + if (filep->f_oflags & O_DIRECTORY) { - if (filep->f_oflags & O_DIRECTORY) + ret = closedir(filep->f_dir); + if (ret != OK) { - ret = closedir(filep->f_dir); - if (ret != OK) - { - return ret; - } + return ret; } - else + } + else + { + /* Close the file, driver, or mountpoint. */ + if (filep->ops && filep->ops->close) { - /* Close the file, driver, or mountpoint. */ + /* Perform the close operation */ - if (inode->u.i_ops && inode->u.i_ops->close) + ret = filep->ops->close(filep); + if (ret != OK) { - /* Perform the close operation */ - - ret = inode->u.i_ops->close(filep); - if (ret != OK) - { - return ret; - } + return ret; } } + VnodeHold(); + vnode->useCount--; + VnodeDrop(); + } - /* Drop file caches */ - - (void)remove_mapping_nolock(filep->f_path, filep); - - /* And release the inode */ - - inode_release(inode); - - /* Release the path of file */ + /* Block char device is removed when close */ + if (vnode->type == VNODE_TYPE_BCHR) + { + VnodeHold(); + ret = VnodeFree(vnode); + if (ret < 0) + { + PRINTK("Removing bchar device %s failed\n", filep->f_path); + } + VnodeDrop(); + } + /* Release the path of file */ - free(filep->f_path); + free(filep->f_path); - /* Release the file descriptor */ + /* 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_inode = NULL; - filep->f_refcount = 0; - filep->f_mapping = NULL; - filep->f_dir = NULL; - } + 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; return ret; } @@ -228,7 +242,7 @@ void files_initialize(void) * ****************************************************************************/ -void files_initlist(FAR struct filelist *list) +void files_initlist(struct filelist *list) { DEBUGASSERT(list); @@ -245,7 +259,7 @@ void files_initlist(FAR struct filelist *list) * ****************************************************************************/ -void files_releaselist(FAR struct filelist *list) +void files_releaselist(struct filelist *list) { int i; @@ -270,7 +284,7 @@ void files_releaselist(FAR struct filelist *list) * Name: file_dup2 * * Description: - * Assign an inode to a specific files structure. This is the heart of + * Assign an vnode to a specific files structure. This is the heart of * dup2. * * Equivalent to the non-standard fs_dupfd2() function except that it @@ -283,20 +297,19 @@ void files_releaselist(FAR struct filelist *list) * ****************************************************************************/ -int file_dup2(FAR struct file *filep1, FAR struct file *filep2) +int file_dup2(struct file *filep1, struct file *filep2) { - FAR struct filelist *list = NULL; - FAR struct inode *inode_ptr = NULL; + struct filelist *list = NULL; + struct Vnode *vnode_ptr = NULL; char *fullpath = NULL; const char *relpath = NULL; int err; int len; int ret; - struct inode_search_s desc; - if (!filep1 || !filep1->f_inode || !filep2) + if (!filep1 || !filep1->f_vnode || !filep2) { - err = EBADF; + err = -EBADF; goto errout; } @@ -314,8 +327,8 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2) _files_semtake(list); } - /* If there is already an inode contained in the new file structure, - * close the file and release the inode. + /* If there is already an vnode contained in the new file structure, + * close the file and release the vnode. */ ret = _files_close(filep2); @@ -340,26 +353,18 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2) goto errout_with_ret; } - /* Increment the reference count on the contained inode */ + /* Increment the reference count on the contained vnode */ - inode_ptr = filep1->f_inode; + vnode_ptr = filep1->f_vnode; /* Then clone the file structure */ filep2->f_oflags = filep1->f_oflags; filep2->f_pos = filep1->f_pos; - filep2->f_inode = inode_ptr; + filep2->f_vnode = vnode_ptr; filep2->f_priv = filep1->f_priv; (void)strncpy_s(fullpath, len + 1, filep1->f_path, len); - SETUP_SEARCH(&desc, fullpath, false); - if (inode_find(&desc) < 0) - { - ret = -EACCES; - free(fullpath); - goto errout_with_ret; - } - relpath = desc.relpath; filep2->f_path = fullpath; filep2->f_relpath = relpath; @@ -367,18 +372,14 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2) * can maintain the correct open counts. */ - if (inode_ptr->u.i_ops) + if (vnode_ptr->vop) { #ifndef CONFIG_DISABLE_MOUNTPOINT - if (INODE_IS_MOUNTPT(inode_ptr)) + if (vnode_ptr->originMount) { /* Dup the open file on the in the new file structure */ - if (inode_ptr->u.i_mops->dup) - { - ret = inode_ptr->u.i_mops->dup(filep1, filep2); - } - else + if (vnode_ptr == NULL) { ret = -ENOSYS; } @@ -388,9 +389,9 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2) { /* (Re-)open the pseudo file or device driver */ - if (inode_ptr->u.i_ops->open) + if (vnode_ptr->vop->Open) { - ret = inode_ptr->u.i_ops->open(filep2); + ret = vnode_ptr->vop->Open(vnode_ptr, 0, 0, 0); } else { @@ -402,7 +403,7 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2) if (ret < 0) { - goto errout_with_inode; + goto errout_with_vnode; } } @@ -414,13 +415,12 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2) /* Handle various error conditions */ -errout_with_inode: +errout_with_vnode: - inode_release(filep2->f_inode); free(filep2->f_path); filep2->f_oflags = 0; filep2->f_pos = 0; - filep2->f_inode = NULL; + filep2->f_vnode = NULL; filep2->f_priv = NULL; filep2->f_path = NULL; filep2->f_relpath = NULL; @@ -451,9 +451,9 @@ static inline unsigned int files_magic_generate(void) * ****************************************************************************/ -int files_allocate(FAR struct inode *inode_ptr, int oflags, off_t pos,void* priv, int minfd) +int files_allocate(struct Vnode *vnode_ptr, int oflags, off_t pos, void *priv, int minfd) { - FAR struct filelist *list = NULL; + struct filelist *list = NULL; unsigned int *p = NULL; unsigned int mask; unsigned int i; @@ -481,7 +481,7 @@ int files_allocate(FAR struct inode *inode_ptr, int oflags, off_t pos,void* priv set_bit(i, bitmap); list->fl_files[i].f_oflags = oflags; list->fl_files[i].f_pos = pos; - list->fl_files[i].f_inode = inode_ptr; + 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; @@ -500,19 +500,18 @@ int files_allocate(FAR struct inode *inode_ptr, int oflags, off_t pos,void* priv i++; } - _files_semgive(list); return VFS_ERROR; } static int files_close_internal(int fd, LosProcessCB *processCB) { - FAR struct filelist *list = NULL; - int ret = OK; + int ret = OK; + struct file *filep = NULL; + struct filelist *list = NULL; struct files_struct *process_files = NULL; /* 0,1,2 fd is not opened in system, no need to close them */ - if ((fd >= STDIN_FILENO) && (fd <= STDERR_FILENO)) { return OK; @@ -525,9 +524,9 @@ static int files_close_internal(int fd, LosProcessCB *processCB) list = sched_getfiles(); DEBUGASSERT(list != NULL); - /* If the file was properly opened, there should be an inode assigned */ + /* If the file was properly opened, there should be an vnode assigned */ - if (fd < 0 || fd >= CONFIG_NFILE_DESCRIPTORS || !list->fl_files[fd].f_inode) + if (fd < 0 || fd >= CONFIG_NFILE_DESCRIPTORS || !list->fl_files[fd].f_vnode) { return -EBADF; } @@ -542,20 +541,18 @@ static int files_close_internal(int fd, LosProcessCB *processCB) _files_semgive(list); return -EINVAL; } - if (list->fl_files[fd].f_mapping) - { - OsFileCacheFlush(list->fl_files[fd].f_mapping); - dec_mapping(list->fl_files[fd].f_mapping); - } - list->fl_files[fd].f_refcount--; /* 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 */ - OsVmmFileRegionFree(&list->fl_files[fd], processCB); + filep = &list->fl_files[fd]; + + OsVmmFileRegionFree(filep, processCB); + list->fl_files[fd].f_refcount--; if (list->fl_files[fd].f_refcount == 0) { + dec_mapping_nolock(filep->f_mapping); ret = _files_close(&list->fl_files[fd]); if (ret == OK) { @@ -594,7 +591,7 @@ int files_close(int fd) void files_release(int fd) { - FAR struct filelist *list = NULL; + struct filelist *list = NULL; list = sched_getfiles(); DEBUGASSERT(list); @@ -605,7 +602,7 @@ void files_release(int fd) list->fl_files[fd].f_magicnum = 0; list->fl_files[fd].f_oflags = 0; - list->fl_files[fd].f_inode = NULL; + 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; @@ -613,15 +610,14 @@ void files_release(int fd) list->fl_files[fd].f_priv = NULL; list->fl_files[fd].f_mapping = NULL; list->fl_files[fd].f_dir = NULL; - clear_bit(fd, bitmap); _files_semgive(list); } } -struct inode * files_get_openfile(int fd) +struct Vnode *files_get_openfile(int fd) { - FAR struct filelist *list = NULL; + struct filelist *list = NULL; unsigned int *p = NULL; unsigned int mask; @@ -635,12 +631,12 @@ struct inode * files_get_openfile(int fd) return NULL; } - return list->fl_files[fd].f_inode; + return list->fl_files[fd].f_vnode; } int alloc_fd(int minfd) { - FAR struct filelist *list = NULL; + struct filelist *list = NULL; unsigned int *p = NULL; unsigned int mask; unsigned int i; @@ -679,16 +675,16 @@ void clear_fd(int fd) clear_bit(fd, bitmap); } -int close_files(struct inode *inode) +int close_files(struct Vnode *vnode) { int fd = 0; int ret = 0; - FAR struct inode *open_file_inode = NULL; + struct Vnode *open_file_vnode = NULL; for (fd = FILE_START_FD; fd < CONFIG_NFILE_DESCRIPTORS; fd++) { - open_file_inode = files_get_openfile(fd); - if (open_file_inode && (open_file_inode == inode)) + open_file_vnode = files_get_openfile(fd); + if (open_file_vnode && (open_file_vnode == vnode)) { ret = files_close(fd); if (ret < 0) diff --git a/fs/inode/inode.h b/fs/inode/inode.h old mode 100755 new mode 100644 index 72c82e5..10ac0ab --- a/fs/inode/inode.h +++ b/fs/inode/inode.h @@ -429,54 +429,6 @@ void inode_release(FAR struct inode *inode); int foreach_inode(foreach_inode_t handler, FAR void *arg); -/**************************************************************************** - * Name: files_initialize - * - * Description: - * This is called from the FS initialization logic to configure the files. - * - ****************************************************************************/ - -void weak_function files_initialize(void); - -/**************************************************************************** - * 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(FAR struct inode *inode, int oflags, off_t pos,void *priv, int minfd); - -/**************************************************************************** - * Name: files_close - * - * Description: - * Close an inode (if open) - * - * Assumuptions: - * Caller holds the list semaphore because the file descriptor will be freed. - * - ****************************************************************************/ - -int files_close(int fd); - -/**************************************************************************** - * Name: files_release - * - * Assumuptions: - * Similar to files_close(). Called only from open() logic on error - * conditions. - * - ****************************************************************************/ - -void files_release(int fd); - -int vfs_normalize_path(const char *directory, const char *filename, char **pathname); -int vfs_normalize_pathat(int fd, const char *filename, char **pathname); - #ifdef __cplusplus #if __cplusplus } diff --git a/fs/mount/fs_foreachmountpoint.c b/fs/mount/fs_foreachmountpoint.c old mode 100755 new mode 100644 index 156bfe0..51c8bdc --- a/fs/mount/fs_foreachmountpoint.c +++ b/fs/mount/fs_foreachmountpoint.c @@ -49,7 +49,8 @@ #include "fs/fs.h" -#include "inode/inode.h" +#include "fs/vnode.h" +#include "limits.h" #ifndef CONFIG_DISABLE_MOUNTPOINT @@ -68,17 +69,17 @@ struct enum_mountpoint_s { foreach_mountpoint_t handler; - FAR void *arg; + void *arg; }; /**************************************************************************** * Private Functions ****************************************************************************/ - -static int mountpoint_filter(FAR struct inode *node, - FAR char dirpath[PATH_MAX], FAR void *arg) +#ifdef VFS_IMPL_LATER +static int mountpoint_filter(struct Vnode *node, + char dirpath[PATH_MAX], void *arg) { - FAR struct enum_mountpoint_s *info = (FAR struct enum_mountpoint_s *)arg; + struct enum_mountpoint_s *info = (struct enum_mountpoint_s *)arg; struct statfs statbuf; int pathlen; int namlen; @@ -86,7 +87,7 @@ static int mountpoint_filter(FAR struct inode *node, DEBUGASSERT(node && info && info->handler); - /* Check if the inode is a mountpoint. Mountpoints must support statfs. + /* Check if the vnode is a mountpoint. Mountpoints must support statfs. * If this one does not for some reason, then it will be ignored. * * The root node is a special case: It has no operations (u.i_mops == NULL) @@ -94,8 +95,8 @@ static int mountpoint_filter(FAR struct inode *node, if (INODE_IS_MOUNTPT(node) && node->u.i_mops && node->u.i_mops->statfs) { - /* Yes... get the full path to the inode by concatenating the inode - * name and the path to the directory containing the inode. + /* Yes... get the full path to the vnode by concatenating the vnode + * name and the path to the directory containing the vnode. */ pathlen = strlen(dirpath); @@ -108,9 +109,9 @@ static int mountpoint_filter(FAR struct inode *node, return -ENAMETOOLONG; } - /* Append the inode name to the directory path */ + /* Append the vnode name to the directory path */ - ret = snprintf_s(&dirpath[pathlen], PATH_MAX - pathlen, PATH_MAX - pathlen - 1, "%s/", node->i_name); + ret = snprintf_s(&dirpath[pathlen], PATH_MAX - pathlen, PATH_MAX - pathlen - 1, "/%s", node->i_name); if (ret < 0) { return -ENAMETOOLONG; @@ -137,6 +138,7 @@ static int mountpoint_filter(FAR struct inode *node, return ret; } +#endif /**************************************************************************** * Public Functions @@ -150,8 +152,8 @@ static int mountpoint_filter(FAR struct inode *node, * terminated when the callback 'handler' returns a non-zero value, or when * all of the mountpoints have been visited. * - * This is just a front end "filter" to foreach_inode() that forwards only - * mountpoint inodes. It is intended to support the mount() command to + * This is just a front end "filter" to foreach_vnode() that forwards only + * mountpoint vnodes. It is intended to support the mount() command to * when the mount command is used to enumerate mounts. * * NOTE 1: Use with caution... The pseudo-file system is locked throughout @@ -162,16 +164,19 @@ static int mountpoint_filter(FAR struct inode *node, * ****************************************************************************/ -int foreach_mountpoint(foreach_mountpoint_t handler, FAR void *arg) +int foreach_mountpoint(foreach_mountpoint_t handler, void *arg) { +#ifdef VFS_IMPL_LATER struct enum_mountpoint_s info; - /* Let foreach_inode do the real work */ + /* Let foreach_vnode do the real work */ info.handler = handler; info.arg = arg; - return foreach_inode(mountpoint_filter, (FAR void *)&info); + return foreach_vnode(mountpoint_filter, (void *)&info); +#endif + return 0; } #endif diff --git a/fs/mount/fs_mount.c b/fs/mount/fs_mount.c index 63f0f23..a4fa796 100755 --- a/fs/mount/fs_mount.c +++ b/fs/mount/fs_mount.c @@ -40,15 +40,14 @@ #include "vfs_config.h" +#include "driver/driver.h" #include "sys/mount.h" #include "string.h" #include "errno.h" #include "assert.h" #include "debug.h" - #include "fs/fs.h" - -#include "inode/inode.h" +#include "fs/vnode.h" #include "stdlib.h" #include "driver/driver.h" #ifdef LOSCFG_DRIVERS_MTD @@ -58,10 +57,15 @@ #include "errcode_fat.h" #endif #include "los_tables.h" - -#ifdef LOSCFG_FS_ZPFS -#include "vfs_zpfs.h" +#ifdef LOSCFG_DRIVERS_RANDOM +#include "hisoc/random.h" +#else +#include "stdlib.h" #endif +#include "fs/vfs_util.h" +#include "fs/path_cache.h" +#include "fs/mount.h" + /* At least one filesystem must be defined, or this file will not compile. * It may be desire-able to make filesystems dynamically registered at @@ -122,6 +126,7 @@ static const struct fsmap_t *mount_findfs(const char *filesystemtype) return (const struct fsmap_t *)NULL; } + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -155,23 +160,20 @@ int mount(const char *source, const char *target, const void *data) { int ret; - void *fshandle = NULL; int errcode = 0; - char *fullpath = NULL; - char *fullpath_bak = NULL; - - struct inode *blkdrvr_inode = NULL; - struct inode *mountpt_inode = NULL; + struct Mount* mnt = NULL; + struct Vnode *device = NULL; + struct Vnode *mountpt_vnode = NULL; const struct fsmap_t *fsmap = NULL; - const struct mountpt_operations *mops = NULL; - + const struct MountOps *mops = NULL; + LIST_HEAD *mount_list = NULL; #ifdef LOSCFG_DRIVERS_MTD mtd_partition *partition = NULL; #endif if (filesystemtype == NULL) { - errcode = EINVAL; + errcode = -EINVAL; goto errout; } @@ -179,23 +181,12 @@ int mount(const char *source, const char *target, DEBUGASSERT(target && filesystemtype); - ret = vfs_normalize_path((const char *)NULL, target, &fullpath); - if (ret < 0) - { - PRINT_ERR("Failed to get fullpath,target: %s\n", target); - errcode = -ret; - goto errout; - } - fullpath_bak = fullpath; - /* Find the specified filesystem. Try the block driver file systems first */ - if ((fsmap = mount_findfs(filesystemtype)) == NULL || - (fsmap->is_bdfs && !source)) + if ((fsmap = mount_findfs(filesystemtype)) == NULL || (fsmap->is_bdfs && !source)) { PRINT_ERR("Failed to find file system %s\n", filesystemtype); - errcode = ENODEV; - free(fullpath_bak); + errcode = -ENODEV; goto errout; } @@ -209,135 +200,77 @@ int mount(const char *source, const char *target, /* Find the block driver */ - ret = find_blockdriver(source, mountflags, &blkdrvr_inode); + ret = find_blockdriver(source, mountflags, &device); if (ret < 0) { PRINT_ERR("Failed to find block driver %s\n", source); - errcode = -ret; - free(fullpath_bak); + errcode = ret; goto errout; } } - /* Insert a dummy node -- we need to hold the inode semaphore - * to do this because we will have a momentarily bad structure. - */ - - inode_semtake(); -#ifdef LOSCFG_FS_ZPFS - if (strcmp(filesystemtype, ZPFS_NAME) == 0) - { - ret = ZpfsPrepare(source, fullpath, &mountpt_inode, true); - if (ret < 0) - { - errcode = -ret; - goto errout_with_semaphore; - } - data = (const void *)mountpt_inode->i_private; - } - else - { -#endif - mountpt_inode = inode_search((const char **)&fullpath, (struct inode **)NULL, (struct inode **)NULL, \ - (const char **)NULL); + VnodeHold(); + ret = VnodeLookup(target, &mountpt_vnode, 0); - /* The mount point must be an existed inode. */ + /* The mount point must be an existed vnode. */ - if (mountpt_inode == NULL) + if (ret != OK) { PRINT_ERR("Failed to find valid mountpoint %s\n", target); - errcode = EINVAL; - goto errout_with_semaphore; + errcode = -EINVAL; + goto errout_with_lock; } - - /* The mount point must be a dangling node with no children and - * no operations. If this inode is mounted, or it has children - * (except "/"), or it has operations, it cannot be mounted. - */ - - if (INODE_IS_MOUNTPT(mountpt_inode) || (mountpt_inode->i_child && strcmp(target, "/")) || mountpt_inode->u.i_ops) + if (mountpt_vnode->flag & VNODE_FLAG_MOUNT_ORIGIN) { - PRINT_ERR("Can't to mount to this inode %s\n", target); - errcode = EINVAL; - goto errout_with_semaphore; + PRINT_ERR("can't mount to %s, already mounted.\n", target); + errcode = -EINVAL; + goto errout_with_lock; } -#ifdef LOSCFG_FS_ZPFS - } -#endif - - mountpt_inode ->mountflags = mountflags; /* Bind the block driver to an instance of the file system. The file * system returns a reference to some opaque, fs-dependent structure * that encapsulates this binding. */ - if (mops->bind == NULL) + if (mops->Mount == NULL) { /* The filesystem does not support the bind operation ??? */ - fdbg("ERROR: Filesystem does not support bind\n"); - errcode = EINVAL; + PRINTK("ERROR: Filesystem does not support bind\n"); + errcode = -ENOSYS; goto errout_with_mountpt; } /* Increment reference count for the reference we pass to the file system */ - - if (blkdrvr_inode != NULL) - { - blkdrvr_inode->i_crefs++; - - /* On failure, the bind method returns -errorcode */ - - if (blkdrvr_inode->e_status != STAT_UNMOUNTED) - { - fdbg("ERROR: The node is busy\n"); - errcode = EBUSY; - blkdrvr_inode->i_crefs--; - goto errout_with_mountpt; - } - } #ifdef LOSCFG_DRIVERS_MTD - if (fsmap->is_mtd_support && (blkdrvr_inode != NULL)) + if (fsmap->is_mtd_support && (device != NULL)) { - partition = (mtd_partition *)blkdrvr_inode->i_private; + partition = (mtd_partition *)((struct drv_data *)device->data)->priv; partition->mountpoint_name = (char *)zalloc(strlen(target) + 1); if (partition->mountpoint_name == NULL) { - errcode = ENOMEM; - blkdrvr_inode->i_crefs--; + errcode = -ENOMEM; goto errout_with_mountpt; } - (void)strncpy_s(partition->mountpoint_name, strlen(target) + 1, target, strlen(target)); partition->mountpoint_name[strlen(target)] = '\0'; } #endif - mountpt_inode ->mountflags = mountflags; - ret = mops->bind(blkdrvr_inode, data, &fshandle, fullpath_bak); -#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION - if (ret >= VIRERR_BASE) - { - errcode = ret; - } - else -#endif + + mnt = MountAlloc(mountpt_vnode, (struct MountOps*)mops); + + ret = mops->Mount(mnt, device, data); if (ret != 0) { - /* The inode is unhappy with the blkdrvr for some reason. Back out + /* The vnode is unhappy with the blkdrvr for some reason. Back out * the count for the reference we failed to pass and exit with an * error. */ fdbg("ERROR: Bind method failed: %d\n", ret); - if (blkdrvr_inode != NULL) - { - blkdrvr_inode->i_crefs--; - } - - errcode = -ret; + errcode = ret; #ifdef LOSCFG_DRIVERS_MTD - if (fsmap->is_mtd_support && (blkdrvr_inode != NULL) && (partition != NULL)) + if (fsmap->is_mtd_support && (device != NULL) && (partition != NULL)) { free(partition->mountpoint_name); partition->mountpoint_name = NULL; @@ -345,68 +278,42 @@ int mount(const char *source, const char *target, #endif goto errout_with_mountpt; } + mnt->vnodeBeCovered->flag |= VNODE_FLAG_MOUNT_NEW; + mnt->vnodeCovered->flag |= VNODE_FLAG_MOUNT_ORIGIN; + mnt->ops = mops; + mnt->mountFlags = mountflags; - /* We have it, now populate it with driver specific information. */ + //* We have it, now populate it with driver specific information. */ - INODE_SET_MOUNTPT(mountpt_inode); + mount_list = GetMountList(); + LOS_ListAdd(mount_list, &mnt->mountList); - mountpt_inode->u.i_mops = mops; - mountpt_inode->i_private = fshandle; -#ifdef LOSCFG_FILE_MODE - struct stat statinfo = {0}; - if ((g_root_inode != mountpt_inode) && (stat(target, &statinfo) == 0)) + if (!strcmp("/", target)) { - mountpt_inode->i_mode = statinfo.st_mode; - mountpt_inode->i_uid = statinfo.st_uid; - mountpt_inode->i_gid = statinfo.st_gid; + ChangeRoot(mnt->vnodeCovered); } -#endif + VnodeDrop(); - if (blkdrvr_inode) - { - blkdrvr_inode->e_status = STAT_MOUNTED; - } - inode_semgive(); - - /* We can release our reference to the blkdrver_inode, if the filesystem - * wants to retain the blockdriver inode (which it should), then it must - * have called inode_addref(). There is one reference on mountpt_inode + /* We can release our reference to the blkdrver_vnode, if the filesystem + * wants to retain the blockdriver vnode (which it should), then it must + * have called vnode_addref(). There is one reference on mountpt_vnode * that will persist until umount() is called. */ - if (blkdrvr_inode != NULL) - { - inode_release(blkdrvr_inode); - } - - free(fullpath_bak); - -#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION - if (errcode >= VIRERR_BASE) - { - set_errno(errcode); - } -#endif - return OK; /* A lot of goto's! But they make the error handling much simpler */ errout_with_mountpt: - (void)inode_remove(fullpath); - -errout_with_semaphore: - inode_semgive(); - if (blkdrvr_inode != NULL) + if (mnt) { - inode_release(blkdrvr_inode); + free(mnt); } - free(fullpath_bak); - +errout_with_lock: + VnodeDrop(); errout: - set_errno(errcode); + set_errno(-errcode); return VFS_ERROR; } - #endif /* CONFIG_FS_READABLE */ diff --git a/fs/mount/fs_umount.c b/fs/mount/fs_umount.c old mode 100644 new mode 100755 index 5be2824..ede3b36 --- a/fs/mount/fs_umount.c +++ b/fs/mount/fs_umount.c @@ -42,35 +42,12 @@ #include "sys/mount.h" #include "errno.h" #include "fs/fs.h" - -#include "inode/inode.h" +#include "fs/vnode.h" #include "stdlib.h" - +#include "unistd.h" #include "string.h" #include "disk.h" - -#ifdef LOSCFG_FS_ZPFS -#include "vfs_zpfs.h" -#endif -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/**************************************************************************** - * Private Variables - ****************************************************************************/ - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ +#include "fs_other.h" /**************************************************************************** * Public Functions @@ -94,15 +71,26 @@ * ****************************************************************************/ +BOOL fs_in_use(struct Mount *mnt, const char *target) +{ + char cwd[PATH_MAX]; + char *pret = getcwd(cwd, PATH_MAX); + if (pret != NULL) + { + if (!strncmp(target, cwd, strlen(target))) + { + return TRUE; + } + } + return VnodeInUseIter(mnt->vnodeCovered); +} + int umount(const char *target) { - FAR struct inode *mountpt_inode = NULL; - FAR struct inode *blkdrvr_inode = NULL; - int errcode = OK; - int status; - char *fullpath = NULL; - const char *relpath = NULL; - struct inode_search_s desc; + struct Vnode *mountpt_vnode = NULL; + struct Vnode *blkdrvr_vnode = NULL; + struct Vnode *covered_vnode = NULL; + struct Mount *mnt = NULL; int ret; #ifdef LOSCFG_FS_ZPFS bool isZpfs = false; @@ -113,117 +101,87 @@ int umount(const char *target) if (target == NULL) { - errcode = EFAULT; + ret = -EFAULT; goto errout; } - /* Get a absolute path*/ - - errcode = vfs_normalize_path((const char *)NULL, target, &fullpath); - if (errcode < 0) + /* Find the mountpt */ + VnodeHold(); + ret = VnodeLookup(target, &mountpt_vnode, 0); + if (ret != OK || !mountpt_vnode) { - errcode = -errcode; goto errout; } - - /* Find the mountpt */ - SETUP_SEARCH(&desc, fullpath, false); - ret = inode_find(&desc); - if (ret < 0) + /* Verify that the vnode is a mountpoint */ + if (!mountpt_vnode || !(mountpt_vnode->flag & VNODE_FLAG_MOUNT_ORIGIN)) { - errcode = EACCES; - free(fullpath); + ret = -EINVAL; goto errout; } - mountpt_inode = desc.node; - relpath = desc.relpath; - /* Verify that the inode is a mountpoint */ - - if (!INODE_IS_MOUNTPT(mountpt_inode)) + /* Get mount point covered vnode and mount structure */ + mnt = mountpt_vnode->originMount; + if (!mnt) { - errcode = EINVAL; - goto errout_with_mountpt; + ret = -EINVAL; + goto errout; } - - /* Verfy the path is a mountpoint path or file path*/ - - if ((relpath != NULL) && strlen(relpath)) + covered_vnode = mnt->vnodeBeCovered; + if (!covered_vnode || !(covered_vnode->flag & VNODE_FLAG_MOUNT_NEW)) { - errcode = EPERM; - goto errout_with_mountpt; + ret = -EINVAL; + goto errout; } /* Unbind the block driver from the file system (destroying any fs * private data. */ - if (mountpt_inode->u.i_mops->unbind == NULL) + if (mnt->ops == NULL || mnt->ops->Unmount == NULL) { /* The filesystem does not support the unbind operation ??? */ - errcode = EINVAL; - goto errout_with_mountpt; + ret = -EINVAL; + goto errout; } - inode_semtake(); /* Hold the semaphore through the unbind logic */ - #ifdef LOSCFG_FS_ZPFS - if (IsZpfsFileSystem(mountpt_inode)) + if (IsZpfsFileSystem(mountpt_vnode)) { isZpfs = true; - zpfsInode.i_private = mountpt_inode->i_private; - zpfsInode.u.i_ops = mountpt_inode->u.i_ops; - zpfsInode.i_flags = mountpt_inode->i_flags; + zpfsInode.i_private = mountpt_vnode->i_private; + zpfsInode.u.i_ops = mountpt_vnode->u.i_ops; + zpfsInode.i_flags = mountpt_vnode->i_flags; } #endif - if (mountpt_inode->i_crefs == 1) + /* Release the vnode under the mount point */ + if (fs_in_use(mnt, target)) { - status = mountpt_inode->u.i_mops->unbind(mountpt_inode->i_private, &blkdrvr_inode); - if (status < 0) - { - /* The inode is unhappy with the blkdrvr for some reason */ - - errcode = -status; - goto errout_with_semaphore; - } - else if (status > 0) - { - errcode = EBUSY; - goto errout_with_semaphore; - } + ret = -EBUSY; + goto errout; } - else + + ret = VnodeFreeAll(mnt); + if (ret != OK) { - errcode = EBUSY; - goto errout_with_semaphore; + goto errout; } - /* Successfully unbound */ - - mountpt_inode->i_private = NULL; - mountpt_inode->u.i_ops= (const struct file_operations_vfs *)NULL; - mountpt_inode->i_flags = 0; - - inode_release(mountpt_inode); - - /* Successfully unbound, remove the mountpoint inode from - * the inode tree. The inode will not be deleted yet because - * there is still at least reference on it (from the mount) - */ - - if (blkdrvr_inode) + /* Umount the filesystem */ + ret = mnt->ops->Unmount(mnt, &blkdrvr_vnode); + if (ret != OK) { - blkdrvr_inode->e_status = STAT_UNMOUNTED; + goto errout; } - inode_semgive(); + VnodeFree(mountpt_vnode); + LOS_ListDelete(&mnt->mountList); + free(mnt); /* Did the unbind method return a contained block driver */ - - if (blkdrvr_inode) + if (blkdrvr_vnode) { - inode_release(blkdrvr_inode); + ; /* block driver operations after umount */ } #ifdef LOSCFG_FS_ZPFS @@ -232,23 +190,16 @@ int umount(const char *target) ZpfsCleanUp((void*)&zpfsInode, fullpath); } #endif + covered_vnode->newMount = NULL; + covered_vnode->flag &= ~(VNODE_FLAG_MOUNT_NEW); + VnodeDrop(); - free(fullpath); return OK; /* A lot of goto's! But they make the error handling much simpler */ - -errout_with_semaphore: - inode_semgive(); -errout_with_mountpt: - mountpt_inode->i_crefs--; - if (blkdrvr_inode) - { - inode_release(blkdrvr_inode); - } - free(fullpath); errout: - set_errno(errcode); + VnodeDrop(); + set_errno(-ret); return VFS_ERROR; } @@ -261,4 +212,3 @@ int umount2(const char* __target, int __flags) } return umount(__target); } - diff --git a/fs/nfs/nfs_vfsops.c b/fs/nfs/nfs_adapter.c old mode 100755 new mode 100644 similarity index 43% rename from fs/nfs/nfs_vfsops.c rename to fs/nfs/nfs_adapter.c index 10a98a3..f5d914c --- a/fs/nfs/nfs_vfsops.c +++ b/fs/nfs/nfs_adapter.c @@ -68,51 +68,13 @@ #include "nfs_node.h" #include "xdr_subs.h" #include "los_tables.h" -#include "inode/inode.h" +#include "fs/vnode.h" #include "los_vm_filemap.h" #include "user_copy.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ - -#ifdef LOSCFG_FS_NFS -/* The V3 EXCLUSIVE file creation logic is not fully supported. */ - -#define USE_GUARDED_CREATE 1 - -/* include/nuttx/fs/dirent.h has its own version of these lengths. They must - * match the NFS versions. - */ - -#if NFSX_V3FHMAX != DIRENT_NFS_MAXHANDLE -# error "Length of file handle in fs_dirent_s is incorrect" -#endif - -#if NFSX_V3COOKIEVERF != DIRENT_NFS_VERFLEN -# error "Length of cookie verify in fs_dirent_s is incorrect" -#endif - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/* Use to pass file information to nfs_stat_common() */ - -struct nfs_statinfo_s -{ - uint16_t ns_mode; /* File access mode */ - uint8_t ns_type; /* File type */ - uint64_t ns_size; /* File size */ - time_t ns_atime; /* Time of last access */ - time_t ns_mtime; /* Time of last modification */ - time_t ns_ctime; /* Time of last status change */ -}; - -#define MIN_IPv4_UDP_MSS (IP_FRAG_MAX_MTU - (14 + 20)) /* (Ethernet MTU - (Eth header size + IP header size)) */ - -#define FILENAME_MAX_LEN 50 - /**************************************************************************** * Public Data ****************************************************************************/ @@ -126,6 +88,7 @@ NFSMOUNT_HOOK g_NFSMOUNT_HOOK = (NFSMOUNT_HOOK)(UINTPTR)NULL; struct nfsstats nfsstats; #endif +#ifdef LOSCFG_FS_NFS /**************************************************************************** * Private Type Definitions ****************************************************************************/ @@ -154,787 +117,847 @@ struct nfsstats nfsstats; } \ while (0) - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -static int nfs_filecreate(FAR struct nfsmount *nmp, - FAR struct nfsnode *np, FAR const char *relpath, - int oflags, mode_t mode); -static int nfs_filetruncate(FAR struct nfsmount *nmp, - FAR struct nfsnode *np, uint32_t length); -static int nfs_fileopen(FAR struct nfsmount *nmp, - FAR struct nfsnode *np, FAR const char *relpath, - int oflags, mode_t mode); - -static int nfs_open(FAR struct file *filep, const char *relpath, - int oflags, mode_t mode); -static int nfs_close(FAR struct file *filep); -static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen); -static ssize_t nfs_write(FAR struct file *filep, const char *buffer, - size_t buflen); -static off_t nfs_seek(FAR struct file *filep, off_t offset, int whence); -static loff_t nfs_seek64(FAR struct file *filep, loff_t offset, int whence); -static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp); -static int nfs_opendir(struct inode *mountpt, const char *relpath, - struct fs_dirent_s *dir); -static int nfs_closedir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir); -static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir); -static int nfs_rewinddir(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir); -static void nfs_decode_args(FAR struct nfs_mount_parameters *nprmt, - FAR struct nfs_args *argp); -static int nfs_bind(FAR struct inode *blkdriver, const void *data, - void **handle, FAR const char *realpath); -static int nfs_unbind(void *handle, FAR struct inode **blkdriver); -static int nfs_statfs(FAR struct inode *mountpt, - FAR struct statfs *buf); -static int nfs_remove(FAR struct inode *mountpt, - FAR const char *relpath); -static int nfs_mkdir(FAR struct inode *mountpt, - FAR const char *relpath, mode_t mode); -static int nfs_rmdir(FAR struct inode *mountpt, - FAR const char *relpath); -static int nfs_rename(FAR struct inode *mountpt, - FAR const char *oldrelpath, FAR const char *newrelpath); -static void nfs_stat_common(FAR struct nfs_statinfo_s *info, - FAR struct stat *buf); -static int nfs_stat(struct inode *mountpt, FAR const char *relpath, - FAR struct stat *buf); - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/* nfs vfs operations. */ - -const struct mountpt_operations nfs_operations = +#define FILENAME_MAX_LEN 50 +struct MountOps nfs_mount_operations; +struct VnodeOps nfs_vops; +struct file_operations_vfs nfs_fops; +struct nfs_statinfo_s { - nfs_open, /* open */ - nfs_close, /* close */ - nfs_read, /* read */ - nfs_write, /* write */ - nfs_seek, /* seek */ - NULL, /* ioctl */ - OsVfsFileMmap, /* mmap */ - - NULL, /* sync */ - nfs_dup, /* dup */ - NULL, /* fstat */ - NULL, /* truncate */ - - nfs_opendir, /* opendir */ - nfs_closedir, /* closedir */ - nfs_readdir, /* readdir */ - nfs_rewinddir, /* rewinddir */ - - nfs_bind, /* bind */ - nfs_unbind, /* unbind */ - nfs_statfs, /* statfs */ - NULL, /* virstatfs */ - nfs_remove, /* unlink */ - nfs_mkdir, /* mkdir */ - nfs_rmdir, /* rmdir */ - nfs_rename, /* rename */ - nfs_stat, /* stat */ - NULL, /* for utime */ - NULL, /* chattr */ - nfs_seek64, /* seek64 */ - NULL, /* getlabel */ - NULL, /* fallocate */ - NULL, /* fallocate64 */ - NULL, /* truncate64 */ - NULL, /* fscheck */ - NULL, /* map_pages */ - NULL, /* readpage */ - NULL, /* writepage */ + uint16_t ns_mode; /* File access mode */ + uint8_t ns_type; /* File type */ + uint64_t ns_size; /* File size */ + time_t ns_atime; /* Time of last access */ + time_t ns_mtime; /* Time of last modification */ + time_t ns_ctime; /* Time of last status change */ }; +extern void nfs_stat_common(struct nfs_statinfo_s *info, struct stat *buf); -FSMAP_ENTRY(nfs_fsmap, "nfs", nfs_operations, FALSE, FALSE); +static mode_t type_to_mode(int type, mode_t permission) +{ + switch (type) + { + case VNODE_TYPE_DIR: + return permission | S_IFDIR; + case VNODE_TYPE_REG: + return permission | S_IFREG; + case VNODE_TYPE_BLK: + return permission | S_IFBLK; + case VNODE_TYPE_CHR: + return permission | S_IFCHR; + case VNODE_TYPE_FIFO: + return permission | S_IFIFO; + default: + break; + } + return permission; +} static int nfs_2_vfs(int result) { - int status; + int status; - if ((result < NFS_OK) || (result > NFSERR_NOTEMPTY)) { - return result; + if ((result < NFS_OK) || (result > NFSERR_NOTEMPTY)) + { + return result; } - /* Nfs errno to Libc errno */ - switch (result) { - case NFSERR_NAMETOL: - status = ENAMETOOLONG; - break; - case NFSERR_NOTEMPTY: - status = ENOTEMPTY; - break; - default: - status = result; - break; + /* Nfs errno to Libc errno */ + switch (result) + { + case NFSERR_NAMETOL: + status = ENAMETOOLONG; + break; + case NFSERR_NOTEMPTY: + status = ENOTEMPTY; + break; + default: + status = result; + break; } - return status; + return status; } /**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: nfs_filecreate + * Name: nfs_fileupdate * * Description: - * Create a file. This is part of the file open logic that is executed if - * the user asks to create a file. + * This is to update the file attributes like size, type. This sends a LOOKUP msg of nfs + * to get latest file attributes. * * Returned Value: * 0 on success; a positive errno value on failure. * ****************************************************************************/ - -static int nfs_filecreate(FAR struct nfsmount *nmp, FAR struct nfsnode *np, - FAR const char *relpath, int oflags, mode_t mode) +static int nfs_fileupdate(struct nfsmount *nmp, char *filename, + struct file_handle *parent_fhandle, struct nfsnode *np) { - struct file_handle fhandle; - struct nfs_fattr fattr; - char filename[NAME_MAX + 1]; - FAR uint32_t *ptr; - uint32_t tmp; - int namelen; - int reqlen; - int error; - - /* Find the NFS node of the directory containing the file to be created */ - - error = nfs_finddir(nmp, relpath, &fhandle, &fattr, filename); + struct file_handle fhandle; + int error; + struct nfs_fattr fattr; + + /* Find the NFS node associate with the path */ + + fhandle.length = parent_fhandle->length; + (void)memcpy_s(&(fhandle.handle), fhandle.length, &(parent_fhandle->handle), parent_fhandle->length); + error = nfs_lookup(nmp, filename, &fhandle, &fattr, NULL); + if (error != OK) { - ferr("ERROR: nfs_finddir returned: %d\n", error); + PRINTK("ERROR: nfs_lookup failed returned: %d\n", error); return error; } - /* Create the CREATE RPC call arguments */ - - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.create.create; - reqlen = 0; - - /* Copy the variable length, directory file handle */ - - *ptr++ = txdr_unsigned(fhandle.length); - reqlen += sizeof(uint32_t); - - memcpy(ptr, &fhandle.handle, fhandle.length); - reqlen += (int)fhandle.length; - ptr += uint32_increment(fhandle.length); + /* Update the file handle */ - /* Copy the variable-length file name */ + error = memcpy_s(&(np->n_fhandle), NFSX_V3FHMAX, &(fhandle.handle), fhandle.length); + if (error != EOK) + { + return ENOBUFS; + } - namelen = strlen(filename); + np->n_fhsize = fhandle.length; - *ptr++ = txdr_unsigned(namelen); - reqlen += sizeof(uint32_t); + /* Save the file attributes */ - memcpy(ptr, filename, namelen); - ptr += uint32_increment(namelen); - reqlen += uint32_alignup(namelen); + nfs_attrupdate(np, &fattr); - /* Set the creation mode */ + return OK; +} -#ifdef USE_GUARDED_CREATE - *ptr++ = htonl(NFSV3CREATE_GUARDED); -#else - *ptr++ = htonl(NFSV3CREATE_EXCLUSIVE); -#endif +int vfs_nfs_reclaim(struct Vnode *node) +{ + if (node->data == NULL) + { + return OK; + } + struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data); + struct nfsnode *np = (struct nfsnode*)(node->data); + struct nfsnode *prev = NULL; + struct nfsnode *curr = NULL; + int ret; - reqlen += sizeof(uint32_t); + if (np->n_crefs > 1) + { + np->n_crefs--; + ret = OK; + } - /* Mode information is not provided if EXCLUSIVE creation is used. - * in this case, we must call SETATTR after successfully creating - * the file. + /* There are no more references to the file structure. Now we need to + * free up all resources associated with the open file. + * + * First, find our file structure in the list of file structures + * containted in the mount structure. */ -#ifndef USE_GUARDED_CREATE - if ((oflags & O_CREAT) == 0) -#endif + else { - /* Set the mode. NOTE: Here we depend on the fact that the NuttX and NFS - * bit settings are the same (at least for the bits of interest). - */ - - *ptr++ = nfs_true; /* True: mode value follows */ - reqlen += sizeof(uint32_t); - - tmp = mode & (NFSMODE_IWOTH | NFSMODE_IROTH | NFSMODE_IWGRP | - NFSMODE_IRGRP | NFSMODE_IWUSR | NFSMODE_IRUSR); - *ptr++ = txdr_unsigned(tmp); - reqlen += sizeof(uint32_t); + /* Assume file structure will not be found. This should never happen. */ - /* Set the user ID to zero */ + ret = -EINVAL; - *ptr++ = nfs_true; /* True: Uid value follows */ - *ptr++ = 0; /* UID = 0 (nobody) */ - reqlen += 2*sizeof(uint32_t); + for (prev = NULL, curr = nmp->nm_head; + curr; + prev = curr, curr = curr->n_next) + { + /* Check if this node is ours */ - /* Set the group ID to one */ + if (np == curr) + { + /* Yes.. remove it from the list of file structures */ - *ptr++ = nfs_true; /* True: Gid value follows */ - *ptr++ = htonl(1); /* GID = 1 (nogroup) */ - reqlen += 2*sizeof(uint32_t); + if (prev) + { + /* Remove from mid-list */ - /* Set the size to zero */ + prev->n_next = np->n_next; + } + else + { + /* Remove from the head of the list */ - *ptr++ = nfs_true; /* True: Size value follows */ - *ptr++ = 0; /* Size = 0 */ - *ptr++ = 0; - reqlen += 3*sizeof(uint32_t); + nmp->nm_head = np->n_next; + } - /* Don't change times */ + /* Then deallocate the file structure and return success */ - *ptr++ = htonl(NFSV3SATTRTIME_DONTCHANGE); /* Don't change atime */ - *ptr++ = htonl(NFSV3SATTRTIME_DONTCHANGE); /* Don't change mtime */ - reqlen += 2*sizeof(uint32_t); + free(np->n_name); + free(np); + ret = OK; + break; + } + } } - /* Send the NFS request. Note there is special logic here to handle version 3 - * exclusive open semantics. - */ + return ret; +} - do +static int vfs_nfs_stat_internal(struct nfsmount *nmp, struct nfsnode *nfs_node) +{ + int ret; + struct timespec ts; + struct rpc_call_fs attr_call; + struct rpc_reply_getattr attr_reply; + attr_call.fs.fsroot.length = txdr_unsigned(nfs_node->n_fhsize); + memcpy_s(&(attr_call.fs.fsroot.handle), sizeof(nfsfh_t), &(nfs_node->n_fhandle), sizeof(nfsfh_t)); + ret = nfs_request(nmp, NFSPROC_GETATTR, &attr_call, + sizeof(struct file_handle), &attr_reply, + sizeof(struct rpc_reply_getattr)); + if (ret != OK) { - nfs_statistics(NFSPROC_CREATE); - error = nfs_request(nmp, NFSPROC_CREATE, - (FAR void *)&nmp->nm_msgbuffer.create, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); + return ret; } -#ifdef USE_GUARDED_CREATE - while (0); -#else - while (((oflags & O_CREAT) != 0) && error == EOPNOTSUPP); -#endif - - /* Check for success */ - - if (error == OK) - { - /* Parse the returned data */ - - ptr = (FAR uint32_t *)&((FAR struct rpc_reply_create *) - nmp->nm_iobuffer)->create; - - /* Save the file handle in the file data structure */ - - tmp = *ptr++; /* handle_follows */ - if (!tmp) - { - ferr("ERROR: no file handle follows\n"); - return EINVAL; - } - - tmp = *ptr++; - tmp = fxdr_unsigned(uint32_t, tmp); - DEBUGASSERT(tmp <= NFSX_V3FHMAX); + /* Extract the file mode, file type, and file size. */ - np->n_fhsize = (uint8_t)tmp; - memcpy(&np->n_fhandle, ptr, tmp); - ptr += uint32_increment(tmp); + nfs_node->n_mode = fxdr_unsigned(uint16_t, attr_reply.attr.fa_mode); + nfs_node->n_type = fxdr_unsigned(uint8_t, attr_reply.attr.fa_type); + nfs_node->n_size = fxdr_hyper(&attr_reply.attr.fa_size); - /* Save the attributes in the file data structure */ + /* Extract time values as type time_t in units of seconds */ - tmp = *ptr; /* handle_follows */ - if (!tmp) - { - fwarn("WARNING: no file attributes\n"); - } - else - { - /* Initialize the file attributes */ + fxdr_nfsv3time(&attr_reply.attr.fa_mtime, &ts); + nfs_node->n_mtime = ts.tv_sec; - nfs_attrupdate(np, (FAR struct nfs_fattr *)ptr); - } + fxdr_nfsv3time(&attr_reply.attr.fa_atime, &ts); + nfs_node->n_atime = ts.tv_sec; - /* Any following dir_wcc data is ignored for now */ - } + fxdr_nfsv3time(&attr_reply.attr.fa_ctime, &ts); + nfs_node->n_ctime = ts.tv_sec; - return error; + return OK; } /**************************************************************************** - * Name: nfs_fileopen - * - * Description: - * Truncate an open file to zero length. This is part of the file open - * logic. + * Name: nfs_decode_args * * Returned Value: - * 0 on success; a positive errno value on failure. + * None * ****************************************************************************/ -static int nfs_filetruncate(FAR struct nfsmount *nmp, - FAR struct nfsnode *np, uint32_t length) +static void nfs_decode_args(struct nfs_mount_parameters *nprmt, + struct nfs_args *argp) { - FAR uint32_t *ptr; - int reqlen; - int error; + int maxio; - finfo("Truncating file\n"); + /* Get the selected timeout value */ - /* Create the SETATTR RPC call arguments */ + if ((argp->flags & NFSMNT_TIMEO) != 0 && argp->timeo > 0) + { + uint32_t tmp = ((uint32_t)argp->timeo * NFS_HZ + 5) / 10; + if (tmp < NFS_MINTIMEO) + { + tmp = NFS_MINTIMEO; + } + else if (tmp > NFS_MAXTIMEO) + { + tmp = NFS_MAXTIMEO; + } - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.setattr.setattr; - reqlen = 0; + nprmt->timeo = tmp; + } - /* Copy the variable length, directory file handle */ + /* Get the selected retransmission count */ - *ptr++ = txdr_unsigned(np->n_fhsize); - reqlen += sizeof(uint32_t); + if ((argp->flags & NFSMNT_RETRANS) != 0 && argp->retrans > 1) + { + if (argp->retrans < NFS_MAXREXMIT) + { + nprmt->retry = argp->retrans; + } + else + { + nprmt->retry = NFS_MAXREXMIT; + } + } - memcpy(ptr, &np->n_fhandle, np->n_fhsize); - reqlen += (int)np->n_fhsize; - ptr += uint32_increment(np->n_fhsize); + if ((argp->flags & NFSMNT_SOFT) == 0) + { + nprmt->retry = NFS_MAXREXMIT + 1; /* Past clip limit */ + } - /* Copy the variable-length attributes */ + /* Get the maximum amount of data that can be transferred in one packet */ - *ptr++ = nfs_false; /* Don't change mode */ - *ptr++ = nfs_false; /* Don't change uid */ - *ptr++ = nfs_false; /* Don't change gid */ - *ptr++ = nfs_true; /* Use the following size */ - *ptr++ = length; /* Truncate to the specified length */ - *ptr++ = 0; - *ptr++ = htonl(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */ - *ptr++ = htonl(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */ - *ptr++ = nfs_false; /* No guard value */ - reqlen += 9 * sizeof(uint32_t); - - /* Perform the SETATTR RPC */ - - nfs_statistics(NFSPROC_SETATTR); - error = nfs_request(nmp, NFSPROC_SETATTR, - (FAR void *)&nmp->nm_msgbuffer.setattr, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - if (error != OK) + if ((argp->sotype == SOCK_DGRAM) != 0) { - ferr("ERROR: nfs_request failed: %d\n", error); - return error; + maxio = NFS_MAXDGRAMDATA; + } + else + { + ferr("ERROR: Only SOCK_DRAM is supported\n"); + maxio = NFS_MAXDATA; } - /* Indicate that the file now has zero length */ - - np->n_size = 0; - return OK; -} + /* Get the maximum amount of data that can be transferred in one write transfer */ -/**************************************************************************** - * Name: nfs_fileopen - * - * Description: - * Open a file. This is part of the file open logic that attempts to open - * an existing file. - * - * Returned Value: - * 0 on success; a positive errno value on failure. - * - ****************************************************************************/ + if ((argp->flags & NFSMNT_WSIZE) != 0 && argp->wsize > 0) + { + nprmt->wsize = argp->wsize; -static int nfs_fileopen(FAR struct nfsmount *nmp, FAR struct nfsnode *np, - FAR const char *relpath, int oflags, mode_t mode) -{ - struct file_handle fhandle; - struct nfs_fattr fattr; - uint32_t tmp; - int error = 0; + /* Round down to multiple of blocksize */ - /* Find the NFS node associate with the path */ + nprmt->wsize &= ~(NFS_FABLKSIZE - 1); + if (nprmt->wsize <= 0) + { + nprmt->wsize = NFS_FABLKSIZE; + } + } - error = nfs_findnode(nmp, relpath, &fhandle, &fattr, NULL); - if (error != OK) + if (nprmt->wsize > maxio) { - ferr("ERROR: nfs_findnode returned: %d\n", error); - return error; + nprmt->wsize = maxio; } - /* Check if the object is a directory */ - - tmp = fxdr_unsigned(uint32_t, fattr.fa_type); - if (tmp == NFDIR) + if (nprmt->wsize > MAXBSIZE) { - /* Exit with EISDIR if we attempt to open a directory */ - - ferr("ERROR: Path is a directory\n"); - return EISDIR; + nprmt->wsize = MAXBSIZE; } - /* Check if the caller has sufficient privileges to open the file */ + /* Get the maximum amount of data that can be transferred in one read transfer */ - if ((oflags & O_WRONLY) != 0) + if ((argp->flags & NFSMNT_RSIZE) != 0 && argp->rsize > 0) { - /* Check if anyone has priveleges to write to the file -- owner, - * group, or other (we are probably "other" and may still not be - * able to write). - */ + nprmt->rsize = argp->rsize; - tmp = fxdr_unsigned(uint32_t, fattr.fa_mode); - if ((tmp & (NFSMODE_IWOTH | NFSMODE_IWGRP | NFSMODE_IWUSR)) == 0) + /* Round down to multiple of blocksize */ + + nprmt->rsize &= ~(NFS_FABLKSIZE - 1); + if (nprmt->rsize <= 0) { - ferr("ERROR: File is read-only: %08x\n", tmp); - return EACCES; + nprmt->rsize = NFS_FABLKSIZE; } } - /* It would be an error if we are asked to create the file exclusively */ - - if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + if (nprmt->rsize > maxio) { - /* Already exists -- can't create it exclusively */ - - ferr("ERROR: File exists\n"); - return EEXIST; + nprmt->rsize = maxio; } - /* Initialize the file private data. - * - * Copy the file handle. - */ - - np->n_fhsize = (uint8_t)fhandle.length; - memcpy(&np->n_fhandle, &fhandle.handle, fhandle.length); + if (nprmt->rsize > MAXBSIZE) + { + nprmt->rsize = MAXBSIZE; + } - /* Save the file attributes */ + /* Get the maximum amount of data that can be transferred in directory transfer */ - nfs_attrupdate(np, &fattr); + if ((argp->flags & NFSMNT_READDIRSIZE) != 0 && argp->readdirsize > 0) + { + nprmt->readdirsize = argp->readdirsize; - /* If O_TRUNC is specified and the file is opened for writing, - * then truncate the file. This operation requires that the file is - * writable, but we have already checked that. O_TRUNC without write - * access is ignored. - */ + /* Round down to multiple of blocksize */ - if ((oflags & O_TRUNC) && (oflags & (O_WRONLY | O_RDWR))) + nprmt->readdirsize &= ~(NFS_DIRBLKSIZ - 1); + if (nprmt->readdirsize < NFS_DIRBLKSIZ) + { + nprmt->readdirsize = NFS_DIRBLKSIZ; + } + } + else if (argp->flags & NFSMNT_RSIZE) { - /* Truncate the file to zero length. I think we can do this with - * the SETATTR call by setting the length to zero. - */ - - return nfs_filetruncate(nmp, np, 0); + nprmt->readdirsize = nprmt->rsize; } - return OK; + if (nprmt->readdirsize > maxio) + { + nprmt->readdirsize = maxio; + } } /**************************************************************************** - * Name: nfs_fileupdate + * Name: nfs_bind * * Description: - * This is to update the file attributes like size, type. This sends a LOOKUP msg of nfs - * to get latest file attributes. + * This implements a portion of the mount operation. This function allocates + * and initializes the mountpoint private data and gets mount information + * from the NFS server. The final binding of the private data (containing + * NFS server mount information) to the mountpoint is performed by mount(). * * Returned Value: - * 0 on success; a positive errno value on failure. + * 0 on success; a negated errno value on failure. * ****************************************************************************/ -static int nfs_fileupdate(FAR struct nfsmount *nmp, struct nfsnode *np, - FAR const char *relpath) +int nfs_bind(struct Vnode *blkdriver, const void *data, + void **handle, const char *relpath) { - struct file_handle fhandle; - struct nfs_fattr fattr; - int error; + struct nfs_args *argp = (struct nfs_args *)data; + struct nfsmount *nmp = NULL; + struct rpcclnt *rpc = NULL; + struct rpc_call_fs getattr; + struct rpc_reply_getattr resok; + struct nfs_mount_parameters nprmt; + uint32_t buflen; + uint32_t pathlen; + uint32_t tmp; + int error = 0; + pthread_mutexattr_t attr; - /* Find the NFS node associate with the path */ + DEBUGASSERT(data && handle); - error = nfs_findnode(nmp, relpath, &fhandle, &fattr, (struct nfs_fattr *)NULL); - if (error != OK) + /* Set default values of the parameters. These may be overridden by + * settings in the argp->flags. + */ + + nprmt.timeo = NFS_TIMEO; + nprmt.retry = NFS_RETRANS; + nprmt.wsize = NFS_WSIZE; + nprmt.rsize = NFS_RSIZE; + nprmt.readdirsize = NFS_READDIRSIZE; + + nfs_decode_args(&nprmt, argp); + + /* Determine the size of a buffer that will hold one RPC data transfer. + * First, get the maximum size of a read and a write transfer. + */ + + pathlen = strlen(argp->path); + if (pathlen >= NFS_MOUNT_PATH_MAX_SIZE) { + return -ENAMETOOLONG; + } + + buflen = SIZEOF_rpc_call_write(nprmt.wsize); + tmp = SIZEOF_rpc_reply_read(nprmt.rsize); + + /* The buffer size will be the maximum of those two sizes */ + + if (tmp > buflen) { - fdbg("ERROR: nfs_findnode returned: %d\n", error); - return error; + buflen = tmp; } - /* Update the file handle */ + /* But don't let the buffer size exceed the MSS of the socket type. + * + * In the case where there are multiple network devices with different + * link layer protocols, each network device may support a different + * UDP MSS value. Here we arbitrarily select the minimum MSS for + * that case. + */ - error = memcpy_s(&np->n_fhandle, NFSX_V3FHMAX, &fhandle.handle, fhandle.length); - if (error != EOK) + /* Create an instance of the mountpt state structure */ + + nmp = (struct nfsmount *)malloc(SIZEOF_nfsmount(buflen)); + if (!nmp) { - return ENOBUFS; + ferr("ERROR: Failed to allocate mountpoint structure\n"); + return -ENOMEM; } - np->n_fhsize = fhandle.length; + (void)memset_s(nmp, SIZEOF_nfsmount(buflen), 0, SIZEOF_nfsmount(buflen)); - /* Save the file attributes */ + /* Save the allocated I/O buffer size */ - nfs_attrupdate(np, &fattr); + nmp->nm_buflen = (uint16_t)buflen; - return OK; -} + nmp->nm_so = -1; -/**************************************************************************** - * Name: nfs_open - * - * Description: - * If oflags == O_CREAT it creates a file, if not it check to see if the - * type is ok and that deletion is not in progress. - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ + /* Initialize the allocated mountpt state structure. */ -static int nfs_open(FAR struct file *filep, FAR const char *relpath, - int oflags, mode_t mode) -{ - struct nfsmount *nmp; - struct nfsnode *np; - int error; + (void)pthread_mutexattr_init(&attr); + (void)pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + error = pthread_mutex_init(&nmp->nm_mux, &attr); + if (error) + { + return -error; + } - /* Sanity checks */ + /* Initialize NFS */ - DEBUGASSERT(filep->f_inode != NULL); + nfs_true = txdr_unsigned(TRUE); + nfs_false = txdr_unsigned(FALSE); + nfs_xdrneg1 = txdr_unsigned(-1); - /* Get the mountpoint inode reference from the file structure and the - * mountpoint private data from the inode structure - */ + rpcclnt_init(); - nmp = (FAR struct nfsmount *)filep->f_inode->i_private; - DEBUGASSERT(nmp != NULL); + /* Set initial values of other fields */ - /* Pre-allocate the file private data to describe the opened file. */ + nmp->nm_timeo = nprmt.timeo; + nmp->nm_retry = nprmt.retry; + nmp->nm_wsize = nprmt.wsize; + nmp->nm_rsize = nprmt.rsize; + nmp->nm_readdirsize = nprmt.readdirsize; + nmp->nm_fhsize = NFSX_V3FHMAX; - np = (struct nfsnode *)malloc(sizeof(struct nfsnode)); - if (!np) - { - ferr("ERROR: Failed to allocate private data\n"); - return ENOMEM; - } + (void)strncpy_s(nmp->nm_path, sizeof(nmp->nm_path), argp->path, pathlen); + (void)memcpy_s(&nmp->nm_nam, sizeof(struct sockaddr), &argp->addr, argp->addrlen); - (void)memset_s(np, sizeof(struct nfsnode), 0, sizeof(struct nfsnode)); + /* Set up the sockets and per-host congestion */ - /* Check if the mount is still healthy */ + nmp->nm_sotype = argp->sotype; - nfs_mux_take(nmp); - error = nfs_checkmount(nmp); - if (error != OK) + if (nmp->nm_sotype == SOCK_DGRAM || nmp->nm_sotype == SOCK_STREAM) { - ferr("ERROR: nfs_checkmount failed: %d\n", error); - goto errout_with_mutex; - } - - /* Try to open an existing file at that path */ + /* Connection-less... connect now */ - error = nfs_fileopen(nmp, np, relpath, oflags, mode); - if (error != OK) - { - /* An error occurred while trying to open the existing file. Check if - * the open failed because the file does not exist. That is not - * necessarily an error; that may only mean that we have to create the - * file. - */ + /* Create an instance of the rpc state structure */ - if (error != ENOENT) + rpc = (struct rpcclnt *)malloc(sizeof(struct rpcclnt)); + if (!rpc) { - ferr("ERROR: nfs_findnode failed: %d\n", error); - goto errout_with_mutex; + ferr("ERROR: Failed to allocate rpc structure\n"); + error = ENOMEM; + goto bad; } - /* The file does not exist. Check if we were asked to create the file. If - * the O_CREAT bit is set in the oflags then we should create the file if it - * does not exist. - */ + (void)memset_s(rpc, sizeof(struct rpcclnt), 0, sizeof(struct rpcclnt)); - if ((oflags & O_CREAT) == 0) - { - /* Return ENOENT if the file does not exist and we were not asked - * to create it. - */ + finfo("Connecting\n"); - ferr("ERROR: File does not exist\n"); - error = ENOENT; - goto errout_with_mutex; - } + /* Translate nfsmnt flags -> rpcclnt flags */ - /* Create the file */ + rpc->rc_path = nmp->nm_path; + rpc->rc_name = &nmp->nm_nam; + rpc->rc_sotype = nmp->nm_sotype; + rpc->rc_retry = nmp->nm_retry; + rpc->rc_so = -1; + + nmp->nm_rpcclnt = rpc; - error = nfs_filecreate(nmp, np, relpath, oflags, mode); + error = rpcclnt_connect(nmp->nm_rpcclnt); if (error != OK) { - ferr("ERROR: nfs_filecreate failed: %d\n", error); - goto errout_with_mutex; + PRINTK("ERROR: nfs_connect failed: %d\n", error); + goto bad; } } - /* Initialize the file private data (only need to initialize - * non-zero elements) - */ + nmp->nm_mounted = true; + nmp->nm_so = nmp->nm_rpcclnt->rc_so; + nmp->nm_head = NULL; + nmp->nm_dir = NULL; + nmp->nm_fhsize = nmp->nm_rpcclnt->rc_fhsize; + (void)memcpy_s(&nmp->nm_fh, sizeof(nfsfh_t), &nmp->nm_rpcclnt->rc_fh, sizeof(nfsfh_t)); - np->n_crefs = 1; + /* Get the file attributes */ - /* Attach the private data to the struct file instance */ + getattr.fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize); + (void)memcpy_s(&getattr.fs.fsroot.handle, sizeof(nfsfh_t), &nmp->nm_fh, sizeof(nfsfh_t)); - filep->f_priv = np; + error = nfs_request(nmp, NFSPROC_GETATTR, + (void *)&getattr, /* sizeof(struct FS3args) */ + (sizeof(getattr.fs.fsroot.length) + nmp->nm_fhsize), + (void *)&resok, sizeof(struct rpc_reply_getattr)); + if (error) + { + ferr("ERROR: nfs_request failed: %d\n", error); + goto bad; + } - /* Then insert the new instance at the head of the list in the mountpoint - * tructure. It needs to be there (1) to handle error conditions that effect - * all files, and (2) to inform the umount logic that we are busy. We - * cannot unmount the file system if this list is not empty! - */ + /* Save the file attributes */ - np->n_next = nmp->nm_head; - nmp->nm_head = np; + (void)memcpy_s(&nmp->nm_fattr, sizeof(struct nfs_fattr), &resok.attr, sizeof(struct nfs_fattr)); - np->n_flags |= (NFSNODE_OPEN | NFSNODE_MODIFIED); - np->n_oflags = oflags; + /* Mounted! */ - if (filep->f_oflags & O_APPEND) - { - np->n_fpos = np->n_size; - } - else - { - np->n_fpos = 0; - } - filep->f_pos = np->n_fpos; - np->n_filep = filep; + *handle = (void *)nmp; - nfs_mux_release(nmp); + finfo("Successfully mounted\n"); return OK; -errout_with_mutex: - if (np) +bad: + if (nmp) { - free(np); + /* Disconnect from the server */ + + if (nmp->nm_rpcclnt) + { + rpcclnt_disconnect(nmp->nm_rpcclnt); + free(nmp->nm_rpcclnt); + nmp->nm_rpcclnt = NULL; + } + + /* Free connection-related resources */ + + (void)pthread_mutex_destroy(&nmp->nm_mux); + + free(nmp); + nmp = NULL; } - nfs_mux_release(nmp); - return -error; + return -error; /*lint !e438*/ } -/**************************************************************************** - * Name: nfs_close - * - * Description: - * Close a file. - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ -static int nfs_close(FAR struct file *filep) +static enum VnodeType filetype_to_vnodetype(uint32_t filetype) { - FAR struct nfsmount *nmp; - FAR struct nfsnode *np; - FAR struct nfsnode *prev; - FAR struct nfsnode *curr; - int ret; + if (filetype < 0 || filetype > 7) + { + return VNODE_TYPE_UNKNOWN; + } - /* Sanity checks */ + enum VnodeType transfer_table[8] = + { + VNODE_TYPE_UNKNOWN, + VNODE_TYPE_REG, + VNODE_TYPE_DIR, + VNODE_TYPE_BLK, + VNODE_TYPE_CHR, + VNODE_TYPE_LNK, + VNODE_TYPE_UNKNOWN, + VNODE_TYPE_FIFO + }; + + return transfer_table[filetype]; +} - DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); +int nfs_mount(const char *server_ip_and_path, const char *mount_path, + unsigned int uid, unsigned int gid) +{ + struct nfs_args nfs_args = {0}; + char *server_ip_addr = NULL; + char *server_nfs_path = NULL; + int found_colon = 0; + unsigned int pos; + int ret = -1; + struct sockaddr_in *nfs_srv_addr = NULL; + size_t len; - /* Recover our private data from the struct file instance */ + rpcclnt_setuidgid(uid, gid); - nmp = (FAR struct nfsmount *) filep->f_inode->i_private; - np = (FAR struct nfsnode *) filep->f_priv; + len = strlen(server_ip_and_path); + for (pos = 0; pos < len; pos++) + { + if (*(server_ip_and_path + pos) == ':') + { + found_colon = 1; + break; + } + } - DEBUGASSERT(nmp != NULL); + if (!found_colon) + { + set_errno(ENOENT); + goto nfs_mount_out; + } - /* Get exclusive access to the mount structure. */ + server_ip_addr = (char *)malloc(pos + 1); + if (server_ip_addr == NULL) + { + PRINTK("malloc failure\n"); + set_errno(ENOMEM); + goto nfs_mount_out; + } - nfs_mux_take(nmp); + ret = strncpy_s(server_ip_addr, pos + 1, server_ip_and_path, pos); + if (ret != EOK) + { + set_errno(ENOBUFS); + goto nfs_free_node_out; + } + *(server_ip_addr + pos) = '\0'; + server_nfs_path = (char *)(server_ip_and_path + pos + 1); - /* Decrement the reference count. If the reference count would not - * decrement to zero, then that is all we have to do. - */ + (void)memset_s(&nfs_args, sizeof(nfs_args), 0, sizeof(nfs_args)); - if (np->n_crefs > 1) + if (g_NFSMOUNT_HOOK != NULL) { - np->n_crefs--; - ret = OK; + g_NFSMOUNT_HOOK(&nfs_args); } - /* There are no more references to the file structure. Now we need to - * free up all resources associated with the open file. - * - * First, find our file structure in the list of file structures - * containted in the mount structure. - */ + nfs_args.path = server_nfs_path; /* server nfs dir */ - else + nfs_srv_addr = (struct sockaddr_in *)&nfs_args.addr; + nfs_srv_addr->sin_family = AF_INET; + ret = inet_pton(AF_INET, server_ip_addr, &nfs_srv_addr->sin_addr.s_addr); + if (ret != 1) { - /* Assume file structure will not be found. This should never happen. */ + ret = -1; + set_errno(ECONNREFUSED); + goto nfs_free_node_out; + } + nfs_srv_addr->sin_port = htons(PMAPPORT); - ret = -EINVAL; + nfs_args.addrlen = sizeof(nfs_args.addr); +#if (NFS_PROTO_TYPE == NFS_IPPROTO_TCP) + nfs_args.sotype = SOCK_STREAM; +#elif (NFS_PROTO_TYPE == NFS_IPPROTO_UDP) + nfs_args.sotype = SOCK_DGRAM; +#endif - for (prev = NULL, curr = nmp->nm_head; - curr; - prev = curr, curr = curr->n_next) - { - /* Check if this node is ours */ + PRINTK("Mount nfs on %s:%s, uid:%d, gid:%d\n", server_ip_addr, server_nfs_path, uid, gid); + ret = mount((const char *)NULL, mount_path, "nfs", 0, &nfs_args); - if (np == curr) - { - /* Yes.. remove it from the list of file structures */ +nfs_free_node_out: + free(server_ip_addr); - if (prev) - { - /* Remove from mid-list */ +nfs_mount_out: + if (ret) + { + perror("mount nfs error"); + return -1; + } + PRINTK("Mount nfs finished.\n"); + return 0; +} - prev->n_next = np->n_next; - } - else - { - /* Remove from the head of the list */ +int vfs_nfs_mount(struct Mount *mnt, struct Vnode *device, const void *data) +{ + struct nfsmount *nmp = NULL; + struct Vnode *vp = NULL; - nmp->nm_head = np->n_next; - } + int ret = VnodeAlloc(&nfs_vops, &vp); + if (ret != OK) + { + return -EADDRNOTAVAIL; + } - /* Then deallocate the file structure and return success */ + struct nfsnode *root = zalloc(sizeof(struct nfsnode)); + if (root == NULL) + { + (void)VnodeFree(vp); + return -EADDRNOTAVAIL; + } - free(np); - filep->f_priv = NULL; - ret = OK; - break; - } - } + ret = nfs_bind(NULL, data, (void **)(&nmp), NULL); + if (ret != OK || nmp == NULL) + { + (void)VnodeFree(vp); + free(root); + return -EAGAIN; } + vp->originMount = mnt; + vp->fop = &nfs_fops; + vp->data = root; + root->n_fhsize = nmp->nm_fhsize; + (void)memcpy_s(&(root->n_fhandle), root->n_fhsize, &(nmp->nm_fh), nmp->nm_fhsize); + mnt->vnodeCovered = vp; + mnt->data = nmp; - nfs_mux_release(nmp); + ret = vfs_nfs_stat_internal(nmp, root); + if (ret == OK) + { + vp->type = root->n_type; + } + nmp->nm_permission = mnt->vnodeBeCovered->mode & 0777; + nmp->nm_gid = mnt->vnodeBeCovered->gid; + nmp->nm_uid = mnt->vnodeBeCovered->uid; + vp->mode = type_to_mode(vp->type, nmp->nm_permission); + vp->gid = nmp->nm_gid; + vp->uid = nmp->nm_uid; + return OK; +} - return ret; +int vfs_nfs_lookup(struct Vnode *parent, const char *path, int len, struct Vnode **vpp) +{ + int ret; + struct nfs_fattr obj_attributes; + struct nfsmount *nmp; + char filename[len + 1]; + (void)memcpy_s(filename, (len + 1), path, len); + filename[len] = '\0'; + struct file_handle fhandle; + struct nfsnode *parent_nfs_node = (struct nfsnode *)parent->data; + fhandle.length = parent_nfs_node->n_fhsize; + memcpy_s(&(fhandle.handle), fhandle.length, &(parent_nfs_node->n_fhandle), parent_nfs_node->n_fhsize); + + nmp = (struct nfsmount *)(parent->originMount->data); + ret = nfs_lookup(nmp, filename, &fhandle, &obj_attributes, NULL); + if (ret != OK) + { + return -ENOENT; + } + + /* Initialize the file private data. + * + * Copy the file handle. + */ + struct nfsnode *nfs_node = zalloc(sizeof(struct nfsnode)); + nfs_node->n_fhsize = (uint8_t)fhandle.length; + memcpy_s(&(nfs_node->n_fhandle), nfs_node->n_fhsize, &(fhandle.handle), fhandle.length); + nfs_node->n_name = zalloc(sizeof(filename)); + memcpy_s(nfs_node->n_name, (len + 1), filename, sizeof(filename)); + + /* Save the file attributes */ + nfs_attrupdate(nfs_node, &obj_attributes); + + (void)VnodeAlloc(&nfs_vops, vpp); + (*vpp)->parent = parent; + (*vpp)->fop = &nfs_fops; + (*vpp)->originMount = parent->originMount; + (*vpp)->data = nfs_node; + (*vpp)->type = filetype_to_vnodetype(nfs_node->n_type); + (*vpp)->mode = type_to_mode((*vpp)->type, nmp->nm_permission); + (*vpp)->gid = nmp->nm_gid; + (*vpp)->uid = nmp->nm_uid; + return OK; } -/**************************************************************************** - * Name: nfs_read - * - * Returned Value: - * The (non-negative) number of bytes read on success; a negated errno - * value on failure. - * - ****************************************************************************/ +int vfs_nfs_stat(struct Vnode *node, struct stat *buf) +{ + struct nfsnode *nfs_node = (struct nfsnode *)node->data; + buf->st_mode = node->mode; + buf->st_gid = node->gid; + buf->st_uid = node->uid; + buf->st_size = (off_t)nfs_node->n_size; + buf->st_blksize = 0; + buf->st_blocks = 0; + buf->st_mtime = nfs_node->n_mtime; + buf->st_atime = nfs_node->n_atime; + buf->st_ctime = nfs_node->n_ctime; + return OK; +} -static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen) +int vfs_nfs_opendir(struct Vnode *node, struct fs_dirent_s *dir) { - FAR struct nfsmount *nmp; - FAR struct nfsnode *np; - struct rpc_reply_read *read_response; - size_t readsize; - size_t tmp; - size_t bytesread; - size_t reqlen; - FAR uint32_t *ptr; - int error = 0; + int ret; + struct nfsdir_s *nfs_dir = NULL; + struct nfsnode *nfs_node = (struct nfsnode *)node->data; + struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data); + if (node->type != VNODE_TYPE_DIR) { + return -ENOTDIR; + } + nfs_mux_take(nmp); + ret = nfs_checkmount(nmp); + if (ret != OK) { + ret = -ret; + PRINTK("ERROR: nfs_checkmount failed: %d\n", ret); + goto errout_with_mutex; + } + nfs_dir = (struct nfsdir_s *)malloc(sizeof(struct nfsdir_s)); + if (!nfs_dir) { + ret = -ENOMEM; + goto errout_with_mutex; + } + nfs_dir->nfs_fhsize = nfs_node->n_fhsize; + nfs_dir->nfs_cookie[0] = 0; + nfs_dir->nfs_cookie[1] = 0; + (void)memcpy_s(nfs_dir->nfs_fhandle, DIRENT_NFS_MAXHANDLE, &(nfs_node->n_fhandle), DIRENT_NFS_MAXHANDLE); + dir->u.fs_dir = (fs_dir_s)nfs_dir; + ret = OK; + + nfs_dir->nfs_next = nmp->nm_dir; + nmp->nm_dir = nfs_dir; + nfs_dir->nfs_dir = dir; + nfs_dir->nfs_entries = NULL; + +errout_with_mutex: + nfs_mux_release(nmp); + return ret; +} - finfo("Read %d bytes from offset %d\n", buflen, filep->f_pos); +int vfs_nfs_readdir(struct Vnode *node, struct fs_dirent_s *dir) +{ + struct nfsmount *nmp; + struct file_handle fhandle; + struct nfs_fattr obj_attributes; + struct nfsdir_s *nfs_dir = NULL; + struct entry3 *entry = NULL; + struct entry3 *entry_pos = NULL; - /* Sanity checks */ + /* Use 2 cookies */ - DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + uint32_t cookies[2]; + uint32_t tmp; + uint32_t *ptr = NULL; + size_t d_name_size; + int reqlen; + int error = 0; + int i = 0; - /* Recover our private data from the struct file instance */ + /* Sanity checks */ - nmp = (FAR struct nfsmount *)filep->f_inode->i_private; - np = (FAR struct nfsnode *)filep->f_priv; + /* Recover our private data from the vnode instance */ - DEBUGASSERT(nmp != NULL); + nmp = (struct nfsmount *)(node->originMount->data); /* Make sure that the mount is still healthy */ @@ -942,243 +965,663 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen) error = nfs_checkmount(nmp); if (error != OK) { - ferr("ERROR: nfs_checkmount failed: %d\n", error); + PRINTK("ERROR: nfs_checkmount failed: %d\n", error); goto errout_with_mutex; } - fvdbg("File attributes before update, file size %d, file type %d\n", np->n_size, np->n_type); + /* Request a block directory entries, copying directory information from + * the dirent structure. + */ + nfs_dir = (struct nfsdir_s *)dir->u.fs_dir; + cookies[0] = 0; + cookies[1] = 0; - error = nfs_fileupdate(nmp, np, filep->f_relpath); - if (error != OK) + if (nfs_dir && nfs_dir->nfs_entries && (nfs_dir->nfs_entries->file_id[0] == (uint32_t)EOF)) { - fdbg("nfs_fileupdate failed: %d\n", error); + error = ENOENT; + free(nfs_dir->nfs_entries); + nfs_dir->nfs_entries = NULL; goto errout_with_mutex; } + while (1) + { + if (i >= MAX_DIRENT_NUM || i >= dir->read_cnt) + { + break; + } - fvdbg("File attributes after update, file size %d, file type %d\n", np->n_size, np->n_type); + if (!nfs_dir->nfs_entries) + { + entry_pos = nfs_dir->nfs_entries; + do + { + ptr = (uint32_t *)&nmp->nm_msgbuffer.readdir.readdir; + reqlen = 0; - /* 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. - */ + /* Copy the variable length, directory file handle */ - tmp = np->n_size - filep->f_pos; - if (buflen > tmp) - { - buflen = tmp; - finfo("Read size truncated to %d\n", buflen); - } + *ptr++ = txdr_unsigned((uint32_t)nfs_dir->nfs_fhsize); + reqlen += sizeof(uint32_t); - /* Now loop until we fill the user buffer (or hit the end of the file) */ + (void)memcpy_s(ptr, nfs_dir->nfs_fhsize, nfs_dir->nfs_fhandle, nfs_dir->nfs_fhsize); + reqlen += (int)nfs_dir->nfs_fhsize; + ptr += uint32_increment((int)nfs_dir->nfs_fhsize); - for (bytesread = 0; bytesread < buflen; ) - { - /* Make sure that the attempted read size does not exceed the RPC maximum */ + /* Cookie and cookie verifier */ - readsize = buflen - bytesread; - if (readsize > nmp->nm_rsize) - { - readsize = nmp->nm_rsize; - } + ptr[0] = cookies[0]; + ptr[1] = cookies[1]; + ptr += 2; + reqlen += 2 * sizeof(uint32_t); - /* Make sure that the attempted read size does not exceed the IO buffer size */ + (void)memcpy_s(ptr, DIRENT_NFS_VERFLEN, nfs_dir->nfs_verifier, DIRENT_NFS_VERFLEN); + ptr += uint32_increment(DIRENT_NFS_VERFLEN); + reqlen += DIRENT_NFS_VERFLEN; - tmp = SIZEOF_rpc_reply_read(readsize); - if (tmp > nmp->nm_buflen) - { - readsize -= (tmp - nmp->nm_buflen); - } + /* Number of directory entries (We currently only process one entry at a time) */ - /* Initialize the request */ + *ptr = txdr_unsigned((uint32_t)nmp->nm_readdirsize); + reqlen += sizeof(uint32_t); - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.read.read; - reqlen = 0; + /* And read the directory */ - /* Copy the variable length, file handle */ + nfs_statistics(NFSPROC_READDIR); + error = nfs_request(nmp, NFSPROC_READDIR, + (void *)&nmp->nm_msgbuffer.readdir, reqlen, + (void *)nmp->nm_iobuffer, nmp->nm_buflen); - *ptr++ = txdr_unsigned((uint32_t)np->n_fhsize); - reqlen += sizeof(uint32_t); + if (error != OK) + { + PRINTK("ERROR: nfs_request failed: %d\n", error); + goto errout_with_mutex; + } - memcpy(ptr, &np->n_fhandle, np->n_fhsize); - reqlen += (int)np->n_fhsize; - ptr += uint32_increment((int)np->n_fhsize); + /* A new group of entries was successfully read. Process the + * information contained in the response header. This information + * includes: + * + * 1) Attributes follow indication - 4 bytes + * 2) Directory attributes - sizeof(struct nfs_fattr) + * 3) Cookie verifier - NFSX_V3COOKIEVERF bytes + * 4) Values follows indication - 4 bytes + */ - /* Copy the file offset */ + ptr = (uint32_t *)&((struct rpc_reply_readdir *)nmp->nm_iobuffer)->readdir; - txdr_hyper((uint64_t)filep->f_pos, ptr); - ptr += 2; - reqlen += 2*sizeof(uint32_t); + /* Check if attributes follow, if 0 so Skip over the attributes */ - /* Set the readsize */ + tmp = *ptr++; + if (tmp != 0) + { + /* Attributes are not currently used */ - *ptr = txdr_unsigned(readsize); - reqlen += sizeof(uint32_t); + ptr += uint32_increment(sizeof(struct nfs_fattr)); + } - /* Perform the read */ + /* Save the verification cookie */ - finfo("Reading %d bytes\n", readsize); - nfs_statistics(NFSPROC_READ); - error = nfs_request(nmp, NFSPROC_READ, - (FAR void *)&nmp->nm_msgbuffer.read, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - if (error) - { - ferr("ERROR: nfs_request failed: %d\n", error); - goto errout_with_mutex; - } + (void)memcpy_s(nfs_dir->nfs_verifier, DIRENT_NFS_VERFLEN, ptr, DIRENT_NFS_VERFLEN); + ptr += uint32_increment(DIRENT_NFS_VERFLEN); - /* The read was successful. Get a pointer to the beginning of the NFS - * response data. - */ + /* Check if values follow. If no values follow, then the EOF indication + * will appear next. + */ - read_response = (struct rpc_reply_read *)nmp->nm_iobuffer; - readsize = fxdr_unsigned(uint32_t, read_response->read.hdr.count); + tmp = *ptr++; + if (tmp == 0) + { + /* No values follow, then the reply should consist only of a 4-byte + * end-of-directory indication. + */ + + tmp = *ptr++; + if (tmp != 0) + { + error = ENOENT; + } + + /* What would it mean if there were not data and we not at the end of + * file? + */ + + else + { + error = EAGAIN; + } + goto errout_with_mutex; + } - /* Copy the read data into the user buffer */ + /* If we are not at the end of the directory listing, then a set of entries + * will follow the header. Each entry is of the form: + * + * File ID (8 bytes) + * Name length (4 bytes) + * Name string (varaiable size but in multiples of 4 bytes) + * Cookie (8 bytes) + * next entry (4 bytes) + */ - if (LOS_CopyFromKernel(buffer, buflen, (const void *)read_response->read.data, readsize) != 0) + do + { + NFS_DIR_ENTRY_MALLOC(entry); + + /* There is an entry. Skip over the file ID and point to the length */ + + entry->file_id[0] = *ptr++; + entry->file_id[1] = *ptr++; /*lint !e662 !e661*/ + + /* Get the length and point to the name */ + + tmp = *ptr++; /*lint !e662 !e661*/ + entry->name_len = fxdr_unsigned(uint32_t, tmp); + entry->contents = (uint8_t *)malloc(entry->name_len + 1); + if (!entry->contents) + { + free(entry); + entry = NULL; + goto errout_with_memory; + } + (void)memset_s(entry->contents, entry->name_len + 1, 0, entry->name_len + 1); + + error = strncpy_s((char *)entry->contents, entry->name_len + 1, (const char *)ptr, entry->name_len); + if (error != EOK) + { + free(entry->contents); + entry->contents = NULL; + free(entry); + entry = NULL; + error = ENOBUFS; + goto errout_with_memory; + } + /* Increment the pointer past the name (allowing for padding). ptr + * now points to the cookie. + */ + + ptr += uint32_increment(entry->name_len); + + /* Save the cookie and increment the pointer to the next entry */ + + entry->cookie[0] = *ptr++; + entry->cookie[1] = *ptr++; + + /* Get the file attributes associated with this name and return + * the file type. + */ + + if (strcmp((char *)entry->contents, ".") == 0 || strcmp((char *)entry->contents, "..") == 0) + { + NFS_DIR_ENTRY_FREE(entry); + continue; + } + + if (!nfs_dir->nfs_entries) + { + entry_pos = entry; + nfs_dir->nfs_entries = entry; + } + else + { + entry_pos->next = entry; + entry_pos = entry; + } + } + while (*ptr++); + if (entry_pos) + { + cookies[0] = entry_pos->cookie[0]; + cookies[1] = entry_pos->cookie[1]; + } + } + while (!(*ptr)); + + if (!nfs_dir->nfs_entries) + { + error = ENOENT; + goto errout_with_mutex; + } + + NFS_DIR_ENTRY_MALLOC(entry); + + /* There is an entry. Skip over the file ID and point to the length */ + + entry->file_id[0] = (uint32_t)EOF; + if (!entry_pos) + { + error = ENOENT; + NFS_DIR_ENTRY_FREE(entry); + goto errout_with_mutex; + } + entry_pos->next = entry; + entry_pos = entry; + } + + entry_pos = nfs_dir->nfs_entries; + if (nfs_dir->nfs_entries->file_id[0] == (uint32_t)EOF) { - error = EINVAL; + error = ENOENT; goto errout_with_mutex; } - /* Update the read state data */ + d_name_size = sizeof(dir->fd_dir[i].d_name); + error = memcpy_s(dir->fd_dir[i].d_name, d_name_size, (const char *)entry_pos->contents, (size_t)entry_pos->name_len); + if (error != EOK) + { + error = ENOBUFS; + goto errout_with_memory; + } + if (entry_pos->name_len >= d_name_size) + { + dir->fd_dir[i].d_name[d_name_size - 1] = '\0'; + } + else + { + dir->fd_dir[i].d_name[entry_pos->name_len] = '\0'; + } - filep->f_pos += readsize; - np->n_fpos += readsize; - bytesread += readsize; - buffer += readsize; + nfs_dir->nfs_entries = entry_pos->next; + NFS_DIR_ENTRY_FREE(entry_pos); - /* Check if we hit the end of file */ + fhandle.length = (uint32_t)nfs_dir->nfs_fhsize; + (void)memcpy_s(&fhandle.handle, DIRENT_NFS_MAXHANDLE, nfs_dir->nfs_fhandle, DIRENT_NFS_MAXHANDLE); - if (read_response->read.hdr.eof != 0) + error = nfs_lookup(nmp, dir->fd_dir[i].d_name, &fhandle, &obj_attributes, NULL); + if (error != OK) + { + PRINTK("ERROR: nfs_lookup failed: %d\n", error); + goto errout_with_memory; + } + + /* Set the dirent file type */ + + tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_type); + switch (tmp) { + default: + case NFNON: /* Unknown type */ + case NFSOCK: /* Socket */ + case NFLNK: /* Symbolic link */ + break; + + case NFREG: /* Regular file */ + dir->fd_dir[i].d_type = DT_REG; + break; + + case NFDIR: /* Directory */ + dir->fd_dir[i].d_type = DT_DIR; + break; + + case NFBLK: /* Block special device file */ + dir->fd_dir[i].d_type = DT_BLK; + break; + + case NFFIFO: /* Named FIFO */ + case NFCHR: /* Character special device file */ + dir->fd_dir[i].d_type = DT_CHR; break; } + dir->fd_position++; + dir->fd_dir[i].d_off = dir->fd_position; + dir->fd_dir[i].d_reclen = (uint16_t)sizeof(struct dirent); + i++; } - - finfo("Read %d bytes\n", bytesread); nfs_mux_release(nmp); - return bytesread; + return i; +errout_with_memory: + for (entry_pos = nfs_dir->nfs_entries; entry_pos != NULL; entry_pos = nfs_dir->nfs_entries) + { + nfs_dir->nfs_entries = entry_pos->next; + NFS_DIR_ENTRY_FREE(entry_pos); + } errout_with_mutex: nfs_mux_release(nmp); + if (error == ENOENT && i > 0) + { + return i; + } return -error; } +extern int nfs_getfilename(char *dstpath, unsigned int dstpathLen, const char *srcpath, unsigned int maxlen); +extern int nfs_rename(struct Vnode *mountpt, const char *oldrelpath, const char *newrelpath); +int vfs_nfs_rename(struct Vnode *from_vnode, struct Vnode *to_parent, + const char *from_name, const char *to_name) +{ + int error; + int reqlen; + int namelen; + uint32_t *ptr = NULL; + struct Vnode *to_vnode = NULL; + struct Vnode *from_parent = from_vnode->parent; + struct nfsmount *nmp = (struct nfsmount *)(to_parent->originMount->data); -/**************************************************************************** - * Name: nfs_write - * - * Returned Value: - * The (non-negative) number of bytes written on success; a negated errno - * value on failure. - * - ****************************************************************************/ + struct nfsnode *from_node = (struct nfsnode *)from_parent->data; + struct nfsnode *to_node = (struct nfsnode *)to_parent->data; -static ssize_t nfs_write(FAR struct file *filep, const char *buffer, - size_t buflen) -{ - struct nfsmount *nmp; - struct nfsnode *np; - loff_t f_pos; - size_t writesize; - size_t bufsize; - size_t byteswritten; - size_t reqlen; - FAR uint32_t *ptr; - uint32_t tmp; - int committed = NFSV3WRITE_UNSTABLE; - int error; - char *temp_buffer; + nfs_mux_take(nmp); + error = nfs_checkmount(nmp); + if (error != OK) + { + PRINTK("ERROR: nfs_checkmount failed: %d\n", error); + goto errout_with_mutex; + } + ptr = (uint32_t *)&nmp->nm_msgbuffer.renamef.rename; + reqlen = 0; - /* Sanity checks */ + /* Copy the variable length, 'from' directory file handle */ - DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + *ptr++ = txdr_unsigned(from_node->n_fhsize); + reqlen += sizeof(uint32_t); - /* Recover our private data from the struct file instance */ + (void)memcpy_s(ptr, from_node->n_fhsize, &from_node->n_fhandle, from_node->n_fhsize); + reqlen += (int)from_node->n_fhsize; + ptr += uint32_increment(from_node->n_fhsize); - nmp = (FAR struct nfsmount *)filep->f_inode->i_private; - np = (FAR struct nfsnode *)filep->f_priv; + /* Copy the variable-length 'from' object name */ - DEBUGASSERT(nmp != NULL); + namelen = strlen(from_name); - /* Make sure that the mount is still healthy */ + *ptr++ = txdr_unsigned(namelen); + reqlen += sizeof(uint32_t); - nfs_mux_take(nmp); - error = nfs_checkmount(nmp); + (void)memcpy_s(ptr, namelen, from_name, namelen); + reqlen += uint32_alignup(namelen); + ptr += uint32_increment(namelen); + + /* Copy the variable length, 'to' directory file handle */ + + *ptr++ = txdr_unsigned(to_node->n_fhsize); + reqlen += sizeof(uint32_t); + + (void)memcpy_s(ptr, to_node->n_fhsize, &to_node->n_fhandle, to_node->n_fhsize); + ptr += uint32_increment(to_node->n_fhsize); + reqlen += (int)to_node->n_fhsize; + + /* Copy the variable-length 'to' object name */ + + namelen = strlen(to_name); + + *ptr++ = txdr_unsigned(namelen); + reqlen += sizeof(uint32_t); + + (void)memcpy_s(ptr, namelen, to_name, namelen); + reqlen += uint32_alignup(namelen); + + /* Perform the RENAME RPC */ + + nfs_statistics(NFSPROC_RENAME); + error = nfs_request(nmp, NFSPROC_RENAME, + (void *)&nmp->nm_msgbuffer.renamef, reqlen, + (void *)nmp->nm_iobuffer, nmp->nm_buflen); if (error != OK) { - ferr("ERROR: nfs_checkmount failed: %d\n", error); + PRINTK("ERROR: nfs_request returned: %d\n", error); goto errout_with_mutex; } - if (filep->f_oflags & O_APPEND) - { - if (nfs_fileupdate(nmp, np, filep->f_relpath) == OK) - { - f_pos = np->n_size; - } - else - { - error = EAGAIN; - goto errout_with_mutex; - } - } - else + error = vfs_nfs_lookup(to_parent, to_name, strlen(to_name), &to_vnode); + if (error != OK) { - f_pos = np->n_fpos; + error = -error; + PRINTK("ERROR: nfs_rename not finish\n"); + goto errout_with_mutex; } + vfs_nfs_reclaim(from_vnode); + from_vnode->data = to_vnode->data; + from_vnode->parent = to_parent; + to_vnode->data = NULL; + VnodeFree(to_vnode); - /* Check if the file size would exceed the range of off_t */ +errout_with_mutex: + nfs_mux_release(nmp); + return -error; +} - if (np->n_size + buflen < np->n_size) - { - error = EFBIG; - goto errout_with_mutex; - } +int vfs_nfs_mkdir(struct Vnode *parent, const char *dirname, mode_t mode, struct Vnode **vpp) +{ + struct nfsmount *nmp = (struct nfsmount *)(parent->originMount->data); + struct nfsnode *parent_nfs_node = (struct nfsnode *)parent->data; + struct nfs_fattr obj_attributes; + struct nfsnode *target_node = NULL; + struct file_handle fhandle; + uint32_t *ptr = NULL; + uint32_t tmp; + int namelen; + int reqlen; + int error; - fvdbg("Write %d bytes to offset %d\n", buflen, np->n_fpos); + /* Sanity checks */ - /* Allocate memory for data */ + DEBUGASSERT(mountpt && mountpt->i_private); - bufsize = (buflen < nmp->nm_wsize) ? buflen : nmp->nm_wsize; - temp_buffer = malloc(bufsize); - if (temp_buffer == NULL) + /* Check if the mount is still healthy */ + + nfs_mux_take(nmp); + error = nfs_checkmount(nmp); + if (error != OK) { - error = ENOMEM; + PRINTK("ERROR: nfs_checkmount: %d\n", error); goto errout_with_mutex; } - /* Now loop until we send the entire user buffer */ + /* Format the MKDIR call message arguments */ - writesize = 0; - for (byteswritten = 0; byteswritten < buflen; ) - { - /* Make sure that the attempted write size does not exceed the RPC - * maximum. - */ + ptr = (uint32_t *)&nmp->nm_msgbuffer.mkdir.mkdir; + reqlen = 0; - writesize = buflen - byteswritten; - if (writesize > nmp->nm_wsize) - { - writesize = nmp->nm_wsize; - } + /* Copy the variable length, directory file handle */ - /* Make sure that the attempted read size does not exceed the IO - * buffer size. - */ + *ptr++ = txdr_unsigned(parent_nfs_node->n_fhsize); + reqlen += sizeof(uint32_t); - bufsize = SIZEOF_rpc_call_write(writesize); - if (bufsize > nmp->nm_buflen) - { - writesize -= (bufsize - nmp->nm_buflen); - } + memcpy_s(ptr, parent_nfs_node->n_fhsize, &(parent_nfs_node->n_fhandle), parent_nfs_node->n_fhsize); + ptr += uint32_increment(parent_nfs_node->n_fhsize); + reqlen += (int)parent_nfs_node->n_fhsize; - /* Copy a chunk of the user data into the temporary buffer */ + /* Copy the variable-length directory name */ - if (LOS_CopyToKernel(temp_buffer, writesize, buffer, writesize) != 0) - { - error = EINVAL; - goto errout_with_memfree; + namelen = strlen(dirname); + + *ptr++ = txdr_unsigned(namelen); + reqlen += sizeof(uint32_t); + + (void)memcpy_s(ptr, namelen, dirname, namelen); + ptr += uint32_increment(namelen); + reqlen += uint32_alignup(namelen); + + /* Set the mode. NOTE: Here we depend on the fact that the NuttX and NFS + * bit settings are the same (at least for the bits of interest). + */ + + *ptr++ = nfs_true; /* True: mode value follows */ + reqlen += sizeof(uint32_t); + + if (!mode) + { + mode = (NFSMODE_IXOTH | NFSMODE_IROTH | + NFSMODE_IXGRP | NFSMODE_IRGRP | + NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR); + } + tmp = mode & (NFSMODE_IXOTH | NFSMODE_IWOTH | NFSMODE_IROTH | + NFSMODE_IXGRP | NFSMODE_IWGRP | NFSMODE_IRGRP | + NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR); + *ptr++ = txdr_unsigned(tmp); + reqlen += sizeof(uint32_t); + + /* Set the user ID to zero */ + + *ptr++ = nfs_true; /* True: Uid value follows */ + *ptr++ = 0; /* UID = 0 (nobody) */ + reqlen += 2*sizeof(uint32_t); + + /* Set the group ID to one */ + + *ptr++ = nfs_true; /* True: Gid value follows */ + *ptr++ = htonl(1); /* GID = 1 (nogroup) */ + reqlen += 2*sizeof(uint32_t); + + /* No size */ + + *ptr++ = nfs_false; /* False: No size value follows */ + reqlen += sizeof(uint32_t); + + /* Don't change times */ + + *ptr++ = htonl(NFSV3SATTRTIME_DONTCHANGE); /* Don't change atime */ + *ptr++ = htonl(NFSV3SATTRTIME_DONTCHANGE); /* Don't change mtime */ + reqlen += 2*sizeof(uint32_t); + + /* Perform the MKDIR RPC */ + + nfs_statistics(NFSPROC_MKDIR); + error = nfs_request(nmp, NFSPROC_MKDIR, + (void *)&nmp->nm_msgbuffer.mkdir, reqlen, + (void *)nmp->nm_iobuffer, nmp->nm_buflen); + if (error) + { + PRINTK("ERROR: nfs_request failed: %d\n", error); + goto errout_with_mutex; + } + + fhandle.length = parent_nfs_node->n_fhsize; + memcpy_s(&(fhandle.handle), DIRENT_NFS_MAXHANDLE, &(parent_nfs_node->n_fhandle), fhandle.length); + error = nfs_lookup(nmp, dirname, &fhandle, &obj_attributes, NULL); + if (error) + { + error = ENOENT; + goto errout_with_mutex; + } + + /* Initialize the file private data. + * + * Copy the file handle. + */ + target_node = zalloc(sizeof(struct nfsnode)); + target_node->n_fhsize = (uint8_t)fhandle.length; + memcpy_s(&(target_node->n_fhandle), target_node->n_fhsize, &(fhandle.handle), fhandle.length); + target_node->n_name = zalloc(sizeof (dirname)); + memcpy_s(target_node->n_name, sizeof(dirname), dirname, sizeof (dirname)); + + /* Save the file attributes */ + nfs_attrupdate(target_node, &obj_attributes); + (void)VnodeAlloc(&nfs_vops, vpp); + (*vpp)->parent = parent; + (*vpp)->fop = &nfs_fops; + (*vpp)->originMount = parent->originMount; + (*vpp)->data = target_node; + (*vpp)->type = filetype_to_vnodetype(target_node->n_type); + (*vpp)->mode = type_to_mode((*vpp)->type, nmp->nm_permission); + (*vpp)->gid = nmp->nm_gid; + (*vpp)->uid = nmp->nm_uid; + +errout_with_mutex: + nfs_mux_release(nmp); + return -error; +} + +int vfs_nfs_write(struct file *filep, const char *buffer, size_t buflen) +{ + struct nfsmount *nmp; + struct nfsnode *np; + loff_t f_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; + + struct Vnode *node = filep->f_vnode; + nmp = (struct nfsmount *)(node->originMount->data); + + np = (struct nfsnode *)node->data; + + DEBUGASSERT(nmp != NULL); + + /* Make sure that the mount is still healthy */ + + nfs_mux_take(nmp); + error = nfs_checkmount(nmp); + if (error != OK) + { + PRINTK("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); + + if (filep->f_oflags & O_APPEND) + { + if (nfs_fileupdate(nmp, np->n_name, &parent_fhandle, np) == OK) + { + f_pos = np->n_size; + } + else + { + error = EAGAIN; + goto errout_with_mutex; + } + } + else + { + f_pos = filep->f_pos; + } + + /* 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; + } + + /* 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 @@ -1186,8 +1629,8 @@ static ssize_t nfs_write(FAR struct file *filep, const char *buffer, * RPC calls in that the entry RPC calls messasge lies in the I/O buffer */ - ptr = (FAR uint32_t *)&((FAR struct rpc_call_write *) - nmp->nm_iobuffer)->write; + ptr = (uint32_t *)&((struct rpc_call_write *) + nmp->nm_iobuffer)->write; reqlen = 0; /* Copy the variable length, file handle */ @@ -1195,7 +1638,7 @@ static ssize_t nfs_write(FAR struct file *filep, const char *buffer, *ptr++ = txdr_unsigned((uint32_t)np->n_fhsize); reqlen += sizeof(uint32_t); - memcpy(ptr, &np->n_fhandle, np->n_fhsize); + (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); @@ -1227,18 +1670,17 @@ static ssize_t nfs_write(FAR struct file *filep, const char *buffer, nfs_statistics(NFSPROC_WRITE); error = nfs_request(nmp, NFSPROC_WRITE, - (FAR void *)nmp->nm_iobuffer, reqlen, - (FAR void *)&nmp->nm_msgbuffer.write, - sizeof(struct rpc_reply_write)); + (void *)nmp->nm_iobuffer, reqlen, + (void *)&nmp->nm_msgbuffer.write, + sizeof(struct rpc_reply_write)); if (error) { - ferr("ERROR: nfs_request failed: %d\n", error); goto errout_with_memfree; } /* Get a pointer to the WRITE reply data */ - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.write.write; + ptr = (uint32_t *)&nmp->nm_msgbuffer.write.write; /* Parse file_wcc. First, check if WCC attributes follow. */ @@ -1257,7 +1699,7 @@ static ssize_t nfs_write(FAR struct file *filep, const char *buffer, { /* Yes.. Update the cached file status in the file structure. */ - nfs_attrupdate(np, (FAR struct nfs_fattr *)ptr); + nfs_attrupdate(np, (struct nfs_fattr *)ptr); ptr += uint32_increment(sizeof(struct nfs_fattr)); } @@ -1285,7 +1727,7 @@ static ssize_t nfs_write(FAR struct file *filep, const char *buffer, } byteswritten += writesize; buffer += writesize; - } + } free(temp_buffer); nfs_mux_release(nmp); @@ -1297,122 +1739,25 @@ errout_with_mutex: return -error; } - -static off_t nfs_seek(FAR struct file *filep, off_t offset, int whence) +off_t vfs_nfs_seek(struct file *filep, off_t offset, int whence) { - FAR struct nfsmount *nmp; - FAR struct nfsnode *np; + struct Vnode *node = filep->f_vnode; + struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data); + struct nfsnode *np = (struct nfsnode *)node->data; int error; off_t position; - fvdbg("Seek started, offset %d whence %d current file pos %lld\n", offset, whence, filep->f_pos); - - /* Sanity checks */ - - DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); - - /* Recover our private data from the struct file instance */ - - nmp = (FAR struct nfsmount *)filep->f_inode->i_private; - np = (FAR struct nfsnode *)filep->f_priv; - - DEBUGASSERT(nmp != NULL); - /* Make sure that the mount is still healthy */ nfs_mux_take(nmp); error = nfs_checkmount(nmp); if (error != OK) { - fdbg("nfs_checkmount failed: %d\n", error); - goto errout_with_mutex; - } - - - filep->f_pos = np->n_fpos; - switch (whence) - { - case SEEK_SET: /* The offset is set to offset bytes. */ - position = offset; - break; - - case SEEK_CUR: /* The offset is set to its current location plus offset bytes. */ - position = offset + (off_t)np->n_fpos; - break; - - case SEEK_END: /* The offset is set to the size of the file plus offset bytes. */ - position = offset + np->n_size; - break; - - default: - error = EINVAL; + PRINTK("nfs_checkmount failed: %d\n", error); goto errout_with_mutex; } - /* Attempts to set the position beyound the end of file will - * work if the file is open for write access. - */ - - if ((position > (off_t)np->n_size) && ((np->n_oflags & O_WRONLY) == 0) && - ((np->n_oflags & O_RDWR) == 0)) - { - position = np->n_size; - } - - /* position less than 0 should be reset to 0 */ - - if (position < 0) - { - position = 0; - } - - np->n_fpos = (loff_t)position; - filep->f_pos = np->n_fpos; - if (position > (off_t)np->n_size) - { - np->n_size = (loff_t)position; - } - - fvdbg("Seek finished, offset %d whence %d current file pos %lld\n", offset, whence, filep->f_pos); - nfs_mux_release(nmp); - return (off_t)filep->f_pos; - -errout_with_mutex: - nfs_mux_release(nmp); - return -error; -} - -static loff_t nfs_seek64(FAR struct file *filep, loff_t offset, int whence) -{ - FAR struct nfsmount *nmp; - FAR struct nfsnode *np; - int error; - loff_t position; - - fvdbg("Seek started, offset %d whence %d current file pos %d\n", offset, whence, filep->f_pos); - - /* Sanity checks */ - - DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); - - /* Recover our private data from the struct file instance */ - - nmp = (FAR struct nfsmount *)filep->f_inode->i_private; - np = (FAR struct nfsnode *)filep->f_priv; - - DEBUGASSERT(nmp != NULL); - - /* Make sure that the mount is still healthy */ - nfs_mux_take(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - fdbg("nfs_checkmount failed: %d\n", error); - goto errout_with_mutex; - } - - filep->f_pos = np->n_fpos; switch (whence) { case SEEK_SET: /* The offset is set to offset bytes. */ @@ -1420,7 +1765,7 @@ static loff_t nfs_seek64(FAR struct file *filep, loff_t offset, int whence) break; case SEEK_CUR: /* The offset is set to its current location plus offset bytes. */ - position = offset + np->n_fpos; + position = offset + filep->f_pos; break; case SEEK_END: /* The offset is set to the size of the file plus offset bytes. */ @@ -1438,1435 +1783,232 @@ static loff_t nfs_seek64(FAR struct file *filep, loff_t offset, int whence) if ((position > (off_t)np->n_size) && ((np->n_oflags & O_WRONLY) == 0) && ((np->n_oflags & O_RDWR) == 0)) - { - position = np->n_size; - } - - /* position less than 0 should be reset to 0 */ - - if (position < 0) - { - position = 0; - } - - np->n_fpos = position; - filep->f_pos = np->n_fpos; - if (position > (loff_t)np->n_size) - { - np->n_size = (uint64_t)position; - } - - fvdbg("Seek finished, offset %d whence %d current file pos %d\n", offset, whence, filep->f_pos); - nfs_mux_release(nmp); - return filep->f_pos; - -errout_with_mutex: - nfs_mux_release(nmp); - return -error; -} - -/**************************************************************************** - * Name: nfs_dup - * - * Description: - * Duplicate open file data in the new file structure. - * - ****************************************************************************/ - -static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp) -{ - struct nfsmount *nmp; - FAR struct nfsnode *np; - int error; - - finfo("Dup %p->%p\n", oldp, newp); - - /* Sanity checks */ - - DEBUGASSERT(oldp->f_priv != NULL && oldp->f_inode != NULL); - - /* Recover our private data from the struct file instance */ - - nmp = (FAR struct nfsmount *)oldp->f_inode->i_private; - np = (FAR struct nfsnode *)oldp->f_priv; - - DEBUGASSERT(nmp != NULL); - - /* Check if the mount is still healthy */ - - nfs_mux_take(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - ferr("ERROR: nfs_checkmount failed: %d\n", error); - nfs_mux_release(nmp); - return -error; - } - - /* Increment the reference count on the NFS node structure */ - - DEBUGASSERT(np->n_crefs < 0xff); - np->n_crefs++; - - /* And save this as the file data for the new node */ - - newp->f_priv = np; - - nfs_mux_release(nmp); - return OK; -} - -/**************************************************************************** - * Name: nfs_opendir - * - * Description: - * Open a directory for read access - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_opendir(struct inode *mountpt, const char *relpath, - struct fs_dirent_s *dir) -{ - struct nfsmount *nmp; - struct file_handle fhandle; - struct nfs_fattr obj_attributes; - struct nfsdir_s *nfs_dir; - uint32_t objtype; - int error; - - finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL"); - - /* Sanity checks */ - - DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL && dir); - - /* Recover our private data from the inode instance */ - - nmp = mountpt->i_private; - - /* Make sure that the mount is still healthy */ - - nfs_mux_take(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - ferr("ERROR: nfs_checkmount failed: %d\n", error); - goto errout_with_mutex; - } - - /* Find the NFS node associate with the path */ - - error = nfs_findnode(nmp, relpath, &fhandle, &obj_attributes, NULL); - if (error != OK) - { - ferr("ERROR: nfs_findnode failed: %d\n", error); - goto errout_with_mutex; - } - - /* The entry is a directory */ - - objtype = fxdr_unsigned(uint32_t, obj_attributes.fa_type); - if (objtype != NFDIR) - { - ferr("ERROR: Not a directory, type=%d\n", objtype); - error = ENOTDIR; - goto errout_with_mutex; - } - - /* Save the directory information in struct fs_dirent_s so that it can be - * used later when readdir() is called. - */ - - nfs_dir = (struct nfsdir_s *)malloc(sizeof(struct nfsdir_s)); - if (!nfs_dir) - { - error = ENOMEM; - goto errout_with_mutex; - } - - nfs_dir->nfs_fhsize = (uint8_t)fhandle.length; - nfs_dir->nfs_cookie[0] = 0; - nfs_dir->nfs_cookie[1] = 0; - - DEBUGASSERT(fhandle.length <= DIRENT_NFS_MAXHANDLE); - (void)memcpy_s(nfs_dir->nfs_fhandle, DIRENT_NFS_MAXHANDLE, &fhandle.handle, DIRENT_NFS_MAXHANDLE); - - dir->u.fs_dir = (fs_dir_s)nfs_dir; - error = OK; - - nfs_dir->nfs_next = nmp->nm_dir; - nmp->nm_dir = nfs_dir; - nfs_dir->nfs_dir = dir; - nfs_dir->nfs_entries = NULL; - -errout_with_mutex: - nfs_mux_release(nmp); - return -error; -} - -static int nfs_closedir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir) -{ - struct nfsmount *nmp; - FAR struct nfsdir_s *prev; - FAR struct nfsdir_s *curr; - struct nfsdir_s *nfs_dir; - struct entry3 *entry_pos; - int ret; - - /* Sanity checks */ - - DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL && dir); - - /* Recover our private data from the inode instance */ - - nmp = (struct nfsmount *)mountpt->i_private; - - nfs_dir = (struct nfsdir_s *)(dir->u.fs_dir); - - DEBUGASSERT(nmp != NULL); - - /* Get exclusive access to the mount structure. */ - - nfs_mux_take(nmp); - - for (entry_pos = nfs_dir->nfs_entries; entry_pos != NULL; entry_pos = nfs_dir->nfs_entries) - { - nfs_dir->nfs_entries = entry_pos->next; - NFS_DIR_ENTRY_FREE(entry_pos); - } - - /* Assume file structure will not be found. This should never happen. */ - - ret = -EINVAL; - - for (prev = (struct nfsdir_s *)NULL, curr = nmp->nm_dir; - curr; - prev = curr, curr = curr->nfs_next) - { - /* Check if this node is ours */ - - if (nfs_dir == curr) - { - /* Yes.. remove it from the list of file structures */ - - if (prev) - { - /* Remove from mid-list */ - - prev->nfs_next = nfs_dir->nfs_next; - } - else - { - /* Remove from the head of the list */ - - nmp->nm_dir= nfs_dir->nfs_next; - } - - /* Then deallocate the file structure and return success */ - - free(nfs_dir); - nfs_dir = NULL; - ret = OK; - break; - } - } - nfs_mux_release(nmp); - - return ret; /*lint !e438*/ -} - -/**************************************************************************** - * Name: nfs_readdir - * - * Description: Read from directory - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) -{ - struct nfsmount *nmp; - struct file_handle fhandle; - struct nfs_fattr obj_attributes; - struct nfsdir_s *nfs_dir; - struct entry3 *entry; - struct entry3 *entry_pos; - - /* Use 2 cookies */ - - uint32_t cookies[2]; - uint32_t tmp; - uint32_t *ptr; - size_t d_name_size; - int reqlen; - int error = 0; - finfo("Entry\n"); - - /* Sanity checks */ - - DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); - - /* Recover our private data from the inode instance */ - - nmp = mountpt->i_private; - - /* Make sure that the mount is still healthy */ - - nfs_mux_take(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - ferr("ERROR: nfs_checkmount failed: %d\n", error); - goto errout_with_mutex; - } - - /* Request a block directory entries, copying directory information from - * the dirent structure. - */ - - nfs_dir = (struct nfsdir_s *)dir->u.fs_dir; - cookies[0] = 0; - cookies[1] = 0; - - if (!nfs_dir->nfs_entries) - { - entry_pos = nfs_dir->nfs_entries; - do - { - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.readdir.readdir; - reqlen = 0; - - /* Copy the variable length, directory file handle */ - - *ptr++ = txdr_unsigned((uint32_t)nfs_dir->nfs_fhsize); - reqlen += sizeof(uint32_t); - - (void)memcpy_s(ptr, nfs_dir->nfs_fhsize, nfs_dir->nfs_fhandle, nfs_dir->nfs_fhsize); - reqlen += (int)nfs_dir->nfs_fhsize; - ptr += uint32_increment((int)nfs_dir->nfs_fhsize); - - /* Cookie and cookie verifier */ - - ptr[0] = cookies[0]; - ptr[1] = cookies[1]; - ptr += 2; - reqlen += 2 * sizeof(uint32_t); - - (void)memcpy_s(ptr, DIRENT_NFS_VERFLEN, nfs_dir->nfs_verifier, DIRENT_NFS_VERFLEN); - ptr += uint32_increment(DIRENT_NFS_VERFLEN); - reqlen += DIRENT_NFS_VERFLEN; - - /* Number of directory entries (We currently only process one entry at a time) */ - - *ptr = txdr_unsigned((uint32_t)nmp->nm_readdirsize); - reqlen += sizeof(uint32_t); - - /* And read the directory */ - - nfs_statistics(NFSPROC_READDIR); - error = nfs_request(nmp, NFSPROC_READDIR, - (FAR void *)&nmp->nm_msgbuffer.readdir, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - if (error != OK) - { - fdbg("ERROR: nfs_request failed: %d\n", error); - goto errout_with_mutex; - } - - /* A new group of entries was successfully read. Process the - * information contained in the response header. This information - * includes: - * - * 1) Attributes follow indication - 4 bytes - * 2) Directory attributes - sizeof(struct nfs_fattr) - * 3) Cookie verifier - NFSX_V3COOKIEVERF bytes - * 4) Values follows indication - 4 bytes - */ - - ptr = (uint32_t *)&((FAR struct rpc_reply_readdir *)nmp->nm_iobuffer)->readdir; - - /* Check if attributes follow, if 0 so Skip over the attributes */ - - tmp = *ptr++; - if (tmp != 0) - { - /* Attributes are not currently used */ - - ptr += uint32_increment(sizeof(struct nfs_fattr)); - } - - - /* Save the verification cookie */ - - (void)memcpy_s(nfs_dir->nfs_verifier, DIRENT_NFS_VERFLEN, ptr, DIRENT_NFS_VERFLEN); - ptr += uint32_increment(DIRENT_NFS_VERFLEN); - - /* Check if values follow. If no values follow, then the EOF indication - * will appear next. - */ - - tmp = *ptr++; - if (tmp == 0) - { - /* No values follow, then the reply should consist only of a 4-byte - * end-of-directory indication. - */ - - tmp = *ptr++; - if (tmp != 0) - { - fvdbg("End of directory\n"); - error = ENOENT; - } - - /* What would it mean if there were not data and we not at the end of - * file? - */ - - else - { - fvdbg("No data but not end of directory?\n"); - error = EAGAIN; - } - - goto errout_with_mutex; - } - - - /* If we are not at the end of the directory listing, then a set of entries - * will follow the header. Each entry is of the form: - * - * File ID (8 bytes) - * Name length (4 bytes) - * Name string (varaiable size but in multiples of 4 bytes) - * Cookie (8 bytes) - * next entry (4 bytes) - */ - - do - { - NFS_DIR_ENTRY_MALLOC(entry); - - /* There is an entry. Skip over the file ID and point to the length */ - - entry->file_id[0] = *ptr++; - entry->file_id[1] = *ptr++; /*lint !e662 !e661*/ - - - /* Get the length and point to the name */ - - tmp = *ptr++; /*lint !e662 !e661*/ - entry->name_len = fxdr_unsigned(uint32_t, tmp); - entry->contents = (uint8_t *)malloc(entry->name_len + 1); - if (!entry->contents) - { - free(entry); - entry = NULL; - goto errout_with_memory; - } - (void)memset_s(entry->contents, entry->name_len + 1, 0, entry->name_len + 1); - - error = strncpy_s((char *)entry->contents, entry->name_len + 1, (const char *)ptr, entry->name_len); - if (error != EOK) - { - free(entry->contents); - entry->contents = NULL; - free(entry); - entry = NULL; - error = ENOBUFS; - goto errout_with_memory; - } - /* Increment the pointer past the name (allowing for padding). ptr - * now points to the cookie. - */ - - ptr += uint32_increment(entry->name_len); - - /* Save the cookie and increment the pointer to the next entry */ - - entry->cookie[0] = *ptr++; - entry->cookie[1] = *ptr++; - - /* Get the file attributes associated with this name and return - * the file type. - */ - - if (strcmp((char *)entry->contents, ".") == 0 || strcmp((char *)entry->contents, "..") == 0) - { - NFS_DIR_ENTRY_FREE(entry); - continue; - } - - if (!nfs_dir->nfs_entries) - { - entry_pos = entry; - nfs_dir->nfs_entries = entry; - } - else - { - entry_pos->next = entry; - entry_pos = entry; - } - } - while (*ptr++); - if (entry_pos) - { - cookies[0] = entry_pos->cookie[0]; - cookies[1] = entry_pos->cookie[1]; - } - - } - while (!(*ptr)); - - fvdbg("End of directory\n"); - if (!nfs_dir->nfs_entries) - { - error = ENOENT; - goto errout_with_mutex; - } - - NFS_DIR_ENTRY_MALLOC(entry); - - /* There is an entry. Skip over the file ID and point to the length */ - - entry->file_id[0] = (uint32_t)EOF; - if (!entry_pos) - { - error = ENOENT; - NFS_DIR_ENTRY_FREE(entry); - goto errout_with_mutex; - } - entry_pos->next = entry; - entry_pos = entry; - } - - entry_pos = nfs_dir->nfs_entries; - if (nfs_dir->nfs_entries->file_id[0] == (uint32_t)EOF) - { - fvdbg("End of directory\n"); - error = ENOENT; - free(nfs_dir->nfs_entries); - nfs_dir->nfs_entries = NULL; - goto errout_with_mutex; - } - - d_name_size = sizeof(dir->fd_dir[0].d_name); - error = memcpy_s(dir->fd_dir[0].d_name, d_name_size, (const char *)entry_pos->contents, (size_t)entry_pos->name_len); - if (error != EOK) - { - error = ENOBUFS; - goto errout_with_memory; - } - if (entry_pos->name_len >= d_name_size) - { - dir->fd_dir[0].d_name[d_name_size - 1] = '\0'; - } - else - { - dir->fd_dir[0].d_name[entry_pos->name_len] = '\0'; - } - - nfs_dir->nfs_entries = entry_pos->next; - NFS_DIR_ENTRY_FREE(entry_pos); - - fvdbg("name: \"%s\"\n", dir->fd_dir[0].d_name); - fhandle.length = (uint32_t)nfs_dir->nfs_fhsize; - (void)memcpy_s(&fhandle.handle, DIRENT_NFS_MAXHANDLE, nfs_dir->nfs_fhandle, DIRENT_NFS_MAXHANDLE); - - error = nfs_lookup(nmp, dir->fd_dir[0].d_name, &fhandle, &obj_attributes, NULL); - if (error != OK) - { - ferr("ERROR: nfs_lookup failed: %d\n", error); - goto errout_with_memory; - } - - /* Set the dirent file type */ - - tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_type); - switch (tmp) - { - default: - case NFNON: /* Unknown type */ - case NFSOCK: /* Socket */ - case NFLNK: /* Symbolic link */ - break; - - case NFREG: /* Regular file */ - dir->fd_dir[0].d_type = DT_REG; - break; - - case NFDIR: /* Directory */ - dir->fd_dir[0].d_type = DT_DIR; - break; - - case NFBLK: /* Block special device file */ - dir->fd_dir[0].d_type = DT_BLK; - break; - - case NFFIFO: /* Named FIFO */ - case NFCHR: /* Character special device file */ - dir->fd_dir[0].d_type = DT_CHR; - break; - } - finfo("type: %d->%d\n", (int)tmp, dir->fd_dir[0].d_type); - - dir->fd_position++; - dir->fd_dir[0].d_off = dir->fd_position; - dir->fd_dir[0].d_reclen = (uint16_t)sizeof(struct dirent); - nfs_mux_release(nmp); - return 1; - -errout_with_memory: - for (entry_pos = nfs_dir->nfs_entries; entry_pos != NULL; entry_pos = nfs_dir->nfs_entries) - { - nfs_dir->nfs_entries = entry_pos->next; - NFS_DIR_ENTRY_FREE(entry_pos); - } -errout_with_mutex: - nfs_mux_release(nmp); - return -error; -} - -/**************************************************************************** - * Name: nfs_rewinddir - * - * Description: - * Reset the directory traveral logic to the first entry in the open - * directory. - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir) -{ - struct nfsmount *nmp; - struct nfsdir_s *nfs_dir; - struct entry3 *entry_pos; - finfo("Entry\n"); - - /* Sanity checks */ - - DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL && dir != NULL); - - nmp = (struct nfsmount *)mountpt->i_private; - nfs_mux_take(nmp); - - /* Reset the NFS-specific portions of dirent structure, retaining only the - * file handle. - */ - - nfs_dir = (struct nfsdir_s *)dir->u.fs_dir; - (void)memset_s(nfs_dir->nfs_verifier, DIRENT_NFS_VERFLEN, 0, DIRENT_NFS_VERFLEN); - nfs_dir->nfs_cookie[0] = 0; - nfs_dir->nfs_cookie[1] = 0; - for (entry_pos = nfs_dir->nfs_entries; entry_pos != NULL; entry_pos = nfs_dir->nfs_entries) - { - nfs_dir->nfs_entries = entry_pos->next; - NFS_DIR_ENTRY_FREE(entry_pos); - } - nfs_mux_release(nmp); - return OK; -} - -/**************************************************************************** - * Name: nfs_decode_args - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void nfs_decode_args(FAR struct nfs_mount_parameters *nprmt, - FAR struct nfs_args *argp) -{ - int maxio; - - /* Get the selected timeout value */ - - if ((argp->flags & NFSMNT_TIMEO) != 0 && argp->timeo > 0) - { - uint32_t tmp = ((uint32_t)argp->timeo * NFS_HZ + 5) / 10; - if (tmp < NFS_MINTIMEO) - { - tmp = NFS_MINTIMEO; - } - else if (tmp > NFS_MAXTIMEO) - { - tmp = NFS_MAXTIMEO; - } - - nprmt->timeo = tmp; - } - - /* Get the selected retransmission count */ - - if ((argp->flags & NFSMNT_RETRANS) != 0 && argp->retrans > 1) - { - if (argp->retrans < NFS_MAXREXMIT) - { - nprmt->retry = argp->retrans; - } - else - { - nprmt->retry = NFS_MAXREXMIT; - } - } - - if ((argp->flags & NFSMNT_SOFT) == 0) - { - nprmt->retry = NFS_MAXREXMIT + 1; /* Past clip limit */ - } - - /* Get the maximum amount of data that can be transferred in one packet */ - - if ((argp->sotype == SOCK_DGRAM) != 0) - { - maxio = NFS_MAXDGRAMDATA; - } - else - { - ferr("ERROR: Only SOCK_DRAM is supported\n"); - maxio = NFS_MAXDATA; - } - - /* Get the maximum amount of data that can be transferred in one write transfer */ - - if ((argp->flags & NFSMNT_WSIZE) != 0 && argp->wsize > 0) - { - nprmt->wsize = argp->wsize; - - /* Round down to multiple of blocksize */ - - nprmt->wsize &= ~(NFS_FABLKSIZE - 1); - if (nprmt->wsize <= 0) - { - nprmt->wsize = NFS_FABLKSIZE; - } - } - - if (nprmt->wsize > maxio) - { - nprmt->wsize = maxio; - } - - if (nprmt->wsize > MAXBSIZE) - { - nprmt->wsize = MAXBSIZE; - } - - /* Get the maximum amount of data that can be transferred in one read transfer */ - - if ((argp->flags & NFSMNT_RSIZE) != 0 && argp->rsize > 0) - { - nprmt->rsize = argp->rsize; - - /* Round down to multiple of blocksize */ - - nprmt->rsize &= ~(NFS_FABLKSIZE - 1); - if (nprmt->rsize <= 0) - { - nprmt->rsize = NFS_FABLKSIZE; - } - } - - if (nprmt->rsize > maxio) - { - nprmt->rsize = maxio; - } - - if (nprmt->rsize > MAXBSIZE) - { - nprmt->rsize = MAXBSIZE; - } - - /* Get the maximum amount of data that can be transferred in directory transfer */ - - if ((argp->flags & NFSMNT_READDIRSIZE) != 0 && argp->readdirsize > 0) - { - nprmt->readdirsize = argp->readdirsize; - - /* Round down to multiple of blocksize */ - - nprmt->readdirsize &= ~(NFS_DIRBLKSIZ - 1); - if (nprmt->readdirsize < NFS_DIRBLKSIZ) - { - nprmt->readdirsize = NFS_DIRBLKSIZ; - } - } - else if (argp->flags & NFSMNT_RSIZE) - { - nprmt->readdirsize = nprmt->rsize; - } - - if (nprmt->readdirsize > maxio) - { - nprmt->readdirsize = maxio; - } -} - -/**************************************************************************** - * Name: nfs_bind - * - * Description: - * This implements a portion of the mount operation. This function allocates - * and initializes the mountpoint private data and gets mount information - * from the NFS server. The final binding of the private data (containing - * NFS server mount information) to the mountpoint is performed by mount(). - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_bind(FAR struct inode *blkdriver, FAR const void *data, - FAR void **handle, FAR const char *relpath) -{ - FAR struct nfs_args *argp = (FAR struct nfs_args *)data; - FAR struct nfsmount *nmp; - struct rpcclnt *rpc; - struct rpc_call_fs getattr; - struct rpc_reply_getattr resok; - struct nfs_mount_parameters nprmt; - uint32_t buflen; - uint32_t pathlen; - uint32_t tmp; - int error = 0; - pthread_mutexattr_t attr; - - DEBUGASSERT(data && handle); - - /* Set default values of the parameters. These may be overridden by - * settings in the argp->flags. - */ - - nprmt.timeo = NFS_TIMEO; - nprmt.retry = NFS_RETRANS; - nprmt.wsize = NFS_WSIZE; - nprmt.rsize = NFS_RSIZE; - nprmt.readdirsize = NFS_READDIRSIZE; - - nfs_decode_args(&nprmt, argp); - - /* Determine the size of a buffer that will hold one RPC data transfer. - * First, get the maximum size of a read and a write transfer. - */ - - pathlen = strlen(argp->path); - if (pathlen >= NFS_MOUNT_PATH_MAX_SIZE) { - return -ENAMETOOLONG; - } - - buflen = SIZEOF_rpc_call_write(nprmt.wsize); - tmp = SIZEOF_rpc_reply_read(nprmt.rsize); - - /* The buffer size will be the maximum of those two sizes */ - - if (tmp > buflen) - { - buflen = tmp; - } - - /* But don't let the buffer size exceed the MSS of the socket type. - * - * In the case where there are multiple network devices with different - * link layer protocols, each network device may support a different - * UDP MSS value. Here we arbitrarily select the minimum MSS for - * that case. - */ - - /* Create an instance of the mountpt state structure */ - - nmp = (FAR struct nfsmount *)malloc(SIZEOF_nfsmount(buflen)); - if (!nmp) - { - ferr("ERROR: Failed to allocate mountpoint structure\n"); - return -ENOMEM; - } - - (void)memset_s(nmp, SIZEOF_nfsmount(buflen), 0, SIZEOF_nfsmount(buflen)); - - /* Save the allocated I/O buffer size */ - - nmp->nm_buflen = (uint16_t)buflen; - - nmp->nm_so = -1; - - /* Initialize the allocated mountpt state structure. */ - - (void)pthread_mutexattr_init(&attr); - (void)pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - error = pthread_mutex_init(&nmp->nm_mux, &attr); - if (error) - { - return -error; - } - - /* Initialize NFS */ - - nfs_true = txdr_unsigned(TRUE); - nfs_false = txdr_unsigned(FALSE); - nfs_xdrneg1 = txdr_unsigned(-1); - - rpcclnt_init(); - - /* Set initial values of other fields */ - - nmp->nm_timeo = nprmt.timeo; - nmp->nm_retry = nprmt.retry; - nmp->nm_wsize = nprmt.wsize; - nmp->nm_rsize = nprmt.rsize; - nmp->nm_readdirsize = nprmt.readdirsize; - nmp->nm_fhsize = NFSX_V3FHMAX; - - (void)strncpy_s(nmp->nm_path, sizeof(nmp->nm_path), argp->path, pathlen); - (void)memcpy_s(&nmp->nm_nam, sizeof(struct sockaddr), &argp->addr, argp->addrlen); - - /* Set up the sockets and per-host congestion */ - - nmp->nm_sotype = argp->sotype; - - if (nmp->nm_sotype == SOCK_DGRAM || nmp->nm_sotype == SOCK_STREAM) - { - /* Connection-less... connect now */ - - /* Create an instance of the rpc state structure */ - - rpc = (struct rpcclnt *)malloc(sizeof(struct rpcclnt)); - if (!rpc) - { - ferr("ERROR: Failed to allocate rpc structure\n"); - error = ENOMEM; - goto bad; - } - - (void)memset_s(rpc, sizeof(struct rpcclnt), 0, sizeof(struct rpcclnt)); - - finfo("Connecting\n"); - - /* Translate nfsmnt flags -> rpcclnt flags */ - - rpc->rc_path = nmp->nm_path; - rpc->rc_name = &nmp->nm_nam; - rpc->rc_sotype = nmp->nm_sotype; - rpc->rc_retry = nmp->nm_retry; - rpc->rc_so = -1; - - nmp->nm_rpcclnt = rpc; - - error = rpcclnt_connect(nmp->nm_rpcclnt); - if (error != OK) - { - ferr("ERROR: nfs_connect failed: %d\n", error); - goto bad; - } - } - - nmp->nm_mounted = true; - nmp->nm_so = nmp->nm_rpcclnt->rc_so; - nmp->nm_head = NULL; - nmp->nm_dir = NULL; - nmp->nm_fhsize = nmp->nm_rpcclnt->rc_fhsize; - memcpy(&nmp->nm_fh, &nmp->nm_rpcclnt->rc_fh, sizeof(nfsfh_t)); - - /* Get the file attributes */ - - getattr.fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize); - memcpy(&getattr.fs.fsroot.handle, &nmp->nm_fh, sizeof(nfsfh_t)); - - error = nfs_request(nmp, NFSPROC_GETATTR, - (FAR void *)&getattr, /* sizeof(struct FS3args) */ - (sizeof(getattr.fs.fsroot.length) + nmp->nm_fhsize), - (FAR void *)&resok, sizeof(struct rpc_reply_getattr)); - if (error) - { - ferr("ERROR: nfs_request failed: %d\n", error); - goto bad; - } - - /* Save the file attributes */ - - memcpy(&nmp->nm_fattr, &resok.attr, sizeof(struct nfs_fattr)); - - /* Mounted! */ - - *handle = (FAR void *)nmp; - nfs_mux_release(nmp); - - finfo("Successfully mounted\n"); - return OK; - -bad: - if (nmp) - { - /* Disconnect from the server */ - - if (nmp->nm_rpcclnt) - { - rpcclnt_disconnect(nmp->nm_rpcclnt); - free(nmp->nm_rpcclnt); - nmp->nm_rpcclnt = NULL; - } - - /* Free connection-related resources */ - - (void)pthread_mutex_destroy(&nmp->nm_mux); - - free(nmp); - nmp = NULL; - } - - return -error; /*lint !e438*/ -} - -/**************************************************************************** - * Name: nfs_unbind - * - * Description: This implements the filesystem portion of the umount - * operation. - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_unbind(FAR void *handle, FAR struct inode **blkdriver) -{ - FAR struct nfsmount *nmp = (FAR struct nfsmount *)handle; - int error; - - finfo("Entry\n"); - DEBUGASSERT(nmp); - - /* Get exclusive access to the mount structure */ - - nfs_mux_take(nmp); - - /* Are there any open files? We can tell if there are open files by looking - * at the list of file structures in the mount structure. If this list - * not empty, then there are open files and we cannot unmount now (or a - * crash is sure to follow). - */ - - if (nmp->nm_head != NULL || nmp->nm_dir != NULL) - { - ferr("ERROR; There are open files: %p or directories: %p\n", nmp->nm_head, nmp->nm_dir); - - /* This implementation currently only supports unmounting if there are - * no open file references. - */ - - error = EBUSY; - goto errout_with_mutex; - } - - /* No open file... Umount the file system. */ - - error = rpcclnt_umount(nmp->nm_rpcclnt); - if (error) - { - ferr("ERROR: rpcclnt_umount failed: %d\n", error); - goto errout_with_mutex; - } - - /* Disconnect from the server */ - - rpcclnt_disconnect(nmp->nm_rpcclnt); - - /* And free any allocated resources */ - - nfs_mux_release(nmp); - (void)pthread_mutex_destroy(&nmp->nm_mux); - free(nmp->nm_rpcclnt); - nmp->nm_rpcclnt = NULL; - free(nmp); - nmp = NULL; - - return -error; - -errout_with_mutex: - nfs_mux_release(nmp); - return -error; -} - -/**************************************************************************** - * Name: nfs_fsinfo - * - * Description: - * Return information about root directory. - * - * Returned Value: - * 0 on success; positive errno value on failure - * - * Assumptions: - * The caller has exclusive access to the NFS mount structure - * - ****************************************************************************/ - -int nfs_fsinfo(FAR struct nfsmount *nmp) -{ - struct rpc_call_fs fsinfo; - struct rpc_reply_fsinfo fsp; - struct nfs_fsinfo *rep_info; - uint32_t pref; - uint32_t max; - int error = 0; - - fsinfo.fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize); - fsinfo.fs.fsroot.handle = nmp->nm_fh; - - /* Request FSINFO from the server */ - - nfs_statistics(NFSPROC_FSINFO); - error = nfs_request(nmp, NFSPROC_FSINFO, - (FAR void *)&fsinfo, sizeof(struct FS3args), - (FAR void *)&fsp, sizeof(struct rpc_reply_fsinfo)); - if (error) - { - return error; - } - - if (txdr_unsigned(fsp.fsinfo.obj_attributes.obj_attribute_follow) == 1) - { - rep_info = (struct nfs_fsinfo *)&fsp.fsinfo.fs_rtmax; - } - else - { - rep_info = (struct nfs_fsinfo *)((void *)(&fsp.fsinfo.obj_attributes.attributes)); - } - - /* Save the root file system attributes */ - -#if 0 - memcpy(&nmp->nm_fattr. &fsp.obj_attributes, sizeof(struct nfs_fattr)); -#endif - - pref = fxdr_unsigned(uint32_t, rep_info->fs_wtpref); - if (pref < nmp->nm_wsize) - { - nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); - } - - max = fxdr_unsigned(uint32_t, rep_info->fs_wtmax); - if (max < nmp->nm_wsize) - { - nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); - if (nmp->nm_wsize == 0) - { - nmp->nm_wsize = max; - } - } - - pref = fxdr_unsigned(uint32_t, rep_info->fs_rtpref); - if (pref < nmp->nm_rsize) - { - nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); - } - - max = fxdr_unsigned(uint32_t, rep_info->fs_rtmax); - if (max < nmp->nm_rsize) - { - nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); - if (nmp->nm_rsize == 0) - { - nmp->nm_rsize = max; - } - } - - pref = fxdr_unsigned(uint32_t, rep_info->fs_dtpref); - if (pref < nmp->nm_readdirsize) - { - nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) & ~(NFS_DIRBLKSIZ - 1); - } - - if (max < nmp->nm_readdirsize) - { - nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1); - if (nmp->nm_readdirsize == 0) - { - nmp->nm_readdirsize = max; - } - } - - return OK; -} - -/**************************************************************************** - * Name: nfs_statfs - * - * Description: - * Return filesystem statistics - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_statfs(FAR struct inode *mountpt, FAR struct statfs *sbp) -{ - FAR struct nfsmount *nmp; - FAR struct rpc_call_fs *fsstat; - FAR struct rpc_reply_fsstat *sfp; - FAR struct nfs_statfs_ctx *stfp; - int error = 0; - uint64_t tquad; - - /* Sanity checks */ - - DEBUGASSERT(mountpt && mountpt->i_private); - - /* Get the mountpoint private data from the inode structure */ - - nmp = (FAR struct nfsmount *)mountpt->i_private; - - /* Check if the mount is still healthy */ - - nfs_mux_take(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - ferr("ERROR: nfs_checkmount failed: %d\n", error); - goto errout_with_mutex; - } - - /* Fill in the statfs info */ - - sbp->f_type = NFS_SUPER_MAGIC; - - error = nfs_fsinfo(nmp); - if (error) - { - fdbg("ERROR: nfs_fsinfo failed: %d\n", error); - goto errout_with_mutex; - } - - fsstat = &nmp->nm_msgbuffer.fsstat; - fsstat->fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize); - memcpy(&fsstat->fs.fsroot.handle, &nmp->nm_fh, sizeof(nfsfh_t)); - - nfs_statistics(NFSPROC_FSSTAT); - error = nfs_request(nmp, NFSPROC_FSSTAT, - (FAR void *)fsstat, sizeof(struct FS3args), - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - if (error) - { - goto errout_with_mutex; - } + { + position = np->n_size; + } - sfp = (FAR struct rpc_reply_fsstat *)nmp->nm_iobuffer; - if (txdr_unsigned(sfp->fsstat.attributes_follow) == 1) - { - stfp = (FAR struct nfs_statfs_ctx *)&sfp->fsstat.sf_tbytes; - } - else - { - stfp = (FAR struct nfs_statfs_ctx *)&sfp->fsstat.obj_attributes; - } + /* position less than 0 should be reset to 0 */ - sbp->f_bsize = NFS_FABLKSIZE; - tquad = fxdr_hyper(&stfp->sf_tbytes); /*lint !e571*/ - sbp->f_blocks = tquad / (uint64_t) NFS_FABLKSIZE; - tquad = fxdr_hyper(&stfp->sf_fbytes); /*lint !e571*/ - sbp->f_bfree = tquad / (uint64_t) NFS_FABLKSIZE; - tquad = fxdr_hyper(&stfp->sf_abytes); /*lint !e571*/ - sbp->f_bavail = tquad / (uint64_t) NFS_FABLKSIZE; - tquad = fxdr_hyper(&stfp->sf_tfiles); /*lint !e571*/ - sbp->f_files = tquad; - tquad = fxdr_hyper(&stfp->sf_ffiles); /*lint !e571*/ - sbp->f_ffree = tquad; - sbp->f_namelen = NAME_MAX; + if (position < 0) + { + position = 0; + } + + np->n_fpos = (loff_t)position; + filep->f_pos = np->n_fpos; + if (position > (off_t)np->n_size) + { + np->n_size = (loff_t)position; + } + nfs_mux_release(nmp); + return (off_t)filep->f_pos; errout_with_mutex: nfs_mux_release(nmp); return -error; } -/**************************************************************************** - * Name: nfs_remove - * - * Description: - * Remove a file - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_remove(struct inode *mountpt, const char *relpath) +ssize_t vfs_nfs_read(struct file *filep, char *buffer, size_t buflen) { - FAR struct nfsmount *nmp; - struct file_handle fhandle; - struct file_handle obj_fhandle; - struct nfs_fattr fattr; - struct nfs_fattr obj_fattr; - char filename[NAME_MAX + 1]; - FAR uint32_t *ptr; - uint32_t f_type; - int namelen; - int reqlen; - int error; - - /* Sanity checks */ + 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; - DEBUGASSERT(mountpt && mountpt->i_private); + struct Vnode *node = filep->f_vnode; + struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data); - /* Get the mountpoint private data from the inode structure */ + np = (struct nfsnode *)node->data; - nmp = (FAR struct nfsmount *)mountpt->i_private; + DEBUGASSERT(nmp != NULL); - /* Check if the mount is still healthy */ + /* Make sure that the mount is still healthy */ nfs_mux_take(nmp); error = nfs_checkmount(nmp); if (error != OK) { - ferr("ERROR: nfs_checkmount failed: %d\n", error); + PRINTK("ERROR: nfs_checkmount failed: %d\n", error); goto errout_with_mutex; } - /* Find the NFS node of the directory containing the file to be deleted */ - error = nfs_finddir(nmp, relpath, &fhandle, &fattr, filename); + 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) { - ferr("ERROR: nfs_finddir returned: %d\n", error); + PRINTK("nfs_fileupdate failed: %d\n", error); goto errout_with_mutex; } - /* Check whether the file to be deleted is a directory */ + /* 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. + */ - memcpy(&obj_fhandle, &fhandle, sizeof(struct file_handle)); - error = nfs_lookup(nmp, filename, &obj_fhandle, &obj_fattr, NULL); - if (error != OK) + tmp = np->n_size - filep->f_pos; + if (buflen > tmp) { - ferr("ERROR: nfs_lookup returned: %d\n", error); - goto errout_with_mutex; + buflen = tmp; } - f_type = fxdr_unsigned(uint32_t, obj_fattr.fa_type); - if (f_type == NFDIR) + + /* Now loop until we fill the user buffer (or hit the end of the file) */ + + for (bytesread = 0; bytesread < buflen; ) { - ferr("ERROR: try to remove a directory\n"); - error = NFSERR_ISDIR; - goto errout_with_mutex; - } + /* Make sure that the attempted read size does not exceed the RPC maximum */ - /* Create the REMOVE RPC call arguments */ + readsize = buflen - bytesread; + if (readsize > nmp->nm_rsize) + { + readsize = nmp->nm_rsize; + } - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.removef.remove; - reqlen = 0; + /* Make sure that the attempted read size does not exceed the IO buffer size */ - /* Copy the variable length, directory file handle */ + tmp = SIZEOF_rpc_reply_read(readsize); + if (tmp > nmp->nm_buflen) + { + readsize -= (tmp - nmp->nm_buflen); + } - *ptr++ = txdr_unsigned(fhandle.length); - reqlen += sizeof(uint32_t); + /* Initialize the request */ - memcpy(ptr, &fhandle.handle, fhandle.length); - reqlen += (int)fhandle.length; - ptr += uint32_increment(fhandle.length); + ptr = (uint32_t *)&nmp->nm_msgbuffer.read.read; + reqlen = 0; - /* Copy the variable-length file name */ + /* Copy the variable length, file handle */ - namelen = strlen(filename); + *ptr++ = txdr_unsigned((uint32_t)np->n_fhsize); + reqlen += sizeof(uint32_t); - *ptr++ = txdr_unsigned(namelen); - 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); - memcpy(ptr, filename, namelen); - reqlen += uint32_alignup(namelen); + /* Copy the file offset */ - /* Perform the REMOVE RPC call */ + txdr_hyper((uint64_t)filep->f_pos, ptr); + ptr += 2; + reqlen += 2*sizeof(uint32_t); - nfs_statistics(NFSPROC_REMOVE); - error = nfs_request(nmp, NFSPROC_REMOVE, - (FAR void *)&nmp->nm_msgbuffer.removef, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); + /* Set the readsize */ -errout_with_mutex: - nfs_mux_release(nmp); - return -error; -} + *ptr = txdr_unsigned(readsize); + reqlen += sizeof(uint32_t); -/**************************************************************************** - * Name: nfs_mkdir - * - * Description: - * Create a directory - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ + /* Perform the read */ -static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) -{ - struct nfsmount *nmp; - struct file_handle fhandle; - struct nfs_fattr fattr; - char dirname[NAME_MAX + 1]; - FAR uint32_t *ptr; - uint32_t tmp; - int namelen; - int reqlen; - int error; + 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) + { + PRINTK("ERROR: nfs_request failed: %d\n", error); + goto errout_with_mutex; + } - /* Sanity checks */ + /* The read was successful. Get a pointer to the beginning of the NFS + * response data. + */ - DEBUGASSERT(mountpt && mountpt->i_private); + read_response = (struct rpc_reply_read *)nmp->nm_iobuffer; + readsize = fxdr_unsigned(uint32_t, read_response->read.hdr.count); - /* Get the mountpoint private data from the inode structure */ + /* Copy the read data into the user buffer */ - nmp = (FAR struct nfsmount *) mountpt->i_private; + if (LOS_CopyFromKernel(buffer, buflen, (const void *)read_response->read.data, readsize) != 0) + { + error = EINVAL; + goto errout_with_mutex; + } - /* Check if the mount is still healthy */ + /* Update the read state data */ - nfs_mux_take(nmp); - error = nfs_checkmount(nmp); - if (error != OK) - { - ferr("ERROR: nfs_checkmount: %d\n", error); - goto errout_with_mutex; + filep->f_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; + } } - /* Find the NFS node of the directory containing the directory to be created */ + nfs_mux_release(nmp); + return bytesread; + +errout_with_mutex: + nfs_mux_release(nmp); + return -error; +} - error = nfs_finddir(nmp, relpath, &fhandle, &fattr, dirname); +int vfs_nfs_create(struct Vnode *parent, const char *filename, int mode, struct Vnode **vpp) +{ + uint32_t *ptr = NULL; + uint32_t tmp; + int namelen; + int reqlen; + int error; + struct nfsnode *parent_nfs_node = (struct nfsnode *)parent->data; + struct nfsmount *nmp = (struct nfsmount *)(parent->originMount->data); + struct nfsnode *np = zalloc(sizeof(struct nfsnode)); + nfs_mux_take(nmp); + error = nfs_checkmount(nmp); if (error != OK) { - ferr("ERROR: nfs_finddir returned: %d\n", error); + PRINTK("ERROR: nfs_checkmount failed: %d\n", error); goto errout_with_mutex; } - - /* Format the MKDIR call message arguments */ - - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.mkdir.mkdir; + ptr = (uint32_t *)&nmp->nm_msgbuffer.create.create; reqlen = 0; /* Copy the variable length, directory file handle */ - *ptr++ = txdr_unsigned(fhandle.length); + *ptr++ = txdr_unsigned(parent_nfs_node->n_fhsize); reqlen += sizeof(uint32_t); - memcpy(ptr, &fhandle.handle, fhandle.length); - ptr += uint32_increment(fhandle.length); - reqlen += (int)fhandle.length; + (void)memcpy_s(ptr, parent_nfs_node->n_fhsize, &parent_nfs_node->n_fhandle, parent_nfs_node->n_fhsize); + reqlen += (int)parent_nfs_node->n_fhsize; + ptr += uint32_increment(parent_nfs_node->n_fhsize); - /* Copy the variable-length directory name */ + /* Copy the variable-length file name */ - namelen = strlen(dirname); + namelen = strlen(filename); *ptr++ = txdr_unsigned(namelen); reqlen += sizeof(uint32_t); - memcpy(ptr, dirname, namelen); + (void)memcpy_s(ptr, namelen, filename, namelen); ptr += uint32_increment(namelen); reqlen += uint32_alignup(namelen); + /* Set the creation mode */ + +#ifdef USE_GUARDED_CREATE + *ptr++ = htonl(NFSV3CREATE_GUARDED); +#else + *ptr++ = htonl(NFSV3CREATE_EXCLUSIVE); +#endif + + reqlen += sizeof(uint32_t); + + /* Mode information is not provided if EXCLUSIVE creation is used. + * in this case, we must call SETATTR after successfully creating + * the file. + */ + /* Set the mode. NOTE: Here we depend on the fact that the NuttX and NFS * bit settings are the same (at least for the bits of interest). */ @@ -2874,15 +2016,8 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) *ptr++ = nfs_true; /* True: mode value follows */ reqlen += sizeof(uint32_t); - if (!mode) - { - mode = (NFSMODE_IXOTH | NFSMODE_IROTH | - NFSMODE_IXGRP | NFSMODE_IRGRP | - NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR); - } - tmp = mode & (NFSMODE_IXOTH | NFSMODE_IWOTH | NFSMODE_IROTH | - NFSMODE_IXGRP | NFSMODE_IWGRP | NFSMODE_IRGRP | - NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR); + tmp = mode & (NFSMODE_IWOTH | NFSMODE_IROTH | NFSMODE_IWGRP | + NFSMODE_IRGRP | NFSMODE_IWUSR | NFSMODE_IRUSR); *ptr++ = txdr_unsigned(tmp); reqlen += sizeof(uint32_t); @@ -2898,10 +2033,12 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) *ptr++ = htonl(1); /* GID = 1 (nogroup) */ reqlen += 2*sizeof(uint32_t); - /* No size */ + /* Set the size to zero */ - *ptr++ = nfs_false; /* False: No size value follows */ - reqlen += sizeof(uint32_t); + *ptr++ = nfs_true; /* True: Size value follows */ + *ptr++ = 0; /* Size = 0 */ + *ptr++ = 0; + reqlen += 3*sizeof(uint32_t); /* Don't change times */ @@ -2909,518 +2046,415 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) *ptr++ = htonl(NFSV3SATTRTIME_DONTCHANGE); /* Don't change mtime */ reqlen += 2*sizeof(uint32_t); - /* Perform the MKDIR RPC */ + /* Send the NFS request. Note there is special logic here to handle version 3 + * exclusive open semantics. + */ + + do + { + nfs_statistics(NFSPROC_CREATE); + error = nfs_request(nmp, NFSPROC_CREATE, + (void *)&nmp->nm_msgbuffer.create, reqlen, + (void *)nmp->nm_iobuffer, nmp->nm_buflen); + } + while (0); + + /* Check for success */ + + if (error == OK) + { + /* Parse the returned data */ + + ptr = (uint32_t *)&((struct rpc_reply_create *) + nmp->nm_iobuffer)->create; + + /* Save the file handle in the file data structure */ + + tmp = *ptr++; /* handle_follows */ + if (!tmp) + { + PRINTK("ERROR: no file handle follows\n"); + error = EINVAL; + goto errout_with_mutex; + } + + tmp = *ptr++; + tmp = fxdr_unsigned(uint32_t, tmp); + DEBUGASSERT(tmp <= NFSX_V3FHMAX); + + np->n_fhsize = (uint8_t)tmp; + (void)memcpy_s(&np->n_fhandle, tmp, ptr, tmp); + ptr += uint32_increment(tmp); + + /* Save the attributes in the file data structure */ + + tmp = *ptr; /* handle_follows */ + if (!tmp) + { + PRINTK("WARNING: no file attributes\n"); + } + else + { + /* Initialize the file attributes */ + + nfs_attrupdate(np, (struct nfs_fattr *)ptr); + } + + /* Any following dir_wcc data is ignored for now */ + np->n_crefs = 1; + + /* Attach the private data to the struct file instance */ + + /* Then insert the new instance at the head of the list in the mountpoint + * tructure. It needs to be there (1) to handle error conditions that effect + * all files, and (2) to inform the umount logic that we are busy. We + * cannot unmount the file system if this list is not empty! + */ + + np->n_next = nmp->nm_head; + nmp->nm_head = np; + + np->n_flags |= (NFSNODE_OPEN | NFSNODE_MODIFIED); + np->n_name = zalloc(namelen + 1); + memcpy_s(np->n_name, (namelen + 1), filename, (namelen + 1)); + + (void)VnodeAlloc(&nfs_vops, vpp); + (*vpp)->parent = parent; + (*vpp)->fop = &nfs_fops; + (*vpp)->originMount = parent->originMount; + (*vpp)->data = np; + (*vpp)->type = filetype_to_vnodetype(np->n_type); + (*vpp)->mode = type_to_mode((*vpp)->type, nmp->nm_permission); + (*vpp)->gid = nmp->nm_gid; + (*vpp)->uid = nmp->nm_uid; - nfs_statistics(NFSPROC_MKDIR); - error = nfs_request(nmp, NFSPROC_MKDIR, - (FAR void *)&nmp->nm_msgbuffer.mkdir, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - if (error) - { - ferr("ERROR: nfs_request failed: %d\n", error); } -errout_with_mutex: + nfs_mux_release(nmp); + return OK; + + errout_with_mutex: + if (np) + { + free(np); + } nfs_mux_release(nmp); return -error; } -/**************************************************************************** - * Name: nfs_rmdir - * - * Description: - * Remove a directory - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_rmdir(struct inode *mountpt, const char *relpath) +int vfs_nfs_unlink(struct Vnode *parent, struct Vnode *target, char *filename) { - struct nfsmount *nmp; - struct file_handle fhandle; - struct nfs_fattr fattr; - char dirname[NAME_MAX + 1]; - FAR uint32_t *ptr; - int namelen; - int reqlen; - int error; - - /* Sanity checks */ - - DEBUGASSERT(mountpt && mountpt->i_private); - - /* Get the mountpoint private data from the inode structure */ - - nmp = (struct nfsmount *)mountpt->i_private; - - /* Check if the mount is still healthy */ + struct nfsmount *nmp = (struct nfsmount *)(parent->originMount->data); + struct nfsnode *parent_node = (struct nfsnode*)(parent->data); + struct nfsnode *target_node = (struct nfsnode*)(target->data); + int reqlen; + int namelen; + uint32_t *ptr = NULL; + int error; nfs_mux_take(nmp); error = nfs_checkmount(nmp); if (error != OK) { - ferr("ERROR: nfs_checkmount failed: %d\n", error); + PRINTK("ERROR: nfs_checkmount failed: %d\n", error); goto errout_with_mutex; } - /* Find the NFS node of the directory containing the directory to be removed */ - - error = nfs_finddir(nmp, relpath, &fhandle, &fattr, dirname); - if (error != OK) + if (target_node->n_type == NFDIR) { - ferr("ERROR: nfs_finddir returned: %d\n", error); + PRINTK("ERROR: try to remove a directory\n"); + error = EISDIR; goto errout_with_mutex; } - /* Set up the RMDIR call message arguments */ + /* Create the REMOVE RPC call arguments */ - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.rmdir.rmdir; + ptr = (uint32_t *)&nmp->nm_msgbuffer.removef.remove; reqlen = 0; /* Copy the variable length, directory file handle */ - *ptr++ = txdr_unsigned(fhandle.length); + *ptr++ = txdr_unsigned(parent_node->n_fhsize); reqlen += sizeof(uint32_t); - memcpy(ptr, &fhandle.handle, fhandle.length); - reqlen += (int)fhandle.length; - ptr += uint32_increment(fhandle.length); + (void)memcpy_s(ptr, parent_node->n_fhsize, &parent_node->n_fhandle, parent_node->n_fhsize); + reqlen += (int)parent_node->n_fhsize; + ptr += uint32_increment(parent_node->n_fhsize); - /* Copy the variable-length directory name */ + /* Copy the variable-length file name */ - namelen = strlen(dirname); + namelen = strlen(filename); *ptr++ = txdr_unsigned(namelen); reqlen += sizeof(uint32_t); - memcpy(ptr, dirname, namelen); + (void)memcpy_s(ptr, namelen, filename, namelen); reqlen += uint32_alignup(namelen); - /* Perform the RMDIR RPC */ + /* Perform the REMOVE RPC call */ - nfs_statistics(NFSPROC_RMDIR); - error = nfs_request(nmp, NFSPROC_RMDIR, - (FAR void *)&nmp->nm_msgbuffer.rmdir, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); + nfs_statistics(NFSPROC_REMOVE); + error = nfs_request(nmp, NFSPROC_REMOVE, + (void *)&nmp->nm_msgbuffer.removef, reqlen, + (void *)nmp->nm_iobuffer, nmp->nm_buflen); errout_with_mutex: nfs_mux_release(nmp); - return -nfs_2_vfs(error); + return -error; } -static int nfs_getfilename(char *dstpath, unsigned int dstpathLen, const char *srcpath, unsigned int maxlen) +int vfs_nfs_rmdir(struct Vnode *parent, struct Vnode *target, char *dirname) { - int ret; - char *path; - unsigned int len; - - if (srcpath == NULL) + struct nfsmount *nmp = (struct nfsmount *)(parent->originMount->data); + struct nfsnode *parent_node = (struct nfsnode*)(parent->data); + struct nfsnode *target_node = (struct nfsnode*)(target->data); + int reqlen; + int namelen; + uint32_t *ptr = NULL; + int error; + if (target_node->n_type != NFDIR) { - return ENOBUFS; + PRINTK("ERROR: try to remove a non-dir\n"); + return -ENOTDIR; } - len = strlen(srcpath); - if (len > maxlen) + nfs_mux_take(nmp); + error = nfs_checkmount(nmp); + if (error != OK) { - return ENOBUFS; + PRINTK("ERROR: nfs_checkmount failed: %d\n", error); + goto errout_with_mutex; } + /* Set up the RMDIR call message arguments */ - if (len == 0) - { - *dstpath = '\0'; - return OK; - } + ptr = (uint32_t *)&nmp->nm_msgbuffer.rmdir.rmdir; + reqlen = 0; - path = (char *)srcpath + len - 1; + /* Copy the variable length, directory file handle */ - while (len > 0 && *path != '/') - { - len--; - path--; - } + *ptr++ = txdr_unsigned(parent_node->n_fhsize); + reqlen += sizeof(uint32_t); - /* When copy path, skip the 1 '/' in NFS URL, for example 'nfs://server/a/b' */ + (void)memcpy_s(ptr, parent_node->n_fhsize, &parent_node->n_fhandle, parent_node->n_fhsize); + reqlen += (int)parent_node->n_fhsize; + ptr += uint32_increment(parent_node->n_fhsize); - ret = strncpy_s(dstpath, dstpathLen, path + 1, strlen(path + 1)); - if (ret != EOK) - { - return ENOBUFS; - } - return OK; -} + /* Copy the variable-length directory name */ -static int nfs_compare_type(struct nfsmount *nmp, const char *oldrelpath, - const char *newrelpath) -{ - struct file_handle fhandle; - struct nfs_fattr stOld_attributes; - struct nfs_fattr stNew_attributes; - int ret; - const char *ch1 = oldrelpath; - const char *ch2 = newrelpath; + namelen = strlen(dirname); - while (*ch1 == *ch2) - { - if (*ch1 == '\0' || *ch2 == '\0') - { - break; - } - ch1++; - ch2++; - } + *ptr++ = txdr_unsigned(namelen); + reqlen += sizeof(uint32_t); - if ((*ch1 == '/' && *ch2 == '\0') || (*ch2 == '/' && *ch1 == '\0')) - { - return 1; - } + (void)memcpy_s(ptr, namelen, dirname, namelen); + reqlen += uint32_alignup(namelen); - ret = nfs_findnode(nmp, oldrelpath, &fhandle, &stOld_attributes, (struct nfs_fattr *)NULL); - if (ret != OK && ret != ENOTDIR) - { - fdbg("ERROR: old path nfs_findnode failed: %d\n", ret); - return 1; - } - ret = nfs_findnode(nmp, newrelpath, &fhandle, &stNew_attributes, (struct nfs_fattr *)NULL); - if (ret != OK) - { - fdbg("ERROR: new path nfs_findnode failed: %d\n", ret); - return 0; - } + /* Perform the RMDIR RPC */ - /* if two value are equal which should return 0;it is not equal should return 1 */ + nfs_statistics(NFSPROC_RMDIR); + error = nfs_request(nmp, NFSPROC_RMDIR, + (void *)&nmp->nm_msgbuffer.rmdir, reqlen, + (void *)nmp->nm_iobuffer, nmp->nm_buflen); - return stOld_attributes.fa_type != stNew_attributes.fa_type; +errout_with_mutex: + nfs_mux_release(nmp); + return -nfs_2_vfs(error); } -/**************************************************************************** - * Name: nfs_rename - * - * Description: - * Rename a file or directory - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ -static int nfs_rename(struct inode *mountpt, const char *oldrelpath, - const char *newrelpath) +int vfs_nfs_close(struct Vnode *node) { - struct nfsmount *nmp; - struct nfsnode *np; - struct nfsdir_s *nd; - struct file_handle from_handle; - struct file_handle to_handle; - char directory[NAME_MAX + 1]; - char from_name[NAME_MAX + 1]; - char to_name[NAME_MAX + 1]; - char *fullpath; - char *relpath; - struct nfs_fattr fattr; - FAR uint32_t *ptr; - int namelen; - int reqlen; - int error; - - /* Sanity checks */ - - DEBUGASSERT(mountpt && mountpt->i_private); - - /* Get the mountpoint private data from the inode structure */ - - nmp = (struct nfsmount *)mountpt->i_private; - - /* Check if the mount is still healthy */ + struct nfsnode *np = (struct nfsnode*)(node->data); + /* Decrement the reference count. If the reference count would not + * decrement to zero, then that is all we have to do. + */ - nfs_mux_take(nmp); - error = nfs_checkmount(nmp); - if (error != OK) + if (np->n_crefs > 1) { - ferr("ERROR: nfs_checkmount returned: %d\n", error); - goto errout_with_mutex; + np->n_crefs--; } + return OK; +} - /* Find the NFS node of the directory containing the 'from' object */ - - error = nfs_finddir(nmp, oldrelpath, &from_handle, &fattr, from_name); - if (error != OK) - { - ferr("ERROR: nfs_finddir returned: %d\n", error); - goto errout_with_mutex; - } - fdbg("nfs_finddir oldrelpath:%s, fattr->fa_type:%x, from_name: %s\n", - oldrelpath, fattr.fa_type, from_name); +int vfs_nfs_close_file(struct file *filep) +{ + struct Vnode *node = (struct Vnode *)filep->f_vnode; + return vfs_nfs_close(node); +} - for (nd = nmp->nm_dir; nd; nd = nd->nfs_next) - { - char filename[FILENAME_MAX_LEN] = {}; - error = nfs_getfilename(filename, sizeof(filename), nd->nfs_dir->fd_dir[0].d_name, NAME_MAX); - if (error != OK) - { - goto errout_with_mutex; - } - if (strcmp(filename, from_name) == 0) - { - break; - } - } - for (np = nmp->nm_head; np; np = np->n_next) - { - char filename[FILENAME_MAX_LEN] = {}; - error = nfs_getfilename(filename, sizeof(filename), np->n_filep->f_relpath, PATH_MAX - 1); - if (error != OK) - { - goto errout_with_mutex; - } - if (strcmp((const char *)filename, from_name) == 0) - { - break; - } - } +int vfs_nfs_closedir(struct Vnode *node, struct fs_dirent_s *dir) +{ + struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data); + struct nfsdir_s *prev = NULL; + struct nfsdir_s *curr = NULL; + struct nfsdir_s *nfs_dir; + struct entry3 *entry_pos = NULL; + int ret; - if (!np && !nd) - { - fdbg("INFO: not opened\n"); - } + /* Sanity checks */ + nfs_dir = (struct nfsdir_s *)(dir->u.fs_dir); - /* Find the NFS node of the directory containing the 'from' object */ + DEBUGASSERT(nmp != NULL); - error = nfs_finddir(nmp, newrelpath, &to_handle, &fattr, to_name); - if (error != OK) - { - ferr("ERROR: nfs_finddir returned: %d\n", error); - goto errout_with_mutex; - } - fdbg("nfs_finddir newrelpath:%s, fattr->fa_type:%x, to_name: %s\n", - newrelpath, fattr.fa_type, to_name); + /* Get exclusive access to the mount structure. */ + nfs_mux_take(nmp); - /* compare new and old type */ - error = nfs_compare_type(nmp, oldrelpath, newrelpath); - if (error != OK) + for (entry_pos = nfs_dir->nfs_entries; entry_pos != NULL; entry_pos = nfs_dir->nfs_entries) { - fdbg("ERROR: nfs_compare_type returned: %d\n", error); - goto errout_with_mutex; + nfs_dir->nfs_entries = entry_pos->next; + NFS_DIR_ENTRY_FREE(entry_pos); } - /* Format the RENAME RPC arguments */ - - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.renamef.rename; - reqlen = 0; - - /* Copy the variable length, 'from' directory file handle */ - - *ptr++ = txdr_unsigned(from_handle.length); - reqlen += sizeof(uint32_t); - - memcpy(ptr, &from_handle.handle, from_handle.length); - reqlen += (int)from_handle.length; - ptr += uint32_increment(from_handle.length); - - /* Copy the variable-length 'from' object name */ - - namelen = strlen(from_name); - - *ptr++ = txdr_unsigned(namelen); - reqlen += sizeof(uint32_t); - - memcpy(ptr, from_name, namelen); - reqlen += uint32_alignup(namelen); - ptr += uint32_increment(namelen); - - /* Copy the variable length, 'to' directory file handle */ - - *ptr++ = txdr_unsigned(to_handle.length); - reqlen += sizeof(uint32_t); - - memcpy(ptr, &to_handle.handle, to_handle.length); - ptr += uint32_increment(to_handle.length); - reqlen += (int)to_handle.length; - - /* Copy the variable-length 'to' object name */ - - namelen = strlen(to_name); - - *ptr++ = txdr_unsigned(namelen); - reqlen += sizeof(uint32_t); - - memcpy(ptr, to_name, namelen); - reqlen += uint32_alignup(namelen); + /* Assume file structure will not be found. This should never happen. */ - /* Perform the RENAME RPC */ + ret = EINVAL; - nfs_statistics(NFSPROC_RENAME); - error = nfs_request(nmp, NFSPROC_RENAME, - (FAR void *)&nmp->nm_msgbuffer.renamef, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); - if (error != OK) + for (prev = (struct nfsdir_s *)NULL, curr = nmp->nm_dir; + curr; + prev = curr, curr = curr->nfs_next) { - fdbg("ERROR: nfs_request returned: %d\n", error); - goto errout_with_mutex; - } + /* Check if this node is ours */ - if (np) - { - error = strncpy_s(directory, NAME_MAX + 1, np->n_filep->f_path, np->n_filep->f_relpath - np->n_filep->f_path); - directory[np->n_filep->f_relpath - np->n_filep->f_path] = '\0'; - if (error != EOK) - { - error = ENOBUFS; - goto errout_with_mutex; - } - error = vfs_normalize_path(directory, newrelpath, &fullpath); - if (error < 0) + if (nfs_dir == curr) { - error = -error; - fdbg("ERROR: vfs_normalize_path returned: %d\n", error); - goto errout_with_mutex; - } + /* Yes.. remove it from the list of file structures */ - relpath = strstr(fullpath, newrelpath); - if (relpath == NULL) - { - fdbg("ERROR: relpath is not sub in fullpath.\n", error); - free(fullpath); - goto errout_with_mutex; - } + if (prev) + { + /* Remove from mid-list */ - /* Update the path of old file. */ + prev->nfs_next = nfs_dir->nfs_next; + } + else + { + /* Remove from the head of the list */ - free(np->n_filep->f_path); - np->n_filep->f_path = fullpath; - np->n_filep->f_relpath = relpath; - } - else if (nd) - { - error = memcpy_s(nd->nfs_dir->fd_dir[0].d_name, strlen(to_name) + 1, to_name, strlen(to_name) + 1); - if (error != EOK) - { - error = ENOBUFS; - goto errout_with_mutex; + nmp->nm_dir= nfs_dir->nfs_next; + } + + /* Then deallocate the file structure and return success */ + + free(nfs_dir); + nfs_dir = NULL; + ret = OK; + break; } } - -errout_with_mutex: nfs_mux_release(nmp); - return -error; + + return -ret; /*lint !e438*/ } /**************************************************************************** - * Name: nfs_stat_common + * Name: nfs_fsinfo * * Description: - * Return information about the file system object described by 'info' + * Return information about root directory. * * Returned Value: - * None + * 0 on success; positive errno value on failure + * + * Assumptions: + * The caller has exclusive access to the NFS mount structure * ****************************************************************************/ -static void nfs_stat_common(FAR struct nfs_statinfo_s *info, - FAR struct stat *buf) +int nfs_fsinfo(struct nfsmount *nmp) { - mode_t mode; - - /* Here we exploit the fact that most mode bits are the same in NuttX - * as in the NFSv3 spec. - */ + struct rpc_call_fs fsinfo; + struct rpc_reply_fsinfo fsp; + struct nfs_fsinfo *rep_info = NULL; + uint32_t pref; + uint32_t max; + int error = 0; - mode = info->ns_mode & - (NFSMODE_IXOTH | NFSMODE_IWOTH | NFSMODE_IROTH | - NFSMODE_IXGRP | NFSMODE_IWGRP | NFSMODE_IRGRP | - NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR); + fsinfo.fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize); + fsinfo.fs.fsroot.handle = nmp->nm_fh; - /* Handle the cases that are not the same */ + /* Request FSINFO from the server */ - if ((info->ns_mode & NFSMODE_ISGID) != 0) + nfs_statistics(NFSPROC_FSINFO); + error = nfs_request(nmp, NFSPROC_FSINFO, + (void *)&fsinfo, sizeof(struct FS3args), + (void *)&fsp, sizeof(struct rpc_reply_fsinfo)); + if (error) { - mode |= S_ISGID; + return error; } - if ((info->ns_mode & NFSMODE_ISUID) != 0) + if (txdr_unsigned(fsp.fsinfo.obj_attributes.obj_attribute_follow) == 1) { - mode |= S_ISUID; + rep_info = (struct nfs_fsinfo *)&fsp.fsinfo.fs_rtmax; } - - /* Now OR in the file type */ - - switch (info->ns_type) + else { - default: - case NFNON: /* Unknown type */ - break; - - case NFREG: /* Regular file */ - mode |= S_IFREG; - break; + rep_info = (struct nfs_fsinfo *)((void *)(&fsp.fsinfo.obj_attributes.attributes)); + } - case NFDIR: /* Directory */ - mode |= S_IFDIR; - break; + /* Save the root file system attributes */ + pref = fxdr_unsigned(uint32_t, rep_info->fs_wtpref); + if (pref < nmp->nm_wsize) + { + nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); + } - case NFBLK: /* Block special device file */ - mode |= S_IFBLK; - break; + max = fxdr_unsigned(uint32_t, rep_info->fs_wtmax); + if (max < nmp->nm_wsize) + { + nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); + if (nmp->nm_wsize == 0) + { + nmp->nm_wsize = max; + } + } - case NFCHR: /* Character special device file */ - mode |= S_IFCHR; - break; + pref = fxdr_unsigned(uint32_t, rep_info->fs_rtpref); + if (pref < nmp->nm_rsize) + { + nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); + } - case NFLNK: /* Symbolic link */ - mode |= S_IFLNK; - break; + max = fxdr_unsigned(uint32_t, rep_info->fs_rtmax); + if (max < nmp->nm_rsize) + { + nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); + if (nmp->nm_rsize == 0) + { + nmp->nm_rsize = max; + } + } - case NFSOCK: /* Socket */ - mode |= S_IFSOCK; - break; + pref = fxdr_unsigned(uint32_t, rep_info->fs_dtpref); + if (pref < nmp->nm_readdirsize) + { + nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) & ~(NFS_DIRBLKSIZ - 1); + } - case NFFIFO: /* Named pipe */ - mode |= S_IFMT; - break; + if (max < nmp->nm_readdirsize) + { + nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1); + if (nmp->nm_readdirsize == 0) + { + nmp->nm_readdirsize = max; + } } - buf->st_mode = mode; - buf->st_uid = 0; - buf->st_gid = 0; - buf->st_size = (off_t)info->ns_size; - buf->st_blksize = 0; - buf->st_blocks = 0; - buf->st_mtime = info->ns_mtime; - buf->st_atime = info->ns_atime; - buf->st_ctime = info->ns_ctime; + return OK; } -/**************************************************************************** - * Name: nfs_stat - * - * Description: - * Return information about the file system object at 'relpath' - * - * Returned Value: - * 0 on success; a negated errno value on failure. - * - ****************************************************************************/ - -static int nfs_stat(struct inode *mountpt, const char *relpath, - struct stat *buf) +int vfs_nfs_statfs(struct Mount *mountpt, struct statfs *sbp) { struct nfsmount *nmp; - struct file_handle fhandle; - struct nfs_fattr obj_attributes; - struct nfs_statinfo_s info; - struct timespec ts; - int error; - - /* Sanity checks */ - - DEBUGASSERT(mountpt && mountpt->i_private); + struct rpc_call_fs *fsstat = NULL; + struct rpc_reply_fsstat *sfp = NULL; + struct nfs_statfs_ctx *stfp = NULL; + int error = 0; + uint64_t tquad; - /* Get the mountpoint private data from the inode structure */ + /* Get the mountpoint private data from the vnode structure */ - nmp = (FAR struct nfsmount *)mountpt->i_private; - DEBUGASSERT(nmp && buf); + nmp = (struct nfsmount *)mountpt->data; /* Check if the mount is still healthy */ @@ -3428,133 +2462,173 @@ static int nfs_stat(struct inode *mountpt, const char *relpath, error = nfs_checkmount(nmp); if (error != OK) { - ferr("ERROR: nfs_checkmount failed: %d\n", error); + PRINTK("ERROR: nfs_checkmount failed: %d\n", error); goto errout_with_mutex; } - /* Get the file handle attributes of the requested node */ + /* Fill in the statfs info */ - error = nfs_findnode(nmp, relpath, &fhandle, &obj_attributes, NULL); - if (error != OK) + sbp->f_type = NFS_SUPER_MAGIC; + + error = nfs_fsinfo(nmp); + if (error) { - ferr("ERROR: nfs_findnode failed: %d\n", error); + PRINTK("ERROR: nfs_fsinfo failed: %d\n", error); goto errout_with_mutex; } - /* Extract the file mode, file type, and file size. */ - - info.ns_mode = fxdr_unsigned(uint16_t, obj_attributes.fa_mode); - info.ns_type = fxdr_unsigned(uint8_t, obj_attributes.fa_type); - info.ns_size = fxdr_hyper(&obj_attributes.fa_size); - - /* Extract time values as type time_t in units of seconds */ - - fxdr_nfsv3time(&obj_attributes.fa_mtime, &ts); - info.ns_mtime = ts.tv_sec; - - fxdr_nfsv3time(&obj_attributes.fa_atime, &ts); - info.ns_atime = ts.tv_sec; + fsstat = &nmp->nm_msgbuffer.fsstat; + fsstat->fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize); + (void)memcpy_s(&fsstat->fs.fsroot.handle, sizeof(nfsfh_t), &nmp->nm_fh, sizeof(nfsfh_t)); - fxdr_nfsv3time(&obj_attributes.fa_ctime, &ts); - info.ns_ctime = ts.tv_sec; + nfs_statistics(NFSPROC_FSSTAT); + error = nfs_request(nmp, NFSPROC_FSSTAT, + (void *)fsstat, sizeof(struct FS3args), + (void *)nmp->nm_iobuffer, nmp->nm_buflen); + if (error) + { + goto errout_with_mutex; + } - /* Then update the stat buffer with this information */ + sfp = (struct rpc_reply_fsstat *)nmp->nm_iobuffer; + if (txdr_unsigned(sfp->fsstat.attributes_follow) == 1) + { + stfp = (struct nfs_statfs_ctx *)&sfp->fsstat.sf_tbytes; + } + else + { + stfp = (struct nfs_statfs_ctx *)&sfp->fsstat.obj_attributes; + } - nfs_stat_common(&info, buf); + sbp->f_bsize = NFS_FABLKSIZE; + tquad = fxdr_hyper(&stfp->sf_tbytes); /*lint !e571*/ + sbp->f_blocks = tquad / (uint64_t) NFS_FABLKSIZE; + tquad = fxdr_hyper(&stfp->sf_fbytes); /*lint !e571*/ + sbp->f_bfree = tquad / (uint64_t) NFS_FABLKSIZE; + tquad = fxdr_hyper(&stfp->sf_abytes); /*lint !e571*/ + sbp->f_bavail = tquad / (uint64_t) NFS_FABLKSIZE; + tquad = fxdr_hyper(&stfp->sf_tfiles); /*lint !e571*/ + sbp->f_files = tquad; + tquad = fxdr_hyper(&stfp->sf_ffiles); /*lint !e571*/ + sbp->f_ffree = tquad; + sbp->f_namelen = NAME_MAX; + sbp->f_flags = mountpt->mountFlags; errout_with_mutex: nfs_mux_release(nmp); - return -nfs_2_vfs(error); + return -error; } -int nfs_mount(const char *server_ip_and_path, const char *mount_path, - unsigned int uid, unsigned int gid) +static int vfs_nfs_rewinddir(struct Vnode *node, struct fs_dirent_s *dir) { - struct nfs_args nfs_args = {0}; - char *server_ip_addr; - char *server_nfs_path; - int found_colon = 0; - unsigned int pos; - int ret = -1; - struct sockaddr_in *nfs_srv_addr; - size_t len; + struct nfsdir_s *nfs_dir = NULL; + struct entry3 *entry_pos = NULL; - rpcclnt_setuidgid(uid, gid); + struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data); + nfs_mux_take(nmp); + /* Reset the NFS-specific portions of dirent structure, retaining only the + * file handle. + */ - len = strlen(server_ip_and_path); - for (pos = 0; pos < len; pos++) + nfs_dir = (struct nfsdir_s *)dir->u.fs_dir; + (void)memset_s(nfs_dir->nfs_verifier, DIRENT_NFS_VERFLEN, 0, DIRENT_NFS_VERFLEN); + nfs_dir->nfs_cookie[0] = 0; + nfs_dir->nfs_cookie[1] = 0; + for (entry_pos = nfs_dir->nfs_entries; entry_pos != NULL; entry_pos = nfs_dir->nfs_entries) { - if (*(server_ip_and_path + pos) == ':') - { - found_colon = 1; - break; - } + nfs_dir->nfs_entries = entry_pos->next; + NFS_DIR_ENTRY_FREE(entry_pos); } + free(nfs_dir->nfs_entries); + nfs_dir->nfs_entries = NULL; + nfs_mux_release(nmp); + return OK; +} - if (!found_colon) - { - set_errno(ENOENT); - goto nfs_mount_out; - } +int vfs_nfs_truncate(struct Vnode *node, off_t length) +{ + uint32_t *ptr; + int reqlen; + int error; - server_ip_addr = (char *)malloc(pos + 1); - if (server_ip_addr == NULL) - { - PRINTK("malloc failure\n"); - set_errno(ENOMEM); - goto nfs_mount_out; - } + struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data); + struct nfsnode *np = (struct nfsnode*)(node->data); - ret = strncpy_s(server_ip_addr, pos + 1, server_ip_and_path, pos); - if (ret != EOK) - { - set_errno(ENOBUFS); - goto nfs_free_node_out; - } - *(server_ip_addr + pos) = '\0'; - server_nfs_path = (char *)(server_ip_and_path + pos + 1); + /* Create the SETATTR RPC call arguments */ - (void)memset_s(&nfs_args, sizeof(nfs_args), 0, sizeof(nfs_args)); + ptr = (uint32_t *)&nmp->nm_msgbuffer.setattr.setattr; + reqlen = 0; - if (g_NFSMOUNT_HOOK != NULL) - { - g_NFSMOUNT_HOOK(&nfs_args); - } + /* Copy the variable length, directory file handle */ - nfs_args.path = server_nfs_path; /* server nfs dir */ + *ptr++ = txdr_unsigned(np->n_fhsize); + reqlen += sizeof(uint32_t); - nfs_srv_addr = (struct sockaddr_in *)&nfs_args.addr; - nfs_srv_addr->sin_family = AF_INET; - ret = inet_pton(AF_INET, server_ip_addr, &nfs_srv_addr->sin_addr.s_addr); - if (ret != 1) - { - ret = -1; - set_errno(ECONNREFUSED); - goto nfs_free_node_out; - } - nfs_srv_addr->sin_port = htons(PMAPPORT); + (void)memcpy_s(ptr, np->n_fhsize, &np->n_fhandle, np->n_fhsize); + reqlen += (int)np->n_fhsize; + ptr += uint32_increment(np->n_fhsize); - nfs_args.addrlen = sizeof(nfs_args.addr); -#if (NFS_PROTO_TYPE == NFS_IPPROTO_TCP) - nfs_args.sotype = SOCK_STREAM; -#elif (NFS_PROTO_TYPE == NFS_IPPROTO_UDP) - nfs_args.sotype = SOCK_DGRAM; -#endif + /* Copy the variable-length attributes */ - PRINTK("Mount nfs on %s:%s, uid:%d, gid:%d\n", server_ip_addr, server_nfs_path, uid, gid); - ret = mount((const char *)NULL, mount_path, "nfs", 0, &nfs_args); + *ptr++ = nfs_false; /* Don't change mode */ + *ptr++ = nfs_false; /* Don't change uid */ + *ptr++ = nfs_false; /* Don't change gid */ + *ptr++ = nfs_true; /* Use the following size */ + *ptr++ = length; /* Truncate to the specified length */ + *ptr++ = 0; + *ptr++ = htonl(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */ + *ptr++ = htonl(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */ + *ptr++ = nfs_false; /* No guard value */ + reqlen += 9 * sizeof(uint32_t); -nfs_free_node_out: - free(server_ip_addr); + /* Perform the SETATTR RPC */ -nfs_mount_out: - if (ret) + nfs_statistics(NFSPROC_SETATTR); + error = nfs_request(nmp, NFSPROC_SETATTR, + (void *)&nmp->nm_msgbuffer.setattr, reqlen, + (void *)nmp->nm_iobuffer, nmp->nm_buflen); + if (error != OK) { - perror("mount nfs error"); - return -1; + PRINTK("ERROR: nfs_request failed: %d\n", error); + return -error; } - PRINTK("Mount nfs finished.\n"); - return 0; + + /* Indicate that the file now has zero length */ + + np->n_size = length; + return OK; } +struct MountOps nfs_mount_operations = +{ + .Mount = vfs_nfs_mount, + .Statfs= vfs_nfs_statfs, +}; + +struct VnodeOps nfs_vops = +{ + .Lookup = vfs_nfs_lookup, + .Getattr = vfs_nfs_stat, + .Opendir = vfs_nfs_opendir, + .Readdir = vfs_nfs_readdir, + .Rename = vfs_nfs_rename, + .Mkdir = vfs_nfs_mkdir, + .Create = vfs_nfs_create, + .Unlink = vfs_nfs_unlink, + .Rmdir = vfs_nfs_rmdir, + .Reclaim = vfs_nfs_reclaim, + .Closedir = vfs_nfs_closedir, + .Close = vfs_nfs_close, + .Rewinddir = vfs_nfs_rewinddir, + .Truncate = vfs_nfs_truncate, +}; +struct file_operations_vfs nfs_fops = +{ + .seek = vfs_nfs_seek, + .write = vfs_nfs_write, + .read = vfs_nfs_read, + .mmap = OsVfsFileMmap, + .close = vfs_nfs_close_file, +}; +FSMAP_ENTRY(nfs_fsmap, "nfs", nfs_mount_operations, FALSE, FALSE); #endif diff --git a/fs/nfs/nfs_mount.h b/fs/nfs/nfs_mount.h old mode 100755 new mode 100644 index 59aa15e..4324e2c --- a/fs/nfs/nfs_mount.h +++ b/fs/nfs/nfs_mount.h @@ -101,6 +101,9 @@ struct nfsmount uint16_t nm_wsize; /* Max size of write RPC */ uint16_t nm_readdirsize; /* Size of a readdir RPC */ uint16_t nm_buflen; /* Size of I/O buffer */ + mode_t nm_permission; + uint nm_gid; + uint nm_uid; /* Set aside memory on the stack to hold the largest call message. NOTE * that for the case of the write call message, it is the reply message that diff --git a/fs/nfs/nfs_node.h b/fs/nfs/nfs_node.h old mode 100755 new mode 100644 index e22a5e7..bcf8582 --- a/fs/nfs/nfs_node.h +++ b/fs/nfs/nfs_node.h @@ -81,6 +81,7 @@ struct nfsnode uint8_t n_fhsize; /* Size in bytes of the file handle */ uint8_t n_flags; /* Node flags */ uint16_t n_mode; /* File mode for fstat() */ + time_t n_atime; /* File access time */ time_t n_mtime; /* File modification time */ time_t n_ctime; /* File creation time */ nfsfh_t n_fhandle; /* NFS File Handle */ @@ -88,6 +89,7 @@ struct nfsnode int n_oflags; /* Flags provided when file was opened */ loff_t n_fpos; /* NFS File position */ struct file *n_filep; /* File pointer from VFS */ + char *n_name; }; #ifdef __cplusplus diff --git a/fs/nfs/nfs_util.c b/fs/nfs/nfs_util.c old mode 100755 new mode 100644 index 110b414..19e1984 --- a/fs/nfs/nfs_util.c +++ b/fs/nfs/nfs_util.c @@ -57,11 +57,11 @@ * Private Functions ****************************************************************************/ -static inline int nfs_pathsegment(FAR const char **path, FAR char *buffer, - FAR char *terminator) +static inline int nfs_pathsegment(const char **path, char *buffer, + char *terminator) { - FAR const char *src = *path; - FAR char *dest = buffer; + const char *src = *path; + char *dest = buffer; int nbytes = 0; char ch; @@ -177,8 +177,8 @@ int nfs_checkmount(struct nfsmount *nmp) ****************************************************************************/ int nfs_request(struct nfsmount *nmp, int procnum, - FAR void *request, size_t reqlen, - FAR void *response, size_t resplen) + void *request, size_t reqlen, + void *response, size_t resplen) { struct rpcclnt *clnt = nmp->nm_rpcclnt; struct nfs_reply_header replyh; @@ -189,7 +189,7 @@ tryagain: request, reqlen, response, resplen); if (error != 0) { - ferr("ERROR: rpcclnt_request failed: %d\n", error); + PRINTK("ERROR: rpcclnt_request failed: %d\n", error); return error; } @@ -213,11 +213,10 @@ tryagain: goto tryagain; } - ferr("ERROR: NFS error %d from server\n", error); + PRINTK("ERROR: NFS error %d from server\n", error); return error; } - finfo("NFS_SUCCESS\n"); return OK; } @@ -235,12 +234,12 @@ tryagain: * ****************************************************************************/ -int nfs_lookup(struct nfsmount *nmp, FAR const char *filename, - FAR struct file_handle *fhandle, - FAR struct nfs_fattr *obj_attributes, - FAR struct nfs_fattr *dir_attributes) +int nfs_lookup(struct nfsmount *nmp, const char *filename, + struct file_handle *fhandle, + struct nfs_fattr *obj_attributes, + struct nfs_fattr *dir_attributes) { - FAR uint32_t *ptr; + uint32_t *ptr = NULL; uint32_t value; int reqlen; int namelen; @@ -259,7 +258,7 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename, /* Initialize the request */ - ptr = (FAR uint32_t *)&nmp->nm_msgbuffer.lookup.lookup; + ptr = (uint32_t *)&nmp->nm_msgbuffer.lookup.lookup; reqlen = 0; /* Copy the variable length, directory file handle */ @@ -283,8 +282,8 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename, nfs_statistics(NFSPROC_LOOKUP); error = nfs_request(nmp, NFSPROC_LOOKUP, - (FAR void *)&nmp->nm_msgbuffer.lookup, reqlen, - (FAR void *)nmp->nm_iobuffer, nmp->nm_buflen); + (void *)&nmp->nm_msgbuffer.lookup, reqlen, + (void *)nmp->nm_iobuffer, nmp->nm_buflen); if (error) { @@ -297,7 +296,7 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename, * may differ in size whereas struct rpc_reply_lookup uses a fixed size. */ - ptr = (FAR uint32_t *)&((FAR struct rpc_reply_lookup *)nmp->nm_iobuffer)->lookup; + ptr = (uint32_t *)&((struct rpc_reply_lookup *)nmp->nm_iobuffer)->lookup; /* Get the length of the file handle */ @@ -355,12 +354,12 @@ int nfs_lookup(struct nfsmount *nmp, FAR const char *filename, * ****************************************************************************/ -int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath, - FAR struct file_handle *fhandle, - FAR struct nfs_fattr *obj_attributes, - FAR struct nfs_fattr *dir_attributes) +int nfs_findnode(struct nfsmount *nmp, const char *relpath, + struct file_handle *fhandle, + struct nfs_fattr *obj_attributes, + struct nfs_fattr *dir_attributes) { - FAR const char *path = relpath; + const char *path = relpath; char buffer[NAME_MAX + 1]; char terminator; uint32_t tmp; @@ -464,11 +463,11 @@ int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath, * ****************************************************************************/ -int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath, - FAR struct file_handle *fhandle, - FAR struct nfs_fattr *attributes, FAR char *filename) +int nfs_finddir(struct nfsmount *nmp, const char *relpath, + struct file_handle *fhandle, + struct nfs_fattr *attributes, char *filename) { - FAR const char *path = relpath; + const char *path = relpath; uint32_t tmp; char terminator; int error; @@ -553,7 +552,7 @@ int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath, * ****************************************************************************/ -void nfs_attrupdate(FAR struct nfsnode *np, FAR struct nfs_fattr *attributes) +void nfs_attrupdate(struct nfsnode *np, struct nfs_fattr *attributes) { struct timespec ts; diff --git a/fs/nfs/rpc_clnt.c b/fs/nfs/rpc_clnt.c old mode 100755 new mode 100644 index c3b6960..b855ffc --- a/fs/nfs/rpc_clnt.c +++ b/fs/nfs/rpc_clnt.c @@ -134,16 +134,16 @@ static struct rpcstats rpcstats; * Private Function Prototypes ****************************************************************************/ -static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog, - FAR void *call, int reqlen); -static int rpcclnt_receive(FAR struct rpcclnt *rpc, struct sockaddr *aname, +static int rpcclnt_send(struct rpcclnt *rpc, int procid, int prog, + void *call, int reqlen); +static int rpcclnt_receive(struct rpcclnt *rpc, struct sockaddr *aname, int proc, int program, void *reply, size_t resplen); -static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog, +static int rpcclnt_reply(struct rpcclnt *rpc, int procid, int prog, void *reply, size_t resplen); static uint32_t rpcclnt_newxid(void); -static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, +static void rpcclnt_fmtheader(struct rpc_call_header *ch, uint32_t xid, int procid, int prog, int vers, size_t reqlen); -static int rpcclnt_reconnect(FAR struct rpcclnt *rpc, struct sockaddr *saddr); +static int rpcclnt_reconnect(struct rpcclnt *rpc, struct sockaddr *saddr); /**************************************************************************** * Private Functions @@ -160,8 +160,8 @@ static int rpcclnt_reconnect(FAR struct rpcclnt *rpc, struct sockaddr *saddr); * ****************************************************************************/ -static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog, - FAR void *call, int reqlen) +static int rpcclnt_send(struct rpcclnt *rpc, int procid, int prog, + void *call, int reqlen) { ssize_t nbytes; int ret = OK; @@ -196,8 +196,8 @@ static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog, * ****************************************************************************/ -static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname, - int proc, int program, FAR void *reply, +static int rpcclnt_receive(struct rpcclnt *rpc, struct sockaddr *aname, + int proc, int program, void *reply, size_t resplen) { ssize_t nbytes; @@ -261,8 +261,8 @@ retry: * ****************************************************************************/ -static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname, - int proc, int program, FAR void *reply, +static int rpcclnt_receive(struct rpcclnt *rpc, struct sockaddr *aname, + int proc, int program, void *reply, size_t resplen) { ssize_t nbytes; @@ -350,8 +350,8 @@ static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname, * ****************************************************************************/ -static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog, - FAR void *reply, size_t resplen) +static int rpcclnt_reply(struct rpcclnt *rpc, int procid, int prog, + void *reply, size_t resplen) { int error; @@ -378,8 +378,8 @@ static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog, else { - FAR struct rpc_reply_header *replyheader = - (FAR struct rpc_reply_header *)reply; + struct rpc_reply_header *replyheader = + (struct rpc_reply_header *)reply; if (replyheader->rp_direction != rpc_reply) { @@ -501,7 +501,7 @@ static int rpcclnt_alivecheck(struct rpcclnt *rpc) * ****************************************************************************/ -static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, +static void rpcclnt_fmtheader(struct rpc_call_header *ch, uint32_t xid, int prog, int vers, int procid, size_t reqlen) { unsigned int high = 0; @@ -545,7 +545,7 @@ static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, ch->rpc_verf.authlen = 0; } -static int rpcclnt_reconnect(FAR struct rpcclnt *rpc, struct sockaddr *saddr) +static int rpcclnt_reconnect(struct rpcclnt *rpc, struct sockaddr *saddr) { int errval; int error; @@ -732,15 +732,15 @@ int rpcclnt_connect(struct rpcclnt *rpc) request.sdata.pmap.port = 0; error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, - (FAR void *)&request.sdata, sizeof(struct call_args_pmap), - (FAR void *)&response.rdata, sizeof(struct rpc_reply_pmap)); + (void *)&request.sdata, sizeof(struct call_args_pmap), + (void *)&response.rdata, sizeof(struct rpc_reply_pmap)); if (error != 0) { ferr("ERROR: rpcclnt_request failed: %d\n", error); goto bad; } - sa = (FAR struct sockaddr_in *)saddr; + sa = (struct sockaddr_in *)saddr; sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); error = rpcclnt_reconnect(rpc, saddr); @@ -768,9 +768,9 @@ int rpcclnt_connect(struct rpcclnt *rpc) request.mountd.mount.len = txdr_unsigned(sizeof(request.mountd.mount.rpath)); error = rpcclnt_request(rpc, RPCMNT_MOUNT, RPCPROG_MNT, RPCMNT_VER3, - (FAR void *)&request.mountd, + (void *)&request.mountd, sizeof(struct call_args_mount), - (FAR void *)&response.mdata, + (void *)&response.mdata, sizeof(struct rpc_reply_mount)); if (error != 0) { @@ -807,9 +807,9 @@ int rpcclnt_connect(struct rpcclnt *rpc) request.sdata.pmap.port = 0; error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, - (FAR void *)&request.sdata, + (void *)&request.sdata, sizeof(struct call_args_pmap), - (FAR void *)&response.rdata, + (void *)&response.rdata, sizeof(struct rpc_reply_pmap)); if (error != 0) { @@ -878,7 +878,7 @@ int rpcclnt_umount(struct rpcclnt *rpc) int error; saddr = rpc->rc_name; - sa = (FAR struct sockaddr_in *)saddr; + sa = (struct sockaddr_in *)saddr; /* Do the RPC to get a dynamic bounding with the server using ppmap. * Get port number for MOUNTD. @@ -899,9 +899,9 @@ int rpcclnt_umount(struct rpcclnt *rpc) request.sdata.pmap.port = 0; error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, - (FAR void *)&request.sdata, + (void *)&request.sdata, sizeof(struct call_args_pmap), - (FAR void *)&response.rdata, + (void *)&response.rdata, sizeof(struct rpc_reply_pmap)); if (error != 0) { @@ -926,9 +926,9 @@ int rpcclnt_umount(struct rpcclnt *rpc) request.mountd.umount.len = txdr_unsigned(sizeof(request.mountd.umount.rpath)); error = rpcclnt_request(rpc, RPCMNT_UMOUNT, RPCPROG_MNT, RPCMNT_VER3, - (FAR void *)&request.mountd, + (void *)&request.mountd, sizeof(struct call_args_umount), - (FAR void *)&response.mdata, + (void *)&response.mdata, sizeof(struct rpc_reply_umount)); if (error != 0) { @@ -960,9 +960,9 @@ bad: * ****************************************************************************/ -int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, - int version, FAR void *request, size_t reqlen, - FAR void *response, size_t resplen) +int rpcclnt_request(struct rpcclnt *rpc, int procnum, int prog, + int version, void *request, size_t reqlen, + void *response, size_t resplen) { struct rpc_reply_header *replymsg; uint32_t tmp; @@ -983,7 +983,7 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, /* Initialize the RPC header fields */ - rpcclnt_fmtheader((FAR struct rpc_call_header *)request, + rpcclnt_fmtheader((struct rpc_call_header *)request, rpc->xid, prog, version, procnum, reqlen); /* Send the RPC call messsages and receive the RPC response. For UDP-RPC, A limited @@ -1081,7 +1081,7 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, /* Break down the RPC header and check if it is OK */ - replymsg = (FAR struct rpc_reply_header *)response; + replymsg = (struct rpc_reply_header *)response; tmp = fxdr_unsigned(uint32_t, replymsg->type); if (tmp == RPC_MSGDENIED) diff --git a/fs/tmpfs/fs_tmpfs.c b/fs/tmpfs/fs_tmpfs.c index 170b0a3..58c38eb 100755 --- a/fs/tmpfs/fs_tmpfs.c +++ b/fs/tmpfs/fs_tmpfs.c @@ -96,11 +96,17 @@ static int tmpfs_remove_dirent(FAR struct tmpfs_directory_s *tdo, static int tmpfs_add_dirent(FAR struct tmpfs_directory_s **tdo, FAR struct tmpfs_object_s *to, FAR const char *name); static FAR struct tmpfs_file_s *tmpfs_alloc_file(void); -static int tmpfs_create_file(FAR struct tmpfs_s *fs, - FAR const char *relpath, FAR struct tmpfs_file_s **tfo); +static int tmpfs_create_file(FAR struct tmpfs_s *fs, + FAR const char *relpath, + FAR struct tmpfs_directory_s *parent_input, + FAR struct tmpfs_file_s **tfo); + static FAR struct tmpfs_directory_s *tmpfs_alloc_directory(void); -static int tmpfs_create_directory(FAR struct tmpfs_s *fs, - FAR const char *relpath, FAR struct tmpfs_directory_s **tdo); +static int tmpfs_create_directory(FAR struct tmpfs_s *fs, + FAR const char *relpath, + FAR struct tmpfs_directory_s *parent, + FAR struct tmpfs_directory_s **tdo); + static int tmpfs_find_object(FAR struct tmpfs_s *fs, FAR const char *relpath, FAR struct tmpfs_object_s **object, FAR struct tmpfs_directory_s **parent); @@ -115,84 +121,68 @@ static int tmpfs_find_directory(FAR struct tmpfs_s *fs, /* File system operations */ -static int tmpfs_open(FAR struct file *filep, FAR const char *relpath, - int oflags, mode_t mode); -static int tmpfs_close(FAR struct file *filep); -static ssize_t tmpfs_read(FAR struct file *filep, FAR char *buffer, - size_t buflen); -static ssize_t tmpfs_write(FAR struct file *filep, FAR const char *buffer, - size_t buflen); -static off_t tmpfs_seek(FAR struct file *filep, off_t offset, int whence); -static loff_t tmpfs_seek64(FAR struct file *filep, loff_t offset, int whence); -static int tmpfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg); -static int tmpfs_dup(FAR const struct file *oldp, FAR struct file *newp); - -static int tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, - FAR struct fs_dirent_s *dir); -static int tmpfs_closedir(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir); -static int tmpfs_readdir(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir); -static int tmpfs_rewinddir(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir); -static int tmpfs_bind(FAR struct inode *blkdriver, FAR const void *data, - FAR void **handle, FAR const char *realpath); -static int tmpfs_unbind(FAR void *handle, FAR struct inode **blkdriver); -static int tmpfs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf); -static int tmpfs_unlink(FAR struct inode *mountpt, FAR const char *relpath); -static int tmpfs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, - mode_t mode); -static int tmpfs_rmdir(FAR struct inode *mountpt, FAR const char *relpath); -static int tmpfs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath, - FAR const char *newrelpath); +int tmpfs_close(struct file *filep); +off_t tmpfs_seek(FAR struct file *filep, off_t offset, int whence); +int tmpfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +int tmpfs_closedir(struct Vnode *node, struct fs_dirent_s *dir); +int tmpfs_rewinddir(struct Vnode *vp, struct fs_dirent_s *dir); +int tmpfs_truncate(struct Vnode *vp, off_t len); + +int tmpfs_mount(struct Mount *mnt, struct Vnode *device, const void *data); +int tmpfs_unmount(struct Mount *mnt, struct Vnode **blkdriver); + +int tmpfs_lookup(struct Vnode *parent, const char *name, int len, struct Vnode **vpp); +ssize_t tmpfs_write(struct file *filep, const char *buffer, size_t buflen); +ssize_t tmpfs_read(struct file *filep, char *buffer, size_t buflen); +int tmpfs_stat(struct Vnode *vp, struct stat *st); +int tmpfs_opendir(struct Vnode *vp, struct fs_dirent_s *dir); +int tmpfs_readdir(struct Vnode *vp, struct fs_dirent_s *dir); +int tmpfs_rename(struct Vnode *oldVnode, struct Vnode *newParent, const char *oldname, const char *newname); +int tmpfs_mkdir(struct Vnode *parent, const char *relpath, mode_t mode, struct Vnode **vpp); +int tmpfs_create(struct Vnode *dvp, const char *path, int mode, struct Vnode **vpp); +int tmpfs_unlink(struct Vnode *parent, struct Vnode *node, char *relpath); +int tmpfs_rmdir(struct Vnode *parent, struct Vnode *target, char *dirname); +int tmpfs_reclaim(struct Vnode *vp); + +int tmpfs_statfs(struct Mount *mp, struct statfs *sbp); + static void tmpfs_stat_common(FAR struct tmpfs_object_s *to, FAR struct stat *buf); -static int tmpfs_stat(FAR struct inode *mountpt, FAR const char *relpath, - FAR struct stat *buf); /**************************************************************************** * Public Data ****************************************************************************/ +const struct MountOps tmpfs_operations = { + .Mount = tmpfs_mount, + .Unmount = tmpfs_unmount, + .Statfs = tmpfs_statfs, +}; -const struct mountpt_operations tmpfs_operations = -{ - tmpfs_open, /* open */ - tmpfs_close, /* close */ - tmpfs_read, /* read */ - tmpfs_write, /* write */ - tmpfs_seek, /* seek */ - tmpfs_ioctl, /* ioctl */ - OsVfsFileMmap, /* mmap */ - NULL, /* sync */ - tmpfs_dup, /* dup */ - NULL, /* fstat */ - NULL, /* truncate */ - - tmpfs_opendir, /* opendir */ - tmpfs_closedir, /* closedir */ - tmpfs_readdir, /* readdir */ - tmpfs_rewinddir, /* rewinddir */ - - tmpfs_bind, /* bind */ - tmpfs_unbind, /* unbind */ - tmpfs_statfs, /* statfs */ - NULL, /* virstafs */ - tmpfs_unlink, /* unlink */ - tmpfs_mkdir, /* mkdir */ - tmpfs_rmdir, /* rmdir */ - tmpfs_rename, /* rename */ - tmpfs_stat, /* stat */ - NULL, /* utime */ - NULL, /* chattr */ - tmpfs_seek64, /* seek64 */ - NULL, /* getlabel */ - NULL, /* fallocate */ - NULL, /* fallocate64 */ - NULL, /* truncate64 */ - NULL, /* fscheck */ - NULL, /* map_pages */ - NULL, /* readpage */ - NULL, /* writepage */ +struct VnodeOps tmpfs_vops = { + .Lookup = tmpfs_lookup, + .Getattr = tmpfs_stat, + .Opendir = tmpfs_opendir, + .Readdir = tmpfs_readdir, + .Rename = tmpfs_rename, + .Mkdir = tmpfs_mkdir, + .Create = tmpfs_create, + .Unlink = tmpfs_unlink, + .Rmdir = tmpfs_rmdir, + .Reclaim = tmpfs_reclaim, + .Closedir = tmpfs_closedir, + .Close = NULL, + .Rewinddir = tmpfs_rewinddir, + .Truncate = tmpfs_truncate, +}; + +struct file_operations_vfs tmpfs_fops = { + .seek = tmpfs_seek, + .write = tmpfs_write, + .read = tmpfs_read, + .ioctl = tmpfs_ioctl, + .mmap = OsVfsFileMmap, + .close = tmpfs_close, + .fsync = NULL, }; static struct tmpfs_s tmpfs_superblock = {0}; @@ -201,6 +191,26 @@ static struct tmpfs_s tmpfs_superblock = {0}; * Private Functions ****************************************************************************/ +static mode_t type_to_mode(int type, mode_t permission) +{ + switch (type) { + case VNODE_TYPE_DIR: + return permission | S_IFDIR; + case VNODE_TYPE_REG: + return permission | S_IFREG; + case VNODE_TYPE_BLK: + return permission | S_IFBLK; + case VNODE_TYPE_CHR: + return permission | S_IFCHR; + case VNODE_TYPE_FIFO: + return permission | S_IFIFO; + default: + break; + } + PRINTK("mode to type failed, unknwon type = %d\n", type); + return permission; +} + /**************************************************************************** * Name: tmpfs_timestamp ****************************************************************************/ @@ -332,7 +342,10 @@ static void tmpfs_release_lockedobject(FAR struct tmpfs_object_s *to) } else { - to->to_refs--; + if(to->to_refs > 0) + { + to->to_refs--; + } tmpfs_unlock_object(to); } } @@ -360,7 +373,10 @@ static void tmpfs_release_lockedfile(FAR struct tmpfs_file_s *tfo) else { - tfo->tfo_refs--; + if(tfo->tfo_refs > 0) + { + tfo->tfo_refs--; + } tmpfs_unlock_file(tfo); } } @@ -426,8 +442,10 @@ static int tmpfs_remove_dirent(FAR struct tmpfs_directory_s *tdo, tde->tde_inuse = false; tde->tde_object = NULL; } - - tdo->tdo_nentries--; + if(tdo->tdo_nentries > 0) + { + tdo->tdo_nentries--; + } return OK; } @@ -527,13 +545,13 @@ static FAR struct tmpfs_file_s *tmpfs_alloc_file(void) static int tmpfs_create_file(FAR struct tmpfs_s *fs, FAR const char *relpath, + FAR struct tmpfs_directory_s *parent_input, FAR struct tmpfs_file_s **tfo) { FAR struct tmpfs_directory_s *parent; FAR struct tmpfs_file_s *newtfo; struct tmpfs_dirent_s *tde; FAR char *copy; - FAR char *name; int ret; /* Duplicate the path variable so that we can modify it */ @@ -547,13 +565,9 @@ static int tmpfs_create_file(FAR struct tmpfs_s *fs, /* Separate the path into the file name and the path to the parent * directory. */ - - name = strrchr(copy, '/'); - if (name == NULL) + if (parent_input == NULL) { /* No subdirectories... use the root directory */ - - name = copy; parent = (FAR struct tmpfs_directory_s *)fs->tfs_root.tde_object; /* Lock the root directory to emulate the behavior of tmpfs_find_directory() */ @@ -563,25 +577,16 @@ static int tmpfs_create_file(FAR struct tmpfs_s *fs, } else { - /* Terminate the parent directory path */ - - *name++ = '\0'; - - /* Locate the parent directory that should contain this name. - * On success, tmpfs_find_directory() will lock the parent - * directory and increment the reference count. - */ - - ret = tmpfs_find_directory(fs, copy, &parent, NULL); - if (ret < 0) - { - goto errout_with_copy; - } + parent = parent_input; + } + if (parent == NULL) + { + ret = -EEXIST; + goto errout_with_copy; } /* Verify that no object of this name already exists in the directory */ - - tde = tmpfs_find_dirent(parent, name); + tde = tmpfs_find_dirent(parent, copy); if (tde != NULL) { /* Something with this name already exists in the directory. @@ -605,15 +610,17 @@ static int tmpfs_create_file(FAR struct tmpfs_s *fs, /* Then add the new, empty file to the directory */ - ret = tmpfs_add_dirent(&parent, (FAR struct tmpfs_object_s *)newtfo, name); + ret = tmpfs_add_dirent(&parent, (FAR struct tmpfs_object_s *)newtfo, copy); if (ret < 0) { goto errout_with_file; } /* Release the reference and lock on the parent directory */ - - parent->tdo_refs--; + if (parent->tdo_refs > 0) + { + parent->tdo_refs--; + } tmpfs_unlock_directory(parent); /* Free the copy of the relpath and return success */ @@ -629,7 +636,10 @@ errout_with_file: kmm_free(newtfo); errout_with_parent: - parent->tdo_refs--; + if (parent->tdo_refs > 0) + { + parent->tdo_refs--; + } tmpfs_unlock_directory(parent); errout_with_copy: @@ -681,13 +691,13 @@ static FAR struct tmpfs_directory_s *tmpfs_alloc_directory(void) static int tmpfs_create_directory(FAR struct tmpfs_s *fs, FAR const char *relpath, + FAR struct tmpfs_directory_s *parent_input, FAR struct tmpfs_directory_s **tdo) { FAR struct tmpfs_directory_s *parent; FAR struct tmpfs_directory_s *newtdo; struct tmpfs_dirent_s *tde; FAR char *copy; - FAR char *name; int ret; /* Duplicate the path variable so that we can modify it */ @@ -701,13 +711,10 @@ static int tmpfs_create_directory(FAR struct tmpfs_s *fs, /* Separate the path into the file name and the path to the parent * directory. */ - - name = strrchr(copy, '/'); - if (name == NULL) + if (parent_input == NULL) { /* No subdirectories... use the root directory */ - name = copy; parent = (FAR struct tmpfs_directory_s *)fs->tfs_root.tde_object; tmpfs_lock_directory(parent); @@ -715,25 +722,16 @@ static int tmpfs_create_directory(FAR struct tmpfs_s *fs, } else { - /* Terminate the parent directory path */ - - *name++ = '\0'; - - /* Locate the parent directory that should contain this name. - * On success, tmpfs_find_directory() will lockthe parent - * directory and increment the reference count. - */ - - ret = tmpfs_find_directory(fs, copy, &parent, NULL); - if (ret < 0) - { - goto errout_with_copy; - } + parent = parent_input; } /* Verify that no object of this name already exists in the directory */ - - tde = tmpfs_find_dirent(parent, name); + if (parent == NULL) + { + ret = -EEXIST; + goto errout_with_copy; + } + tde = tmpfs_find_dirent(parent, copy); if (tde != NULL) { /* Something with this name already exists in the directory. @@ -758,7 +756,7 @@ static int tmpfs_create_directory(FAR struct tmpfs_s *fs, /* Then add the new, empty file to the directory */ - ret = tmpfs_add_dirent(&parent, (FAR struct tmpfs_object_s *)newtdo, name); + ret = tmpfs_add_dirent(&parent, (FAR struct tmpfs_object_s *)newtdo, copy); if (ret < 0) { goto errout_with_directory; @@ -767,8 +765,10 @@ static int tmpfs_create_directory(FAR struct tmpfs_s *fs, /* Free the copy of the relpath, release our reference to the parent directory, * and return success */ - - parent->tdo_refs--; + if (parent->tdo_refs > 0) + { + parent->tdo_refs--; + } tmpfs_unlock_directory(parent); kmm_free(copy); @@ -788,7 +788,10 @@ errout_with_directory: kmm_free(newtdo); errout_with_parent: - parent->tdo_refs--; + if (parent->tdo_refs > 0) + { + parent->tdo_refs--; + } tmpfs_unlock_directory(parent); errout_with_copy: @@ -1023,177 +1026,22 @@ static int tmpfs_find_directory(FAR struct tmpfs_s *fs, } /**************************************************************************** - * Name: tmpfs_open + * Name: tmpfs_close ****************************************************************************/ -static int tmpfs_open(FAR struct file *filep, FAR const char *relpath, - int oflags, mode_t mode) +int tmpfs_close(struct file *filep) { - FAR struct inode *inode; - FAR struct tmpfs_s *fs; FAR struct tmpfs_file_s *tfo; - off_t offset; - int ret; finfo("filep: %p\n", filep); - DEBUGASSERT(filep->f_priv == NULL && filep->f_inode != NULL); + DEBUGASSERT(filep != NULL); - if (oflags & O_DIRECTORY) + /* Recover our private data from the struct file instance */ + tfo = (FAR struct tmpfs_file_s *)(filep->f_vnode->data); + if (tfo == NULL) { return -EINVAL; } - - /* Get the mountpoint inode reference from the file structure and the - * mountpoint private data from the inode structure - */ - - inode = filep->f_inode; - fs = inode->i_private; - - DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL); - - /* Get exclusive access to the file system */ - - tmpfs_lock(fs); - - /* Skip over any leading directory separators (shouldn't be any) */ - - for (; *relpath == '/'; relpath++); - - /* Find the file object associated with this relative path. - * If successful, this action will lock both the parent directory and - * the file object, adding one to the reference count of both. - * In the event that -ENOENT, there will still be a reference and - * lock on the returned directory. - */ - - ret = tmpfs_find_file(fs, relpath, &tfo, NULL); - if (ret >= 0) - { - /* The file exists. We hold the lock and one reference count - * on the file object. - * - * It would be an error if we are asked to create it exclusively - */ - - if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) - { - /* Already exists -- can't create it exclusively */ - - ret = -EEXIST; - goto errout_with_filelock; - } - - /* Check if the caller has sufficient privileges to open the file. - * REVISIT: No file protection implemented - */ - - /* If O_TRUNC is specified and the file is opened for writing, - * then truncate the file. This operation requires that the file is - * writeable, but we have already checked that. O_TRUNC without write - * access is ignored. - */ - - if (oflags & O_TRUNC) - { - /* Truncate the file to zero length (if it is not already - * zero length) - */ - - if (tfo->tfo_size > 0 && tfo->tfo_data != NULL) - { - kmm_free(tfo->tfo_data); - tfo->tfo_size = 0; - tfo->tfo_data = (char *)NULL; - } - - /* Update file times */ - - tfo->tfo_mtime = tfo->tfo_ctime = tmpfs_timestamp(); - } - } - - /* ENOENT would be returned by tmpfs_find_file() if the full directory - * path was found, but the file was not found in the final directory. - */ - - else if (ret == -ENOENT) - { - /* The file does not exist. Were we asked to create it? */ - - if ((oflags & O_CREAT) == 0) - { - /* No.. then we fail with -ENOENT */ - - ret = -ENOENT; - goto errout_with_fslock; - } - - /* Yes.. create the file object. There will be a reference and a lock - * on the new file object. - */ - - ret = tmpfs_create_file(fs, relpath, &tfo); - if (ret < 0) - { - goto errout_with_fslock; - } - } - - /* Some other error occurred */ - - else - { - goto errout_with_fslock; - } - - /* Save the struct tmpfs_file_s instance as the file private data */ - - filep->f_priv = tfo; - - /* In write/append mode, we need to set the file pointer to the end of the - * file. - */ - - offset = 0; - if (oflags & O_APPEND) - { - offset = tfo->tfo_size; - } - - filep->f_pos = offset; - - /* Unlock the file file object, but retain the reference count */ - - tmpfs_unlock_file(tfo); - tmpfs_unlock(fs); - return OK; - - /* Error exits */ - -errout_with_filelock: - tmpfs_release_lockedfile(tfo); - -errout_with_fslock: - tmpfs_unlock(fs); - return ret; -} - -/**************************************************************************** - * Name: tmpfs_close - ****************************************************************************/ - -static int tmpfs_close(FAR struct file *filep) -{ - FAR struct tmpfs_file_s *tfo; - - finfo("filep: %p\n", filep); - DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); - - /* Recover our private data from the struct file instance */ - - tfo = filep->f_priv; - /* Get exclusive access to the file */ tmpfs_lock_file(tfo); @@ -1204,12 +1052,6 @@ static int tmpfs_close(FAR struct file *filep) { tfo->tfo_refs--; } - else - { - return -EPERM; - } - - filep->f_priv = NULL; /* If the reference count decremented to zero and the file has been * unlinked, then free the file allocation now. @@ -1238,8 +1080,7 @@ static int tmpfs_close(FAR struct file *filep) * Name: tmpfs_read ****************************************************************************/ -static ssize_t tmpfs_read(FAR struct file *filep, FAR char *buffer, - size_t buflen) +ssize_t tmpfs_read(struct file *filep, char *buffer, size_t buflen) { FAR struct tmpfs_file_s *tfo; ssize_t nread; @@ -1252,7 +1093,11 @@ static ssize_t tmpfs_read(FAR struct file *filep, FAR char *buffer, /* Recover our private data from the struct file instance */ - tfo = filep->f_priv; + tfo = (FAR struct tmpfs_file_s *)(filep->f_vnode->data); + if (tfo == NULL) + { + return -EINVAL; + } if (filep->f_pos >= tfo->tfo_size || buflen == 0) { return 0; @@ -1293,6 +1138,68 @@ static ssize_t tmpfs_read(FAR struct file *filep, FAR char *buffer, return nread; } +/**************************************************************************** + * Name: tmpfs_create + ****************************************************************************/ + +int tmpfs_create(struct Vnode *dvp, const char *path, int mode, struct Vnode **vpp) +{ + struct Vnode *vp = NULL; + FAR struct tmpfs_file_s *tfo; + FAR struct tmpfs_s *fs; + int ret = 0; + FAR struct tmpfs_directory_s *parent_tdo = NULL; + + if (dvp == NULL) + { + return -ENOENT; + } + + fs = dvp->originMount->data; + if (fs == NULL) + { + return -ENOENT; + } + + tmpfs_lock(fs); + + if (dvp->data != NULL) + { + parent_tdo = (FAR struct tmpfs_directory_s *)(dvp->data); + } + + ret = tmpfs_create_file(fs, path, parent_tdo, &tfo); + if (ret < 0) + { + goto errout_with_fslock; + } + + ret = VnodeAlloc(&tmpfs_vops, &vp); + if (ret != 0) + { + tmpfs_unlock_file(tfo); + goto errout_with_fslock; + } + vp->parent = dvp; + vp->vop = dvp->vop; + vp->fop = dvp->fop; + vp->data = tfo; + vp->originMount = dvp->originMount; + vp->type = VNODE_TYPE_REG; + vp->mode = type_to_mode(vp->type, fs->permission); + vp->gid = fs->gid; + vp->uid = fs->uid; + + ret = VfsHashInsert(vp, (uint32_t)tfo); + + *vpp = vp; + tmpfs_unlock_file(tfo); +errout_with_fslock: + tmpfs_unlock(fs); + return 0; +} + + /**************************************************************************** * Name: los_set_ramfs_unit ****************************************************************************/ @@ -1315,8 +1222,7 @@ void los_set_ramfs_unit(off_t size) * Name: tmpfs_write ****************************************************************************/ -static ssize_t tmpfs_write(FAR struct file *filep, FAR const char *buffer, - size_t buflen) +ssize_t tmpfs_write(struct file *filep, const char *buffer, size_t buflen) { FAR struct tmpfs_file_s *tfo; ssize_t nwritten; @@ -1332,13 +1238,15 @@ static ssize_t tmpfs_write(FAR struct file *filep, FAR const char *buffer, if (buflen == 0) { - return 0; + return 0; } /* Recover our private data from the struct file instance */ - - tfo = filep->f_priv; - + tfo = (FAR struct tmpfs_file_s *)(filep->f_vnode->data); + if (tfo == NULL) + { + return -EINVAL; + } /* Get exclusive access to the file */ tmpfs_lock_file(tfo); @@ -1412,18 +1320,21 @@ errout_with_lock: * Name: tmpfs_seek ****************************************************************************/ -static off_t tmpfs_seek(FAR struct file *filep, off_t offset, int whence) +off_t tmpfs_seek(FAR struct file *filep, off_t offset, int whence) { FAR struct tmpfs_file_s *tfo; off_t position; finfo("filep: %p\n", filep); - DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + DEBUGASSERT(filep->f_priv != NULL && filep->f_vnode != NULL); /* Recover our private data from the struct file instance */ - tfo = filep->f_priv; - + tfo = (FAR struct tmpfs_file_s *)(filep->f_vnode->data); + if (tfo == NULL) + { + return -EINVAL; + } /* Map the offset according to the whence option */ switch (whence) @@ -1452,17 +1363,7 @@ static off_t tmpfs_seek(FAR struct file *filep, off_t offset, int whence) * REVISIT: This simple implementation has no per-open storage that * would be needed to retain the open flags. */ - -#if 0 - if (position > tfo->tfo_size && (tfo->tfo_oflags & O_WROK) == 0) - { - /* Otherwise, the position is limited to the file size */ - - position = tfo->tfo_size; - } -#endif - - if (position < 0) + if (position < 0) { return -EINVAL; } @@ -1473,55 +1374,33 @@ static off_t tmpfs_seek(FAR struct file *filep, off_t offset, int whence) return position; } -/**************************************************************************** - * Name: tmpfs_seek64 - ****************************************************************************/ - -static loff_t tmpfs_seek64(FAR struct file *filep, loff_t offset, int whence) -{ - return (loff_t)tmpfs_seek(filep, (off_t)offset, whence); -} - /**************************************************************************** * Name: tmpfs_ioctl ****************************************************************************/ -static int tmpfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +int tmpfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { return -EINVAL; } - -/**************************************************************************** - * Name: tmpfs_dup - ****************************************************************************/ - -static int tmpfs_dup(FAR const struct file *oldp, FAR struct file *newp) -{ - return -1; -} - - /**************************************************************************** * Name: tmpfs_opendir ****************************************************************************/ -static int tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, - FAR struct fs_dirent_s *dir) +int tmpfs_opendir(struct Vnode *vp, struct fs_dirent_s *dir) { FAR struct tmpfs_s *fs; FAR struct tmpfs_directory_s *tdo; - int ret; + int ret = 0; FAR struct fs_tmpfsdir_s *tmp; - finfo("mountpt: %p relpath: %s dir: %p\n", - mountpt, relpath, dir); - DEBUGASSERT(mountpt != NULL && relpath != NULL && dir != NULL); + finfo("vp: %p dir: %p\n", vp, dir); + DEBUGASSERT(vp != NULL && dir != NULL); /* Get the mountpoint private data from the inode structure */ - fs = mountpt->i_private; - DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL); + fs = vp->originMount->data; + DEBUGASSERT(fs != NULL); tmp = (FAR struct fs_tmpfsdir_s *)malloc(sizeof(struct fs_tmpfsdir_s)); if (!tmp) @@ -1533,10 +1412,6 @@ static int tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, tmpfs_lock(fs); - /* Skip over any leading directory separators (shouldn't be any) */ - - for (; *relpath == '/'; relpath++); - /* Find the directory object associated with this relative path. * If successful, this action will lock both the parent directory and * the file object, adding one to the reference count of both. @@ -1544,19 +1419,27 @@ static int tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, * lock on the returned directory. */ - ret = tmpfs_find_directory(fs, relpath, &tdo, NULL); - if (ret >= 0) + if (vp->data != NULL) { - tmp->tf_tdo = tdo; - tmp->tf_index = 0; - dir->u.fs_dir = (fs_dir_s)tmp; - tdo->tdo_count++; - tmpfs_unlock_directory(tdo); + tdo = (FAR struct tmpfs_directory_s *)vp->data; } else + { + tdo = (FAR struct tmpfs_directory_s *)fs->tfs_root.tde_object; + } + + if (tdo == NULL) { free(tmp); + tmpfs_unlock(fs); + return -EINTR; } + tmp->tf_tdo = tdo; + tmp->tf_index = 0; + dir->u.fs_dir = (fs_dir_s)tmp; + tdo->tdo_count++; + tdo->tdo_refs++; + tmpfs_unlock_directory(tdo); /* Release the lock on the file system and return the result */ @@ -1568,18 +1451,21 @@ static int tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, * Name: tmpfs_closedir ****************************************************************************/ -static int tmpfs_closedir(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir) +int tmpfs_closedir(struct Vnode *vp, struct fs_dirent_s *dir) { FAR struct tmpfs_directory_s *tdo; struct fs_tmpfsdir_s *tmp; - finfo("mountpt: %p dir: %p\n", mountpt, dir); - DEBUGASSERT(mountpt != NULL && dir != NULL); + finfo("vp: %p dir: %p\n", vp, dir); + DEBUGASSERT(vp != NULL && dir != NULL); /* Get the directory structure from the dir argument */ tmp = (FAR struct fs_tmpfsdir_s *)dir->u.fs_dir; + if (tmp == NULL) + { + return -ENOENT; + } tdo = tmp->tf_tdo; DEBUGASSERT(tdo != NULL); @@ -1601,8 +1487,14 @@ static int tmpfs_closedir(FAR struct inode *mountpt, } } } - tdo->tdo_refs--; - tdo->tdo_count--; + if (tdo->tdo_refs > 0) + { + tdo->tdo_refs--; + } + if (tdo->tdo_count > 0) + { + tdo->tdo_count--; + } tmpfs_unlock_directory(tdo); free(tmp); @@ -1614,8 +1506,7 @@ static int tmpfs_closedir(FAR struct inode *mountpt, * Name: tmpfs_readdir ****************************************************************************/ -static int tmpfs_readdir(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir) +int tmpfs_readdir(struct Vnode *vp, struct fs_dirent_s *dir) { FAR struct tmpfs_directory_s *tdo; unsigned int index; @@ -1624,14 +1515,22 @@ static int tmpfs_readdir(FAR struct inode *mountpt, LOS_DL_LIST *node; FAR struct tmpfs_dirent_s *tde; - finfo("mountpt: %p dir: %p\n", mountpt, dir); - DEBUGASSERT(mountpt != NULL && dir != NULL); + finfo("vp: %p dir: %p\n", vp, dir); + DEBUGASSERT(vp != NULL && dir != NULL); /* Get the directory structure from the dir argument and lock it */ tmp = (FAR struct fs_tmpfsdir_s *)dir->u.fs_dir; + if (tmp == NULL) + { + return -ENOENT; + } + tdo = tmp->tf_tdo; - DEBUGASSERT(tdo != NULL); + if (tdo == NULL) + { + return -ENOENT; + } tmpfs_lock_directory(tdo); @@ -1706,12 +1605,11 @@ static int tmpfs_readdir(FAR struct inode *mountpt, * Name: tmpfs_rewinddir ****************************************************************************/ -static int tmpfs_rewinddir(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir) +int tmpfs_rewinddir(struct Vnode *vp, struct fs_dirent_s *dir) { struct fs_tmpfsdir_s *tmp; - fvdbg("mountpt: %p dir: %p\n", mountpt, dir); - DEBUGASSERT(mountpt != NULL && dir != NULL); + fvdbg("vp: %p dir: %p\n", vp, dir); + DEBUGASSERT(vp != NULL && dir != NULL); tmp = (struct fs_tmpfsdir_s *)dir->u.fs_dir; /* Set the readdir index to zero */ @@ -1720,18 +1618,34 @@ static int tmpfs_rewinddir(FAR struct inode *mountpt, return OK; } +int tmpfs_truncate(struct Vnode *vp, off_t len) +{ + FAR struct tmpfs_file_s *tfo = NULL; + + tfo = vp->data; + tfo->tfo_size = 0; + + if (tfo->tfo_data) + { + free(tfo->tfo_data); + } + + return OK; +} + + /**************************************************************************** - * Name: tmpfs_bind + * Name: tmpfs_mount ****************************************************************************/ -static int tmpfs_bind(FAR struct inode *blkdriver, FAR const void *data, - FAR void **handle, FAR const char *relpath) +int tmpfs_mount(struct Mount *mnt, struct Vnode *device, const void *data) { FAR struct tmpfs_directory_s *tdo; FAR struct tmpfs_s *fs = &tmpfs_superblock; + struct Vnode *vp = NULL; + int ret; - finfo("blkdriver: %p data: %p handle: %p\n", blkdriver, data, handle); - DEBUGASSERT(blkdriver == NULL && handle != NULL); + DEBUGASSERT(device == NULL && data != NULL); if (fs->tfs_root.tde_object != NULL) { @@ -1764,19 +1678,42 @@ static int tmpfs_bind(FAR struct inode *blkdriver, FAR const void *data, /* Return the new file system handle */ - *handle = (FAR void *)fs; spin_lock_init(&tmpfs_alloc_unit_lock); is_tmpfs_lock_init = true; + + ret = VnodeAlloc(&tmpfs_vops, &vp); + if (ret != 0) + { + ret = ENOMEM; + goto ERROR_WITH_FSWIN; + } + + fs->permission = mnt->vnodeBeCovered->mode & 0777; + fs->gid = mnt->vnodeBeCovered->gid; + fs->uid = mnt->vnodeBeCovered->uid; + vp->originMount = mnt; + vp->fop = &tmpfs_fops; + vp->type = VNODE_TYPE_DIR; + vp->data = NULL; + vp->mode = type_to_mode(vp->type, fs->permission); + vp->gid = fs->gid; + vp->uid = fs->uid; + mnt->data = fs; + mnt->vnodeCovered = vp; + return OK; + +ERROR_WITH_FSWIN: + return ret; } /**************************************************************************** - * Name: tmpfs_unbind + * Name: tmpfs_unmount ****************************************************************************/ -static int tmpfs_unbind(FAR void *handle, FAR struct inode **blkdriver) +int tmpfs_unmount(struct Mount *mnt, struct Vnode **blkdriver) { - FAR struct tmpfs_s *fs = (FAR struct tmpfs_s *)handle; + FAR struct tmpfs_s *fs = (FAR struct tmpfs_s *)mnt->data; FAR struct tmpfs_directory_s *tdo; int ret = 0; @@ -1788,6 +1725,11 @@ static int tmpfs_unbind(FAR void *handle, FAR struct inode **blkdriver) tmpfs_lock(fs); tdo = (FAR struct tmpfs_directory_s *)fs->tfs_root.tde_object; + if (tdo == NULL) + { + ret = -EINVAL; + goto errout_with_objects; + } if (tdo->tdo_nentries > 0 || tdo->tdo_refs > 1) { @@ -1812,15 +1754,128 @@ errout_with_objects: return ret; } + +int tmpfs_lookup(struct Vnode *parent, const char *relPath, int len, struct Vnode **vpp) +{ + // 1. when first time create file, lookup fail, then call tmpfs_create. + // 2. when ls, lookup will success to show. + // 3. when cd, lookup success. + FAR struct tmpfs_object_s *to; + FAR struct tmpfs_s *fs; + struct tmpfs_dirent_s *tde = NULL; + FAR struct tmpfs_directory_s *parent_tdo; + + struct Vnode *vp = NULL; + int ret = 0; + char filename[len + 1]; + ret = memcpy_s(filename, (len + 1), relPath, len); + if (ret != 0) + { + ret = -ENOMEM; + goto errout; + } + filename[len] = '\0'; + + fs = parent->originMount->data; + DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL); + + tmpfs_lock(fs); + + parent_tdo = (FAR struct tmpfs_directory_s *)(parent->data); + + if (parent_tdo == NULL) + { + // if parent_tdo don't exist, find file in root. + ret = tmpfs_find_object(fs, filename, &to, NULL); + if (ret < 0) + { + goto errout_with_lock; + } + } + else + { + PRINTK("tmpfs_lookup parent_tdo->tdo_type = %d\n", parent_tdo->tdo_type); + if (parent_tdo->tdo_type != TMPFS_DIRECTORY) + { + ret = -ENOENT; + goto errout_with_lock; + } + // if parent_tdo exist£¬search for the relationship between parent_tdo and the current dirname. + tde = tmpfs_find_dirent(parent_tdo, filename); + if (tde == NULL) + { + ret = -ENOENT; + goto errout_with_lock; + } + to = tde->tde_object; + } + + if (to == NULL) + { + ret = -ENOENT; + goto errout_with_lock; + } + + ret = VfsHashGet(parent->originMount, (uint32_t)to, &vp, NULL, NULL); + if (ret != 0) + { + ret = -ENOENT; + goto errout_with_objects; + } + + if (vp == NULL) + { + ret = VnodeAlloc(&tmpfs_vops, &vp); + if (ret != 0) + { + PRINTK("%s-%d \n", __FUNCTION__, __LINE__); + goto errout_with_objects; + } + + vp->parent = parent; + vp->vop = parent->vop; + vp->fop = parent->fop; + vp->data = to; + vp->originMount = parent->originMount; + vp->type = to->to_type == TMPFS_REGULAR ? VNODE_TYPE_REG : VNODE_TYPE_DIR; + vp->mode = type_to_mode(vp->type, fs->permission); + vp->gid = fs->gid; + vp->uid = fs->uid; + + ret = VfsHashInsert(vp, (uint32_t)to); + } + + *vpp = vp; + + tmpfs_release_lockedobject(to); + tmpfs_unlock(fs); + + return 0; + +errout_with_objects: + tmpfs_release_lockedobject(to); +errout_with_lock: + tmpfs_unlock(fs); +errout: + return ret; +} + +int tmpfs_reclaim(struct Vnode *vp) +{ + vp->data = NULL; + return 0; +} + /**************************************************************************** * Name: tmpfs_statfs ****************************************************************************/ -static int tmpfs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf) +int tmpfs_statfs(struct Mount *mp, struct statfs *sbp) { - (void)memset_s(buf, sizeof(struct statfs), 0, sizeof(struct statfs)); + (void)memset_s(sbp, sizeof(struct statfs), 0, sizeof(struct statfs)); - buf->f_type = TMPFS_MAGIC; + sbp->f_type = TMPFS_MAGIC; + sbp->f_flags = mp->mountFlags; return OK; } @@ -1829,16 +1884,15 @@ static int tmpfs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf) * Name: tmpfs_unlink ****************************************************************************/ -static int tmpfs_unlink(FAR struct inode *mountpt, FAR const char *relpath) +int tmpfs_unlink(struct Vnode *parent, struct Vnode *node, char *relpath) { FAR struct tmpfs_s *fs; - FAR struct tmpfs_directory_s *tdo; + FAR struct tmpfs_directory_s *parent_dir; FAR struct tmpfs_file_s *tfo = NULL; - FAR const char *name; int ret; - finfo("mountpt: %p relpath: %s\n", mountpt, relpath); - DEBUGASSERT(mountpt != NULL && relpath != NULL); + finfo("mountpt: %p node: %p relpath: %s\n", parent, node, relpath); + DEBUGASSERT(parent != NULL && node != NULL && relpath != NULL); if (strlen(relpath) == 0) { @@ -1846,8 +1900,17 @@ static int tmpfs_unlink(FAR struct inode *mountpt, FAR const char *relpath) } /* Get the file system structure from the inode reference. */ + if (node->originMount == NULL) + { + return -EISDIR; + } + + fs = node->originMount->data; + if (fs == NULL) + { + return -EISDIR; + } - fs = mountpt->i_private; DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL); /* Get exclusive access to the file system */ @@ -1859,33 +1922,29 @@ static int tmpfs_unlink(FAR struct inode *mountpt, FAR const char *relpath) * and the parent directory and take one reference count on each. */ - ret = tmpfs_find_file(fs, relpath, &tfo, &tdo); - if (ret < 0) + parent_dir = (FAR struct tmpfs_directory_s *)(parent->data); + if (parent_dir == NULL) { - goto errout_with_lock; - } - - DEBUGASSERT(tfo != NULL); - - /* Get the file name from the relative path */ - - name = strrchr(relpath, '/'); - if (name != NULL) - { - /* Skip over the file '/' character */ - - name++; + ret = tmpfs_find_file(fs, relpath, &tfo, &parent_dir); + if (ret < 0) + { + goto errout_with_lock; + } } else { - /* The name must lie in the root directory */ + tfo = (FAR struct tmpfs_file_s *)node->data; + } - name = relpath; + if (tfo == NULL || parent_dir == NULL) + { + ret = -EISDIR; + goto errout_with_lock; } + DEBUGASSERT(tfo != NULL); /* Remove the file from parent directory */ - - ret = tmpfs_remove_dirent(tdo, (struct tmpfs_object_s *)tfo); + ret = tmpfs_remove_dirent(parent_dir, (struct tmpfs_object_s *)tfo); if (ret < 0) { goto errout_with_objects; @@ -1914,12 +1973,16 @@ static int tmpfs_unlink(FAR struct inode *mountpt, FAR const char *relpath) sem_destroy(&tfo->tfo_exclsem.ts_sem); kmm_free(tfo->tfo_data); kmm_free(tfo); + node->data = NULL; } /* Release the reference and lock on the parent directory */ - tdo->tdo_refs--; - tmpfs_unlock_directory(tdo); + if (parent_dir->tdo_refs > 0) + { + parent_dir->tdo_refs--; + } + tmpfs_unlock_directory(parent_dir); tmpfs_unlock(fs); return OK; @@ -1927,8 +1990,12 @@ static int tmpfs_unlink(FAR struct inode *mountpt, FAR const char *relpath) errout_with_objects: tmpfs_release_lockedfile(tfo); - tdo->tdo_refs--; - tmpfs_unlock_directory(tdo); + if (parent_dir->tdo_refs > 0) + { + parent_dir->tdo_refs--; + } + + tmpfs_unlock_directory(parent_dir); errout_with_lock: tmpfs_unlock(fs); @@ -1939,14 +2006,16 @@ errout_with_lock: * Name: tmpfs_mkdir ****************************************************************************/ -static int tmpfs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, - mode_t mode) +int tmpfs_mkdir(struct Vnode *parent, const char *relpath, mode_t mode, struct Vnode **vpp) { FAR struct tmpfs_s *fs; + struct Vnode *vp = NULL; + FAR struct tmpfs_directory_s *tdo; + FAR struct tmpfs_directory_s *parent_tdo = NULL; int ret; - finfo("mountpt: %p relpath: %s mode: %04x\n", mountpt, relpath, mode); - DEBUGASSERT(mountpt != NULL && relpath != NULL); + finfo("parent: %p relpath: %s mode: %04x\n", parent, relpath, mode); + DEBUGASSERT(parent != NULL && relpath != NULL); if (strlen(relpath) == 0) { @@ -1955,16 +2024,44 @@ static int tmpfs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, /* Get the file system structure from the inode reference. */ - fs = mountpt->i_private; + fs = parent->originMount->data; DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL); /* Get exclusive access to the file system */ tmpfs_lock(fs); + if (parent->data != NULL) + { + parent_tdo = (FAR struct tmpfs_directory_s *)(parent->data); + } /* Create the directory. */ + ret = tmpfs_create_directory(fs, relpath, parent_tdo, &tdo); + if (ret != OK) + { + goto errout_with_lock; + } - ret = tmpfs_create_directory(fs, relpath, NULL); + ret = VnodeAlloc(&tmpfs_vops, &vp); + if (ret != 0) + { + goto errout_with_lock; + } + + vp->parent = parent; + vp->vop = parent->vop; + vp->fop = parent->fop; + vp->data = tdo; + vp->originMount = parent->originMount; + vp->type = VNODE_TYPE_DIR; + vp->mode = type_to_mode(vp->type, fs->permission); + vp->gid = fs->gid; + vp->uid = fs->uid; + + ret = VfsHashInsert(vp, (uint32_t)tdo); + *vpp = vp; + +errout_with_lock: tmpfs_unlock(fs); return ret; } @@ -1973,25 +2070,22 @@ static int tmpfs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, * Name: tmpfs_rmdir ****************************************************************************/ -static int tmpfs_rmdir(FAR struct inode *mountpt, FAR const char *relpath) +int tmpfs_rmdir(struct Vnode *parent, struct Vnode *target, char *dirname) { FAR struct tmpfs_s *fs; - FAR struct tmpfs_directory_s *parent; + FAR struct tmpfs_directory_s *parent_dir; FAR struct tmpfs_directory_s *tdo; - FAR const char *name; - int ret; + int ret = 0; - finfo("mountpt: %p relpath: %s\n", mountpt, relpath); - DEBUGASSERT(mountpt != NULL && relpath != NULL); + finfo("parent: %p relpath: %s\n", target, relpath); + DEBUGASSERT(parent != NULL && target != NULL && relpath != NULL); - if (strlen(relpath) == 0) + /* Get the file system structure from the inode reference. */ + fs = parent->originMount->data; + if (fs == NULL) { - return -EINVAL; + return -EISDIR; } - - /* Get the file system structure from the inode reference. */ - - fs = mountpt->i_private; DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL); /* Get exclusive access to the file system */ @@ -2003,10 +2097,23 @@ static int tmpfs_rmdir(FAR struct inode *mountpt, FAR const char *relpath) * directory object and the parent directory and take one reference count * on each. */ + parent_dir = (FAR struct tmpfs_directory_s *)(parent->data); + if (parent_dir == NULL) + { + ret = tmpfs_find_directory(fs, dirname, &tdo, &parent_dir); + if (ret < 0) + { + goto errout_with_lock; + } + } + else + { + tdo = (FAR struct tmpfs_directory_s *)target->data; + } - ret = tmpfs_find_directory(fs, relpath, &tdo, &parent); - if (ret < 0) + if (tdo == NULL || tdo->tdo_type != TMPFS_DIRECTORY) { + ret = -EISDIR; goto errout_with_lock; } @@ -2021,26 +2128,8 @@ static int tmpfs_rmdir(FAR struct inode *mountpt, FAR const char *relpath) ret = -EBUSY; goto errout_with_objects; } - - /* Get the directory name from the relative path */ - - name = strrchr(relpath, '/'); - if (name != NULL) - { - /* Skip over the fidirectoryle '/' character */ - - name++; - } - else - { - /* The name must lie in the root directory */ - - name = relpath; - } - /* Remove the directory from parent directory */ - - ret = tmpfs_remove_dirent(parent, (struct tmpfs_object_s *)tdo); + ret = tmpfs_remove_dirent(parent_dir, (struct tmpfs_object_s *)tdo); if (ret < 0) { goto errout_with_objects; @@ -2050,21 +2139,32 @@ static int tmpfs_rmdir(FAR struct inode *mountpt, FAR const char *relpath) sem_destroy(&tdo->tdo_exclsem.ts_sem); kmm_free(tdo); + target->data = NULL; /* Release the reference and lock on the parent directory */ - parent->tdo_refs--; - tmpfs_unlock_directory(parent); + if (parent_dir->tdo_refs > 0) + { + parent_dir->tdo_refs--; + } + + tmpfs_unlock_directory(parent_dir); tmpfs_unlock(fs); return OK; errout_with_objects: - tdo->tdo_refs--; + if (tdo->tdo_refs > 0) + { + tdo->tdo_refs--; + } tmpfs_unlock_directory(tdo); - parent->tdo_refs--; - tmpfs_unlock_directory(parent); + if (parent_dir->tdo_refs > 0) + { + parent_dir->tdo_refs--; + } + tmpfs_unlock_directory(parent_dir); errout_with_lock: tmpfs_unlock(fs); @@ -2075,44 +2175,53 @@ errout_with_lock: * Name: tmpfs_rename ****************************************************************************/ -static int tmpfs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath, - FAR const char *newrelpath) +int tmpfs_rename(struct Vnode *oldVnode, struct Vnode *newParent, const char *oldname, const char *newname) { FAR struct tmpfs_directory_s *oldparent; - FAR struct tmpfs_directory_s *newparent; + FAR struct tmpfs_directory_s *newparent_tdo; FAR struct tmpfs_object_s *old_to; FAR struct tmpfs_dirent_s *tde; FAR struct tmpfs_directory_s *tdo; FAR struct tmpfs_file_s *tfo; FAR struct tmpfs_s *fs; - FAR const char *oldname; - FAR char *newname; + FAR struct tmpfs_s *new_fs; + FAR struct Vnode *old_parent_vnode; + FAR char *copy; - int ret; + int ret = 0; unsigned int oldrelpath_len, newrelpath_len, cmp_namelen; - finfo("mountpt: %p oldrelpath: %s newrelpath: %s\n", - mountpt, oldrelpath, newrelpath); + finfo("oldParent: %p newParent: %p oldname: %s newname: %s\n", + oldParent, newParent, oldname, newname); - oldrelpath_len = strlen(oldrelpath); - newrelpath_len = strlen(newrelpath); + oldrelpath_len = strlen(oldname); + newrelpath_len = strlen(newname); cmp_namelen = (oldrelpath_len <= newrelpath_len) ? oldrelpath_len : newrelpath_len; - if (!cmp_namelen || ((!strncmp(oldrelpath, newrelpath, cmp_namelen)) && - (oldrelpath[cmp_namelen] == '/' || - newrelpath[cmp_namelen] == '/'))) + if (!cmp_namelen || ((!strncmp(oldname, newname, cmp_namelen)) && + (oldname[cmp_namelen] == '/' || + newname[cmp_namelen] == '/'))) { return -EPERM; } /* Get the file system structure from the inode reference. */ + if (oldVnode->parent == NULL) + { + return -EPERM; + } + + fs = oldVnode->parent->originMount->data; + if (fs == NULL) + { + return -EPERM; + } - fs = mountpt->i_private; DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL); /* Duplicate the newpath variable so that we can modify it */ - copy = strdup(newrelpath); + copy = strdup(newname); if (copy == NULL) { return -ENOSPC; @@ -2125,48 +2234,40 @@ static int tmpfs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath, /* Separate the new path into the new file name and the path to the new * parent directory. */ - - newname = strrchr(copy, '/'); - if (newname == NULL) + newparent_tdo = (FAR struct tmpfs_directory_s *)(newParent->data); + if (newparent_tdo == NULL) { - /* No subdirectories... use the root directory */ - - newname = copy; - newparent = (FAR struct tmpfs_directory_s *)fs->tfs_root.tde_object; - - tmpfs_lock_directory(newparent); - newparent->tdo_refs++; - } - else - { - /* Terminate the parent directory path */ - - *newname++ = '\0'; - - /* Locate the parent directory that should contain this name. - * On success, tmpfs_find_directory() will lockthe parent - * directory and increment the reference count. - */ - - ret = tmpfs_find_directory(fs, copy, &newparent, NULL); - if (ret < 0) + new_fs = newParent->originMount->data; + newparent_tdo = (FAR struct tmpfs_directory_s *)new_fs->tfs_root.tde_object; + if (newparent_tdo == NULL) { + ret = -ENOTEMPTY; goto errout_with_lock; } + tmpfs_lock_directory(newparent_tdo); + newparent_tdo->tdo_refs++; } /* Find the old object at oldpath. If successful, tmpfs_find_object() * will lock both the object and the parent directory and will increment * the reference count on both. */ + old_parent_vnode = oldVnode->parent; + oldparent = (FAR struct tmpfs_directory_s *)(old_parent_vnode->data); + old_to = (FAR struct tmpfs_object_s *)oldVnode->data; - ret = tmpfs_find_object(fs, oldrelpath, &old_to, &oldparent); - if (ret < 0) + if (oldparent == NULL) { - goto errout_with_newparent; + oldparent = (FAR struct tmpfs_directory_s *)fs->tfs_root.tde_object; + if (oldparent == NULL || old_to == NULL) + { + ret = -ENOTEMPTY; + goto errout_with_newparent; + } } - tde = tmpfs_find_dirent(newparent, newname); + tmpfs_lock_directory(oldparent); + tde = tmpfs_find_dirent(newparent_tdo, copy); if (tde != NULL) { FAR struct tmpfs_object_s *new_to = tde->tde_object; @@ -2207,7 +2308,7 @@ static int tmpfs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath, /* Now delete the destination directory entry */ - ret = tmpfs_remove_dirent(newparent, new_to); + ret = tmpfs_remove_dirent(newparent_tdo, new_to); if (ret < 0) { goto errout_with_oldparent; @@ -2239,22 +2340,6 @@ static int tmpfs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath, } } - /* Get the old file name from the relative path */ - - oldname = strrchr(oldrelpath, '/'); - if (oldname != NULL) - { - /* Skip over the file '/' character */ - - oldname++; - } - else - { - /* The name must lie in the root directory */ - - oldname = oldrelpath; - } - /* Remove the entry from the parent directory */ ret = tmpfs_remove_dirent(oldparent, old_to); @@ -2265,17 +2350,35 @@ static int tmpfs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath, /* Add an entry to the new parent directory. */ - ret = tmpfs_add_dirent(&newparent, old_to, newname); + ret = tmpfs_add_dirent(&newparent_tdo, old_to, copy); + oldVnode->parent = newParent; errout_with_oldparent: - oldparent->tdo_refs--; + if (oldparent == NULL) + { + tmpfs_unlock(fs); + kmm_free(copy); + return ret; + } + if (oldparent->tdo_refs > 0) + { + oldparent->tdo_refs--; + } tmpfs_unlock_directory(oldparent); - tmpfs_release_lockedobject(old_to); errout_with_newparent: - newparent->tdo_refs--; - tmpfs_unlock_directory(newparent); + if (newparent_tdo == NULL) + { + tmpfs_unlock(fs); + kmm_free(copy); + return ret; + } + if (newparent_tdo->tdo_refs > 0) + { + newparent_tdo->tdo_refs--; + } + tmpfs_unlock_directory(newparent_tdo); errout_with_lock: tmpfs_unlock(fs); @@ -2339,19 +2442,17 @@ static void tmpfs_stat_common(FAR struct tmpfs_object_s *to, * Name: tmpfs_stat ****************************************************************************/ -static int tmpfs_stat(FAR struct inode *mountpt, FAR const char *relpath, - FAR struct stat *buf) +int tmpfs_stat(struct Vnode *vp, struct stat *st) { FAR struct tmpfs_s *fs; FAR struct tmpfs_object_s *to; int ret; - finfo("mountpt=%p relpath=%s buf=%p\n", mountpt, relpath, buf); - DEBUGASSERT(mountpt != NULL && relpath != NULL && buf != NULL); - + finfo("vp=%p st=%p\n", vp, st); + DEBUGASSERT(vp != NULL && st != NULL); /* Get the file system structure from the inode reference. */ - fs = mountpt->i_private; + fs = vp->originMount->data; DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL); /* Get exclusive access to the file system */ @@ -2362,19 +2463,26 @@ static int tmpfs_stat(FAR struct inode *mountpt, FAR const char *relpath, * tmpfs_find_object() will lock the object and increment the * reference count on the object. */ - - ret = tmpfs_find_object(fs, relpath, &to, NULL); - if (ret < 0) + if (vp->data != NULL) { - goto errout_with_fslock; + to = (FAR struct tmpfs_object_s *)vp->data; + } + else + { + to = fs->tfs_root.tde_object; } + to->to_refs++; /* We found it... Return information about the file object in the stat * buffer. */ - + if(to == NULL) + { + ret = -ENOENT; + goto errout_with_fslock; + } DEBUGASSERT(to != NULL); - tmpfs_stat_common(to, buf); + tmpfs_stat_common(to, st); /* Unlock the object and return success */ diff --git a/fs/tmpfs/fs_tmpfs.h b/fs/tmpfs/fs_tmpfs.h index 823d4f3..6249d6b 100755 --- a/fs/tmpfs/fs_tmpfs.h +++ b/fs/tmpfs/fs_tmpfs.h @@ -177,9 +177,11 @@ struct tmpfs_file_s struct tmpfs_s { /* The root directory */ - FAR struct tmpfs_dirent_s tfs_root; struct tmpfs_sem_s tfs_exclsem; + mode_t permission; + uint gid; + uint uid; }; /* This is the type used the tmpfs_statfs_callout to accumulate memory usage */ diff --git a/fs/vfs/fs_close.c b/fs/vfs/fs_close.c old mode 100755 new mode 100644 index 8b7fc53..7d518fa --- a/fs/vfs/fs_close.c +++ b/fs/vfs/fs_close.c @@ -48,7 +48,6 @@ # include "net/net.h" #endif -#include "inode/inode.h" #include "mqueue.h" /**************************************************************************** diff --git a/fs/vfs/fs_dup.c b/fs/vfs/fs_dup.c index b31ed25..accbf50 100755 --- a/fs/vfs/fs_dup.c +++ b/fs/vfs/fs_dup.c @@ -44,7 +44,7 @@ #include "sched.h" #include "fs/fs.h" -#include "inode/inode.h" +#include "fs/vnode.h" #include "net/net.h" /**************************************************************************** diff --git a/fs/vfs/fs_dup2.c b/fs/vfs/fs_dup2.c index 2668186..c6a7c0f 100755 --- a/fs/vfs/fs_dup2.c +++ b/fs/vfs/fs_dup2.c @@ -43,8 +43,7 @@ #include "errno.h" #include "unistd.h" #include "sched.h" - -#include "inode/inode.h" +#include "fs/vnode.h" /* This logic in this applies only when both socket and file descriptors are * in that case, this function descriminates which type of dup2 is being diff --git a/fs/vfs/fs_dupfd.c b/fs/vfs/fs_dupfd.c old mode 100755 new mode 100644 index 0aba3d6..3c663d6 --- a/fs/vfs/fs_dupfd.c +++ b/fs/vfs/fs_dupfd.c @@ -47,7 +47,7 @@ #include "fs/fs.h" #include "fs/file.h" -#include "inode/inode.h" +#include "fs/vnode.h" #include "stdlib.h" #include "string.h" #if CONFIG_NFILE_DESCRIPTORS > 0 @@ -74,19 +74,18 @@ * ****************************************************************************/ -int file_dup(FAR struct file *filep, int minfd) +int file_dup(struct file *filep, int minfd) { int fd2; int ret; - int err,len; + int err,len,rellen; struct file *filep2 = NULL; char *fullpath = NULL; - const char *relpath = NULL; - struct inode_search_s desc; + char *relpath = NULL; /* Verify that fd is a valid, open file descriptor */ - if ((filep->f_inode == NULL) || (filep->f_path == NULL)) + if ((filep->f_vnode == NULL) || (filep->f_path == NULL)) { set_errno(EBADF); return VFS_ERROR; @@ -100,12 +99,11 @@ int file_dup(FAR struct file *filep, int minfd) return VFS_ERROR; } - /* Then allocate a new file descriptor for the inode */ + /* Then allocate a new file descriptor for the vnode */ - fd2 = files_allocate(filep->f_inode, filep->f_oflags, filep->f_pos, filep->f_priv, minfd); + fd2 = files_allocate(filep->f_vnode, filep->f_oflags, filep->f_pos, filep->f_priv, minfd); if (fd2 < 0) { - inode_release(filep->f_inode); free(fullpath); set_errno(EMFILE); return VFS_ERROR; @@ -114,39 +112,29 @@ int file_dup(FAR struct file *filep, int minfd) ret = fs_getfilep(fd2, &filep2); (void)strncpy_s(fullpath, len + 1, filep->f_path, len); - SETUP_SEARCH(&desc, fullpath, false); - if (inode_find(&desc) < 0) + if (filep->f_relpath != NULL) { - ret = -EACCES; - goto errout_with_inode; + rellen = strlen(filep->f_relpath); + relpath = (char *)zalloc(rellen + 1); + (void)strncpy_s(relpath, rellen + 1, filep->f_relpath, rellen); } - relpath = desc.relpath; filep2->f_path = fullpath; filep2->f_relpath = relpath; - - if (filep->f_inode->u.i_mops && filep->f_inode->u.i_mops->dup) - { - ret = filep->f_inode->u.i_mops->dup(filep, filep2); - } - else - { - ret = -ENOSYS; - } + filep2->f_priv = filep->f_priv; if (ret < 0) { - goto errout_with_inode; + goto errout_with_vnode; } return fd2; -errout_with_inode: +errout_with_vnode: clear_fd(fd2); - inode_release(filep2->f_inode); free(fullpath); filep2->f_oflags = 0; filep2->f_pos = 0; - filep2->f_inode = NULL; + filep2->f_vnode = NULL; filep2->f_priv = NULL; filep2->f_path = NULL; filep2->f_relpath = NULL; @@ -175,7 +163,7 @@ errout_with_inode: int fs_dupfd(int fd, int minfd) { - FAR struct file *filep; + struct file *filep; /* Get the file structure corresponding to the file descriptor. */ diff --git a/fs/vfs/fs_dupfd2.c b/fs/vfs/fs_dupfd2.c old mode 100755 new mode 100644 index 70bf663..a52c071 --- a/fs/vfs/fs_dupfd2.c +++ b/fs/vfs/fs_dupfd2.c @@ -44,7 +44,7 @@ #include "unistd.h" #include "sched.h" -#include "inode/inode.h" +#include "fs/vnode.h" #if CONFIG_NFILE_DESCRIPTORS > 0 @@ -82,8 +82,8 @@ int fs_dupfd2(int fd1, int fd2) int dup2(int fd1, int fd2) #endif { - FAR struct file *filep1; - FAR struct file *filep2; + struct file *filep1; + struct file *filep2; int ret; /* Get the file structures corresponding to the file descriptors. */ @@ -103,7 +103,7 @@ int dup2(int fd1, int fd2) /* Verify that fd1 is a valid, open file descriptor */ - if (filep1->f_inode == NULL) + if (filep1->f_vnode == NULL) { set_errno(EBADF); return VFS_ERROR; diff --git a/fs/vfs/fs_fcntl.c b/fs/vfs/fs_fcntl.c old mode 100755 new mode 100644 index 43cea0b..a7d753b --- a/fs/vfs/fs_fcntl.c +++ b/fs/vfs/fs_fcntl.c @@ -45,7 +45,7 @@ #include "errno.h" #include "assert.h" #include "fs/fs.h" -#include "inode/inode.h" +#include "fs/vnode.h" #if defined(LOSCFG_NET_LWIP_SACK) #include "lwip/sockets.h" @@ -81,14 +81,14 @@ ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -int file_vfcntl(FAR struct file *filep, int cmd, va_list ap) +int file_vfcntl(struct file *filep, int cmd, va_list ap) { int err = 0; int ret = OK; /* Was this file opened ? */ - if (!filep || !filep->f_inode) + if (!filep || !filep->f_vnode) { err = EBADF; goto errout; @@ -257,7 +257,7 @@ errout: int fcntl(int fd, int cmd, ...) { - FAR struct file *filep; + struct file *filep = NULL; va_list ap; int ret; int val = 0; @@ -319,7 +319,7 @@ int fcntl(int fd, int cmd, ...) int fcntl64(int fd, int cmd, ...) { - FAR struct file *filep = NULL; + struct file *filep = NULL; va_list va_ap; int reval; int va_val = 0; diff --git a/fs/vfs/fs_fsync.c b/fs/vfs/fs_fsync.c old mode 100755 new mode 100644 index e181d69..d94adc3 --- a/fs/vfs/fs_fsync.c +++ b/fs/vfs/fs_fsync.c @@ -48,9 +48,7 @@ #include "fs/fs.h" -#include "inode/inode.h" - -#ifndef CONFIG_DISABLE_MOUNTPOINT +#include "fs/vnode.h" /**************************************************************************** * Public Functions @@ -66,9 +64,8 @@ * ****************************************************************************/ -int file_fsync(FAR struct file *filep) +int file_fsync(struct file *filep) { - struct inode *inode; int ret; /* Was this file opened for write access? */ @@ -79,14 +76,12 @@ int file_fsync(FAR struct file *filep) goto errout; } - /* Is this inode a registered mountpoint? Does it support the + /* Is this vnode a registered mountpoint? Does it support the * sync operations may be relevant to device drivers but only * the mountpoint operations vtable contains a sync method. */ - inode = filep->f_inode; - if (!inode || !INODE_IS_MOUNTPT(inode) || - !inode->u.i_mops || !inode->u.i_mops->sync) + if (!filep || !filep->ops || !filep->ops->fsync) { ret = EINVAL; goto errout; @@ -94,7 +89,7 @@ int file_fsync(FAR struct file *filep) /* Yes, then tell the mountpoint to sync this file */ - ret = inode->u.i_mops->sync(filep); + ret = filep->ops->fsync(filep); if (ret >= 0) { return OK; @@ -111,13 +106,13 @@ errout: * Name: fsync * * Description: - * This func simply binds inode sync methods to the sync system call. + * This func simply binds vnode sync methods to the sync system call. * ****************************************************************************/ int fsync(int fd) { - FAR struct file *filep; + struct file *filep = NULL; /* Get the file structure corresponding to the file descriptor. */ @@ -133,4 +128,3 @@ int fsync(int fd) return file_fsync(filep); } -#endif /* !CONFIG_DISABLE_MOUNTPOINT */ diff --git a/fs/vfs/fs_getfilep.c b/fs/vfs/fs_getfilep.c old mode 100755 new mode 100644 index 8401f03..7e5c337 --- a/fs/vfs/fs_getfilep.c +++ b/fs/vfs/fs_getfilep.c @@ -41,9 +41,12 @@ #include "sys/types.h" #include "errno.h" +#include "unistd.h" +#include "console.h" #include "sched.h" - -#include "inode/inode.h" +#include "sys/types.h" +#include "fs/vnode.h" +#include "vfs_config.h" /**************************************************************************** * Public Functions @@ -67,7 +70,7 @@ * ****************************************************************************/ -int fs_getfilep_normal(int fd, FAR struct file **filep) +static int fs_getfilep_normal(int fd, struct file **filep) { struct filelist *list; @@ -102,12 +105,13 @@ int fs_getfilep_normal(int fd, FAR struct file **filep) return OK; } -int fs_getfilep(int fd, FAR struct file **filep) +int fs_getfilep(int fd, struct file **filep) { int ret = fs_getfilep_normal(fd, filep); if (ret < 0) { set_errno(-ret); + return VFS_ERROR; } - return ret; + return OK; } diff --git a/fs/vfs/fs_ioctl.c b/fs/vfs/fs_ioctl.c old mode 100755 new mode 100644 index a956f78..7f072cb --- a/fs/vfs/fs_ioctl.c +++ b/fs/vfs/fs_ioctl.c @@ -49,7 +49,7 @@ # include "net/net.h" #endif -#include "inode/inode.h" +#include "fs/vnode.h" /**************************************************************************** * Public Functions @@ -94,8 +94,7 @@ int ioctl(int fd, int req, ...) UINTPTR arg = 0; va_list ap; #if CONFIG_NFILE_DESCRIPTORS > 0 - FAR struct file *filep; - FAR struct inode *inode; + struct file *filep; int ret = OK; #endif @@ -149,12 +148,11 @@ int ioctl(int fd, int req, ...) /* Is a driver registered? Does it support the ioctl method? */ - inode = filep->f_inode; - if (inode && inode->u.i_ops && inode->u.i_ops->ioctl) + if (filep->ops && filep->ops->ioctl) { /* Yes, then let it perform the ioctl */ - ret = (int)inode->u.i_ops->ioctl(filep, req, arg); + ret = (int) filep->ops->ioctl(filep, req, arg); if (ret < 0) { err = -ret; @@ -163,7 +161,7 @@ int ioctl(int fd, int req, ...) } else { - err = EBADF; + err = ENOSYS; ret = VFS_ERROR; goto errout; } @@ -173,5 +171,5 @@ int ioctl(int fd, int req, ...) errout: set_errno(err); - return ret; + return VFS_ERROR; } diff --git a/fs/vfs/fs_lseek.c b/fs/vfs/fs_lseek.c old mode 100755 new mode 100644 index 029a247..ab2d532 --- a/fs/vfs/fs_lseek.c +++ b/fs/vfs/fs_lseek.c @@ -44,7 +44,7 @@ #include "sched.h" #include "assert.h" #include "errno.h" -#include "inode/inode.h" +#include "fs/vnode.h" #if CONFIG_NFILE_DESCRIPTORS > 0 @@ -70,36 +70,37 @@ * ****************************************************************************/ -off_t file_seek(FAR struct file *filep, off_t offset, int whence) +off_t file_seek(struct file *filep, off_t offset, int whence) { - FAR struct inode *inode; - int ret; + struct Vnode *vnode; int err = OK; + off_t pos; - DEBUGASSERT(filep); - inode = filep->f_inode; + vnode = filep->f_vnode; - if (!inode) + if (!vnode) { - err = EBADF; + err = -EBADF; goto errout; } /* Invoke the file seek method if available */ - if (inode->u.i_ops && inode->u.i_ops->seek) + if (filep->ops != NULL && filep->ops->seek != NULL) { - ret = inode->u.i_ops->seek(filep, offset, whence); - if (ret < 0) + pos = filep->ops->seek(filep, offset, whence); + if (pos < 0) { - err = -ret; + err = pos; goto errout; } + else + { + filep->f_pos = pos; + } } else - { - /* No... Just set the common file position value */ - + { /* No... Just set the common file position value */ switch (whence) { case SEEK_CUR: @@ -114,25 +115,24 @@ off_t file_seek(FAR struct file *filep, off_t offset, int whence) } else { - err = EINVAL; + err = -EINVAL; goto errout; } break; - case SEEK_END: - err = ENOSYS; + err = -ENOSYS; goto errout; default: - err = EINVAL; + err = -EINVAL; goto errout; } - } + } return (off_t)filep->f_pos; errout: - set_errno(err); + set_errno(-err); return (off_t)VFS_ERROR; } @@ -175,7 +175,7 @@ errout: off_t lseek(int fd, off_t offset, int whence) { - FAR struct file *filep; + struct file *filep; /* Get the file structure corresponding to the file descriptor. */ @@ -190,5 +190,4 @@ off_t lseek(int fd, off_t offset, int whence) return file_seek(filep, offset, whence); } - #endif diff --git a/fs/vfs/fs_lseek64.c b/fs/vfs/fs_lseek64.c old mode 100755 new mode 100644 index c168f91..69fa50b --- a/fs/vfs/fs_lseek64.c +++ b/fs/vfs/fs_lseek64.c @@ -44,7 +44,7 @@ #include "sched.h" #include "assert.h" #include "errno.h" -#include "inode/inode.h" +#include "fs/vnode.h" #if CONFIG_NFILE_DESCRIPTORS > 0 @@ -70,37 +70,38 @@ * ****************************************************************************/ -off64_t file_seek64(FAR struct file *filep, off64_t offset, int whence) +off64_t file_seek64(struct file *filep, off64_t offset, int whence) { - FAR struct inode *inode = NULL; - off64_t ret; + struct Vnode *vnode = NULL; int err = OK; + off64_t pos; DEBUGASSERT(filep); - inode = filep->f_inode; + vnode = filep->f_vnode; - if (inode == NULL) + if (vnode == NULL) { - err = EBADF; + err = -EBADF; goto errout; } /* Invoke the file seek method if available */ - if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops && inode->u.i_mops->seek64) + if (filep->ops != NULL && filep->ops->seek != NULL) { - ret = inode->u.i_mops->seek64(filep, offset, whence); - if (ret < 0) + pos = filep->ops->seek(filep, offset, whence); + if (pos < 0) { - err = -(int)ret; + err = pos; goto errout; } - filep->f_pos = ret; + else + { + filep->f_pos = pos; + } } else - { - /* No... Just set the common file position value */ - + { /* No... Just set the common file position value */ switch (whence) { case SEEK_CUR: @@ -115,17 +116,17 @@ off64_t file_seek64(FAR struct file *filep, off64_t offset, int whence) } else { - err = EINVAL; + err = -EINVAL; goto errout; } break; case SEEK_END: - err = ENOSYS; + err = -ENOSYS; goto errout; default: - err = EINVAL; + err = -EINVAL; goto errout; } } @@ -133,7 +134,7 @@ off64_t file_seek64(FAR struct file *filep, off64_t offset, int whence) return filep->f_pos; errout: - set_errno(err); + set_errno(-err); return (off64_t)VFS_ERROR; } @@ -176,7 +177,7 @@ errout: off64_t lseek64(int fd, off64_t offset, int whence) { - FAR struct file *filep; + struct file *filep; /* Get the file structure corresponding to the file descriptor. */ @@ -191,5 +192,4 @@ off64_t lseek64(int fd, off64_t offset, int whence) return file_seek64(filep, offset, whence); } - #endif diff --git a/fs/vfs/fs_mkdir.c b/fs/vfs/fs_mkdir.c old mode 100755 new mode 100644 index 7435ca0..31f5ea3 --- a/fs/vfs/fs_mkdir.c +++ b/fs/vfs/fs_mkdir.c @@ -43,47 +43,24 @@ #include "sys/stat.h" #include "fs/fs.h" #include "stdlib.h" -#include "inode/inode.h" +#include "fs/vnode.h" #include "string.h" #include "fs_other.h" #include "capability_api.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#undef FS_HAVE_WRITABLE_MOUNTPOINT -#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \ - CONFIG_NFILE_STREAMS > 0 -# define FS_HAVE_WRITABLE_MOUNTPOINT 1 -#endif - -#undef FS_HAVE_PSEUDOFS_OPERATIONS -#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0 -# define FS_HAVE_PSEUDOFS_OPERATIONS 1 -#endif - -#undef FS_HAVE_MKDIR -#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS) -# define FS_HAVE_MKDIR 1 -#endif - -#ifdef FS_HAVE_MKDIR +#include "fs/path_cache.h" +#include "fs/vfs_util.h" /**************************************************************************** * Private Functions ****************************************************************************/ int do_mkdir(int dirfd, const char *pathname, mode_t mode) { - FAR struct inode *inode; - FAR struct inode *pathnode; - const char *relpath = NULL; - int errcode; - int ret; - char *fullpath = NULL; - char *relativepath = NULL; - struct inode_search_s desc; - uint c_uid = OsCurrUserGet()->effUserID; - uint c_gid = OsCurrUserGet()->effGid; + struct Vnode *parentVnode = NULL; + struct Vnode *vnode = NULL; + int ret; + char *fullpath = NULL; + char *relativepath = NULL; + char *dirname = NULL; mode &= ~GetUmask(); mode &= (S_IRWXU|S_IRWXG|S_IRWXO); @@ -92,7 +69,6 @@ int do_mkdir(int dirfd, const char *pathname, mode_t mode) ret = get_path_from_fd(dirfd, &relativepath); if (ret < 0) { - errcode = -ret; goto errout; } @@ -104,145 +80,82 @@ int do_mkdir(int dirfd, const char *pathname, mode_t mode) if (ret < 0) { - errcode = -ret; goto errout; } - - /* Find the inode that includes this path */ - SETUP_SEARCH(&desc, fullpath, false); - ret = inode_find(&desc); - inode = desc.node; - relpath = desc.relpath; - - if ((ret >= 0) && (inode != NULL)) + if (!strncmp(fullpath, "/dev", 4) || !strncmp(fullpath, "/proc", 5)) { - if (!strlen(relpath)) + // virtual root create virtual dir + VnodeHold(); + ret = VnodeLookup(fullpath, &vnode, V_DUMMY|V_CREATE); + if (ret != OK) { - /* Find the inode that exactly match this path. */ - - errcode = EEXIST; - goto errout_with_inode; - } - - /* If the path doesn't include the existed rootfs dirs, - * then make a pseudo dir. - */ - -#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS - if (((inode == g_root_inode) && !IsInRootfs(relpath)) || (!INODE_IS_MOUNTPT(g_root_inode))) - { - if (VfsPermissionCheck(desc.parent->i_uid, desc.parent->i_gid, desc.parent->i_mode, EXEC_OP | WRITE_OP)) - { - errcode = EACCES; - goto errout_with_inode; - } - /* Create a pseudo inode. */ - inode_semtake(); - - ret = inode_reserve(fullpath, &pathnode); - if (ret < 0) - { - errcode = -ret; - inode_semgive(); - goto errout_with_inode; - } - pathnode->i_mode = mode; - pathnode->i_uid = c_uid; - pathnode->i_gid = c_gid; - inode_semgive(); - } - else -#endif - - /* An inode was found that includes this path and possibly refers to a - * mountpoint. - */ - -#ifndef CONFIG_DISABLE_MOUNTPOINT - /* Check if the inode is a valid mountpoint. */ - - if (!INODE_IS_MOUNTPT(inode) || !inode->u.i_mops) - { - /* The inode is not a mountpoint */ - - errcode = EEXIST; - goto errout_with_inode; - } - - /* Perform the mkdir operation using the relative path - * at the mountpoint. - */ - - else if (inode->u.i_mops->mkdir) - { - ret = inode->u.i_mops->mkdir(inode, relpath, mode); - if (ret < 0) - { - errcode = -ret; - goto errout_with_inode; - } - } - else - { - errcode = ENOSYS; - goto errout_with_inode; + goto errout_with_lock; } + vnode->mode = mode | S_IFDIR; + vnode->type = VNODE_TYPE_DIR; + VnodeDrop(); + goto out; + } - /* Release our reference on the inode */ + dirname = strrchr(fullpath, '/') + 1; - inode_release(inode); -#else - /* But mountpoints are not supported in this configuration */ + VnodeHold(); + ret = VnodeLookup(fullpath, &parentVnode, 0); + if (ret == OK) + { + ret = -EEXIST; + goto errout_with_lock; + } - errcode = EEXIST; - goto errout_with_inode; -#endif + if (parentVnode == NULL) + { + ret = -ENOENT; + goto errout_with_lock; } + parentVnode->useCount++; -#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS - /* No inode exists that contains this path. Create a new inode in the - * pseudo-filesystem at this location. - */ + if (VfsVnodePermissionCheck(parentVnode, WRITE_OP)) + { + ret = -EACCES; + goto errout_with_count; + } - else + if ((parentVnode->vop != NULL) && (parentVnode->vop->Mkdir != NULL)) { - /* Create an inode in the pseudo-filesystem at this path. - * NOTE that the new inode will be created with a reference - * count of zero. - */ - inode_semtake(); - ret = inode_reserve(fullpath, &inode); - if (ret < 0) - { - errcode = -ret; - free(fullpath); - inode_semgive(); - goto errout; - } - inode->i_mode = mode; - inode->i_uid = c_uid; - inode->i_gid = c_gid; - inode_semgive(); + ret = parentVnode->vop->Mkdir(parentVnode, dirname, mode, &vnode); } -#else else { - errcode = ENXIO; - free(fullpath); - goto errout; + ret = -ENOSYS; } -#endif - /* Directory successfully created */ + if (ret < 0) + { + goto errout_with_count; + } + struct PathCache *dt = PathCacheAlloc(parentVnode, vnode, dirname, strlen(dirname)); + if (dt == NULL) { + // alloc name cache failed is not a critical problem, let it go. + PRINT_ERR("alloc path cache %s failed\n", dirname); + } + parentVnode->useCount--; + VnodeDrop(); +out: + /* Directory successfully created */ free(fullpath); - return OK; -errout_with_inode: - inode_release(inode); - free(fullpath); + return OK; +errout_with_count: + parentVnode->useCount--; +errout_with_lock: + VnodeDrop(); errout: - set_errno(errcode); + set_errno(-ret); + if (fullpath) + { + free(fullpath); + } return VFS_ERROR; } @@ -273,5 +186,3 @@ int mkdirat(int dirfd, const char *pathname, mode_t mode) { return do_mkdir(dirfd, pathname, mode); } - -#endif /* FS_HAVE_MKDIR */ diff --git a/fs/vfs/fs_open.c b/fs/vfs/fs_open.c index a24124a..a9adcf0 100755 --- a/fs/vfs/fs_open.c +++ b/fs/vfs/fs_open.c @@ -50,10 +50,12 @@ #endif #include "stdlib.h" #include "fs/fs.h" - -#include "inode/inode.h" +#include "fs/vnode.h" #include "driver/blockproxy.h" #include "fs_other.h" +#include "fs/vfs_util.h" +#include "fs/path_cache.h" +#include "unistd.h" /**************************************************************************** * Public Functions @@ -97,7 +99,7 @@ static int oflag_convert_mode(int oflags) int get_path_from_fd(int fd, char **path) { - FAR struct file *file = NULL; + struct file *file = NULL; char *copypath = NULL; if (fd == AT_FDCWD) @@ -111,7 +113,7 @@ int get_path_from_fd(int fd, char **path) return -ENOENT; } - if ((file == NULL) || (file->f_inode == NULL) || (file->f_path == NULL)) + if ((file == NULL) || (file->f_vnode == NULL) || (file->f_path == NULL)) { return -EBADF; } @@ -141,173 +143,218 @@ int get_path_from_fd(int fd, char **path) return -ENOENT; } -int do_open(int dirfd, const char *path, int oflags, ...) +static int do_creat(struct Vnode **node, char *fullpath, mode_t mode) { - FAR struct file *filep = NULL; - FAR struct inode *inode = NULL; - FAR const char *relpath = NULL; - char *fullpath = NULL; - char *relativepath = NULL; - struct inode_search_s desc; -#if defined(LOSCFG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT) - mode_t mode = DEFAULT_FILE_MODE; -#endif int ret; - int fd; - int acc_mode; -#ifdef LOSCFG_FILE_MODE - /* If the file is opened for creation, then get the mode bits */ + struct Vnode *parentNode = *node; + char *name = strrchr(fullpath, '/') + 1; - if ((oflags & (O_WRONLY | O_CREAT)) != 0) + if (parentNode->vop != NULL && parentNode->vop->Create != NULL) { - va_list ap; - va_start(ap, oflags); - mode = va_arg(ap, int); - va_end(ap); - mode &= ~GetUmask(); - mode &= (S_IRWXU|S_IRWXG|S_IRWXO); + ret = parentNode->vop->Create(parentNode, name, mode, node); } -#endif - - /* Get relative path by dirfd*/ - ret = get_path_from_fd(dirfd, &relativepath); - if (ret < 0) + else { - ret = -ret; - goto errout; + ret = -ENOSYS; } - ret = vfs_normalize_path((const char *)relativepath, path, &fullpath); - if (relativepath) + if (ret < 0) { - free(relativepath); + return ret; } - if (ret < 0) + struct PathCache *dt = PathCacheAlloc(parentNode, *node, name, strlen(name)); + if (dt == NULL) { - ret = -ret; - goto errout; + // alloc name cache failed is not a critical problem, let it go. + PRINT_ERR("alloc path cache %s failed\n", name); } + return OK; +} - /* Get an inode for this file */ - SETUP_SEARCH(&desc, fullpath, false); - ret = inode_find(&desc); - if (ret < 0) +int fp_open(char *fullpath, int oflags, mode_t mode) +{ + int ret; + int fd; + int accmode; + struct file *filep = NULL; + struct Vnode *vnode = NULL; + + VnodeHold(); + ret = VnodeLookup(fullpath, &vnode, 0); + if (ret == OK) { - ret = EACCES; - free(fullpath); - goto errout; + /* if file exist */ + if (vnode->type == VNODE_TYPE_BCHR) + { + ret = -EINVAL; + goto errout_without_count; + } + if (vnode->type == VNODE_TYPE_BLK) { + fd = block_proxy(fullpath, oflags); + VnodeDrop(); + if (fd < 0) + { + ret = fd; + goto errout_without_count; + } + return fd; + } + if ((oflags & O_CREAT) && (oflags & O_EXCL)) + { + ret = -EEXIST; + VnodeDrop(); + goto errout_without_count; + } + if (vnode->type == VNODE_TYPE_DIR) + { + ret = -EISDIR; + VnodeDrop(); + goto errout_without_count; + } + accmode = oflag_convert_mode(oflags); + if (VfsVnodePermissionCheck(vnode, accmode)) + { + ret = -EACCES; + VnodeDrop(); + goto errout_without_count; + } } - inode = desc.node; - relpath = desc.relpath; -#if !defined(CONFIG_DISABLE_MOUNTPOINT) -#ifdef LOSCFG_FS_VFS_BLOCK_DEVICE - if (INODE_IS_BLOCK(inode)) + if ((ret != OK) && (oflags & O_CREAT) && vnode) { - fd = block_proxy(path, oflags); - if (fd < 0) + /* if file not exist, but parent dir of the file is exist */ + if (VfsVnodePermissionCheck(vnode, WRITE_OP)) { - ret = fd; - goto errout_with_inode; + ret = -EACCES; + VnodeDrop(); + goto errout_without_count; + } + ret = do_creat(&vnode, fullpath, mode); + if (ret != OK) + { + VnodeDrop(); + goto errout_without_count; } - - inode_release(inode); - free(fullpath); - return fd; } -#endif -#endif - /* Verify that the inode is valid and either a "normal" character driver or a - * mountpoint. We specifically exclude block drivers and and "special" - * inodes (semaphores, message queues, shared memory). - */ - -#ifndef CONFIG_DISABLE_MOUNTPOINT - if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) || !inode->u.i_ops) -#else - if (!INODE_IS_DRIVER(inode) || !inode->u.i_ops) -#endif + if (ret != OK) { - ret = ENXIO; - goto errout_with_inode; + /* found nothing */ + VnodeDrop(); + goto errout_without_count; } + vnode->useCount++; + VnodeDrop(); + + if (oflags & O_TRUNC) + { + if (vnode->useCount > 1) + { + ret = -EBUSY; + goto errout; + } - /* Associate the inode with a file structure */ + if (vnode->vop->Truncate) + { + ret = vnode->vop->Truncate(vnode, 0); + if (ret != OK) + { + goto errout; + } + } + else + { + ret = -ENOSYS; + goto errout; + } + } - fd = files_allocate(inode, oflags, 0, NULL, 3); /* 3: file start fd */ + fd = files_allocate(vnode, oflags, 0, NULL, 3); /* 3: file start fd */ if (fd < 0) { - ret = EMFILE; - goto errout_with_inode; + ret = -EMFILE; + goto errout; } /* Get the file structure corresponding to the file descriptor. */ - ret = fs_getfilep(fd, &filep); if (ret < 0) { - ret = EPERM; - - /* The errno value has already been set */ - goto errout_with_fd; + files_release(fd); + ret = -get_errno(); + goto errout; } - /* Perform the driver open operation. NOTE that the open method may be - * called many times. The driver/mountpoint logic should handled this - * because it may also be closed that many times. - */ + filep->f_vnode = vnode; + filep->ops = vnode->fop; + filep->f_path = fullpath; - ret = OK; - filep->f_path = fullpath; /* The mem will free in close(fd); */ - filep->f_relpath = relpath; - - acc_mode = oflag_convert_mode(oflags); - if (inode->u.i_ops->open) + if (filep->ops && filep->ops->open) { -#ifndef CONFIG_DISABLE_MOUNTPOINT - if (INODE_IS_MOUNTPT(inode)) - { - if (VfsPermissionCheck(inode->i_uid, inode->i_gid, inode->i_mode, EXEC_OP)) - { - ret = EACCES; - goto errout_with_fd; - } - ret = inode->u.i_mops->open(filep, relpath, oflags, mode); - } - else -#endif - { - if (VfsPermissionCheck(inode->i_uid, inode->i_gid, inode->i_mode, acc_mode)) - { - ret = EACCES; - goto errout_with_fd; - } - ret = inode->u.i_ops->open(filep); - } + ret = filep->ops->open(filep); } if (ret < 0) { - ret = -ret; - goto errout_with_fd; + files_release(fd); + goto errout; } /* we do not bother to handle the NULL scenario, if so, page-cache feature will not be used * when we do the file fault */ - add_mapping(filep, fullpath); return fd; -errout_with_fd: - files_release(fd); -errout_with_inode: - inode_release(inode); - free(fullpath); errout: - set_errno(ret); + VnodeHold(); + vnode->useCount--; + VnodeDrop(); +errout_without_count: + set_errno(-ret); + return VFS_ERROR; +} + +int do_open(int dirfd, const char *path, int oflags, mode_t mode) +{ + int ret; + int fd; + char *fullpath = NULL; + char *relativepath = NULL; + + /* Get relative path by dirfd*/ + ret = get_path_from_fd(dirfd, &relativepath); + if (ret < 0) + { + goto errout; + } + + ret = vfs_normalize_path((const char *)relativepath, path, &fullpath); + if (relativepath) + { + free(relativepath); + } + if (ret < 0) + { + goto errout; + } + + fd = fp_open(fullpath, oflags, mode); + if (fd < 0) + { + ret = -get_errno(); + goto errout; + } + + return fd; + +errout: + if (fullpath) + { + free(fullpath); + } + set_errno(-ret); return VFS_ERROR; } @@ -320,43 +367,36 @@ errout: int open(const char *path, int oflags, ...) { - mode_t mode = 0666; /* File read-write properties. */ + mode_t mode = DEFAULT_FILE_MODE; /* File read-write properties. */ #ifdef LOSCFG_FILE_MODE va_list ap; va_start(ap, oflags); mode = va_arg(ap, int); va_end(ap); + + if ((oflags & (O_WRONLY | O_CREAT)) != 0) + { + mode &= ~GetUmask(); + mode &= (S_IRWXU|S_IRWXG|S_IRWXO); + } #endif + return do_open(AT_FDCWD, path, oflags, mode); } int open64 (const char *__path, int __oflag, ...) { - mode_t mode = 0666; /* File read-write properties. */ + mode_t mode = DEFAULT_FILE_MODE; /* File read-write properties. */ #ifdef LOSCFG_FILE_MODE va_list ap; va_start(ap, __oflag); mode = va_arg(ap, int); va_end(ap); + if ((__oflag & (O_WRONLY | O_CREAT)) != 0) + { + mode &= ~GetUmask(); + mode &= (S_IRWXU|S_IRWXG|S_IRWXO); + } #endif return open (__path, ((unsigned int)__oflag) | O_LARGEFILE, mode); } - -/**************************************************************************** - * Name: openat - * - * Description: open by dirfd - * - ****************************************************************************/ - -int openat(int dirfd, const char * path, int oflags, ...) -{ - mode_t mode = 0666; /* File read-write properties. */ -#ifdef LOSCFG_FILE_MODE - va_list ap; - va_start(ap, oflags); - mode = va_arg(ap, int); - va_end(ap); -#endif - return do_open(dirfd, path, oflags, mode); -} diff --git a/fs/vfs/fs_poll.c b/fs/vfs/fs_poll.c old mode 100755 new mode 100644 index 5152165..8830a59 --- a/fs/vfs/fs_poll.c +++ b/fs/vfs/fs_poll.c @@ -45,7 +45,7 @@ #include "errno.h" #include "debug.h" #include "fs/fs.h" -#include "inode/inode.h" +#include "fs/vnode.h" #include "stdlib.h" #include "stdio.h" #include "console.h" @@ -226,14 +226,11 @@ static int wait_sem_time(poll_wait_head wait, const struct timespec *time_ptr) static int file_poll(struct file *filep, poll_table *wait) { - struct inode *inode = NULL; int ret = -ENOSYS; - inode = filep->f_inode; - - if (inode != NULL && inode->u.i_ops != NULL && inode->u.i_ops->poll != NULL) + if (filep->ops != NULL && filep->ops->poll != NULL) { - ret = inode->u.i_ops->poll(filep, wait); + ret = filep->ops->poll(filep, wait); } return ret; diff --git a/fs/vfs/fs_read.c b/fs/vfs/fs_read.c old mode 100755 new mode 100644 index 253ec4d..9f4fc14 --- a/fs/vfs/fs_read.c +++ b/fs/vfs/fs_read.c @@ -48,7 +48,7 @@ #include "assert.h" #include "errno.h" #include "user_copy.h" -#include "inode/inode.h" +#include "fs/vnode.h" /**************************************************************************** * Public Functions @@ -77,14 +77,10 @@ * ****************************************************************************/ -ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes) +ssize_t file_read(struct file *filep, void *buf, size_t nbytes) { - FAR struct inode *inode = NULL; int ret = -EBADF; - DEBUGASSERT(filep); - inode = filep->f_inode; - if (buf == NULL) { ret = -EFAULT; @@ -103,14 +99,14 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes) * method? */ - else if (inode && inode->u.i_ops && inode->u.i_ops->read) + else if (filep->ops && filep->ops->read) { /* Yes.. then let it perform the read. NOTE that for the case of the * mountpoint, we depend on the read methods being identical in * signature and position in the operations vtable. */ - ret = (int)inode->u.i_ops->read(filep, (char *)buf, (size_t)nbytes); + ret = (int)filep->ops->read(filep, (char *)buf, (size_t)nbytes); } /* If an error occurred, set errno and return -1 (ERROR) */ @@ -143,12 +139,12 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes) * ****************************************************************************/ -ssize_t read(int fd, FAR void *buf, size_t nbytes) +ssize_t read(int fd, void *buf, size_t nbytes) { /* Did we get a valid file descriptor? */ #if CONFIG_NFILE_DESCRIPTORS > 0 - FAR struct file *filep = NULL; + struct file *filep = NULL; if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) #endif @@ -158,7 +154,7 @@ ssize_t read(int fd, FAR void *buf, size_t nbytes) */ #if defined(LOSCFG_NET_LWIP_SACK) - FAR void *bufbak = buf; + void *bufbak = buf; ssize_t ret; if (LOS_IsUserAddress((VADDR_T)(uintptr_t)buf)) { @@ -208,7 +204,6 @@ ssize_t read(int fd, FAR void *buf, size_t nbytes) } } - /* The descriptor is in a valid range to file descriptor... do the * read. First, get the file structure. */ diff --git a/fs/vfs/fs_rename.c b/fs/vfs/fs_rename.c old mode 100755 new mode 100644 index 143324a..813f169 --- a/fs/vfs/fs_rename.c +++ b/fs/vfs/fs_rename.c @@ -40,253 +40,197 @@ #include "vfs_config.h" #include "stdio.h" +#include "unistd.h" #include "errno.h" #include "fs/fs.h" #include "stdlib.h" -#include "inode/inode.h" +#include "fs/vnode.h" #include "fs_other.h" +#include "limits.h" +#include "fs/fs_operation.h" /**************************************************************************** - * Pre-processor Definitions + * Public Functions ****************************************************************************/ +static int check_rename_target(struct Vnode *old_vnode, struct Vnode *old_parent_vnode, + struct Vnode *new_vnode, struct Vnode *new_parent_vnode) +{ + if (old_vnode == NULL || old_parent_vnode == NULL || + new_parent_vnode == NULL || new_parent_vnode->type != VNODE_TYPE_DIR) + { + return -ENOENT; + } + if (old_vnode->type != VNODE_TYPE_DIR && old_vnode->type != VNODE_TYPE_REG) + { + return -EACCES; + } + if (new_vnode != NULL && new_vnode->type != old_vnode->type) + { + if (new_vnode->type == VNODE_TYPE_DIR) + { + return -EISDIR; + } + return -ENOTDIR; + } + if (new_vnode != NULL && new_vnode->useCount != 0) + { + return -EBUSY; + } -#undef FS_HAVE_WRITABLE_MOUNTPOINT -#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \ - CONFIG_NFILE_STREAMS > 0 -# define FS_HAVE_WRITABLE_MOUNTPOINT 1 -#endif + if (VfsVnodePermissionCheck(old_parent_vnode, WRITE_OP) + || VfsVnodePermissionCheck(new_parent_vnode, WRITE_OP)) + { + return -EACCES; + } -#undef FS_HAVE_PSEUDOFS_OPERATIONS -#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0 -# define FS_HAVE_PSEUDOFS_OPERATIONS 1 -#endif + if (old_parent_vnode->originMount != new_parent_vnode->originMount) + { + return -EXDEV; + } + if ((old_vnode->flag & VNODE_FLAG_MOUNT_NEW) + || (old_vnode->flag & VNODE_FLAG_MOUNT_ORIGIN)) + { + return -EBUSY; + } + if (new_vnode != NULL && ((new_vnode->flag & VNODE_FLAG_MOUNT_NEW) + || (new_vnode->flag & VNODE_FLAG_MOUNT_ORIGIN))) + { + return -EBUSY; + } -#undef FS_HAVE_RENAME -#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS) -# define FS_HAVE_RENAME 1 -#endif + return OK; +} -#ifdef FS_HAVE_RENAME +static int check_path_invalid(const char *fulloldpath, const char *fullnewpath) +{ + char cwd[PATH_MAX]; + char *pret = getcwd(cwd, PATH_MAX); + ssize_t len = strlen(fulloldpath); + if (pret != NULL) + { + if (!strcmp(fulloldpath, cwd)) + { + return -EBUSY; + } + } -/**************************************************************************** - * Public Functions - ****************************************************************************/ + if (strncmp(fulloldpath, fullnewpath, len)) + { + return OK; + } -int do_rename(int oldfd, FAR const char *oldpath, int newfd, FAR const char *newpath) -{ - FAR struct inode *oldinode; - FAR struct inode *newinode; - const char *oldrelpath = NULL; - char *fulloldpath = NULL; - char *fulloldpath_bak = NULL; - char *fullnewpath = NULL; - char *fullnewpath_bak = NULL; -#ifndef CONFIG_DISABLE_MOUNTPOINT - const char *newrelpath = NULL; -#endif - int errcode = ENOERR; - int ret; - struct inode_search_s old_desc, new_desc; + if (fullnewpath[len] != '/') + { + return OK; + } - /* Ignore paths that are interpreted as the root directory which has no name - * and cannot be moved - */ + return -EINVAL; +} - if (!oldpath || *oldpath == '\0' || - !newpath || *newpath == '\0') +int do_rename(int oldfd, const char *oldpath, int newfd, const char *newpath) +{ + struct Vnode *old_parent_vnode = NULL; + struct Vnode *new_parent_vnode = NULL; + struct Vnode *old_vnode = NULL; + struct Vnode *new_vnode = NULL; + char *fulloldpath = NULL; + char *fullnewpath = NULL; + char *oldname = NULL; + char *newname = NULL; + int ret; + if (!oldpath || *oldpath == '\0' || !newpath || *newpath == '\0') { - errcode = EINVAL; + ret = -EINVAL; goto errout; } ret = vfs_normalize_pathat(oldfd, oldpath, &fulloldpath); if (ret < 0) - { - errcode = -ret; - goto errout; - } - fulloldpath_bak = fulloldpath; + { + goto errout; + } ret = vfs_normalize_pathat(newfd, newpath, &fullnewpath); if (ret < 0) - { - errcode = -ret; - goto errout_with_path; - } - fullnewpath_bak = fullnewpath; + { + goto errout_with_oldpath; + } + oldname = strrchr(fulloldpath, '/') + 1; + newname = strrchr(fullnewpath, '/') + 1; + ret = check_path_invalid(fulloldpath, fullnewpath); + if (ret != OK) + { + goto errout_with_newpath; + } - /* Get an inode that includes the oldpath */ - SETUP_SEARCH(&old_desc, fulloldpath, false); - ret = inode_find(&old_desc); + VnodeHold(); + ret = VnodeLookup(fulloldpath, &old_vnode, 0); if (ret < 0) { - errcode = EACCES; - free(fullnewpath_bak); - goto errout_with_path; + goto errout_with_vnode; } - oldinode = old_desc.node; - oldrelpath = old_desc.relpath; - -#ifndef CONFIG_DISABLE_MOUNTPOINT - /* Verify that the old inode is a valid mountpoint. */ - - if (INODE_IS_MOUNTPT(oldinode) && oldinode->u.i_mops) + old_parent_vnode = old_vnode->parent; + ret = VnodeLookup(fullnewpath, &new_vnode, 0); + if (ret == OK) { - /* Get an inode for the new relpath -- it should like on the same - * mountpoint - */ - SETUP_SEARCH(&new_desc, fullnewpath, false); - ret = inode_find(&new_desc); - if (ret < 0) - { - errcode = EACCES; - goto errout_with_oldinode; - } - newinode = new_desc.node; - newrelpath = new_desc.relpath; - - /* Verify that the two paths lie on the same mountpoint inode */ - - if (oldinode != newinode) - { - errcode = EXDEV; - goto errout_with_newinode; - } - - /* Perform the rename operation using the relative paths - * at the common mountpoint. - */ - - if (oldinode->u.i_mops->rename) - { - ret = oldinode->u.i_mops->rename(oldinode, oldrelpath, newrelpath); - if (ret < 0) - { - errcode = -ret; - goto errout_with_newinode; - } - } - else - { - errcode = ENOSYS; - goto errout_with_newinode; - } - - /* Successfully renamed */ - - inode_release(newinode); + new_parent_vnode = new_vnode->parent; } else -#endif -#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS { - /* Create a new, empty inode at the destination location */ - if (VfsPermissionCheck(old_desc.parent->i_uid, old_desc.parent->i_gid, - old_desc.parent->i_mode, EXEC_OP | WRITE_OP)) - { - ret = EACCES; - goto errout_with_oldinode; - } - SETUP_SEARCH(&new_desc, fullnewpath, false); - ret = inode_find(&new_desc); - if (ret < 0) - { - errcode = EACCES; - goto errout_with_oldinode; - } - newinode = new_desc.node; - newrelpath = new_desc.relpath; - - if (VfsPermissionCheck(new_desc.parent->i_uid, new_desc.parent->i_gid, - new_desc.parent->i_mode, EXEC_OP | WRITE_OP)) - { - ret = EACCES; - goto errout_with_oldinode; - } - inode_semtake(); - ret = inode_reserve(fullnewpath, &newinode); - if (ret < 0) - { - /* It is an error if a node at newpath already exists in the tree - * OR if we fail to allocate memory for the new inode (and possibly - * any new intermediate path segments). - */ - - inode_semgive(); - errcode = EEXIST; - goto errout_with_oldinode; - } - - /* Copy the inode state from the old inode to the newly allocated inode */ - - newinode->i_child = oldinode->i_child; /* Link to lower level inode */ - newinode->i_flags = oldinode->i_flags; /* Flags for inode */ - newinode->u.i_ops = oldinode->u.i_ops; /* Inode operations */ -#ifdef LOSCFG_FILE_MODE - newinode->i_mode = oldinode->i_mode; /* Access mode flags */ -#endif - newinode->i_private = oldinode->i_private; /* Per inode driver private data */ - - /* We now have two copies of the inode. One with a reference count of - * zero (the new one), and one that may have multiple references - * including one by this logic (the old one) - * - * Remove the old inode. Because we hold a reference count on the - * inode, it will not be deleted now. It will be deleted when all of - * the references to to the inode have been released (perhaps when - * inode_release() is called below). inode_remove() should return - * -EBUSY to indicate that the inode was not deleted now. - */ - - ret = inode_remove(fulloldpath); - if (ret < 0 && ret != -EBUSY) - { - /* Remove the new node we just recreated */ - - (void)inode_remove(fullnewpath); - inode_semgive(); - - errcode = -ret; - goto errout_with_oldinode; - } - - /* Remove all of the children from the unlinked inode */ - - oldinode->i_child = NULL; - inode_semgive(); + new_parent_vnode = new_vnode; + new_vnode = NULL; } -#else + ret = check_rename_target(old_vnode, old_parent_vnode, new_vnode, new_parent_vnode); + if (ret != OK) { - errcode = ENXIO; - goto errout_with_oldinode; + goto errout_with_vnode; } -#endif - - /* rename file page cache mapping if necessary */ + if (old_vnode == new_vnode) + { + VnodeDrop(); + free(fulloldpath); + free(fullnewpath); + return OK; + } + if (!old_vnode->vop || !old_vnode->vop->Rename) + { + ret = -ENOSYS; + goto errout_with_vnode; + } + ret = old_vnode->vop->Rename(old_vnode, new_parent_vnode, oldname, newname); + if (ret < 0) + { + goto errout_with_vnode; + } + VnodeFree(new_vnode); + VnodePathCacheFree(old_vnode); + 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); - /* Successfully renamed */ - - inode_release(oldinode); - free(fulloldpath_bak); - free(fullnewpath_bak); + free(fulloldpath); + free(fullnewpath); return OK; -#ifndef CONFIG_DISABLE_MOUNTPOINT -errout_with_newinode: - inode_release(newinode); -#endif -errout_with_oldinode: - inode_release(oldinode); - free(fullnewpath_bak); -errout_with_path: - free(fulloldpath_bak); +errout_with_vnode: + VnodeDrop(); +errout_with_newpath: + free(fullnewpath); +errout_with_oldpath: + free(fulloldpath); errout: - set_errno(errcode); + set_errno(-ret); return VFS_ERROR; } + /**************************************************************************** * Name: rename * @@ -294,7 +238,7 @@ errout: * ****************************************************************************/ -int rename(FAR const char *oldpath, FAR const char *newpath) +int rename(const char *oldpath, const char *newpath) { return do_rename(AT_FDCWD, oldpath, AT_FDCWD, newpath); } @@ -306,9 +250,7 @@ int rename(FAR const char *oldpath, FAR const char *newpath) * ****************************************************************************/ -int renameat(int oldfd, FAR const char *oldpath, int newdfd, FAR const char *newpath) +int renameat(int oldfd, const char *oldpath, int newdfd, const char *newpath) { return do_rename(oldfd, oldpath, newdfd, newpath); } - -#endif /* FS_HAVE_RENAME */ diff --git a/fs/vfs/fs_rmdir.c b/fs/vfs/fs_rmdir.c old mode 100755 new mode 100644 index 00c61b5..1418cd7 --- a/fs/vfs/fs_rmdir.c +++ b/fs/vfs/fs_rmdir.c @@ -43,32 +43,50 @@ #include "errno.h" #include "fs/fs.h" #include "stdlib.h" -#include "inode/inode.h" +#include "fs/vnode.h" #include "sys/stat.h" #include "string.h" #include "fs_other.h" +#include "limits.h" + /**************************************************************************** - * Pre-processor Definitions + * Private Functions ****************************************************************************/ +static int check_target(struct Vnode *vnode, char *name) { + if (vnode == NULL) + { + return -ENOENT; + } -#undef FS_HAVE_WRITABLE_MOUNTPOINT -#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \ - CONFIG_NFILE_STREAMS > 0 -# define FS_HAVE_WRITABLE_MOUNTPOINT 1 -#endif - -#undef FS_HAVE_PSEUDOFS_OPERATIONS -#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0 -# define FS_HAVE_PSEUDOFS_OPERATIONS 1 -#endif + if (vnode->type != VNODE_TYPE_DIR) + { + return -ENOTDIR; + } -#undef FS_HAVE_RMDIR -#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS) -# define FS_HAVE_RMDIR 1 -#endif + if (vnode->useCount > 0) + { + return -EBUSY; + } -#ifdef FS_HAVE_RMDIR + if ((vnode->flag & VNODE_FLAG_MOUNT_NEW) + || (vnode->flag & VNODE_FLAG_MOUNT_ORIGIN)) + { + return -EBUSY; + } + char cwd[PATH_MAX]; + char *pret = getcwd(cwd, PATH_MAX); + if (pret != NULL) + { + struct Vnode *cwdnode = NULL; + int ret = VnodeLookup(cwd, &cwdnode, 0); + if (ret == OK && (cwdnode == vnode)) + { + return -EBUSY; + } + } + return OK; +} /**************************************************************************** * Public Functions ****************************************************************************/ @@ -80,143 +98,94 @@ * ****************************************************************************/ -int do_rmdir(int dirfd, FAR const char *pathname) +int do_rmdir(int dirfd, const char *pathname) { - FAR struct inode *inode; - const char *relpath = NULL; - int errcode; + struct Vnode *vnode = NULL; char *fullpath = NULL; char *relativepath = NULL; + char *name = NULL; int ret; - struct inode_search_s desc; /* Get relative path by dirfd*/ ret = get_path_from_fd(dirfd, &relativepath); if (ret < 0) { - errcode = ret; goto errout; } - ret = vfs_normalize_path((const char *)relativepath, pathname, &fullpath); if (relativepath) { + ret = vfs_normalize_path((const char *)relativepath, pathname, &fullpath); free(relativepath); - } - - if (ret < 0) - { - errcode = -ret; - goto errout; - } - - /* Get an inode for this file. inode_find() automatically increments the - * reference count on the inode if one is found. - */ - SETUP_SEARCH(&desc, fullpath, false); - ret = inode_find(&desc); - if (ret < 0) - { - free(fullpath); - errcode = EACCES; - goto errout; - } - inode = desc.node; - relpath = desc.relpath; - -#ifndef CONFIG_DISABLE_MOUNTPOINT - /* Check if the inode is a valid mountpoint. */ - - if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops) - { - /* Perform the rmdir operation using the relative path - * from the mountpoint. - */ - - if (inode->u.i_mops->rmdir) - { - if (!strlen(relpath)) - { - errcode = EPERM; - goto errout_with_inode; - } - - ret = inode->u.i_mops->rmdir(inode, relpath); - if (ret < 0) - { - errcode = -ret; - goto errout_with_inode; - } - } - else + if (ret < 0) { - errcode = ENOSYS; - goto errout_with_inode; + goto errout; } + + name = strrchr(fullpath, '/'); + VnodeHold(); + ret = VnodeLookup(fullpath, &vnode, 0); } else -#endif - -#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS - /* If this is a "dangling" pseudo-directory node (i.e., it has no - * operations) then rmdir should remove the node. - */ - - if (!inode->u.i_ops) { - /* If the directory inode has children, however, then it cannot be - * removed. - */ - - if (inode->i_child) - { - errcode = ENOTEMPTY; - goto errout_with_inode; - } - - /* Remove the inode. NOTE: Because we hold a reference count on the - * inode, it will not be deleted now. But probably when inode_release() - * is called below. inode_remove should return -EBUSY to indicate that - * the inode was not deleted now. - */ - if (VfsPermissionCheck(desc.parent->i_uid, desc.parent->i_gid, desc.parent->i_mode, EXEC_OP | WRITE_OP)) + name = strrchr(pathname, '/'); + VnodeHold(); + if (name == NULL) { - errcode = EACCES; - goto errout_with_inode; + name = (char *)pathname; } - inode_semtake(); - ret = inode_remove(fullpath); - inode_semgive(); - - if (ret < 0 && ret != -EBUSY) + else { - errcode = -ret; - goto errout_with_inode; + name++; } + ret = VnodeLookup(pathname, &vnode, 0); } - else + + if (ret != OK) { - errcode = ENOTDIR; - goto errout_with_inode; + goto errout_with_lock; } -#else + + ret = check_target(vnode, name); + if (ret != OK) { + PRINT_ERR("rmdir failed err = %d\n", ret); + goto errout_with_lock; + } + + if (VfsVnodePermissionCheck(vnode->parent, WRITE_OP)) { + ret = -EACCES; + goto errout_with_lock; + } + + if (vnode && vnode->vop && vnode->vop->Rmdir) { + ret = vnode->vop->Rmdir(vnode->parent, vnode, name); + } else { + ret = -ENOSYS; + } + if (ret < 0) { + goto errout_with_lock; + } + VnodeFree(vnode); + VnodeDrop(); + + /* Successfully unlinked */ + if (fullpath) { - errcode = ENXIO; - goto errout_with_inode; + free(fullpath); } -#endif - - /* Successfully removed the directory */ - inode_release(inode); - free(fullpath); return OK; -errout_with_inode: - inode_release(inode); - free(fullpath); +errout_with_lock: + VnodeDrop(); + errout: - set_errno(errcode); + if (fullpath) + { + free(fullpath); + } + + set_errno(-ret); return VFS_ERROR; } @@ -227,9 +196,7 @@ errout: * ****************************************************************************/ -int rmdir(FAR const char *pathname) +int rmdir(const char *pathname) { return do_rmdir(AT_FDCWD, pathname); } - -#endif /* FS_HAVE_RMDIR */ diff --git a/fs/vfs/fs_select.c b/fs/vfs/fs_select.c old mode 100755 new mode 100644 index cd61c95..5e6bd85 --- a/fs/vfs/fs_select.c +++ b/fs/vfs/fs_select.c @@ -54,7 +54,6 @@ #include "los_signal.h" #include "los_syscall.h" -#include "inode/inode.h" #ifndef CONFIG_DISABLE_POLL diff --git a/fs/vfs/fs_stat.c b/fs/vfs/fs_stat.c old mode 100755 new mode 100644 index 7932c5d..f7d7880 --- a/fs/vfs/fs_stat.c +++ b/fs/vfs/fs_stat.c @@ -43,99 +43,8 @@ #include "sys/stat.h" #include "string.h" #include "stdlib.h" -#include "inode/inode.h" +#include "fs/vnode.h" #include "fs_other.h" -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: statpseudo - ****************************************************************************/ - -static inline int statpseudo(FAR struct inode *inode, FAR struct stat *buf) -{ - /* Most of the stat entries just do not apply */ - - (void)memset_s(buf, sizeof(struct stat), 0, sizeof(struct stat)); - - buf->st_mode |= inode->i_mode; - buf->st_uid = inode->i_uid; - buf->st_gid = inode->i_gid; - if (INODE_IS_SPECIAL(inode)) - { -#if defined(CONFIG_FS_NAMED_SEMAPHORES) - if (INODE_IS_NAMEDSEM(inode)) - { - buf->st_mode = S_IFSEM; - } - else -#endif -#if !defined(CONFIG_DISABLE_MQUEUE) - if (INODE_IS_MQUEUE(inode)) - { - buf->st_mode = S_IFMQ; - } - else -#endif -#if defined(CONFIG_FS_SHM) - if (INODE_IS_SHM(inode)) - { - buf->st_mode = S_IFSHM; - } - else -#endif - { - } - } - else if (inode->u.i_ops) - { - /* Determine the type of the inode */ - - if (INODE_IS_MOUNTPT(inode)) - { - buf->st_mode |= S_IFDIR; - } - else if (INODE_IS_BLOCK(inode)) - { - /* What is if also has child inodes? */ - - buf->st_mode |= S_IFBLK; - } - else /* if (INODE_IS_DRIVER(inode)) */ - { - /* What is it if it also has child inodes? */ - - buf->st_mode |= S_IFCHR; - } - } - else - { - /* If it has no operations, then it must just be a intermediate - * node in the inode tree. It is something like a directory. - * We'll say that all pseudo-directories are read-able but not - * write-able. - */ - - buf->st_mode |= S_IFDIR | inode->i_mode; - } - - return OK; -} - -/**************************************************************************** - * Name: statroot - ****************************************************************************/ - -static inline int statroot(FAR struct stat *buf) -{ - /* There is no inode associated with the fake root directory */ - - (void)memset_s(buf, sizeof(struct stat), 0, sizeof(struct stat)); - buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR; - return OK; -} - /**************************************************************************** * Global Functions ****************************************************************************/ @@ -156,120 +65,64 @@ static inline int statroot(FAR struct stat *buf) * ****************************************************************************/ -int stat(FAR const char *path, FAR struct stat *buf) +int stat(const char *path, struct stat *buf) { - FAR struct inode *inode; - const char *relpath = NULL; - int ret = OK; - char *fullpath = NULL; - struct inode_search_s desc; + struct Vnode *vp = NULL; + int ret; /* Sanity checks */ if (!path || !buf) { - ret = EFAULT; + ret = -EFAULT; goto errout; } if (!path[0]) { - ret = ENOENT; + ret = -ENOENT; goto errout; } - ret = vfs_normalize_path((const char *)NULL, path, &fullpath); + /* Get an vnode for this file */ + VnodeHold(); + ret = VnodeLookup(path, &vp, 0); if (ret < 0) { - ret = -ret; + VnodeDrop(); goto errout; } - /* Check for the fake root directory (which has no inode) */ - - if (strcmp(fullpath, "/") == 0) - { - free(fullpath); - return statroot(buf); - } - - /* Get an inode for this file */ - SETUP_SEARCH(&desc, fullpath, false); - ret = inode_find(&desc); - if (ret < 0) - { - ret = EACCES; - goto errout_with_path; - } - inode = desc.node; - relpath = desc.relpath; - - /* The way we handle the stat depends on the type of inode that we + /* The way we handle the stat depends on the type of vnode that we * are dealing with. */ -#ifndef CONFIG_DISABLE_MOUNTPOINT - if (INODE_IS_MOUNTPT(inode)) + if (vp->vop != NULL && vp->vop->Getattr != NULL) { - /* The node is a file system mointpoint. Verify that the mountpoint - * supports the stat() method - */ - - if (inode->u.i_mops && inode->u.i_mops->stat) - { - /* Perform the stat() operation */ - - ret = inode->u.i_mops->stat(inode, relpath, buf); - } - else - { - ret = ENOSYS; - } + vp->useCount++; + VnodeDrop(); + ret = vp->vop->Getattr(vp, buf); + VnodeHold(); + vp->useCount--; + VnodeDrop(); } else -#endif { - if (strlen(relpath) > 0) - { - ret = ENOENT; - goto errout_with_inode; - } - /* The node is part of the root pseudo file system */ - - if (VfsPermissionCheck(desc.parent->i_uid, desc.parent->i_gid, desc.parent->i_mode, EXEC_OP)) - { - ret = EACCES; - goto errout_with_inode; - } - ret = statpseudo(inode, buf); + VnodeDrop(); + ret = -ENOSYS; + goto errout; } - /* Check if the stat operation was successful */ - if (ret < 0) { - ret = -ret; - goto errout_with_inode; + goto errout; } - /* Successfully stat'ed the file */ - - inode_release(inode); - free(fullpath); return OK; /* Failure conditions always set the errno appropriately */ -errout_with_inode: - inode_release(inode); -errout_with_path: - free(fullpath); errout: - set_errno(ret); + set_errno(-ret); return VFS_ERROR; } - -int isatty(int fd) -{ - return 0; -} diff --git a/fs/vfs/fs_statfs.c b/fs/vfs/fs_statfs.c old mode 100755 new mode 100644 index 1bd7c20..c5a79f5 --- a/fs/vfs/fs_statfs.c +++ b/fs/vfs/fs_statfs.c @@ -42,23 +42,9 @@ #include "sys/statfs.h" #include "string.h" #include "sched.h" - -#include "inode/inode.h" +#include "fs/vnode.h" #include "errno.h" #include "stdlib.h" -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: statpseudo - ****************************************************************************/ - -static inline int statpseudofs(FAR struct inode *inode, FAR struct statfs *buf) -{ - (void)memset_s(buf, sizeof(struct statfs), 0, sizeof(struct statfs)); - return OK; -} /**************************************************************************** * Public Functions @@ -81,113 +67,62 @@ static inline int statpseudofs(FAR struct inode *inode, FAR struct statfs *buf) * ****************************************************************************/ -int statfs(FAR const char *path, FAR struct statfs *buf) +int statfs(const char *path, struct statfs *buf) { - FAR struct inode *inode; - int ret = OK; - char *fullpath = NULL; - struct inode_search_s desc; + struct Vnode *vnode = NULL; + struct Mount *mnt = NULL; + int ret = OK; /* Sanity checks */ - if (!path || !buf) { - ret = EFAULT; + ret = -EFAULT; goto errout; } - if (!path[0]) { - ret = ENOENT; + ret = -ENOENT; goto errout; } - - ret = vfs_normalize_path((const char *)NULL, path, &fullpath); + /* Get an vnode for this file */ + VnodeHold(); + ret = VnodeLookup(path, &vnode, 0); if (ret < 0) { - ret = -ret; + VnodeDrop(); goto errout; } + vnode->useCount++; + VnodeDrop(); - /* Get an inode for this file */ - SETUP_SEARCH(&desc, fullpath, false); - ret = inode_find(&desc); - if (ret < 0) + mnt = vnode->originMount; + if (mnt == NULL || mnt->ops == NULL || mnt->ops->Statfs == NULL) { - ret = EACCES; - free(fullpath); - goto errout; - } - inode = desc.node; - - /* The way we handle the statfs depends on the type of inode that we - * are dealing with. - */ - -#ifndef CONFIG_DISABLE_MOUNTPOINT - if (INODE_IS_MOUNTPT(inode)) - { - /* The node is a file system mointpoint. Verify that the mountpoint - * supports the statfs() method - */ - - if (inode->u.i_mops && inode->u.i_mops->stat && inode->u.i_mops->statfs) - { - struct stat *statbuf = LOS_MemAlloc(m_aucSysMem0, sizeof(struct stat)); - if (statbuf == NULL) - { - ret = ENOMEM; - } - else - { - /* Check whether the path is available or not */ - - ret = inode->u.i_mops->stat(inode, desc.relpath, statbuf); - if (ret == 0) - { - /* Perform the statfs() operation */ - - (void)memset_s((void *)buf, sizeof(struct statfs), 0, sizeof(struct statfs)); - ret = inode->u.i_mops->statfs(inode, buf); - } - (VOID)LOS_MemFree(m_aucSysMem0, statbuf); - } - } + ret = -ENOSYS; + goto errout_with_useCount; } else -#endif { - /* The node is part of the root pseudo file system */ - - if (strlen(desc.relpath) > 0) + ret = mnt->ops->Statfs(mnt, buf); + if (ret < 0) { - ret = ENOENT; - goto errout_with_inode; + goto errout_with_useCount; } - - ret = statpseudofs(inode, buf); - } - - /* Check if the statfs operation was successful */ - - if (ret < 0) - { - ret = -ret; - goto errout_with_inode; } - /* Successfully statfs'ed the file */ + VnodeHold(); + vnode->useCount--; + VnodeDrop(); - inode_release(inode); - free(fullpath); return OK; /* Failure conditions always set the errno appropriately */ -errout_with_inode: - inode_release(inode); - free(fullpath); +errout_with_useCount: + VnodeHold(); + vnode->useCount--; + VnodeDrop(); errout: - set_errno(ret); + set_errno(-ret); return VFS_ERROR; } diff --git a/fs/vfs/fs_truncate.c b/fs/vfs/fs_truncate.c old mode 100755 new mode 100644 index b43a220..0621ba3 --- a/fs/vfs/fs_truncate.c +++ b/fs/vfs/fs_truncate.c @@ -45,7 +45,7 @@ #include "assert.h" #include "errno.h" -#include "inode/inode.h" +#include "fs/vnode.h" /**************************************************************************** * Name: file_truncate @@ -56,9 +56,9 @@ * the errno variable. * ****************************************************************************/ -static int file_truncate(FAR struct file *filep, off_t length) +static int file_truncate(struct file *filep, off_t length) { - FAR struct inode *inode = NULL; + struct Vnode *vnode = NULL; int ret; int err; @@ -70,13 +70,13 @@ static int file_truncate(FAR struct file *filep, off_t length) goto errout; } - /* Is this inode a registered mountpoint? Does it support the + /* Is this vnode a registered mountpoint? Does it support the * truncate operations may be relevant to device drivers but only * the mountpoint operations vtable contains a truncate method. */ - inode = filep->f_inode; - if (!inode || !inode->u.i_mops || !inode->u.i_mops->truncate) + vnode = filep->f_vnode; + if (!vnode || !vnode->vop || !vnode->vop->Truncate) { err = EBADF; goto errout; @@ -86,7 +86,7 @@ static int file_truncate(FAR struct file *filep, off_t length) * a write-able file system. */ - ret = inode->u.i_mops->truncate(filep, length); + ret = vnode->vop->Truncate(vnode, length); if (ret < 0) { err = -ret; @@ -136,7 +136,7 @@ errout: int ftruncate(int fd, off_t length) { #if CONFIG_NFILE_DESCRIPTORS > 0 - FAR struct file *filep = NULL; + struct file *filep = NULL; #endif /* Did we get a valid file descriptor? */ diff --git a/fs/vfs/fs_truncate64.c b/fs/vfs/fs_truncate64.c old mode 100755 new mode 100644 index e1229d1..ff4ead3 --- a/fs/vfs/fs_truncate64.c +++ b/fs/vfs/fs_truncate64.c @@ -45,7 +45,7 @@ #include "assert.h" #include "errno.h" -#include "inode/inode.h" +#include "fs/vnode.h" /**************************************************************************** * Name: file_truncate @@ -57,55 +57,53 @@ * ****************************************************************************/ -static int file_truncate64(FAR struct file *filep, off64_t length) +static int file_truncate64(struct file *filep, off64_t length) { - FAR struct inode *inode = NULL; - int ret; - int err; - - /* Was this file opened for write access? */ - - if (((unsigned int)(filep->f_oflags) & O_ACCMODE) == O_RDONLY) - { - err = EACCES; - goto errout; - } - - /* Is this inode a registered mountpoint? Does it support the + struct Vnode *vnode = NULL; + int err; + + /* Was this file opened for write access? */ + + if (((unsigned int)(filep->f_oflags) & O_ACCMODE) == O_RDONLY) + { + err = -EACCES; + goto errout; + } + + /* Is this vnode a registered mountpoint? Does it support the * truncate operations may be relevant to device drivers but only * the mountpoint operations vtable contains a truncate method. */ - - inode = filep->f_inode; - if (!inode || !inode->u.i_mops || !inode->u.i_mops->truncate64) - { - err = EBADF; - goto errout; - } - - /* Does the file system support the truncate method? It should if it is + + vnode = filep->f_vnode; + if (!vnode || !vnode->vop || !vnode->vop->Truncate64) + { + err = -ENOSYS; + goto errout; + } + + /* Does the file system support the truncate method? It should if it is * a write-able file system. */ - - ret = inode->u.i_mops->truncate64(filep, length); - if (ret < 0) - { - err = -ret; - goto errout; - } - - return ret; - -errout: - set_errno(err); - return VFS_ERROR; -} - -/**************************************************************************** - * Name: ftruncate - * - * Description: - * The ftruncate() function causes the regular file referenced by fd to + + err = vnode->vop->Truncate64(vnode, length); + if (err < 0) + { + goto errout; + } + + return OK; + +errout: + set_errno(-err); + return VFS_ERROR; +} + +/**************************************************************************** + * Name: ftruncate + * + * Description: + * The ftruncate() function causes the regular file referenced by fd to * have a size of length bytes. * * If the file previously was larger than length, the extra data is @@ -137,7 +135,7 @@ errout: int ftruncate64(int fd, off64_t length) { #if CONFIG_NFILE_DESCRIPTORS > 0 - FAR struct file *filep = NULL; + struct file *filep = NULL; #endif /* Did we get a valid file descriptor? */ @@ -173,21 +171,3 @@ int ftruncate64(int fd, off64_t length) return file_truncate64(filep, length); #endif } - -int truncate64(const char *path, off64_t length) -{ - int fd; - int ret; - - fd = open(path, O_RDWR); - if (fd == VFS_ERROR) - { - /* The errno value has already been set */ - return VFS_ERROR; - } - - ret = ftruncate64(fd, length); - close(fd); - - return ret; -} diff --git a/fs/vfs/fs_unlink.c b/fs/vfs/fs_unlink.c old mode 100755 new mode 100644 index 98c3385..4936457 --- a/fs/vfs/fs_unlink.c +++ b/fs/vfs/fs_unlink.c @@ -44,32 +44,31 @@ #include "fs/fs.h" #include "fcntl.h" -#include "inode/inode.h" +#include "fs/vnode.h" #include "stdlib.h" #include "fs_other.h" /**************************************************************************** - * Pre-processor Definitions + * Private Functions ****************************************************************************/ +static int check_target(struct Vnode *vnode) +{ + if (vnode->type == VNODE_TYPE_DIR) + { + return -EISDIR; + } -#undef FS_HAVE_WRITABLE_MOUNTPOINT -#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \ - CONFIG_NFILE_STREAMS > 0 -# define FS_HAVE_WRITABLE_MOUNTPOINT 1 -#endif - -#undef FS_HAVE_PSEUDOFS_OPERATIONS -#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0 -# define FS_HAVE_PSEUDOFS_OPERATIONS 1 -#endif - -#undef FS_HAVE_UNLINK -#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS) -# define FS_HAVE_UNLINK 1 -#endif - -#ifdef FS_HAVE_UNLINK + if (vnode->useCount > 0) + { + return -EBUSY; + } + if (VfsVnodePermissionCheck(vnode->parent, WRITE_OP)) + { + return -EACCES; + } + return OK; +} /**************************************************************************** * Public Functions ****************************************************************************/ @@ -81,177 +80,82 @@ * ****************************************************************************/ -int do_unlink(int dirfd, FAR const char *pathname) +int do_unlink(int dirfd, const char *pathname) { - FAR struct inode *inode; - const char *relpath = NULL; - int errcode; - int ret; - char *fullpath = NULL; - char *relativepath = NULL; - struct inode_search_s desc; + struct Vnode *vnode = NULL; + int ret; + char *name = NULL; + char *fullpath = NULL; + char *relativepath = NULL; /* Get relative path by dirfd*/ ret = get_path_from_fd(dirfd, &relativepath); if (ret < 0) { - errcode = ret; goto errout; } - errcode = vfs_normalize_path((const char *)relativepath, pathname, &fullpath); + ret = vfs_normalize_path((const char *)relativepath, pathname, &fullpath); if (relativepath) { free(relativepath); } - if (errcode < 0) + if (ret < 0) { - errcode = -errcode; goto errout; } - /* Get an inode for this file */ - SETUP_SEARCH(&desc, fullpath, false); - ret = inode_find(&desc); + VnodeHold(); + ret = VnodeLookup(fullpath, &vnode, 0); if (ret < 0) { - errcode = EACCES; - free(fullpath); - goto errout; + goto errout_with_lock; } - inode = desc.node; - relpath = desc.relpath; -#ifndef CONFIG_DISABLE_MOUNTPOINT - /* Check if the inode is a valid mountpoint. */ - - if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops) + ret = check_target(vnode); + if (ret < 0) { - /* Perform the unlink operation using the relative path at the - * mountpoint. - */ - - if (inode->u.i_mops->unlink) - { - ret = inode->u.i_mops->unlink(inode, relpath); - if (ret < 0) - { - errcode = -ret; - goto errout_with_inode; - } - } - else - { - errcode = ENOSYS; - goto errout_with_inode; - } + goto errout_with_lock; } - else -#endif + name = strrchr(fullpath, '/') + 1; -#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS - /* If this is a "dangling" pseudo-file node (i.e., it has no operations) - * or a soft link, then rm should remove the node. - */ - - if (!INODE_IS_SPECIAL(inode) && inode->u.i_ops) + if (vnode && vnode->vop && vnode->vop->Unlink) { - /* If this is a pseudo-file node (i.e., it has no operations) - * then rmdir should remove the node. - */ - - inode_semtake(); - if (VfsPermissionCheck(desc.parent->i_uid, desc.parent->i_gid, desc.parent->i_mode, EXEC_OP | WRITE_OP)) - { - errcode = EACCES; - goto errout_with_inode; - } - - /* Refuse to unlink the inode if it has children. I.e., if it is - * functioning as a directory and the directory is not empty. - */ - - if (inode->i_child != NULL) - { - errcode = ENOTEMPTY; - inode_semgive(); - goto errout_with_inode; - } - - /* Notify the driver that it has been unlinked. If there are no - * open references to the driver instance, then the driver should - * release all resources because it is no longer accessible. - */ - - if (INODE_IS_DRIVER(inode) && inode->u.i_ops->unlink) - { - /* Notify the character driver that it has been unlinked */ - - ret = inode->u.i_ops->unlink(inode); - if (ret < 0) - { - errcode = -ret; - inode_semgive(); - goto errout_with_inode; - } - } -#ifndef CONFIG_DISABLE_MOUNTPOINT - else if (INODE_IS_BLOCK(inode) && inode->u.i_bops->unlink) - { - /* Notify the block driver that it has been unlinked */ - - ret = inode->u.i_bops->unlink(inode); - if (ret < 0) - { - errcode = -ret; - inode_semgive(); - goto errout_with_inode; - } - } -#endif - else - { - inode_semgive(); - errcode = EACCES; - goto errout_with_inode; - } - - inode_semgive(); + ret = vnode->vop->Unlink(vnode->parent, vnode, name); } - else if (!INODE_IS_SPECIAL(inode) && (inode->u.i_ops == NULL)) + else if (vnode && vnode->fop && vnode->fop->unlink) { - /* It is a "dangling" pseudo-file node with no operations */ - - errcode = EISDIR; - goto errout_with_inode; + ret = vnode->fop->unlink(vnode); } else -#endif { - errcode = ENXIO; - goto errout_with_inode; + ret = -ENOSYS; } - /* Thie file is being deleted, page-caches of the file will no longer be used, - * so drop all the page-caches for the file at this moment, and then remove mapping - * between the file and pagecache. - */ - - (void)remove_mapping(fullpath, NULL); + if (ret != OK) + { + goto errout_with_lock; + } + VnodeFree(vnode); + VnodeDrop(); + (void)remove_mapping(fullpath); /* Successfully unlinked */ - inode_release(inode); free(fullpath); return OK; -errout_with_inode: - inode_release(inode); - free(fullpath); +errout_with_lock: + VnodeDrop(); errout: - set_errno(errcode); + if (fullpath) + { + free(fullpath); + } + set_errno(-ret); + return VFS_ERROR; } @@ -262,7 +166,7 @@ errout: * ****************************************************************************/ -int unlink(FAR const char *pathname) +int unlink(const char *pathname) { return do_unlink(AT_FDCWD, pathname); } @@ -273,9 +177,9 @@ int unlink(FAR const char *pathname) * Description: Remove a file managed a mountpoint by dirfd * ****************************************************************************/ -extern int do_rmdir(int dirfd, FAR const char *pathname); +extern int do_rmdir(int dirfd, const char *pathname); -int unlinkat(int dirfd, FAR const char *pathname, int flag) +int unlinkat(int dirfd, const char *pathname, int flag) { /* Now flag only support 0 && AT_REMOVEDIR */ if ((flag & ~AT_REMOVEDIR) != 0) @@ -286,5 +190,3 @@ int unlinkat(int dirfd, FAR const char *pathname, int flag) return do_unlink(dirfd, pathname); } - -#endif /* FS_HAVE_UNLINK */ diff --git a/fs/vfs/fs_write.c b/fs/vfs/fs_write.c old mode 100755 new mode 100644 index 529f0c6..11a94a8 --- a/fs/vfs/fs_write.c +++ b/fs/vfs/fs_write.c @@ -48,7 +48,7 @@ #include "sys/socket.h" #include "console.h" #include "user_copy.h" -#include "inode/inode.h" +#include "fs/vnode.h" /**************************************************************************** * Public Functions @@ -79,10 +79,8 @@ * values). * ****************************************************************************/ - -ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes) +ssize_t file_write(struct file *filep, const void *buf, size_t nbytes) { - FAR struct inode *inode; int ret; int err; @@ -102,8 +100,7 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes) /* Is a driver registered? Does it support the write method? */ - inode = filep->f_inode; - if (!inode || !inode->u.i_ops || !inode->u.i_ops->write) + if (!filep->ops || !filep->ops->write) { err = EBADF; goto errout; @@ -111,7 +108,7 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes) /* Yes, then let the driver perform the write */ - ret = inode->u.i_ops->write(filep, (const char *)buf, nbytes); + ret = filep->ops->write(filep, (const char *)buf, nbytes); if (ret < 0) { err = -ret; @@ -161,7 +158,7 @@ errout: * specified in buf, the value specified in count, or the current * file offset is not suitably aligned. * EIO - * A low-level I/O error occurred while modifying the inode. + * A low-level I/O error occurred while modifying the vnode. * ENOSPC * The device containing the file referred to by fd has no room for * the data. @@ -173,10 +170,10 @@ errout: * ****************************************************************************/ -ssize_t write(int fd, FAR const void *buf, size_t nbytes) +ssize_t write(int fd, const void *buf, size_t nbytes) { #if CONFIG_NFILE_DESCRIPTORS > 0 - FAR struct file *filep; + struct file *filep; #endif /* Did we get a valid file descriptor? */ @@ -188,7 +185,7 @@ ssize_t write(int fd, FAR const void *buf, size_t nbytes) /* Write to a socket descriptor is equivalent to send with flags == 0 */ #if defined(LOSCFG_NET_LWIP_SACK) - FAR const void *bufbak = buf; + const void *bufbak = buf; ssize_t ret; if (LOS_IsUserAddress((VADDR_T)(uintptr_t)buf)) { diff --git a/include/nuttx/fs/dirent_fs.h b/include/nuttx/fs/dirent_fs.h old mode 100755 new mode 100644 index 9498eac..16baae5 --- a/include/nuttx/fs/dirent_fs.h +++ b/include/nuttx/fs/dirent_fs.h @@ -46,7 +46,6 @@ #include "sys/types.h" #include "stdint.h" #include "dirent.h" - #include "fs/fs.h" #ifdef __cplusplus @@ -132,7 +131,7 @@ struct fs_cromfsdir_s struct tmpfs_directory_s; /* Forward reference */ struct fs_tmpfsdir_s { - FAR struct tmpfs_directory_s *tf_tdo; /* Directory being enumerated */ + struct tmpfs_directory_s *tf_tdo; /* Directory being enumerated */ unsigned int tf_index; /* Directory index */ }; @@ -147,12 +146,12 @@ struct fs_binfsdir_s #ifdef CONFIG_FS_NXFFS /* NXFFS is the tiny NuttX wear-leveling FLASH file system. The state value is - * the offset in FLASH memory to the next inode entry. + * the offset in FLASH memory to the next vnode entry. */ struct fs_nxffsdir_s { - off_t nx_offset; /* Offset to the next inode */ + off_t nx_offset; /* Offset to the next vnode */ }; #endif @@ -203,8 +202,8 @@ struct fs_unionfsdir_s uint8_t fu_ndx; /* Index of file system being enumerated */ bool fu_eod; /* True: At end of directory */ bool fu_prefix[2]; /* True: Fake directory in prefix */ - FAR char *fu_relpath; /* Path being enumerated */ - FAR struct fs_dirent_s *fu_lower[2]; /* dirent struct used by contained file system */ + char *fu_relpath; /* Path being enumerated */ + struct fs_dirent_s *fu_lower[2]; /* dirent struct used by contained file system */ }; #endif @@ -215,7 +214,7 @@ struct fs_unionfsdir_s struct fs_userfsdir_s { - FAR void *fs_dir; /* Opaque pointer to UserFS DIR */ + void *fs_dir; /* Opaque pointer to UserFS DIR */ }; #endif @@ -226,21 +225,21 @@ struct fs_userfsdir_s struct fs_hostfsdir_s { - FAR void *fs_dir; /* Opaque pointer to host DIR */ + void *fs_dir; /* Opaque pointer to host DIR */ }; #endif struct fs_dirent_s { - /* This is the node that was opened by opendir. The type of the inode + /* This is the node that was opened by opendir. The type of the vnode * determines the way that the readdir() operations are performed. For the * pseudo root pseudo-file system, it is also used to support rewind. * - * We hold a reference on this inode so we know that it will persist until - * closedir() is called (although inodes linked to this inode may change). + * We hold a reference on this vnode so we know that it will persist until + * closedir() is called (although vnodes linked to this vnode may change). */ - struct inode *fd_root; + struct Vnode *fd_root; /* At present, only mountpoints require special handling flags */ @@ -252,6 +251,10 @@ struct fs_dirent_s off_t fd_position; + /* This keeps track of the internal offset for some FSs */ + off_t fd_int_offset; + + /* Retained control information depends on the type of file system that * provides is provides the mountpoint. Ideally this information should * be hidden behind an opaque, file-system-dependent void *, but we put @@ -282,7 +285,7 @@ struct fs_dirent_s struct fs_binfsdir_s binfs; #endif #ifdef CONFIG_FS_PROCFS - FAR void *procfs; + void *procfs; #endif #ifdef CONFIG_FS_NXFFS struct fs_nxffsdir_s nxffs; @@ -297,7 +300,7 @@ struct fs_dirent_s struct fs_spiffsdir_s spiffs; #endif #ifdef CONFIG_FS_LITTLEFS - FAR void *littlefs; + void *littlefs; #endif #ifdef CONFIG_FS_UNIONFS struct fs_unionfsdir_s unionfs; diff --git a/include/nuttx/fs/file.h b/include/nuttx/fs/file.h old mode 100755 new mode 100644 index 952f140..a9e9b9f --- a/include/nuttx/fs/file.h +++ b/include/nuttx/fs/file.h @@ -67,9 +67,9 @@ extern "C" { #ifndef CONFIG_DISABLE_MOUNTPOINT struct statfs; /* Forward reference */ -typedef int (*foreach_mountpoint_t)(FAR const char *mountpoint, - FAR struct statfs *statbuf, - FAR void *arg); +typedef int (*foreach_mountpoint_t)(const char *mountpoint, + struct statfs *statbuf, + void *arg); #endif struct filelist *sched_getfiles(void); @@ -110,6 +110,8 @@ ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count); */ extern int get_path_from_fd(int fd, char **path); +extern int get_path_from_dirfd(int fd, char **path); +bool get_bit(int i); /**************************************************************************** * Name: foreach_mountpoint @@ -119,8 +121,8 @@ extern int get_path_from_fd(int fd, char **path); * terminated when the callback 'handler' returns a non-zero value, or when * all of the mountpoints have been visited. * - * This is just a front end "filter" to foreach_inode() that forwards only - * mountpoint inodes. It is intended to support the mount() command to + * This is just a front end "filter" to foreach_vnode() that forwards only + * mountpoint vnodes. It is intended to support the mount() command to * when the mount command is used to enumerate mounts. * * NOTE 1: Use with caution... The pseudo-file system is locked throughout @@ -136,39 +138,7 @@ extern int get_path_from_fd(int fd, char **path); ****************************************************************************/ #ifndef CONFIG_DISABLE_MOUNTPOINT -int foreach_mountpoint(foreach_mountpoint_t handler, FAR void *arg); -#endif - -/**************************************************************************** - * Name: find_blockdriver - * - * Description: - * Return the inode of the block driver specified by 'pathname' - * - * Input Parameters: - * pathname - The full path to the block driver to be located - * mountflags - If MS_RDONLY is not set, then driver must support write - * operations (see include/sys/mount.h) - * ppinode - Address of the location to return the inode reference - * - * Returned Value: - * Returns zero on success or a negated errno on failure: - * - * EINVAL - Pathname or pinode is NULL. - * ENOENT - No block driver of this name is registered - * ENOTBLK - The inode associated with the pathname is not a block driver - * EACCESS - The MS_RDONLY option was not set but this driver does not - * support write access - * - * Attention: - * The parameter pathname is a full path, which begin with '/'. - * The parameter ppinode must point a valid memory, which size must be enough for storing struct inode. - * - ****************************************************************************/ - -#if CONFIG_NFILE_DESCRIPTORS > 0 -int find_blockdriver(FAR const char *pathname, int mountflags, - FAR struct inode **ppinode); +int foreach_mountpoint(foreach_mountpoint_t handler, void *arg); #endif #ifdef __cplusplus diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h old mode 100755 new mode 100644 index 93905b4..3248761 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -58,6 +58,7 @@ #include "los_atomic.h" #include "semaphore.h" #include "los_spinlock.h" +#include "mount.h" #ifndef CONFIG_DISABLE_MQUEUE #include "mqueue.h" @@ -158,8 +159,9 @@ extern "C" { #define CHG_MTIME 32 #define CHG_CTIME 64 -struct IATTR { - /* This structure is used for record inode attr. */ +struct IATTR +{ + /* This structure is used for record vnode attr. */ unsigned int attr_chg_valid; unsigned int attr_chg_flags; unsigned attr_chg_mode; @@ -174,7 +176,7 @@ struct IATTR { /* Forward references */ struct file; -struct inode; +struct Vnode; struct stat; struct statfs; struct pollfd; @@ -188,25 +190,30 @@ struct file_operations_vfs { /* The device driver open method differs from the mountpoint open method */ - int (*open)(FAR struct file *filep); + int (*open)(struct file *filep); /* The following methods must be identical in signature and position because * the struct file_operations and struct mountp_operations are treated like * unions. */ - int (*close)(FAR struct file *filep); - ssize_t (*read)(FAR struct file *filep, FAR char *buffer, size_t buflen); - ssize_t (*write)(FAR struct file *filep, FAR const char *buffer, size_t buflen); - off_t (*seek)(FAR struct file *filep, off_t offset, int whence); - int (*ioctl)(FAR struct file *filep, int cmd, unsigned long arg); - int (*mmap)(FAR struct file* filep, struct VmMapRegion *region); + int (*close)(struct file *filep); + ssize_t (*read)(struct file *filep, char *buffer, size_t buflen); + ssize_t (*write)(struct file *filep, const char *buffer, size_t buflen); + off_t (*seek)(struct file *filep, off_t offset, int whence); + int (*ioctl)(struct file *filep, int cmd, unsigned long arg); + int (*mmap)(struct file* filep, struct VmMapRegion *region); /* The two structures need not be common after this point */ #ifndef CONFIG_DISABLE_POLL - int (*poll)(FAR struct file *filep, poll_table *fds); + int (*poll)(struct file *filep, poll_table *fds); #endif - int (*unlink)(FAR struct inode *inode); + int (*stat)(struct file *filep, struct stat* st); + int (*fallocate)(struct file* filep, int mode, off_t offset, off_t len); + int (*fallocate64)(struct file *filep, int mode, off64_t offset, off64_t len); + int (*fsync)(struct file *filep); + ssize_t (*readpage)(struct file *filep, char *buffer, size_t buflen); + int (*unlink)(struct Vnode *vnode); }; /* This structure provides information about the state of a block driver */ @@ -214,68 +221,42 @@ struct file_operations_vfs #ifndef CONFIG_DISABLE_MOUNTPOINT struct geometry { - bool geo_available; /* true: The device is available */ - bool geo_mediachanged; /* true: The media has changed since last query */ - bool geo_writeenabled; /* true: It is okay to write to this device */ + bool geo_available; /* true: The device is available */ + bool geo_mediachanged; /* true: The media has changed since last query */ + bool geo_writeenabled; /* true: It is okay to write to this device */ unsigned long long geo_nsectors; /* Number of sectors on the device */ - size_t geo_sectorsize; /* Size of one sector */ + size_t geo_sectorsize; /* Size of one sector */ }; /* This structure is provided by block devices when they register with the * system. It is used by file systems to perform filesystem transfers. It * differs from the normal driver vtable in several ways -- most notably in - * that it deals in struct inode vs. struct filep. + * that it deals in struct Vnode vs. struct filep. */ -struct inode; +struct Vnode; struct block_operations { - int (*open)(FAR struct inode *inode); - int (*close)(FAR struct inode *inode); - ssize_t (*read)(FAR struct inode *inode, FAR unsigned char *buffer, + int (*open)(struct Vnode *vnode); + int (*close)(struct Vnode *vnode); + ssize_t (*read)(struct Vnode *vnode, unsigned char *buffer, unsigned long long start_sector, unsigned int nsectors); - ssize_t (*write)(FAR struct inode *inode, FAR const unsigned char *buffer, + ssize_t (*write)(struct Vnode *vnode, const unsigned char *buffer, unsigned long long start_sector, unsigned int nsectors); - int (*geometry)(FAR struct inode *inode, FAR struct geometry *geometry); - int (*ioctl)(FAR struct inode *inode, int cmd, unsigned long arg); - int (*unlink)(FAR struct inode *inode); -}; - -/* This structure is provided by a filesystem to describe a mount point. - * Note that this structure differs from file_operations ONLY in the form of - * the open method. Once the file is opened, it can be accessed either as a - * struct file_operations or struct mountpt_operations - */ - -/* 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; - char *owner; /* owner: full path of file */ + int (*geometry)(struct Vnode *vnode, struct geometry *geometry); + int (*ioctl)(struct Vnode *vnode, int cmd, unsigned long arg); + int (*unlink)(struct Vnode *vnode); }; - -struct mountpt_operations +struct mountpt_operations2 { /* The mountpoint open method differs from the driver open method - * because it receives (1) the inode that contains the mountpoint + * because it receives (1) the vnode that contains the mountpoint * private data, (2) the relative path into the mountpoint, and (3) * information to manage privileges. */ - int (*open)(FAR struct file *filep, FAR const char *relpath, + int (*open)(struct file *filep, const char *relpath, int oflags, mode_t mode); /* The following methods must be identical in signature and position @@ -283,13 +264,13 @@ struct mountpt_operations * treated like unions. */ - int (*close)(FAR struct file *filep); - ssize_t (*read)(FAR struct file *filep, FAR char *buffer, size_t buflen); - ssize_t (*write)(FAR struct file *filep, FAR const char *buffer, + int (*close)(struct file *filep); + ssize_t (*read)(struct file *filep, char *buffer, size_t buflen); + ssize_t (*write)(struct file *filep, const char *buffer, size_t buflen); - off_t (*seek)(FAR struct file *filep, off_t offset, int whence); - int (*ioctl)(FAR struct file *filep, int cmd, unsigned long arg); - int (*mmap)(FAR struct file* filep, LosVmMapRegion *region); + off_t (*seek)(struct file *filep, off_t offset, int whence); + int (*ioctl)(struct file *filep, int cmd, unsigned long arg); + int (*mmap)(struct file* filep, LosVmMapRegion *region); /* The two structures need not be common after this point. The following * are extended methods needed to deal with the unique needs of mounted * file systems. @@ -297,58 +278,90 @@ struct mountpt_operations * Additional open-file-specific mountpoint operations: */ - int (*sync)(FAR struct file *filep); - int (*dup)(FAR const struct file *oldp, FAR struct file *newp); - int (*fstat)(FAR const struct file *filep, FAR struct stat *buf); - int (*truncate)(FAR struct file *filep, off_t length); + int (*sync)(struct file *filep); + int (*dup)(const struct file *oldp, struct file *newp); + int (*fstat)(const struct file *filep, struct stat *buf); + int (*truncate)(struct file *filep, off_t length); /* Directory operations */ - int (*opendir)(FAR struct inode *mountpt, FAR const char *relpath, - FAR struct fs_dirent_s *dir); - int (*closedir)(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir); - int (*readdir)(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir); - int (*rewinddir)(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir); + int (*opendir)(struct Vnode *mountpt, const char *relpath, + struct fs_dirent_s *dir); + int (*closedir)(struct Vnode *mountpt, + struct fs_dirent_s *dir); + int (*readdir)(struct Vnode *mountpt, + struct fs_dirent_s *dir); + int (*rewinddir)(struct Vnode *mountpt, + struct fs_dirent_s *dir); /* General volume-related mountpoint operations: */ - int (*bind)(FAR struct inode *blkdriver, FAR const void *data, - FAR void **handle, FAR const char *realpath); - int (*unbind)(FAR void *handle, FAR struct inode **blkdriver); - int (*statfs)(FAR struct inode *mountpt, FAR struct statfs *buf); - int (*virstatfs)(struct inode *mountpt, const char* relpath, struct statfs *buf); + int (*bind)(struct Vnode *blkdriver, const void *data, void **handle, const char *realpath); + int (*unbind)(void *handle, struct Vnode **blkdriver); + int (*statfs)(struct Vnode *mountpt, struct statfs *buf); + int (*virstatfs)(struct Vnode *mountpt, const char* relpath, struct statfs *buf); /* Operations on paths */ - int (*unlink)(FAR struct inode *mountpt, FAR const char *relpath); - int (*mkdir)(FAR struct inode *mountpt, FAR const char *relpath, + int (*unlink)(struct Vnode *mountpt, const char *relpath); + int (*mkdir)(struct Vnode *mountpt, const char *relpath, mode_t mode); - int (*rmdir)(FAR struct inode *mountpt, FAR const char *relpath); - int (*rename)(FAR struct inode *mountpt, FAR const char *oldrelpath, - FAR const char *newrelpath); - int (*stat)(FAR struct inode *mountpt, FAR const char *relpath, - FAR struct stat *buf); - int (*utime)(FAR struct inode *mountpt, FAR const char *relpath, - FAR const struct tm *times); - int (*chattr)(FAR struct inode *mountpt, FAR const char *relpath, + int (*rmdir)(struct Vnode *mountpt, const char *relpath); + int (*rename)(struct Vnode *mountpt, const char *oldrelpath, + const char *newrelpath); + int (*stat)(struct Vnode *mountpt, const char *relpath, + struct stat *buf); + int (*utime)(struct Vnode *mountpt, const char *relpath, + const struct tm *times); + int (*chattr)(struct Vnode *mountpt, const char *relpath, struct IATTR *attr); - loff_t (*seek64)(FAR struct file *filep, loff_t offset, int whence); - int (*getlabel)(FAR void *handle, FAR char* label); - int (*fallocate)(FAR struct file *filep, int mode, off_t offset, off_t len); - int (*fallocate64)(FAR struct file *filep, int mode, off64_t offset, off64_t len); - int (*truncate64)(FAR struct file *filep, off64_t length); - int (*fscheck)(FAR struct inode *mountpt, FAR const char *relpath, - FAR struct fs_dirent_s *dir); + loff_t (*seek64)(struct file *filep, loff_t offset, int whence); + int (*getlabel)(void *handle, char* label); + int (*fallocate)(struct file *filep, int mode, off_t offset, off_t len); + int (*fallocate64)(struct file *filep, int mode, off64_t offset, off64_t len); + int (*truncate64)(struct file *filep, off64_t length); + int (*fscheck)(struct Vnode *mountpt, const char *relpath, + struct fs_dirent_s *dir); int (*map_pages)(LosVmMapRegion *region, LosVmPgFault *pgFault); - ssize_t (*readpage)(struct file *filep, char *buffer, size_t buflen); ssize_t (*writepage)(struct file *filep, const char *buffer, size_t buflen); /* NOTE: More operations will be needed here to support: disk usage * stats file stat(), file attributes, file truncation, etc. */ }; + +struct drv_data +{ + const void *ops; + mode_t mode; + void *priv; +}; + +/* This structure is provided by a filesystem to describe a mount point. + * Note that this structure differs from file_operations ONLY in the form of + * the open method. Once the file is opened, it can be accessed either as a + * struct file_operations or struct mountpt_operations + */ + +/* 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 */ +}; #endif /* CONFIG_DISABLE_MOUNTPOINT */ #ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION @@ -366,7 +379,7 @@ typedef struct virtual_partition_info struct fsmap_t { const char *fs_filesystemtype; - const struct mountpt_operations *fs_mops; + const struct MountOps *fs_mops; const BOOL is_mtd_support; const BOOL is_bdfs; }; @@ -391,25 +404,10 @@ struct fsmap_t _l LOS_HAL_TABLE_ENTRY(fsmap) = \ */ /* These are the various kinds of operations that can be associated with - * an inode. + * an vnode. */ -union inode_ops_u -{ - FAR const struct file_operations_vfs *i_ops; /* Driver operations for inode */ -#ifndef CONFIG_DISABLE_MOUNTPOINT - FAR const struct block_operations *i_bops; /* Block driver operations */ - FAR const struct mountpt_operations *i_mops; /* Operations on a mountpoint */ -#endif -#ifdef CONFIG_FS_NAMED_SEMAPHORES - FAR struct nsem_inode_s *i_nsem; /* Named semaphore */ -#endif -#ifndef CONFIG_DISABLE_MQUEUE - FAR struct mqueue_inode_s *i_mqueue; /* POSIX message queue */ -#endif -}; - -/* This structure represents one inode in the NuttX pseudo-file system */ +/* This structure represents one vnode in the NuttX pseudo-file system */ typedef enum mount_status { @@ -417,36 +415,19 @@ typedef enum mount_status STAT_MOUNTED, } MOUNT_STATE; -struct inode -{ - FAR struct inode *i_peer; /* Link to same level inode */ - FAR struct inode *i_child; /* Link to lower level inode */ - int16_t i_crefs; /* References to inode */ - uint16_t i_flags; /* Flags for inode */ - unsigned long mountflags; /* Flags for mount */ - union inode_ops_u u; /* Inode operations */ -#ifdef LOSCFG_FILE_MODE - unsigned int i_uid; - unsigned int i_gid; - mode_t i_mode; /* Access mode flags */ -#endif - FAR void *i_private; /* Per inode driver private data */ - MOUNT_STATE e_status; - char i_name[1]; /* Name of inode (variable) */ -}; -#define FSNODE_SIZE(n) (sizeof(struct inode) + (n)) +#define FSNODE_SIZE(n) (sizeof(struct Vnode) + (n)) /* 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 inode operations. + * the file descriptor to the file state and to a set of vnode operations. */ struct file { unsigned int f_magicnum; /* file magic number */ int f_oflags; /* Open mode flags */ - FAR struct inode *f_inode; /* Driver interface */ + struct Vnode *f_vnode; /* Driver interface */ loff_t f_pos; /* File position */ unsigned long f_refcount; /* reference count */ char *f_path; /* File fullpath */ @@ -454,6 +435,8 @@ struct file const char *f_relpath; /* realpath */ 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; + int fd; }; /* This defines a list of files indexed by the file descriptor */ @@ -502,10 +485,10 @@ struct file_struct sem_t fs_sem; /* For thread safety */ pid_t fs_holder; /* Holder of sem */ int fs_counts; /* Number of times sem is held */ - FAR unsigned char *fs_bufstart; /* Pointer to start of buffer */ - FAR unsigned char *fs_bufend; /* Pointer to 1 past end of buffer */ - FAR unsigned char *fs_bufpos; /* Current position in buffer */ - FAR unsigned char *fs_bufread; /* Pointer to 1 past last buffered read char. */ + unsigned char *fs_bufstart; /* Pointer to start of buffer */ + unsigned char *fs_bufend; /* Pointer to 1 past end of buffer */ + unsigned char *fs_bufpos; /* Current position in buffer */ + unsigned char *fs_bufread; /* Pointer to 1 past last buffered read char. */ #endif uint16_t fs_oflags; /* Open mode flags */ uint8_t fs_flags; /* Stream flags */ @@ -539,21 +522,21 @@ void fs_initialize(void); * Name: register_driver * * Description: - * Register a character driver inode the pseudo file system. + * Register a character driver vnode the pseudo file system. * * Input Parameters: - * path - The path to the inode to create + * path - The path to the vnode to create * fops - The file operations structure * mode - Access privileges (not used) - * priv - Private, user data that will be associated with the inode. + * priv - Private, user data that will be associated with the vnode. * * Returned Value: - * Zero on success (with the inode point in 'inode'); A negated errno + * Zero on success (with the vnode point in 'vnode'); A negated errno * value is returned on a failure (all error values returned by - * inode_reserve): + * vnode_reserve): * * EINVAL - 'path' is invalid for this operation - * EEXIST - An inode already exists at 'path' + * EEXIST - An vnode already exists at 'path' * ENOMEM - Failed to allocate in-memory resources for the operation * * Attention: @@ -565,15 +548,15 @@ void fs_initialize(void); * ****************************************************************************/ -int register_driver(FAR const char *path, - FAR const struct file_operations_vfs *fops, mode_t mode, - FAR void *priv); +int register_driver(const char *path, + const struct file_operations_vfs *fops, mode_t mode, + void *priv); /**************************************************************************** * Name: register_blockdriver * * Description: - * Register a block driver inode the pseudo file system. + * Register a block driver vnode the pseudo file system. * * Attention: * This function should be called after los_vfs_init has been called. @@ -583,38 +566,38 @@ int register_driver(FAR const char *path, * The bops must pointed the right functions, otherwise the system will crash when the device is being operated. * * Input Parameters: - * path - The path to the inode to create + * path - The path to the vnode to create * bops - The block driver operations structure * mode - Access privileges (not used) - * priv - Private, user data that will be associated with the inode. + * priv - Private, user data that will be associated with the vnode. * * Returned Value: - * Zero on success (with the inode point in 'inode'); A negated errno + * Zero on success (with the vnode point in 'vnode'); A negated errno * value is returned on a failure (all error values returned by - * inode_reserve): + * vnode_reserve): * * EINVAL - 'path' is invalid for this operation - * EEXIST - An inode already exists at 'path' + * EEXIST - An vnode already exists at 'path' * ENOMEM - Failed to allocate in-memory resources for the operation * ****************************************************************************/ #ifndef CONFIG_DISABLE_MOUNTPOINT -int register_blockdriver(FAR const char *path, - FAR const struct block_operations *bops, - mode_t mode, FAR void *priv); +int register_blockdriver(const char *path, + const struct block_operations *bops, + mode_t mode, void *priv); #endif /**************************************************************************** * Name: unregister_driver * * Description: - * Remove the character driver inode at 'path' from the pseudo-file system + * Remove the character driver vnode at 'path' from the pseudo-file system * * Returned Value: - * Zero on success (with the inode point in 'inode'); A negated errno + * Zero on success (with the vnode point in 'vnode'); A negated errno * value is returned on a failure (all error values returned by - * inode_reserve): + * vnode_reserve): * * EBUSY - Resource is busy ,not permit for this operation. * ENOENT - 'path' is invalid for this operation. @@ -626,21 +609,21 @@ int register_blockdriver(FAR const char *path, * The block device node referred by parameter path must be really exist. ****************************************************************************/ -int unregister_driver(FAR const char *path); +int unregister_driver(const char *path); /**************************************************************************** * Name: unregister_blockdriver * * Description: - * Remove the block driver inode at 'path' from the pseudo-file system + * Remove the block driver vnode at 'path' from the pseudo-file system * * Input Parameters: - * path - The path that the inode to be destroyed. + * path - The path that the vnode to be destroyed. * * Returned Value: - * Zero on success (with the inode point in 'inode'); A negated errno + * Zero on success (with the vnode point in 'vnode'); A negated errno * value is returned on a failure (all error values returned by - * inode_reserve): + * vnode_reserve): * * EBUSY - Resource is busy ,not permit for this operation. * ENOENT - 'path' is invalid for this operation. @@ -653,7 +636,7 @@ int unregister_driver(FAR const char *path); * ****************************************************************************/ -int unregister_blockdriver(FAR const char *path); +int unregister_blockdriver(const char *path); /**************************************************************************** * Name: files_initlist @@ -664,7 +647,7 @@ int unregister_blockdriver(FAR const char *path); ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -void files_initlist(FAR struct filelist *list); +void files_initlist(struct filelist *list); #endif /**************************************************************************** @@ -676,14 +659,14 @@ void files_initlist(FAR struct filelist *list); ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -void files_releaselist(FAR struct filelist *list); +void files_releaselist(struct filelist *list); #endif /**************************************************************************** * Name: file_dup2 * * Description: - * Assign an inode to a specific files structure. This is the heart of + * Assign an vnode to a specific files structure. This is the heart of * dup2. * * Equivalent to the non-standard fs_dupfd2() function except that it @@ -697,7 +680,7 @@ void files_releaselist(FAR struct filelist *list); ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -int file_dup2(FAR struct file *filep1, FAR struct file *filep2); +int file_dup2(struct file *filep1, struct file *filep2); #endif /**************************************************************************** @@ -738,7 +721,7 @@ int fs_dupfd(int fd, int minfd); * ****************************************************************************/ -int file_dup(FAR struct file *filep, int minfd); +int file_dup(struct file *filep, int minfd); /**************************************************************************** * Name: fs_dupfd2 OR dup2 @@ -768,49 +751,79 @@ int fs_dupfd2(int fd1, int fd2); * Name: open_blockdriver * * Description: - * Return the inode of the block driver specified by 'pathname' + * Return the vnode of the block driver specified by 'pathname' * * Input Parameters: * pathname - the full path to the block driver to be opened * mountflags - if MS_RDONLY is not set, then driver must support write * operations (see include/sys/mount.h) - * ppinode - address of the location to return the inode reference + * ppvnode - address of the location to return the vnode reference * * Returned Value: * Returns zero on success or a negated errno on failure: * - * EINVAL - pathname or pinode is NULL + * EINVAL - pathname or pvnode is NULL * ENOENT - No block driver of this name is registered - * ENOTBLK - The inode associated with the pathname is not a block driver + * ENOTBLK - The vnode associated with the pathname is not a block driver * EACCESS - The MS_RDONLY option was not set but this driver does not * support write access * * Aattention: * The parameter path must point a valid string, which end with the terminating null byte. * The total length of parameter path must less than the value defined by PATH_MAX. - * The parameter ppinode must point a valid memory, which size must be enough for storing struct inode. + * The parameter ppvnode must point a valid memory, which size must be enough for storing struct Vnode. ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -int open_blockdriver(FAR const char *pathname, int mountflags, - FAR struct inode **ppinode); +int open_blockdriver(const char *pathname, int mountflags, + struct Vnode **ppvnode); #endif +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: find_blockdriver + * + * Description: + * Return the inode of the block driver specified by 'pathname' + * + * Input Parameters: + * pathname - The full path to the block driver to be located + * mountflags - If MS_RDONLY is not set, then driver must support write + * operations (see include/sys/mount.h) + * ppinode - Address of the location to return the inode reference + * + * Returned Value: + * Returns zero on success or a negated errno on failure: + * + * ENOENT - No block driver of this name is registered + * ENOTBLK - The inode associated with the pathname is not a block driver + * EACCESS - The MS_RDONLY option was not set but this driver does not + * support write access + * + ****************************************************************************/ + +int find_blockdriver(const char *pathname, int mountflags, + struct Vnode **vpp); + + /**************************************************************************** * Name: close_blockdriver * * Description: - * Call the close method and release the inode + * Call the close method and release the vnode * * Input Parameters: - * inode - reference to the inode of a block driver opened by open_blockdriver + * vnode - reference to the vnode of a block driver opened by open_blockdriver * * Returned Value: * Returns zero on success or a negated errno on failure: * - * EINVAL - inode is NULL - * ENOTBLK - The inode is not a block driver + * EINVAL - vnode is NULL + * ENOTBLK - The vnode is not a block driver * * Attention: * This function should be called after open_blockdriver has been called. @@ -818,7 +831,7 @@ int open_blockdriver(FAR const char *pathname, int mountflags, ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -int close_blockdriver(FAR struct inode *inode); +int close_blockdriver(struct Vnode *vnode); #endif /**************************************************************************** @@ -865,7 +878,7 @@ int fs_ioctl(int fd, int req, unsigned long arg); #if CONFIG_NFILE_STREAMS > 0 struct tcb_s; /* Forward reference */ -FAR struct file_struct *fs_fdopen(int fd, int oflags); +struct file_struct *fs_fdopen(int fd, int oflags); #endif /**************************************************************************** @@ -878,7 +891,7 @@ FAR struct file_struct *fs_fdopen(int fd, int oflags); ****************************************************************************/ #if CONFIG_NFILE_STREAMS > 0 -int lib_flushall(FAR struct streamlist *list); +int lib_flushall(struct streamlist *list); #endif /**************************************************************************** @@ -912,7 +925,7 @@ ssize_t lib_sendfile(int outfd, int infd, off_t *offset, size_t count); ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -int fs_getfilep(int fd, FAR struct file **filep); +int fs_getfilep(int fd, struct file **filep); #endif /**************************************************************************** @@ -939,7 +952,7 @@ int fs_getfilep(int fd, FAR struct file **filep); ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes); +ssize_t file_read(struct file *filep, void *buf, size_t nbytes); #endif /**************************************************************************** @@ -953,7 +966,7 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes); ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes); +ssize_t file_write(struct file *filep, const void *buf, size_t nbytes); #endif /**************************************************************************** @@ -967,7 +980,7 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes); ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -ssize_t file_pread(FAR struct file *filep, FAR void *buf, size_t nbytes, +ssize_t file_pread(struct file *filep, void *buf, size_t nbytes, off_t offset); #endif @@ -982,7 +995,7 @@ ssize_t file_pread(FAR struct file *filep, FAR void *buf, size_t nbytes, ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -ssize_t file_pwrite(FAR struct file *filep, FAR const void *buf, +ssize_t file_pwrite(struct file *filep, const void *buf, size_t nbytes, off_t offset); #endif @@ -997,7 +1010,7 @@ ssize_t file_pwrite(FAR struct file *filep, FAR const void *buf, ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -off_t file_seek(FAR struct file *filep, off_t offset, int whence); +off_t file_seek(struct file *filep, off_t offset, int whence); #endif /**************************************************************************** @@ -1011,7 +1024,7 @@ off_t file_seek(FAR struct file *filep, off_t offset, int whence); ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -int file_fsync(FAR struct file *filep); +int file_fsync(struct file *filep); #endif /**************************************************************************** @@ -1034,7 +1047,7 @@ int file_fsync(FAR struct file *filep); ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -int file_vfcntl(FAR struct file *filep, int cmd, va_list ap); +int file_vfcntl(struct file *filep, int cmd, va_list ap); #endif /**************************************************************************** @@ -1048,9 +1061,57 @@ int file_vfcntl(FAR struct file *filep, int cmd, va_list ap); ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -off64_t file_seek64(FAR struct file *filep, off64_t offset, int whence); +off64_t file_seek64(struct file *filep, off64_t offset, int whence); #endif +/**************************************************************************** + * Name: files_allocate + * + * Description: + * Allocate a struct files instance and associate it with an vnode instance. + * Returns the file descriptor == index into the files array. + * + ****************************************************************************/ + +int files_allocate(struct Vnode *vnode, int oflags, off_t pos,void *priv, int minfd); + +/**************************************************************************** + * Name: files_close + * + * Description: + * Close an vnode (if open) + * + * Assumuptions: + * Caller holds the list semaphore because the file descriptor will be freed. + * + ****************************************************************************/ + +int files_close(int fd); + +/**************************************************************************** + * Name: files_release + * + * Assumuptions: + * Similar to files_close(). Called only from open() logic on error + * conditions. + * + ****************************************************************************/ + +void files_release(int fd); + +/**************************************************************************** + * Name: files_initialize + * + * Description: + * This is called from the FS initialization logic to configure the files. + * + ****************************************************************************/ + +void weak_function files_initialize(void); + +int vfs_normalize_path(const char *directory, const char *filename, char **pathname); +int vfs_normalize_pathat(int fd, const char *filename, char **pathname); + #ifdef __cplusplus #if __cplusplus } -- Gitee From d146c2fbdb1d7d58b1db5548f087ffadf6d59bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=87=8E=E7=94=9F=E6=AF=9B=E9=9C=89=E5=90=9B?= Date: Mon, 22 Mar 2021 18:52:02 +0800 Subject: [PATCH 2/2] update fs/nfs/nfs_adapter.c. fix:compatible with the old version of nfs server, add unmount ops. --- fs/nfs/nfs_adapter.c | 63 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/fs/nfs/nfs_adapter.c b/fs/nfs/nfs_adapter.c index f5d914c..1c676de 100644 --- a/fs/nfs/nfs_adapter.c +++ b/fs/nfs/nfs_adapter.c @@ -88,6 +88,8 @@ NFSMOUNT_HOOK g_NFSMOUNT_HOOK = (NFSMOUNT_HOOK)(UINTPTR)NULL; struct nfsstats nfsstats; #endif +#define USE_GUARDED_CREATE 1 + #ifdef LOSCFG_FS_NFS /**************************************************************************** * Private Type Definitions @@ -2598,9 +2600,70 @@ int vfs_nfs_truncate(struct Vnode *node, off_t length) np->n_size = length; return OK; } + +static int vfs_nfs_unmount(struct Mount *mnt, struct Vnode **blkDriver) +{ + (void)blkDriver; + struct nfsmount *nmp = (struct nfsmount *)mnt->data; + int error; + + DEBUGASSERT(nmp); + + /* Get exclusive access to the mount structure */ + + nfs_mux_take(nmp); + + /* Are there any open files? We can tell if there are open files by looking + * at the list of file structures in the mount structure. If this list + * not empty, then there are open files and we cannot unmount now (or a + * crash is sure to follow). + */ + + if (nmp->nm_head != NULL || nmp->nm_dir != NULL) + { + ferr("ERROR; There are open files: %p or directories: %p\n", nmp->nm_head, nmp->nm_dir); + + /* This implementation currently only supports unmounting if there are + * no open file references. + */ + + error = EBUSY; + goto errout_with_mutex; + } + + /* No open file... Umount the file system. */ + + error = rpcclnt_umount(nmp->nm_rpcclnt); + if (error) + { + ferr("ERROR: rpcclnt_umount failed: %d\n", error); + goto errout_with_mutex; + } + + /* Disconnect from the server */ + + rpcclnt_disconnect(nmp->nm_rpcclnt); + + /* And free any allocated resources */ + + nfs_mux_release(nmp); + (void)pthread_mutex_destroy(&nmp->nm_mux); + free(nmp->nm_rpcclnt); + nmp->nm_rpcclnt = NULL; + free(nmp); + nmp = NULL; + + return -error; + +errout_with_mutex: + nfs_mux_release(nmp); + return -error; +} + struct MountOps nfs_mount_operations = { .Mount = vfs_nfs_mount, + .Unmount = vfs_nfs_unmount, .Statfs= vfs_nfs_statfs, }; -- Gitee