nfsd: vfs_llseek() with 32 or 64 bit offsets (hashes)
authorBernd Schubert <bernd.schubert@itwm.fraunhofer.de>
Mon, 19 Mar 2012 02:44:50 +0000 (22:44 -0400)
committerBen Hutchings <ben@decadent.org.uk>
Thu, 28 Nov 2013 14:01:59 +0000 (14:01 +0000)
commit 06effdbb49af5f6c7d20affaec74603914acc768 upstream.

Use 32-bit or 64-bit llseek() hashes for directory offsets depending on
the NFS version. NFSv2 gets 32-bit hashes only.

NOTE: This patch got rather complex as Christoph asked to set the
filp->f_mode flag in the open call or immediatly after dentry_open()
in nfsd_open() to avoid races.
Personally I still do not see a reason for that and in my opinion
FMODE_32BITHASH/FMODE_64BITHASH flags could be set nfsd_readdir(), as it
follows directly after nfsd_open() without a chance of races.

Signed-off-by: Bernd Schubert <bernd.schubert@itwm.fraunhofer.de>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Acked-by: J. Bruce Fields <bfields@redhat.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
fs/nfsd/vfs.c
fs/nfsd/vfs.h

index 3a80c40..61b697e 100644 (file)
@@ -786,9 +786,15 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
        if (IS_ERR(*filp)) {
                host_err = PTR_ERR(*filp);
                *filp = NULL;
-       } else
+       } else {
                host_err = ima_file_check(*filp, may_flags);
 
+               if (may_flags & NFSD_MAY_64BIT_COOKIE)
+                       (*filp)->f_mode |= FMODE_64BITHASH;
+               else
+                       (*filp)->f_mode |= FMODE_32BITHASH;
+       }
+
 out_nfserr:
        err = nfserrno(host_err);
 out:
@@ -2018,8 +2024,13 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
        __be32          err;
        struct file     *file;
        loff_t          offset = *offsetp;
+       int             may_flags = NFSD_MAY_READ;
+
+       /* NFSv2 only supports 32 bit cookies */
+       if (rqstp->rq_vers > 2)
+               may_flags |= NFSD_MAY_64BIT_COOKIE;
 
-       err = nfsd_open(rqstp, fhp, S_IFDIR, NFSD_MAY_READ, &file);
+       err = nfsd_open(rqstp, fhp, S_IFDIR, may_flags, &file);
        if (err)
                goto out;
 
index 3f54ad0..85d4d42 100644 (file)
@@ -27,6 +27,8 @@
 #define NFSD_MAY_BYPASS_GSS            0x400
 #define NFSD_MAY_READ_IF_EXEC          0x800
 
+#define NFSD_MAY_64BIT_COOKIE          0x1000 /* 64 bit readdir cookies for >= NFSv3 */
+
 #define NFSD_MAY_CREATE                (NFSD_MAY_EXEC|NFSD_MAY_WRITE)
 #define NFSD_MAY_REMOVE                (NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)