fa7403db5a
Summary: 1.The relpath information is stored in the fid structure 2.The relative path information is only saved in the client. When the server changes, the relpath saved in the fid will not change. Signed-off-by: chenrun1 <chenrun1@xiaomi.com>
988 lines
27 KiB
C
988 lines
27 KiB
C
/****************************************************************************
|
|
* fs/v9fs/v9fs.c
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <debug.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <inttypes.h>
|
|
#include <libgen.h>
|
|
#include <string.h>
|
|
|
|
#include <nuttx/fs/fs.h>
|
|
#include <nuttx/fs/ioctl.h>
|
|
#include <nuttx/kmalloc.h>
|
|
|
|
#include "inode/inode.h"
|
|
#include "client.h"
|
|
|
|
/****************************************************************************
|
|
* Private Type
|
|
****************************************************************************/
|
|
|
|
struct v9fs_vfs_file_s
|
|
{
|
|
uint32_t fid;
|
|
mutex_t lock;
|
|
};
|
|
|
|
struct v9fs_vfs_dirent_s
|
|
{
|
|
struct fs_dirent_s base;
|
|
uint32_t fid;
|
|
mutex_t lock;
|
|
off_t offset;
|
|
off_t head;
|
|
size_t size;
|
|
uint8_t buffer[1];
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Private Function Prototypes
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_open(FAR struct file *filep, FAR const char *relpath,
|
|
int oflags, mode_t mode);
|
|
static int v9fs_vfs_close(FAR struct file *filep);
|
|
static ssize_t v9fs_vfs_read(FAR struct file *filep, FAR char *buffer,
|
|
size_t buflen);
|
|
static ssize_t v9fs_vfs_write(FAR struct file *filep,
|
|
FAR const char *buffer, size_t buflen);
|
|
static off_t v9fs_vfs_seek(FAR struct file *filep, off_t offset,
|
|
int whence);
|
|
static int v9fs_vfs_ioctl(FAR struct file *filep, int cmd,
|
|
unsigned long arg);
|
|
static int v9fs_vfs_sync(FAR struct file *filep);
|
|
static int v9fs_vfs_dup(FAR const struct file *oldp, FAR struct file *newp);
|
|
static int v9fs_vfs_fstat(FAR const struct file *filep,
|
|
FAR struct stat *buf);
|
|
static int v9fs_vfs_fchstat(FAR const struct file *filep,
|
|
FAR const struct stat *buf, int flags);
|
|
static int v9fs_vfs_truncate(FAR struct file *filep, off_t length);
|
|
static int v9fs_vfs_opendir(FAR struct inode *mountpt,
|
|
FAR const char *relpath,
|
|
FAR struct fs_dirent_s **dir);
|
|
static int v9fs_vfs_closedir(FAR struct inode *mountpt,
|
|
FAR struct fs_dirent_s *dir);
|
|
static int v9fs_vfs_readdir(FAR struct inode *mountpt,
|
|
FAR struct fs_dirent_s *dir,
|
|
FAR struct dirent *entry);
|
|
static int v9fs_vfs_rewinddir(FAR struct inode *mountpt,
|
|
FAR struct fs_dirent_s *dir);
|
|
static int v9fs_vfs_statfs(FAR struct inode *mountpt,
|
|
FAR struct statfs *buf);
|
|
static int v9fs_vfs_unlink(FAR struct inode *mountpt,
|
|
FAR const char *relpath);
|
|
static int v9fs_vfs_mkdir(FAR struct inode *mountpt,
|
|
FAR const char *relpath, mode_t mode);
|
|
static int v9fs_vfs_rmdir(FAR struct inode *mountpt,
|
|
FAR const char *relpath);
|
|
static int v9fs_vfs_rename(FAR struct inode *mountpt,
|
|
FAR const char *oldrelpath,
|
|
FAR const char *newrelpath);
|
|
static int v9fs_vfs_stat(FAR struct inode *mountpt,
|
|
FAR const char *relpath, FAR struct stat *buf);
|
|
static int v9fs_vfs_chstat(FAR struct inode *mountpt,
|
|
FAR const char *relpath,
|
|
FAR const struct stat *buf, int flags);
|
|
static int v9fs_vfs_bind(FAR struct inode *driver, FAR const void *data,
|
|
FAR void **handle);
|
|
static int v9fs_vfs_unbind(FAR void *handle, FAR struct inode **blkdriver,
|
|
unsigned int flags);
|
|
|
|
/****************************************************************************
|
|
* Public Data
|
|
****************************************************************************/
|
|
|
|
const struct mountpt_operations g_v9fs_operations =
|
|
{
|
|
v9fs_vfs_open, /* open */
|
|
v9fs_vfs_close, /* close */
|
|
v9fs_vfs_read, /* read */
|
|
v9fs_vfs_write, /* write */
|
|
v9fs_vfs_seek, /* seek */
|
|
v9fs_vfs_ioctl, /* ioctl */
|
|
NULL, /* mmap */
|
|
v9fs_vfs_truncate, /* truncate */
|
|
NULL, /* poll */
|
|
|
|
v9fs_vfs_sync, /* sync */
|
|
v9fs_vfs_dup, /* dup */
|
|
v9fs_vfs_fstat, /* fstat */
|
|
v9fs_vfs_fchstat, /* fchstat */
|
|
|
|
v9fs_vfs_opendir, /* opendir */
|
|
v9fs_vfs_closedir, /* closedir */
|
|
v9fs_vfs_readdir, /* readdir */
|
|
v9fs_vfs_rewinddir, /* rewinddir */
|
|
|
|
v9fs_vfs_bind, /* bind */
|
|
v9fs_vfs_unbind, /* unbind */
|
|
v9fs_vfs_statfs, /* statfs */
|
|
|
|
v9fs_vfs_unlink, /* unlink */
|
|
v9fs_vfs_mkdir, /* mkdir */
|
|
v9fs_vfs_rmdir, /* rmdir */
|
|
v9fs_vfs_rename, /* rename */
|
|
v9fs_vfs_stat, /* stat */
|
|
v9fs_vfs_chstat /* chstat */
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_open
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_open(FAR struct file *filep, FAR const char *relpath,
|
|
int oflags, mode_t mode)
|
|
{
|
|
FAR struct v9fs_vfs_file_s *file;
|
|
FAR struct v9fs_client_s *client;
|
|
int ret;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = filep->f_inode->i_private;
|
|
|
|
file = kmm_zalloc(sizeof(struct v9fs_vfs_file_s));
|
|
if (file == NULL)
|
|
{
|
|
return -ENOMEM;
|
|
}
|
|
|
|
ret = v9fs_client_walk(client, relpath, NULL);
|
|
if (ret >= 0)
|
|
{
|
|
file->fid = ret;
|
|
ret = v9fs_client_open(client, file->fid, oflags);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Failed to open the fid: %d\n", ret);
|
|
goto err_put;
|
|
}
|
|
}
|
|
else if ((oflags & O_CREAT) != 0)
|
|
{
|
|
/* We expect to create this file */
|
|
|
|
ret = v9fs_client_walk(client, relpath, &relpath);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Can't find the parent fid of relpath: %d\n", ret);
|
|
goto err_free;
|
|
}
|
|
|
|
file->fid = ret;
|
|
ret = v9fs_client_create(client, file->fid, relpath, oflags, mode);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Failed to create the file: %d\n", ret);
|
|
goto err_put;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* We expect to open this file */
|
|
|
|
ferr("ERROR: Can't find the fid of relpath: %d\n", ret);
|
|
ret = -ENOENT;
|
|
goto err_free;
|
|
}
|
|
|
|
if ((oflags & O_APPEND) != 0)
|
|
{
|
|
filep->f_pos = v9fs_client_getsize(client, file->fid);
|
|
if (filep->f_pos < 0)
|
|
{
|
|
ret = filep->f_pos;
|
|
ferr("ERROR: Failed to get the file status: %d\n", ret);
|
|
goto err_put;
|
|
}
|
|
}
|
|
|
|
nxmutex_init(&file->lock);
|
|
filep->f_priv = file;
|
|
return 0;
|
|
|
|
err_put:
|
|
v9fs_fid_put(client, file->fid);
|
|
err_free:
|
|
kmm_free(file);
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_close
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_close(FAR struct file *filep)
|
|
{
|
|
FAR struct v9fs_client_s *client;
|
|
FAR struct v9fs_vfs_file_s *file;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = filep->f_inode->i_private;
|
|
file = filep->f_priv;
|
|
|
|
v9fs_fid_put(client, file->fid);
|
|
nxmutex_destroy(&file->lock);
|
|
kmm_free(file);
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_read
|
|
****************************************************************************/
|
|
|
|
static ssize_t v9fs_vfs_read(FAR struct file *filep, FAR char *buffer,
|
|
size_t buflen)
|
|
{
|
|
FAR struct v9fs_vfs_file_s *file;
|
|
FAR struct v9fs_client_s *client;
|
|
ssize_t ret;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = filep->f_inode->i_private;
|
|
file = filep->f_priv;
|
|
|
|
nxmutex_lock(&file->lock);
|
|
ret = v9fs_client_read(client, file->fid, buffer, filep->f_pos, buflen);
|
|
if (ret > 0)
|
|
{
|
|
filep->f_pos += ret;
|
|
}
|
|
|
|
nxmutex_unlock(&file->lock);
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_write
|
|
****************************************************************************/
|
|
|
|
static ssize_t v9fs_vfs_write(FAR struct file *filep, FAR const char *buffer,
|
|
size_t buflen)
|
|
{
|
|
FAR struct v9fs_vfs_file_s *file;
|
|
FAR struct v9fs_client_s *client;
|
|
ssize_t ret;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = filep->f_inode->i_private;
|
|
file = filep->f_priv;
|
|
|
|
nxmutex_lock(&file->lock);
|
|
ret = v9fs_client_write(client, file->fid, buffer, filep->f_pos, buflen);
|
|
if (ret > 0)
|
|
{
|
|
filep->f_pos += ret;
|
|
}
|
|
|
|
nxmutex_unlock(&file->lock);
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_seek
|
|
****************************************************************************/
|
|
|
|
static off_t v9fs_vfs_seek(FAR struct file *filep, off_t offset, int whence)
|
|
{
|
|
FAR struct v9fs_vfs_file_s *file;
|
|
FAR struct v9fs_client_s *client;
|
|
off_t ret;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = filep->f_inode->i_private;
|
|
file = filep->f_priv;
|
|
|
|
nxmutex_lock(&file->lock);
|
|
switch (whence)
|
|
{
|
|
case SEEK_SET:
|
|
ret = offset;
|
|
break;
|
|
case SEEK_CUR:
|
|
ret = filep->f_pos + offset;
|
|
break;
|
|
case SEEK_END:
|
|
ret = v9fs_client_getsize(client, file->fid);
|
|
if (ret >= 0)
|
|
{
|
|
ret += offset;
|
|
}
|
|
|
|
break;
|
|
default:
|
|
ferr("ERROR: Invalid whence: %d\n", whence);
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
if (ret >= 0)
|
|
{
|
|
filep->f_pos = ret;
|
|
}
|
|
|
|
nxmutex_unlock(&file->lock);
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_ioctl
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|
{
|
|
FAR struct v9fs_vfs_file_s *file;
|
|
FAR struct v9fs_client_s *client;
|
|
int ret = -ENOTTY;
|
|
|
|
client = filep->f_inode->i_private;
|
|
file = filep->f_priv;
|
|
|
|
if (cmd == FIOC_FILEPATH)
|
|
{
|
|
FAR char *ptr = (FAR char *)((uintptr_t)arg);
|
|
inode_getpath(filep->f_inode, ptr, PATH_MAX);
|
|
ret = v9fs_client_getname(client, file->fid, ptr);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_sync
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_sync(FAR struct file *filep)
|
|
{
|
|
FAR struct v9fs_vfs_file_s *file;
|
|
FAR struct v9fs_client_s *client;
|
|
|
|
client = filep->f_inode->i_private;
|
|
file = filep->f_priv;
|
|
|
|
return v9fs_client_fsync(client, file->fid);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_dup
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_dup(FAR const struct file *oldp, FAR struct file *newp)
|
|
{
|
|
FAR struct v9fs_vfs_file_s *newfile;
|
|
FAR struct v9fs_vfs_file_s *file;
|
|
FAR struct v9fs_client_s *client;
|
|
int ret;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(oldp != NULL && oldp->f_inode != NULL &&
|
|
newp != NULL && newp->f_inode != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = oldp->f_inode->i_private;
|
|
file = oldp->f_priv;
|
|
|
|
newfile = kmm_zalloc(sizeof(struct v9fs_vfs_file_s));
|
|
if (newfile == NULL)
|
|
{
|
|
return -ENOMEM;
|
|
}
|
|
|
|
ret = v9fs_fid_get(client, file->fid);
|
|
if (ret < 0)
|
|
{
|
|
kmm_free(newfile);
|
|
return ret;
|
|
}
|
|
|
|
nxmutex_init(&newfile->lock);
|
|
newfile->fid = file->fid;
|
|
newp->f_priv = newfile;
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_fstat
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_fstat(FAR const struct file *filep,
|
|
FAR struct stat *buf)
|
|
{
|
|
FAR struct v9fs_vfs_file_s *file;
|
|
FAR struct v9fs_client_s *client;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = filep->f_inode->i_private;
|
|
file = filep->f_priv;
|
|
memset(buf, 0, sizeof(struct stat));
|
|
|
|
return v9fs_client_stat(client, file->fid, buf);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_fchstat
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_fchstat(FAR const struct file *filep,
|
|
FAR const struct stat *buf, int flags)
|
|
{
|
|
FAR struct v9fs_vfs_file_s *file;
|
|
FAR struct v9fs_client_s *client;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = filep->f_inode->i_private;
|
|
file = filep->f_priv;
|
|
|
|
return v9fs_client_chstat(client, file->fid, buf, flags);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_truncate
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_truncate(FAR struct file *filep, off_t length)
|
|
{
|
|
struct stat buf;
|
|
|
|
buf.st_size = length;
|
|
return v9fs_vfs_fchstat(filep, &buf, CH_STAT_SIZE);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_opendir
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_opendir(FAR struct inode *mountpt,
|
|
FAR const char *relpath,
|
|
FAR struct fs_dirent_s **dir)
|
|
{
|
|
FAR struct v9fs_vfs_dirent_s *fsdir;
|
|
FAR struct v9fs_client_s *client;
|
|
uint32_t fid;
|
|
int ret;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = mountpt->i_private;
|
|
|
|
fsdir = kmm_zalloc(sizeof(struct v9fs_vfs_dirent_s) + client->msize);
|
|
if (fsdir == NULL)
|
|
{
|
|
return -ENOMEM;
|
|
}
|
|
|
|
ret = v9fs_client_walk(client, relpath, NULL);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Can't find the fid of the relpath: %d\n", ret);
|
|
goto err;
|
|
}
|
|
|
|
fid = ret;
|
|
ret = v9fs_client_open(client, fid, 0);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Failed to open the fid: %d\n", ret);
|
|
v9fs_fid_put(client, fid);
|
|
goto err;
|
|
}
|
|
|
|
nxmutex_init(&fsdir->lock);
|
|
fsdir->fid = fid;
|
|
*dir = &fsdir->base;
|
|
return 0;
|
|
|
|
err:
|
|
kmm_free(fsdir);
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_closedir
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_closedir(FAR struct inode *mountpt,
|
|
FAR struct fs_dirent_s *dir)
|
|
{
|
|
FAR struct v9fs_vfs_dirent_s *fsdir;
|
|
FAR struct v9fs_client_s *client;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
fsdir = (FAR struct v9fs_vfs_dirent_s *)dir;
|
|
client = mountpt->i_private;
|
|
|
|
v9fs_fid_put(client, fsdir->fid);
|
|
nxmutex_destroy(&fsdir->lock);
|
|
kmm_free(fsdir);
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_readdir
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_readdir(FAR struct inode *mountpt,
|
|
FAR struct fs_dirent_s *dir,
|
|
FAR struct dirent *entry)
|
|
{
|
|
FAR struct v9fs_vfs_dirent_s *fsdir;
|
|
FAR struct v9fs_client_s *client;
|
|
ssize_t ret;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
fsdir = (FAR struct v9fs_vfs_dirent_s *)dir;
|
|
client = mountpt->i_private;
|
|
|
|
nxmutex_lock(&fsdir->lock);
|
|
for (; ; )
|
|
{
|
|
if (fsdir->head == fsdir->size)
|
|
{
|
|
ret = v9fs_client_readdir(client, fsdir->fid, fsdir->buffer,
|
|
fsdir->offset, client->msize);
|
|
if (ret < 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
fsdir->head = 0;
|
|
fsdir->size = ret;
|
|
}
|
|
|
|
ret = v9fs_client_convertdir(fsdir->buffer, fsdir->size, fsdir->head,
|
|
&fsdir->offset, entry);
|
|
if (ret < 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
fsdir->head += ret;
|
|
if (strcmp(entry->d_name, ".") != 0 &&
|
|
strcmp(entry->d_name, "..") != 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
nxmutex_unlock(&fsdir->lock);
|
|
return ret < 0 ? ret : 0;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_rewinddir
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_rewinddir(FAR struct inode *mountpt,
|
|
FAR struct fs_dirent_s *dir)
|
|
{
|
|
FAR struct v9fs_vfs_dirent_s *fsdir;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
fsdir = (FAR struct v9fs_vfs_dirent_s *)dir;
|
|
|
|
nxmutex_lock(&fsdir->lock);
|
|
fsdir->head = 0;
|
|
fsdir->offset = 0;
|
|
fsdir->size = 0;
|
|
nxmutex_unlock(&fsdir->lock);
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_statfs
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_statfs(FAR struct inode *mountpt,
|
|
FAR struct statfs *buf)
|
|
{
|
|
FAR struct v9fs_client_s *client;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = mountpt->i_private;
|
|
|
|
memset(buf, 0, sizeof(struct statfs));
|
|
return v9fs_client_statfs(client, buf);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_unlink
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_unlink(FAR struct inode *mountpt,
|
|
FAR const char *relpath)
|
|
{
|
|
FAR struct v9fs_client_s *client;
|
|
FAR const char *filename;
|
|
uint32_t fid;
|
|
int ret;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = mountpt->i_private;
|
|
|
|
ret = v9fs_client_walk(client, relpath, &filename);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Can't find the parent fid of relpath: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
fid = ret;
|
|
ret = v9fs_client_unlink(client, fid, filename, false);
|
|
v9fs_fid_put(client, fid);
|
|
if (ret == -EOPNOTSUPP)
|
|
{
|
|
/* Maybe the server does not support this method of deletion.
|
|
* Let's change the protocol to send
|
|
*/
|
|
|
|
ret = v9fs_client_walk(client, relpath, NULL);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Can't find the fid of relpath: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
fid = ret;
|
|
ret = v9fs_client_remove(client, fid);
|
|
v9fs_fid_put(client, fid);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_mkdir
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_mkdir(FAR struct inode *mountpt,
|
|
FAR const char *relpath, mode_t mode)
|
|
{
|
|
FAR struct v9fs_client_s *client;
|
|
uint32_t fid;
|
|
int ret;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = mountpt->i_private;
|
|
|
|
ret = v9fs_client_walk(client, relpath, &relpath);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Can't find the parent fid of relpath: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
fid = ret;
|
|
ret = v9fs_client_mkdir(client, fid, relpath, mode);
|
|
v9fs_fid_put(client, fid);
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_rmdir
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_rmdir(FAR struct inode *mountpt,
|
|
FAR const char *relpath)
|
|
{
|
|
FAR struct v9fs_client_s *client;
|
|
FAR const char *dirname;
|
|
uint32_t fid;
|
|
int ret;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = mountpt->i_private;
|
|
|
|
ret = v9fs_client_walk(client, relpath, &dirname);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Can't find the parent fid of relpath: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
fid = ret;
|
|
ret = v9fs_client_unlink(client, fid, dirname, true);
|
|
v9fs_fid_put(client, fid);
|
|
if (ret == -EOPNOTSUPP)
|
|
{
|
|
/* Maybe the server does not support this method of deletion.
|
|
* Let's change the protocol to send
|
|
*/
|
|
|
|
ret = v9fs_client_walk(client, relpath, NULL);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Can't find the fid of relpath: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
fid = ret;
|
|
ret = v9fs_client_remove(client, fid);
|
|
v9fs_fid_put(client, fid);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_rename
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_rename(FAR struct inode *mountpt,
|
|
FAR const char *oldrelpath,
|
|
FAR const char *newrelpath)
|
|
{
|
|
FAR struct v9fs_client_s *client;
|
|
uint32_t oldfid;
|
|
uint32_t newpfid;
|
|
int ret;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = mountpt->i_private;
|
|
|
|
ret = v9fs_client_walk(client, oldrelpath, NULL);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Can't find the fid of the oldrelpath: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
oldfid = ret;
|
|
ret = v9fs_client_walk(client, newrelpath, &newrelpath);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Can't find the new parent fid of the newrelpath: %d\n",
|
|
ret);
|
|
v9fs_fid_put(client, oldfid);
|
|
return ret;
|
|
}
|
|
|
|
newpfid = ret;
|
|
ret = v9fs_client_rename(client, oldfid, newpfid, newrelpath);
|
|
v9fs_fid_put(client, oldfid);
|
|
v9fs_fid_put(client, newpfid);
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_stat
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
|
|
FAR struct stat *buf)
|
|
{
|
|
FAR struct v9fs_client_s *client;
|
|
uint32_t fid;
|
|
int ret;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = mountpt->i_private;
|
|
memset(buf, 0, sizeof(struct stat));
|
|
|
|
ret = v9fs_client_walk(client, relpath, NULL);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Can't find the fid of the relpath: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
fid = ret;
|
|
ret = v9fs_client_stat(client, fid, buf);
|
|
v9fs_fid_put(client, fid);
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_chstat
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_chstat(FAR struct inode *mountpt,
|
|
FAR const char *relpath,
|
|
FAR const struct stat *buf, int flags)
|
|
{
|
|
FAR struct v9fs_client_s *client;
|
|
uint32_t fid;
|
|
int ret;
|
|
|
|
/* Sanity checks */
|
|
|
|
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
|
|
|
|
/* Recover out private data from the struct file instance */
|
|
|
|
client = mountpt->i_private;
|
|
|
|
ret = v9fs_client_walk(client, relpath, NULL);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Can't find the fid of the relpath %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
fid = ret;
|
|
ret = v9fs_client_chstat(client, fid, buf, flags);
|
|
v9fs_fid_put(client, fid);
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_unbind
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_unbind(FAR void *handle, FAR struct inode **blkdriver,
|
|
unsigned int flags)
|
|
{
|
|
FAR struct v9fs_client_s *client;
|
|
int ret;
|
|
|
|
client = handle;
|
|
|
|
ret = v9fs_client_uninit(client);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Failed to clunk root fid\n");
|
|
return ret;
|
|
}
|
|
|
|
kmm_free(client);
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: v9fs_vfs_bind
|
|
****************************************************************************/
|
|
|
|
static int v9fs_vfs_bind(FAR struct inode *driver, FAR const void *data,
|
|
FAR void **handle)
|
|
{
|
|
FAR struct v9fs_client_s *client;
|
|
int ret;
|
|
|
|
client = kmm_zalloc(sizeof(struct v9fs_client_s));
|
|
if (client == NULL)
|
|
{
|
|
return -ENOMEM;
|
|
}
|
|
|
|
ret = v9fs_client_init(client, data);
|
|
if (ret < 0)
|
|
{
|
|
ferr("ERROR: Failed to initialize for client: %d\n", ret);
|
|
kmm_free(client);
|
|
return ret;
|
|
}
|
|
|
|
*handle = client;
|
|
return ret;
|
|
}
|