]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
nfsd: Fix possible BUG_ON firing in set_change_info
authorNeil Brown <neilb@suse.de>
Thu, 2 Dec 2010 00:14:30 +0000 (11:14 +1100)
committerWilly Tarreau <w@1wt.eu>
Wed, 9 Feb 2011 21:15:37 +0000 (22:15 +0100)
commit c1ac3ffcd0bc7e9617f62be8c7043d53ab84deac upstream.

If vfs_getattr in fill_post_wcc returns an error, we don't
set fh_post_change.
For NFSv4, this can result in set_change_info triggering a BUG_ON.
i.e. fh_post_saved being zero isn't really a bug.

So:
 - instead of BUGging when fh_post_saved is zero, just clear ->atomic.
 - if vfs_getattr fails in fill_post_wcc, take a copy of i_ctime anyway.
   This will be used i seg_change_info, but not overly trusted.
 - While we are there, remove the pointless 'if' statements in set_change_info.
   There is no harm setting all the values.

Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Willy Tarreau <w@1wt.eu>
fs/nfsd/nfs3xdr.c
include/linux/nfsd/xdr4.h

index 17d0dd997204a8442efc3514c98045c81363730c..05569c7d94f9450568d10d2d56b1b46e2c3a818d 100644 (file)
@@ -272,9 +272,11 @@ void fill_post_wcc(struct svc_fh *fhp)
 
        err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry,
                        &fhp->fh_post_attr);
-       if (err)
+       if (err) {
                fhp->fh_post_saved = 0;
-       else
+               /* Grab the ctime anyway - set_change_info might use it */
+               fhp->fh_post_attr.ctime = fhp->fh_dentry->d_inode->i_ctime;
+       } else
                fhp->fh_post_saved = 1;
 }
 
index 27bd3e38ec5ad86b290a0f73feb73e973b917749..dca69e339f972b7ebe69f9cb9be7fa1a40d23105 100644 (file)
@@ -424,8 +424,8 @@ struct nfsd4_compoundres {
 static inline void
 set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
 {
-       BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved);
-       cinfo->atomic = 1;
+       BUG_ON(!fhp->fh_pre_saved);
+       cinfo->atomic = fhp->fh_post_saved;
        cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
        cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
        cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;