1
0
Fork 0
forked from nuttx/nuttx-update

fs/nfs: Support fchstat and chstat callback

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
Xiang Xiao 2021-08-10 15:35:43 +08:00 committed by Masayuki Ishikawa
parent 580de38832
commit d7cb4567e6

View file

@ -97,6 +97,8 @@
# error "Length of cookie verify in fs_dirent_s is incorrect"
#endif
#define CH_STAT_SIZE (1 << 7)
/****************************************************************************
* Private Data
****************************************************************************/
@ -115,8 +117,9 @@ static void nfs_semgive(FAR struct nfsmount *nmp);
static int nfs_filecreate(FAR struct nfsmount *nmp,
FAR struct nfsnode *np, FAR const char *relpath,
mode_t mode);
static int nfs_filetruncate(FAR struct nfsmount *nmp,
FAR struct nfsnode *np, off_t length);
static int nfs_filechstat(FAR struct nfsmount *nmp,
FAR struct nfsnode *np,
FAR const struct stat *buf, int flags);
static int nfs_fileopen(FAR struct nfsmount *nmp,
FAR struct nfsnode *np, FAR const char *relpath,
int oflags, mode_t mode);
@ -131,6 +134,8 @@ static ssize_t nfs_write(FAR struct file *filep, FAR const char *buffer,
static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp);
static int nfs_fsinfo(FAR struct nfsmount *nmp);
static int nfs_fstat(FAR const struct file *filep, FAR struct stat *buf);
static int nfs_fchstat(FAR const struct file *filep,
FAR const struct stat *buf, int flags);
static int nfs_truncate(FAR struct file *filep, off_t length);
static int nfs_opendir(FAR struct inode *mountpt,
FAR const char *relpath, FAR struct fs_dirent_s *dir);
@ -157,6 +162,8 @@ static int nfs_rename(FAR struct inode *mountpt,
static mode_t nfs_stat_mode(unsigned int mode, unsigned int type);
static int nfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct stat *buf);
static int nfs_chstat(FAR struct inode *mountpt, FAR const char *relpath,
FAR const struct stat *buf, int flags);
/****************************************************************************
* Public Data
@ -180,7 +187,7 @@ const struct mountpt_operations nfs_operations =
NULL, /* sync */
nfs_dup, /* dup */
nfs_fstat, /* fstat */
NULL, /* fchstat */
nfs_fchstat, /* fchstat */
nfs_truncate, /* truncate */
nfs_opendir, /* opendir */
@ -197,7 +204,7 @@ const struct mountpt_operations nfs_operations =
nfs_rmdir, /* rmdir */
nfs_rename, /* rename */
nfs_stat, /* stat */
NULL /* chstat */
nfs_chstat /* chstat */
};
/****************************************************************************
@ -378,24 +385,24 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
}
/****************************************************************************
* Name: nfs_filetruncate
* Name: nfs_filechstat
*
* Description:
* Truncate an open file to length. This is part of the file open logic.
* Change the status of an open file. This is part of the file open logic.
*
* Returned Value:
* 0 on success; a negative errno value on failure.
*
****************************************************************************/
static int nfs_filetruncate(FAR struct nfsmount *nmp,
FAR struct nfsnode *np, off_t length)
static int nfs_filechstat(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
FAR const struct stat *buf, int flags)
{
FAR uint32_t *ptr;
int reqlen;
int ret;
finfo("Truncating file\n");
finfo("Changing file status\n");
/* Create the SETATTR RPC call arguments */
@ -413,16 +420,83 @@ static int nfs_filetruncate(FAR struct nfsmount *nmp,
/* Copy the variable-length attributes */
*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++ = txdr_unsigned(length >> 32); /* Truncate to the specified length */
*ptr++ = txdr_unsigned(length);
*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);
if (flags & CH_STAT_MODE)
{
*ptr++ = nfs_true;
*ptr++ = txdr_unsigned(buf->st_mode);
reqlen += 2 * sizeof(uint32_t);
}
else
{
*ptr++ = nfs_false;
reqlen += sizeof(uint32_t);
}
if (flags & CH_STAT_UID)
{
*ptr++ = nfs_true;
*ptr++ = txdr_unsigned(buf->st_uid);
reqlen += 2 * sizeof(uint32_t);
}
else
{
*ptr++ = nfs_false;
reqlen += sizeof(uint32_t);
}
if (flags & CH_STAT_GID)
{
*ptr++ = nfs_true;
*ptr++ = txdr_unsigned(buf->st_gid);
reqlen += 2 * sizeof(uint32_t);
}
else
{
*ptr++ = nfs_false;
reqlen += sizeof(uint32_t);
}
if (flags & CH_STAT_SIZE)
{
*ptr++ = nfs_true;
txdr_hyper(buf->st_size, ptr);
ptr += 2;
reqlen += 3 * sizeof(uint32_t);
}
else
{
*ptr++ = nfs_false;
reqlen += sizeof(uint32_t);
}
if (flags & CH_STAT_ATIME)
{
*ptr++ = nfs_true;
txdr_nfsv3time(&buf->st_atim, ptr);
ptr += 2;
reqlen += 3 * sizeof(uint32_t);
}
else
{
*ptr++ = nfs_false;
reqlen += sizeof(uint32_t);
}
if (flags & CH_STAT_MTIME)
{
*ptr++ = nfs_true;
txdr_nfsv3time(&buf->st_mtim, ptr);
ptr += 2;
reqlen += 3 * sizeof(uint32_t);
}
else
{
*ptr++ = nfs_false;
reqlen += sizeof(uint32_t);
}
*ptr++ = nfs_false; /* No guard value */
reqlen += sizeof(uint32_t);
/* Perform the SETATTR RPC */
@ -549,11 +623,14 @@ static int nfs_fileopen(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
if ((oflags & (O_TRUNC | O_WRONLY)) == (O_TRUNC | O_WRONLY))
{
struct stat buf;
/* 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);
buf.st_size = 0;
return nfs_filechstat(nmp, np, &buf, CH_STAT_SIZE);
}
return OK;
@ -1235,6 +1312,47 @@ static int nfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
return OK;
}
/****************************************************************************
* Name: nfs_fchstat
*
* Description:
* Change information about an open file associated with the file
* structure 'filep'.
*
****************************************************************************/
static int nfs_fchstat(FAR const struct file *filep,
FAR const struct stat *buf, int flags)
{
FAR struct nfsmount *nmp;
FAR struct nfsnode *np;
int ret;
finfo("Buf %p\n", buf);
DEBUGASSERT(filep != NULL && buf != NULL);
/* Recover our private data from the struct file instance */
DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
np = (FAR struct nfsnode *)filep->f_priv;
nmp = (FAR struct nfsmount *)filep->f_inode->i_private;
DEBUGASSERT(nmp != NULL);
ret = nfs_semtake(nmp);
if (ret < 0)
{
return ret;
}
/* Change the file mode, owner, group and time. */
ret = nfs_filechstat(nmp, np, buf, flags);
nfs_semgive(nmp);
return ret;
}
/****************************************************************************
* Name: nfs_truncate
*
@ -1263,9 +1381,12 @@ static int nfs_truncate(FAR struct file *filep, off_t length)
ret = nfs_semtake(nmp);
if (ret >= 0)
{
struct stat buf;
/* Then perform the SETATTR RPC to set the new file size */
ret = nfs_filetruncate(nmp, np, length);
buf.st_size = length;
ret = nfs_filechstat(nmp, np, &buf, CH_STAT_SIZE);
nfs_semgive(nmp);
}
@ -2730,3 +2851,60 @@ errout_with_semaphore:
nfs_semgive(nmp);
return ret;
}
/****************************************************************************
* Name: nfs_chstat
*
* Description:
* Change information about the file system object at 'relpath'
*
* Returned Value:
* 0 on success; a negated errno value on failure.
*
****************************************************************************/
static int nfs_chstat(FAR struct inode *mountpt, FAR const char *relpath,
FAR const struct stat *buf, int flags)
{
FAR struct nfsmount *nmp;
struct file_handle fhandle;
struct nfsnode np;
int ret;
/* Sanity checks */
DEBUGASSERT(mountpt && mountpt->i_private);
/* Get the mountpoint private data from the inode structure */
nmp = (FAR struct nfsmount *)mountpt->i_private;
DEBUGASSERT(nmp && buf);
ret = nfs_semtake(nmp);
if (ret < 0)
{
return ret;
}
/* Get the file handle of the requested node */
ret = nfs_findnode(nmp, relpath, &fhandle, NULL, NULL);
if (ret != OK)
{
ferr("ERROR: nfs_findnode failed: %d\n", ret);
goto errout_with_semaphore;
}
/* Initialize the nfs node */
np.n_fhsize = (uint8_t)fhandle.length;
memcpy(&np.n_fhandle, &fhandle.handle, fhandle.length);
/* Change the file mode, owner, group and time. */
ret = nfs_filechstat(nmp, &np, buf, flags);
errout_with_semaphore:
nfs_semgive(nmp);
return ret;
}