
This is similar to what we do with the normal permission()
call: it makes sure that we have the vfsmount available
so that we can do the inode_is_readonly() check against it.

Note that, unlike the permission() patch, we use the
actual vfsmount here, instead of the nameidata.  That is
because there are a number of fd-based calls which do
not have nameidata availalble.  We just grab the
vfsmount out of the 'struct file' instead.

Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
---

 lxc-dave/fs/nfsd/vfs.c         |   11 +++++----
 lxc-dave/fs/xattr.c            |   47 +++++++++++++++++++++--------------------
 lxc-dave/include/linux/xattr.h |    6 ++---
 3 files changed, 34 insertions(+), 30 deletions(-)

diff -puN fs/nfsd/vfs.c~D2-pass-vfsmnt-into-xattr_permission fs/nfsd/vfs.c
--- lxc/fs/nfsd/vfs.c~D2-pass-vfsmnt-into-xattr_permission	2006-05-31 12:48:50.000000000 -0700
+++ lxc-dave/fs/nfsd/vfs.c	2006-05-31 12:48:50.000000000 -0700
@@ -372,7 +372,7 @@ static ssize_t nfsd_getxattr(struct dent
 {
 	ssize_t buflen;
 
-	buflen = vfs_getxattr(dentry, key, NULL, 0);
+	buflen = vfs_getxattr(dentry, key, NULL, 0, NULL);
 	if (buflen <= 0)
 		return buflen;
 
@@ -380,7 +380,7 @@ static ssize_t nfsd_getxattr(struct dent
 	if (!*buf)
 		return -ENOMEM;
 
-	return vfs_getxattr(dentry, key, *buf, buflen);
+	return vfs_getxattr(dentry, key, *buf, buflen, NULL);
 }
 #endif
 
@@ -405,7 +405,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
 		goto out;
 	}
 
-	error = vfs_setxattr(dentry, key, buf, len, 0);
+	error = vfs_setxattr(dentry, key, buf, len, 0, NULL);
 out:
 	kfree(buf);
 	return error;
@@ -1931,12 +1931,13 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
 		size = 0;
 
 	if (size)
-		error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
+		error = vfs_setxattr(fhp->fh_dentry, name, value,
+				     size, 0, NULL);
 	else {
 		if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
 			error = 0;
 		else {
-			error = vfs_removexattr(fhp->fh_dentry, name);
+			error = vfs_removexattr(fhp->fh_dentry, name, NULL);
 			if (error == -ENODATA)
 				error = 0;
 		}
diff -puN fs/xattr.c~D2-pass-vfsmnt-into-xattr_permission fs/xattr.c
--- lxc/fs/xattr.c~D2-pass-vfsmnt-into-xattr_permission	2006-05-31 12:48:50.000000000 -0700
+++ lxc-dave/fs/xattr.c	2006-05-31 12:48:50.000000000 -0700
@@ -26,7 +26,8 @@
  * because different namespaces have very different rules.
  */
 static int
-xattr_permission(struct inode *inode, const char *name, int mask)
+xattr_permission(struct inode *inode, const char *name, int mask,
+		 struct vfsmount *mnt)
 {
 	/*
 	 * We can never set or remove an extended attribute on a read-only
@@ -64,12 +65,12 @@ xattr_permission(struct inode *inode, co
 
 int
 vfs_setxattr(struct dentry *dentry, char *name, void *value,
-		size_t size, int flags)
+		size_t size, int flags, struct vfsmount *mnt)
 {
 	struct inode *inode = dentry->d_inode;
 	int error;
 
-	error = xattr_permission(inode, name, MAY_WRITE);
+	error = xattr_permission(inode, name, MAY_WRITE, mnt);
 	if (error)
 		return error;
 
@@ -100,12 +101,13 @@ out:
 EXPORT_SYMBOL_GPL(vfs_setxattr);
 
 ssize_t
-vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
+vfs_getxattr(struct dentry *dentry, char *name, void *value,
+	     size_t size, struct vfsmount *mnt)
 {
 	struct inode *inode = dentry->d_inode;
 	int error;
 
-	error = xattr_permission(inode, name, MAY_READ);
+	error = xattr_permission(inode, name, MAY_READ, mnt);
 	if (error)
 		return error;
 
@@ -136,7 +138,7 @@ vfs_getxattr(struct dentry *dentry, char
 EXPORT_SYMBOL_GPL(vfs_getxattr);
 
 int
-vfs_removexattr(struct dentry *dentry, char *name)
+vfs_removexattr(struct dentry *dentry, char *name, struct vfsmount *mnt)
 {
 	struct inode *inode = dentry->d_inode;
 	int error;
@@ -144,7 +146,7 @@ vfs_removexattr(struct dentry *dentry, c
 	if (!inode->i_op->removexattr)
 		return -EOPNOTSUPP;
 
-	error = xattr_permission(inode, name, MAY_WRITE);
+	error = xattr_permission(inode, name, MAY_WRITE, mnt);
 	if (error)
 		return error;
 
@@ -168,7 +170,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
  */
 static long
 setxattr(struct dentry *d, char __user *name, void __user *value,
-	 size_t size, int flags)
+	 size_t size, int flags, struct vfsmount *mnt)
 {
 	int error;
 	void *kvalue = NULL;
@@ -195,7 +197,7 @@ setxattr(struct dentry *d, char __user *
 		}
 	}
 
-	error = vfs_setxattr(d, kname, kvalue, size, flags);
+	error = vfs_setxattr(d, kname, kvalue, size, flags, mnt);
 	kfree(kvalue);
 	return error;
 }
@@ -210,7 +212,7 @@ sys_setxattr(char __user *path, char __u
 	error = user_path_walk(path, &nd);
 	if (error)
 		return error;
-	error = setxattr(nd.dentry, name, value, size, flags);
+	error = setxattr(nd.dentry, name, value, size, flags, nd.mnt);
 	path_release(&nd);
 	return error;
 }
@@ -225,7 +227,7 @@ sys_lsetxattr(char __user *path, char __
 	error = user_path_walk_link(path, &nd);
 	if (error)
 		return error;
-	error = setxattr(nd.dentry, name, value, size, flags);
+	error = setxattr(nd.dentry, name, value, size, flags, nd.mnt);
 	path_release(&nd);
 	return error;
 }
@@ -243,7 +245,7 @@ sys_fsetxattr(int fd, char __user *name,
 		return error;
 	dentry = f->f_dentry;
 	audit_inode(NULL, dentry->d_inode, 0);
-	error = setxattr(dentry, name, value, size, flags);
+	error = setxattr(dentry, name, value, size, flags, f->f_vfsmnt);
 	fput(f);
 	return error;
 }
@@ -252,7 +254,8 @@ sys_fsetxattr(int fd, char __user *name,
  * Extended attribute GET operations
  */
 static ssize_t
-getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
+getxattr(struct dentry *d, char __user *name, void __user *value,
+	 size_t size, struct vfsmount *mnt)
 {
 	ssize_t error;
 	void *kvalue = NULL;
@@ -272,7 +275,7 @@ getxattr(struct dentry *d, char __user *
 			return -ENOMEM;
 	}
 
-	error = vfs_getxattr(d, kname, kvalue, size);
+	error = vfs_getxattr(d, kname, kvalue, size, mnt);
 	if (error > 0) {
 		if (size && copy_to_user(value, kvalue, error))
 			error = -EFAULT;
@@ -295,7 +298,7 @@ sys_getxattr(char __user *path, char __u
 	error = user_path_walk(path, &nd);
 	if (error)
 		return error;
-	error = getxattr(nd.dentry, name, value, size);
+	error = getxattr(nd.dentry, name, value, size, nd.mnt);
 	path_release(&nd);
 	return error;
 }
@@ -310,7 +313,7 @@ sys_lgetxattr(char __user *path, char __
 	error = user_path_walk_link(path, &nd);
 	if (error)
 		return error;
-	error = getxattr(nd.dentry, name, value, size);
+	error = getxattr(nd.dentry, name, value, size, nd.mnt);
 	path_release(&nd);
 	return error;
 }
@@ -324,7 +327,7 @@ sys_fgetxattr(int fd, char __user *name,
 	f = fget(fd);
 	if (!f)
 		return error;
-	error = getxattr(f->f_dentry, name, value, size);
+	error = getxattr(f->f_dentry, name, value, size, f->f_vfsmnt);
 	fput(f);
 	return error;
 }
@@ -416,7 +419,7 @@ sys_flistxattr(int fd, char __user *list
  * Extended attribute REMOVE operations
  */
 static long
-removexattr(struct dentry *d, char __user *name)
+removexattr(struct dentry *d, char __user *name, struct vfsmount *mnt)
 {
 	int error;
 	char kname[XATTR_NAME_MAX + 1];
@@ -427,7 +430,7 @@ removexattr(struct dentry *d, char __use
 	if (error < 0)
 		return error;
 
-	return vfs_removexattr(d, kname);
+	return vfs_removexattr(d, kname, mnt);
 }
 
 asmlinkage long
@@ -439,7 +442,7 @@ sys_removexattr(char __user *path, char 
 	error = user_path_walk(path, &nd);
 	if (error)
 		return error;
-	error = removexattr(nd.dentry, name);
+	error = removexattr(nd.dentry, name, nd.mnt);
 	path_release(&nd);
 	return error;
 }
@@ -453,7 +456,7 @@ sys_lremovexattr(char __user *path, char
 	error = user_path_walk_link(path, &nd);
 	if (error)
 		return error;
-	error = removexattr(nd.dentry, name);
+	error = removexattr(nd.dentry, name, nd.mnt);
 	path_release(&nd);
 	return error;
 }
@@ -470,7 +473,7 @@ sys_fremovexattr(int fd, char __user *na
 		return error;
 	dentry = f->f_dentry;
 	audit_inode(NULL, dentry->d_inode, 0);
-	error = removexattr(dentry, name);
+	error = removexattr(dentry, name, f->f_vfsmnt);
 	fput(f);
 	return error;
 }
diff -L home/linux/views/linux-2.6.17-rc4-mm3/fs/nfsd/vfs.c -puN /dev/null /dev/null
diff -L home/linux/views/linux-2.6.17-rc4-mm3/fs/xattr.c -puN /dev/null /dev/null
diff -L home/linux/views/linux-2.6.17-rc4-mm3/include/linux/xattr.h -puN /dev/null /dev/null
diff -puN include/linux/xattr.h~D2-pass-vfsmnt-into-xattr_permission include/linux/xattr.h
--- lxc/include/linux/xattr.h~D2-pass-vfsmnt-into-xattr_permission	2006-05-31 12:48:50.000000000 -0700
+++ lxc-dave/include/linux/xattr.h	2006-05-31 12:48:50.000000000 -0700
@@ -40,9 +40,9 @@ struct xattr_handler {
 		   size_t size, int flags);
 };
 
-ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
-int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
-int vfs_removexattr(struct dentry *, char *);
+ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t, struct vfsmount *);
+int vfs_setxattr(struct dentry *, char *, void *, size_t, int, struct vfsmount *);
+int vfs_removexattr(struct dentry *, char *, struct vfsmount *);
 
 ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
_
