浏览代码

NFS: Store the file system "fsid" value in the NFS super block.

This should enable us to detect if we are crossing a mountpoint in the
case where the server is exporting "nohide" mounts.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Trond Myklebust 19 年之前
父节点
当前提交
8b4bdcf899
共有 9 个文件被更改,包括 30 次插入15 次删除
  1. 0 1
      fs/nfs/idmap.c
  2. 8 0
      fs/nfs/inode.c
  3. 2 1
      fs/nfs/nfs2xdr.c
  4. 2 1
      fs/nfs/nfs3xdr.c
  5. 2 2
      fs/nfs/nfs4xdr.c
  6. 3 2
      include/linux/nfs_fs.h
  7. 1 0
      include/linux/nfs_fs_sb.h
  8. 0 1
      include/linux/nfs_page.h
  9. 12 7
      include/linux/nfs_xdr.h

+ 0 - 1
fs/nfs/idmap.c

@@ -47,7 +47,6 @@
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
 
 
-#include <linux/nfs_fs_sb.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_fs.h>
 
 
 #include <linux/nfs_idmap.h>
 #include <linux/nfs_idmap.h>

+ 8 - 0
fs/nfs/inode.c

@@ -236,6 +236,7 @@ nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *f
 		return ERR_PTR(error);
 		return ERR_PTR(error);
 	}
 	}
 
 
+	server->fsid = fsinfo->fattr->fsid;
 	return nfs_fhget(sb, rootfh, fsinfo->fattr);
 	return nfs_fhget(sb, rootfh, fsinfo->fattr);
 }
 }
 
 
@@ -1493,6 +1494,7 @@ out:
  */
  */
 static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 {
 {
+	struct nfs_server *server;
 	struct nfs_inode *nfsi = NFS_I(inode);
 	struct nfs_inode *nfsi = NFS_I(inode);
 	loff_t cur_isize, new_isize;
 	loff_t cur_isize, new_isize;
 	unsigned int	invalid = 0;
 	unsigned int	invalid = 0;
@@ -1511,6 +1513,12 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 	if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
 	if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
 		goto out_changed;
 		goto out_changed;
 
 
+	server = NFS_SERVER(inode);
+	/* Update the fsid if and only if this is the root directory */
+	if (inode == inode->i_sb->s_root->d_inode
+			&& !nfs_fsid_equal(&server->fsid, &fattr->fsid))
+		server->fsid = fattr->fsid;
+
 	/*
 	/*
 	 * Update the read time so we don't revalidate too often.
 	 * Update the read time so we don't revalidate too often.
 	 */
 	 */

+ 2 - 1
fs/nfs/nfs2xdr.c

@@ -131,7 +131,8 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
 	fattr->du.nfs2.blocksize = ntohl(*p++);
 	fattr->du.nfs2.blocksize = ntohl(*p++);
 	rdev = ntohl(*p++);
 	rdev = ntohl(*p++);
 	fattr->du.nfs2.blocks = ntohl(*p++);
 	fattr->du.nfs2.blocks = ntohl(*p++);
-	fattr->fsid_u.nfs3 = ntohl(*p++);
+	fattr->fsid.major = ntohl(*p++);
+	fattr->fsid.minor = 0;
 	fattr->fileid = ntohl(*p++);
 	fattr->fileid = ntohl(*p++);
 	p = xdr_decode_time(p, &fattr->atime);
 	p = xdr_decode_time(p, &fattr->atime);
 	p = xdr_decode_time(p, &fattr->mtime);
 	p = xdr_decode_time(p, &fattr->mtime);

+ 2 - 1
fs/nfs/nfs3xdr.c

@@ -166,7 +166,8 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
 	if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
 	if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
 		fattr->rdev = 0;
 		fattr->rdev = 0;
 
 
-	p = xdr_decode_hyper(p, &fattr->fsid_u.nfs3);
+	p = xdr_decode_hyper(p, &fattr->fsid.major);
+	fattr->fsid.minor = 0;
 	p = xdr_decode_hyper(p, &fattr->fileid);
 	p = xdr_decode_hyper(p, &fattr->fileid);
 	p = xdr_decode_time3(p, &fattr->atime);
 	p = xdr_decode_time3(p, &fattr->atime);
 	p = xdr_decode_time3(p, &fattr->mtime);
 	p = xdr_decode_time3(p, &fattr->mtime);

+ 2 - 2
fs/nfs/nfs4xdr.c

@@ -2217,7 +2217,7 @@ static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap,
 	return 0;
 	return 0;
 }
 }
 
 
-static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fsid *fsid)
+static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid)
 {
 {
 	uint32_t *p;
 	uint32_t *p;
 
 
@@ -2863,7 +2863,7 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons
 		goto xdr_error;
 		goto xdr_error;
 	if ((status = decode_attr_size(xdr, bitmap, &fattr->size)) != 0)
 	if ((status = decode_attr_size(xdr, bitmap, &fattr->size)) != 0)
 		goto xdr_error;
 		goto xdr_error;
-	if ((status = decode_attr_fsid(xdr, bitmap, &fattr->fsid_u.nfs4)) != 0)
+	if ((status = decode_attr_fsid(xdr, bitmap, &fattr->fsid)) != 0)
 		goto xdr_error;
 		goto xdr_error;
 	if ((status = decode_attr_fileid(xdr, bitmap, &fattr->fileid)) != 0)
 	if ((status = decode_attr_fileid(xdr, bitmap, &fattr->fileid)) != 0)
 		goto xdr_error;
 		goto xdr_error;

+ 3 - 2
include/linux/nfs_fs.h

@@ -16,8 +16,6 @@
 #include <linux/rwsem.h>
 #include <linux/rwsem.h>
 #include <linux/wait.h>
 #include <linux/wait.h>
 
 
-#include <linux/nfs_fs_sb.h>
-
 #include <linux/sunrpc/debug.h>
 #include <linux/sunrpc/debug.h>
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/clnt.h>
@@ -27,6 +25,9 @@
 #include <linux/nfs3.h>
 #include <linux/nfs3.h>
 #include <linux/nfs4.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_xdr.h>
 #include <linux/nfs_xdr.h>
+
+#include <linux/nfs_fs_sb.h>
+
 #include <linux/rwsem.h>
 #include <linux/rwsem.h>
 #include <linux/mempool.h>
 #include <linux/mempool.h>
 
 

+ 1 - 0
include/linux/nfs_fs_sb.h

@@ -35,6 +35,7 @@ struct nfs_server {
 	char *			hostname;	/* remote hostname */
 	char *			hostname;	/* remote hostname */
 	struct nfs_fh		fh;
 	struct nfs_fh		fh;
 	struct sockaddr_in	addr;
 	struct sockaddr_in	addr;
+	struct nfs_fsid		fsid;
 	unsigned long		mount_time;	/* when this fs was mounted */
 	unsigned long		mount_time;	/* when this fs was mounted */
 #ifdef CONFIG_NFS_V4
 #ifdef CONFIG_NFS_V4
 	/* Our own IP address, as a null-terminated string.
 	/* Our own IP address, as a null-terminated string.

+ 0 - 1
include/linux/nfs_page.h

@@ -13,7 +13,6 @@
 #include <linux/list.h>
 #include <linux/list.h>
 #include <linux/pagemap.h>
 #include <linux/pagemap.h>
 #include <linux/wait.h>
 #include <linux/wait.h>
-#include <linux/nfs_fs_sb.h>
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/auth.h>
 #include <linux/nfs_xdr.h>
 #include <linux/nfs_xdr.h>
 
 

+ 12 - 7
include/linux/nfs_xdr.h

@@ -14,11 +14,19 @@
 #define NFS_DEF_FILE_IO_SIZE	(4096U)
 #define NFS_DEF_FILE_IO_SIZE	(4096U)
 #define NFS_MIN_FILE_IO_SIZE	(1024U)
 #define NFS_MIN_FILE_IO_SIZE	(1024U)
 
 
-struct nfs4_fsid {
-	__u64 major;
-	__u64 minor;
+struct nfs_fsid {
+	uint64_t		major;
+	uint64_t		minor;
 };
 };
 
 
+/*
+ * Helper for checking equality between 2 fsids.
+ */
+static inline int nfs_fsid_equal(const struct nfs_fsid *a, const struct nfs_fsid *b)
+{
+	return a->major == b->major && a->minor == b->minor;
+}
+
 struct nfs_fattr {
 struct nfs_fattr {
 	unsigned short		valid;		/* which fields are valid */
 	unsigned short		valid;		/* which fields are valid */
 	__u64			pre_size;	/* pre_op_attr.size	  */
 	__u64			pre_size;	/* pre_op_attr.size	  */
@@ -40,10 +48,7 @@ struct nfs_fattr {
 		} nfs3;
 		} nfs3;
 	} du;
 	} du;
 	dev_t			rdev;
 	dev_t			rdev;
-	union {
-		__u64		nfs3;		/* also nfs2 */
-		struct nfs4_fsid nfs4;
-	} fsid_u;
+	struct nfs_fsid		fsid;
 	__u64			fileid;
 	__u64			fileid;
 	struct timespec		atime;
 	struct timespec		atime;
 	struct timespec		mtime;
 	struct timespec		mtime;