NFSD: Add a cache for fs_locations information
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Mon, 12 Sep 2011 23:37:26 +0000 (19:37 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Wed, 14 Sep 2011 02:44:17 +0000 (22:44 -0400)
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
[ cel: since this is server-side, use nfsd4_ prefix instead of nfs4_ prefix. ]
[ cel: implement S_ISVTX filter in bfields-normal form ]
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Reviewed-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfsd.h
fs/nfsd/vfs.c

index 8da03e1..58134a2 100644 (file)
@@ -361,6 +361,13 @@ static inline u32 nfsd_suppattrs2(u32 minorversion)
 #define NFSD_SUPPATTR_EXCLCREAT_WORD2 \
        NFSD_WRITEABLE_ATTRS_WORD2
 
+extern int nfsd4_is_junction(struct dentry *dentry);
+#else
+static inline int nfsd4_is_junction(struct dentry *dentry)
+{
+       return 0;
+}
+
 #endif /* CONFIG_NFSD_V4 */
 
 #endif /* LINUX_NFSD_NFSD_H */
index 75c35fa..4dd9128 100644 (file)
@@ -168,6 +168,8 @@ int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
 {
        if (d_mountpoint(dentry))
                return 1;
+       if (nfsd4_is_junction(dentry))
+               return 1;
        if (!(exp->ex_flags & NFSEXP_V4ROOT))
                return 0;
        return dentry->d_inode != NULL;
@@ -592,6 +594,22 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_ac
        return error;
 }
 
+#define NFSD_XATTR_JUNCTION_PREFIX XATTR_TRUSTED_PREFIX "junction."
+#define NFSD_XATTR_JUNCTION_TYPE NFSD_XATTR_JUNCTION_PREFIX "type"
+int nfsd4_is_junction(struct dentry *dentry)
+{
+       struct inode *inode = dentry->d_inode;
+
+       if (inode == NULL)
+               return 0;
+       if (inode->i_mode & S_IXUGO)
+               return 0;
+       if (!(inode->i_mode & S_ISVTX))
+               return 0;
+       if (vfs_getxattr(dentry, NFSD_XATTR_JUNCTION_TYPE, NULL, 0) <= 0)
+               return 0;
+       return 1;
+}
 #endif /* defined(CONFIG_NFSD_V4) */
 
 #ifdef CONFIG_NFSD_V3