Message ID | 20191127220551.36159-1-trond.myklebust@hammerspace.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | nfsd: Ensure CLONE persists data and metadata changes to the target file | expand |
On Wed, Nov 27, 2019 at 05:05:51PM -0500, Trond Myklebust wrote: > The NFSv4.2 CLONE operation has implicit persistence requirements on the > target file, since there is no protocol requirement that the client issue > a separate operation to persist data. > For that reason, we should call vfs_fsync_range() on the destination file > after a successful call to vfs_clone_file_range(). Looking at RFC 7862.... So, COPY has a stable_how4 field in the reply, but CLONE doesn't. That's interesting! OK, I guess this makes sense, then. --b. > > Fixes: ffa0160a1039 ("nfsd: implement the NFSv4.2 CLONE operation") > Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> > Cc: stable@vger.kernel.org # v4.5+ > --- > fs/nfsd/nfs4proc.c | 3 ++- > fs/nfsd/vfs.c | 9 ++++++++- > fs/nfsd/vfs.h | 2 +- > 3 files changed, 11 insertions(+), 3 deletions(-) > > diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c > index 4e3e77b76411..38c0aeda500e 100644 > --- a/fs/nfsd/nfs4proc.c > +++ b/fs/nfsd/nfs4proc.c > @@ -1077,7 +1077,8 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, > goto out; > > status = nfsd4_clone_file_range(src->nf_file, clone->cl_src_pos, > - dst->nf_file, clone->cl_dst_pos, clone->cl_count); > + dst->nf_file, clone->cl_dst_pos, clone->cl_count, > + EX_ISSYNC(cstate->current_fh.fh_export)); > > nfsd_file_put(dst); > nfsd_file_put(src); > diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c > index bd0a385df3fc..9d66c4719067 100644 > --- a/fs/nfsd/vfs.c > +++ b/fs/nfsd/vfs.c > @@ -525,7 +525,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp, > #endif > > __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, > - u64 dst_pos, u64 count) > + u64 dst_pos, u64 count, bool sync) > { > loff_t cloned; > > @@ -534,6 +534,13 @@ __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, > return nfserrno(cloned); > if (count && cloned != count) > return nfserrno(-EINVAL); > + if (sync) { > + loff_t dst_end = count ? dst_pos + count - 1 : LLONG_MAX; > + int status = vfs_fsync_range(dst, dst_pos, dst_end, > + commit_is_datasync); > + if (status < 0) > + return nfserrno(status); > + } > return 0; > } > > diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h > index a13fd9d7e1f5..cc110a10bfe8 100644 > --- a/fs/nfsd/vfs.h > +++ b/fs/nfsd/vfs.h > @@ -56,7 +56,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *, > __be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *, > struct file *, loff_t, loff_t, int); > __be32 nfsd4_clone_file_range(struct file *, u64, struct file *, > - u64, u64); > + u64, u64, bool); > #endif /* CONFIG_NFSD_V4 */ > __be32 nfsd_create_locked(struct svc_rqst *, struct svc_fh *, > char *name, int len, struct iattr *attrs, > -- > 2.23.0
Hi Trond, I love your patch! Yet something to improve: [auto build test ERROR on nfsd/nfsd-next] [also build test ERROR on v5.4 next-20191128] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982] url: https://github.com/0day-ci/linux/commits/Trond-Myklebust/nfsd-Ensure-CLONE-persists-data-and-metadata-changes-to-the-target-file/20191128-061009 base: git://linux-nfs.org/~bfields/linux.git nfsd-next config: parisc-defconfig (attached as .config) compiler: hppa-linux-gcc (GCC) 7.4.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree GCC_VERSION=7.4.0 make.cross ARCH=parisc If you fix the issue, kindly add following tag Reported-by: kbuild test robot <lkp@intel.com> All errors (new ones prefixed by >>): fs//nfsd/vfs.c: In function 'nfsd4_clone_file_range': >> fs//nfsd/vfs.c:540:5: error: 'commit_is_datasync' undeclared (first use in this function); did you mean 'commit_metadata'? commit_is_datasync); ^~~~~~~~~~~~~~~~~~ commit_metadata fs//nfsd/vfs.c:540:5: note: each undeclared identifier is reported only once for each function it appears in vim +540 fs//nfsd/vfs.c 526 527 __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, 528 u64 dst_pos, u64 count, bool sync) 529 { 530 loff_t cloned; 531 532 cloned = vfs_clone_file_range(src, src_pos, dst, dst_pos, count, 0); 533 if (cloned < 0) 534 return nfserrno(cloned); 535 if (count && cloned != count) 536 return nfserrno(-EINVAL); 537 if (sync) { 538 loff_t dst_end = count ? dst_pos + count - 1 : LLONG_MAX; 539 int status = vfs_fsync_range(dst, dst_pos, dst_end, > 540 commit_is_datasync); 541 if (status < 0) 542 return nfserrno(status); 543 } 544 return 0; 545 } 546 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation
On Fri, Nov 29, 2019 at 01:53:13AM +0800, kbuild test robot wrote: > fs//nfsd/vfs.c: In function 'nfsd4_clone_file_range': > >> fs//nfsd/vfs.c:540:5: error: 'commit_is_datasync' undeclared (first use in this function); did you mean 'commit_metadata'? ... > 539 int status = vfs_fsync_range(dst, dst_pos, dst_end, > > 540 commit_is_datasync); I've replaced commit_is_datasync by 0. Trond, correct me if I got that wrong. --b. > 541 if (status < 0) > 542 return nfserrno(status); > 543 } > 544 return 0; > 545 } > 546 > > --- > 0-DAY kernel test infrastructure Open Source Technology Center > https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation
On Sat, 2019-11-30 at 14:58 -0500, J. Bruce Fields wrote: > On Fri, Nov 29, 2019 at 01:53:13AM +0800, kbuild test robot wrote: > > fs//nfsd/vfs.c: In function 'nfsd4_clone_file_range': > > > > fs//nfsd/vfs.c:540:5: error: 'commit_is_datasync' undeclared > > > > (first use in this function); did you mean 'commit_metadata'? > ... > > 539 int status = vfs_fsync_range(dst, > > dst_pos, dst_end, > > > 540 commit_is_datasync); > > I've replaced commit_is_datasync by 0. Trond, correct me if I got > that > wrong. Doh! Sorry about that. I blame ENOCOFFEE... Thanks! Trond > > --b. > > > 541 if (status < 0) > > 542 return nfserrno(status); > > 543 } > > 544 return 0; > > 545 } > > 546 > > > > --- > > 0-DAY kernel test infrastructure Open Source > > Technology Center > > https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel > > Corporation > >
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 4e3e77b76411..38c0aeda500e 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -1077,7 +1077,8 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, goto out; status = nfsd4_clone_file_range(src->nf_file, clone->cl_src_pos, - dst->nf_file, clone->cl_dst_pos, clone->cl_count); + dst->nf_file, clone->cl_dst_pos, clone->cl_count, + EX_ISSYNC(cstate->current_fh.fh_export)); nfsd_file_put(dst); nfsd_file_put(src); diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index bd0a385df3fc..9d66c4719067 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -525,7 +525,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp, #endif __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, - u64 dst_pos, u64 count) + u64 dst_pos, u64 count, bool sync) { loff_t cloned; @@ -534,6 +534,13 @@ __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, return nfserrno(cloned); if (count && cloned != count) return nfserrno(-EINVAL); + if (sync) { + loff_t dst_end = count ? dst_pos + count - 1 : LLONG_MAX; + int status = vfs_fsync_range(dst, dst_pos, dst_end, + commit_is_datasync); + if (status < 0) + return nfserrno(status); + } return 0; } diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index a13fd9d7e1f5..cc110a10bfe8 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h @@ -56,7 +56,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *, __be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *, struct file *, loff_t, loff_t, int); __be32 nfsd4_clone_file_range(struct file *, u64, struct file *, - u64, u64); + u64, u64, bool); #endif /* CONFIG_NFSD_V4 */ __be32 nfsd_create_locked(struct svc_rqst *, struct svc_fh *, char *name, int len, struct iattr *attrs,
The NFSv4.2 CLONE operation has implicit persistence requirements on the target file, since there is no protocol requirement that the client issue a separate operation to persist data. For that reason, we should call vfs_fsync_range() on the destination file after a successful call to vfs_clone_file_range(). Fixes: ffa0160a1039 ("nfsd: implement the NFSv4.2 CLONE operation") Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Cc: stable@vger.kernel.org # v4.5+ --- fs/nfsd/nfs4proc.c | 3 ++- fs/nfsd/vfs.c | 9 ++++++++- fs/nfsd/vfs.h | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-)