kernel: backport and enable tmpfs xattr support for 2.6.39
SVN-Revision: 27691
This commit is contained in:
		@@ -2631,6 +2631,7 @@ CONFIG_TINY_RCU=y
 | 
			
		||||
# CONFIG_TLAN is not set
 | 
			
		||||
# CONFIG_TMD_HERMES is not set
 | 
			
		||||
CONFIG_TMPFS=y
 | 
			
		||||
CONFIG_TMPFS_XATTR=y
 | 
			
		||||
# CONFIG_TMPFS_POSIX_ACL is not set
 | 
			
		||||
# CONFIG_TOUCHSCREEN_AD7877 is not set
 | 
			
		||||
# CONFIG_TOUCHSCREEN_AD7879 is not set
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,477 @@
 | 
			
		||||
--- a/fs/Kconfig
 | 
			
		||||
+++ b/fs/Kconfig
 | 
			
		||||
@@ -121,9 +121,25 @@ config TMPFS
 | 
			
		||||
 
 | 
			
		||||
 	  See <file:Documentation/filesystems/tmpfs.txt> for details.
 | 
			
		||||
 
 | 
			
		||||
+config TMPFS_XATTR
 | 
			
		||||
+	bool "Tmpfs extended attributes"
 | 
			
		||||
+	depends on TMPFS
 | 
			
		||||
+	default n
 | 
			
		||||
+	help
 | 
			
		||||
+	  Extended attributes are name:value pairs associated with inodes by
 | 
			
		||||
+	  the kernel or by users (see the attr(5) manual page, or visit
 | 
			
		||||
+	  <http://acl.bestbits.at/> for details).
 | 
			
		||||
+
 | 
			
		||||
+	  Currently this enables support for the trusted.* and
 | 
			
		||||
+	  security.* namespaces.
 | 
			
		||||
+
 | 
			
		||||
+	  If unsure, say N.
 | 
			
		||||
+
 | 
			
		||||
+	  You need this for POSIX ACL support on tmpfs.
 | 
			
		||||
+
 | 
			
		||||
 config TMPFS_POSIX_ACL
 | 
			
		||||
 	bool "Tmpfs POSIX Access Control Lists"
 | 
			
		||||
-	depends on TMPFS
 | 
			
		||||
+	depends on TMPFS_XATTR
 | 
			
		||||
 	select GENERIC_ACL
 | 
			
		||||
 	help
 | 
			
		||||
 	  POSIX Access Control Lists (ACLs) support permissions for users and
 | 
			
		||||
--- a/include/linux/shmem_fs.h
 | 
			
		||||
+++ b/include/linux/shmem_fs.h
 | 
			
		||||
@@ -9,6 +9,8 @@
 | 
			
		||||
 
 | 
			
		||||
 #define SHMEM_NR_DIRECT 16
 | 
			
		||||
 
 | 
			
		||||
+#define SHMEM_SYMLINK_INLINE_LEN (SHMEM_NR_DIRECT * sizeof(swp_entry_t))
 | 
			
		||||
+
 | 
			
		||||
 struct shmem_inode_info {
 | 
			
		||||
 	spinlock_t		lock;
 | 
			
		||||
 	unsigned long		flags;
 | 
			
		||||
@@ -17,8 +19,12 @@ struct shmem_inode_info {
 | 
			
		||||
 	unsigned long		next_index;	/* highest alloced index + 1 */
 | 
			
		||||
 	struct shared_policy	policy;		/* NUMA memory alloc policy */
 | 
			
		||||
 	struct page		*i_indirect;	/* top indirect blocks page */
 | 
			
		||||
-	swp_entry_t		i_direct[SHMEM_NR_DIRECT]; /* first blocks */
 | 
			
		||||
+	union {
 | 
			
		||||
+		swp_entry_t	i_direct[SHMEM_NR_DIRECT]; /* first blocks */
 | 
			
		||||
+		char		inline_symlink[SHMEM_SYMLINK_INLINE_LEN];
 | 
			
		||||
+	};
 | 
			
		||||
 	struct list_head	swaplist;	/* chain of maybes on swap */
 | 
			
		||||
+	struct list_head	xattr_list;	/* list of shmem_xattr */
 | 
			
		||||
 	struct inode		vfs_inode;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
--- a/mm/shmem.c
 | 
			
		||||
+++ b/mm/shmem.c
 | 
			
		||||
@@ -99,6 +99,13 @@ static struct vfsmount *shm_mnt;
 | 
			
		||||
 /* Pretend that each entry is of this size in directory's i_size */
 | 
			
		||||
 #define BOGO_DIRENT_SIZE 20
 | 
			
		||||
 
 | 
			
		||||
+struct shmem_xattr {
 | 
			
		||||
+	struct list_head list;	/* anchored by shmem_inode_info->xattr_list */
 | 
			
		||||
+	char *name;		/* xattr name */
 | 
			
		||||
+	size_t size;
 | 
			
		||||
+	char value[0];
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
 /* Flag allocation requirements to shmem_getpage and shmem_swp_alloc */
 | 
			
		||||
 enum sgp_type {
 | 
			
		||||
 	SGP_READ,	/* don't exceed i_size, don't allocate page */
 | 
			
		||||
@@ -822,6 +829,7 @@ static int shmem_notify_change(struct de
 | 
			
		||||
 static void shmem_evict_inode(struct inode *inode)
 | 
			
		||||
 {
 | 
			
		||||
 	struct shmem_inode_info *info = SHMEM_I(inode);
 | 
			
		||||
+	struct shmem_xattr *xattr, *nxattr;
 | 
			
		||||
 
 | 
			
		||||
 	if (inode->i_mapping->a_ops == &shmem_aops) {
 | 
			
		||||
 		truncate_inode_pages(inode->i_mapping, 0);
 | 
			
		||||
@@ -834,6 +842,11 @@ static void shmem_evict_inode(struct ino
 | 
			
		||||
 			mutex_unlock(&shmem_swaplist_mutex);
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
+
 | 
			
		||||
+	list_for_each_entry_safe(xattr, nxattr, &info->xattr_list, list) {
 | 
			
		||||
+		kfree(xattr->name);
 | 
			
		||||
+		kfree(xattr);
 | 
			
		||||
+	}
 | 
			
		||||
 	BUG_ON(inode->i_blocks);
 | 
			
		||||
 	shmem_free_inode(inode->i_sb);
 | 
			
		||||
 	end_writeback(inode);
 | 
			
		||||
@@ -1615,6 +1628,7 @@ static struct inode *shmem_get_inode(str
 | 
			
		||||
 		spin_lock_init(&info->lock);
 | 
			
		||||
 		info->flags = flags & VM_NORESERVE;
 | 
			
		||||
 		INIT_LIST_HEAD(&info->swaplist);
 | 
			
		||||
+		INIT_LIST_HEAD(&info->xattr_list);
 | 
			
		||||
 		cache_no_acl(inode);
 | 
			
		||||
 
 | 
			
		||||
 		switch (mode & S_IFMT) {
 | 
			
		||||
@@ -2014,9 +2028,9 @@ static int shmem_symlink(struct inode *d
 | 
			
		||||
 
 | 
			
		||||
 	info = SHMEM_I(inode);
 | 
			
		||||
 	inode->i_size = len-1;
 | 
			
		||||
-	if (len <= (char *)inode - (char *)info) {
 | 
			
		||||
+	if (len <= SHMEM_SYMLINK_INLINE_LEN) {
 | 
			
		||||
 		/* do it inline */
 | 
			
		||||
-		memcpy(info, symname, len);
 | 
			
		||||
+		memcpy(info->inline_symlink, symname, len);
 | 
			
		||||
 		inode->i_op = &shmem_symlink_inline_operations;
 | 
			
		||||
 	} else {
 | 
			
		||||
 		error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
 | 
			
		||||
@@ -2042,7 +2056,7 @@ static int shmem_symlink(struct inode *d
 | 
			
		||||
 
 | 
			
		||||
 static void *shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd)
 | 
			
		||||
 {
 | 
			
		||||
-	nd_set_link(nd, (char *)SHMEM_I(dentry->d_inode));
 | 
			
		||||
+	nd_set_link(nd, SHMEM_I(dentry->d_inode)->inline_symlink);
 | 
			
		||||
 	return NULL;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -2066,63 +2080,253 @@ static void shmem_put_link(struct dentry
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static const struct inode_operations shmem_symlink_inline_operations = {
 | 
			
		||||
-	.readlink	= generic_readlink,
 | 
			
		||||
-	.follow_link	= shmem_follow_link_inline,
 | 
			
		||||
-};
 | 
			
		||||
-
 | 
			
		||||
-static const struct inode_operations shmem_symlink_inode_operations = {
 | 
			
		||||
-	.readlink	= generic_readlink,
 | 
			
		||||
-	.follow_link	= shmem_follow_link,
 | 
			
		||||
-	.put_link	= shmem_put_link,
 | 
			
		||||
-};
 | 
			
		||||
-
 | 
			
		||||
-#ifdef CONFIG_TMPFS_POSIX_ACL
 | 
			
		||||
+#ifdef CONFIG_TMPFS_XATTR
 | 
			
		||||
 /*
 | 
			
		||||
- * Superblocks without xattr inode operations will get security.* xattr
 | 
			
		||||
- * support from the VFS "for free". As soon as we have any other xattrs
 | 
			
		||||
+ * Superblocks without xattr inode operations may get some security.* xattr
 | 
			
		||||
+ * support from the LSM "for free". As soon as we have any other xattrs
 | 
			
		||||
  * like ACLs, we also need to implement the security.* handlers at
 | 
			
		||||
  * filesystem level, though.
 | 
			
		||||
  */
 | 
			
		||||
 
 | 
			
		||||
-static size_t shmem_xattr_security_list(struct dentry *dentry, char *list,
 | 
			
		||||
-					size_t list_len, const char *name,
 | 
			
		||||
-					size_t name_len, int handler_flags)
 | 
			
		||||
+static int shmem_xattr_get(struct dentry *dentry, const char *name,
 | 
			
		||||
+			   void *buffer, size_t size)
 | 
			
		||||
 {
 | 
			
		||||
-	return security_inode_listsecurity(dentry->d_inode, list, list_len);
 | 
			
		||||
-}
 | 
			
		||||
+	struct shmem_inode_info *info;
 | 
			
		||||
+	struct shmem_xattr *xattr;
 | 
			
		||||
+	int ret = -ENODATA;
 | 
			
		||||
 
 | 
			
		||||
-static int shmem_xattr_security_get(struct dentry *dentry, const char *name,
 | 
			
		||||
-		void *buffer, size_t size, int handler_flags)
 | 
			
		||||
-{
 | 
			
		||||
-	if (strcmp(name, "") == 0)
 | 
			
		||||
-		return -EINVAL;
 | 
			
		||||
-	return xattr_getsecurity(dentry->d_inode, name, buffer, size);
 | 
			
		||||
+	info = SHMEM_I(dentry->d_inode);
 | 
			
		||||
+
 | 
			
		||||
+	spin_lock(&info->lock);
 | 
			
		||||
+	list_for_each_entry(xattr, &info->xattr_list, list) {
 | 
			
		||||
+		if (strcmp(name, xattr->name))
 | 
			
		||||
+			continue;
 | 
			
		||||
+
 | 
			
		||||
+		ret = xattr->size;
 | 
			
		||||
+		if (buffer) {
 | 
			
		||||
+			if (size < xattr->size)
 | 
			
		||||
+				ret = -ERANGE;
 | 
			
		||||
+			else
 | 
			
		||||
+				memcpy(buffer, xattr->value, xattr->size);
 | 
			
		||||
+		}
 | 
			
		||||
+		break;
 | 
			
		||||
+	}
 | 
			
		||||
+	spin_unlock(&info->lock);
 | 
			
		||||
+	return ret;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int shmem_xattr_security_set(struct dentry *dentry, const char *name,
 | 
			
		||||
-		const void *value, size_t size, int flags, int handler_flags)
 | 
			
		||||
+static int shmem_xattr_set(struct dentry *dentry, const char *name,
 | 
			
		||||
+			   const void *value, size_t size, int flags)
 | 
			
		||||
 {
 | 
			
		||||
-	if (strcmp(name, "") == 0)
 | 
			
		||||
-		return -EINVAL;
 | 
			
		||||
-	return security_inode_setsecurity(dentry->d_inode, name, value,
 | 
			
		||||
-					  size, flags);
 | 
			
		||||
+	struct inode *inode = dentry->d_inode;
 | 
			
		||||
+	struct shmem_inode_info *info = SHMEM_I(inode);
 | 
			
		||||
+	struct shmem_xattr *xattr;
 | 
			
		||||
+	struct shmem_xattr *new_xattr = NULL;
 | 
			
		||||
+	size_t len;
 | 
			
		||||
+	int err = 0;
 | 
			
		||||
+
 | 
			
		||||
+	/* value == NULL means remove */
 | 
			
		||||
+	if (value) {
 | 
			
		||||
+		/* wrap around? */
 | 
			
		||||
+		len = sizeof(*new_xattr) + size;
 | 
			
		||||
+		if (len <= sizeof(*new_xattr))
 | 
			
		||||
+			return -ENOMEM;
 | 
			
		||||
+
 | 
			
		||||
+		new_xattr = kmalloc(len, GFP_KERNEL);
 | 
			
		||||
+		if (!new_xattr)
 | 
			
		||||
+			return -ENOMEM;
 | 
			
		||||
+
 | 
			
		||||
+		new_xattr->name = kstrdup(name, GFP_KERNEL);
 | 
			
		||||
+		if (!new_xattr->name) {
 | 
			
		||||
+			kfree(new_xattr);
 | 
			
		||||
+			return -ENOMEM;
 | 
			
		||||
+		}
 | 
			
		||||
+
 | 
			
		||||
+		new_xattr->size = size;
 | 
			
		||||
+		memcpy(new_xattr->value, value, size);
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	spin_lock(&info->lock);
 | 
			
		||||
+	list_for_each_entry(xattr, &info->xattr_list, list) {
 | 
			
		||||
+		if (!strcmp(name, xattr->name)) {
 | 
			
		||||
+			if (flags & XATTR_CREATE) {
 | 
			
		||||
+				xattr = new_xattr;
 | 
			
		||||
+				err = -EEXIST;
 | 
			
		||||
+			} else if (new_xattr) {
 | 
			
		||||
+				list_replace(&xattr->list, &new_xattr->list);
 | 
			
		||||
+			} else {
 | 
			
		||||
+				list_del(&xattr->list);
 | 
			
		||||
+			}
 | 
			
		||||
+			goto out;
 | 
			
		||||
+		}
 | 
			
		||||
+	}
 | 
			
		||||
+	if (flags & XATTR_REPLACE) {
 | 
			
		||||
+		xattr = new_xattr;
 | 
			
		||||
+		err = -ENODATA;
 | 
			
		||||
+	} else {
 | 
			
		||||
+		list_add(&new_xattr->list, &info->xattr_list);
 | 
			
		||||
+		xattr = NULL;
 | 
			
		||||
+	}
 | 
			
		||||
+out:
 | 
			
		||||
+	spin_unlock(&info->lock);
 | 
			
		||||
+	if (xattr)
 | 
			
		||||
+		kfree(xattr->name);
 | 
			
		||||
+	kfree(xattr);
 | 
			
		||||
+	return err;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static const struct xattr_handler shmem_xattr_security_handler = {
 | 
			
		||||
-	.prefix = XATTR_SECURITY_PREFIX,
 | 
			
		||||
-	.list   = shmem_xattr_security_list,
 | 
			
		||||
-	.get    = shmem_xattr_security_get,
 | 
			
		||||
-	.set    = shmem_xattr_security_set,
 | 
			
		||||
-};
 | 
			
		||||
 
 | 
			
		||||
 static const struct xattr_handler *shmem_xattr_handlers[] = {
 | 
			
		||||
+#ifdef CONFIG_TMPFS_POSIX_ACL
 | 
			
		||||
 	&generic_acl_access_handler,
 | 
			
		||||
 	&generic_acl_default_handler,
 | 
			
		||||
-	&shmem_xattr_security_handler,
 | 
			
		||||
+#endif
 | 
			
		||||
 	NULL
 | 
			
		||||
 };
 | 
			
		||||
+
 | 
			
		||||
+static int shmem_xattr_validate(const char *name)
 | 
			
		||||
+{
 | 
			
		||||
+	struct { const char *prefix; size_t len; } arr[] = {
 | 
			
		||||
+		{ XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN },
 | 
			
		||||
+		{ XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN }
 | 
			
		||||
+	};
 | 
			
		||||
+	int i;
 | 
			
		||||
+
 | 
			
		||||
+	for (i = 0; i < ARRAY_SIZE(arr); i++) {
 | 
			
		||||
+		size_t preflen = arr[i].len;
 | 
			
		||||
+		if (strncmp(name, arr[i].prefix, preflen) == 0) {
 | 
			
		||||
+			if (!name[preflen])
 | 
			
		||||
+				return -EINVAL;
 | 
			
		||||
+			return 0;
 | 
			
		||||
+		}
 | 
			
		||||
+	}
 | 
			
		||||
+	return -EOPNOTSUPP;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static ssize_t shmem_getxattr(struct dentry *dentry, const char *name,
 | 
			
		||||
+			      void *buffer, size_t size)
 | 
			
		||||
+{
 | 
			
		||||
+	int err;
 | 
			
		||||
+
 | 
			
		||||
+	/*
 | 
			
		||||
+	 * If this is a request for a synthetic attribute in the system.*
 | 
			
		||||
+	 * namespace use the generic infrastructure to resolve a handler
 | 
			
		||||
+	 * for it via sb->s_xattr.
 | 
			
		||||
+	 */
 | 
			
		||||
+	if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 | 
			
		||||
+		return generic_getxattr(dentry, name, buffer, size);
 | 
			
		||||
+
 | 
			
		||||
+	err = shmem_xattr_validate(name);
 | 
			
		||||
+	if (err)
 | 
			
		||||
+		return err;
 | 
			
		||||
+
 | 
			
		||||
+	return shmem_xattr_get(dentry, name, buffer, size);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int shmem_setxattr(struct dentry *dentry, const char *name,
 | 
			
		||||
+			  const void *value, size_t size, int flags)
 | 
			
		||||
+{
 | 
			
		||||
+	int err;
 | 
			
		||||
+
 | 
			
		||||
+	/*
 | 
			
		||||
+	 * If this is a request for a synthetic attribute in the system.*
 | 
			
		||||
+	 * namespace use the generic infrastructure to resolve a handler
 | 
			
		||||
+	 * for it via sb->s_xattr.
 | 
			
		||||
+	 */
 | 
			
		||||
+	if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 | 
			
		||||
+		return generic_setxattr(dentry, name, value, size, flags);
 | 
			
		||||
+
 | 
			
		||||
+	err = shmem_xattr_validate(name);
 | 
			
		||||
+	if (err)
 | 
			
		||||
+		return err;
 | 
			
		||||
+
 | 
			
		||||
+	if (size == 0)
 | 
			
		||||
+		value = "";  /* empty EA, do not remove */
 | 
			
		||||
+
 | 
			
		||||
+	return shmem_xattr_set(dentry, name, value, size, flags);
 | 
			
		||||
+
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int shmem_removexattr(struct dentry *dentry, const char *name)
 | 
			
		||||
+{
 | 
			
		||||
+	int err;
 | 
			
		||||
+
 | 
			
		||||
+	/*
 | 
			
		||||
+	 * If this is a request for a synthetic attribute in the system.*
 | 
			
		||||
+	 * namespace use the generic infrastructure to resolve a handler
 | 
			
		||||
+	 * for it via sb->s_xattr.
 | 
			
		||||
+	 */
 | 
			
		||||
+	if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 | 
			
		||||
+		return generic_removexattr(dentry, name);
 | 
			
		||||
+
 | 
			
		||||
+	err = shmem_xattr_validate(name);
 | 
			
		||||
+	if (err)
 | 
			
		||||
+		return err;
 | 
			
		||||
+
 | 
			
		||||
+	return shmem_xattr_set(dentry, name, NULL, 0, XATTR_REPLACE);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static bool xattr_is_trusted(const char *name)
 | 
			
		||||
+{
 | 
			
		||||
+	return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size)
 | 
			
		||||
+{
 | 
			
		||||
+	bool trusted = capable(CAP_SYS_ADMIN);
 | 
			
		||||
+	struct shmem_xattr *xattr;
 | 
			
		||||
+	struct shmem_inode_info *info;
 | 
			
		||||
+	size_t used = 0;
 | 
			
		||||
+
 | 
			
		||||
+	info = SHMEM_I(dentry->d_inode);
 | 
			
		||||
+
 | 
			
		||||
+	spin_lock(&info->lock);
 | 
			
		||||
+	list_for_each_entry(xattr, &info->xattr_list, list) {
 | 
			
		||||
+		size_t len;
 | 
			
		||||
+
 | 
			
		||||
+		/* skip "trusted." attributes for unprivileged callers */
 | 
			
		||||
+		if (!trusted && xattr_is_trusted(xattr->name))
 | 
			
		||||
+			continue;
 | 
			
		||||
+
 | 
			
		||||
+		len = strlen(xattr->name) + 1;
 | 
			
		||||
+		used += len;
 | 
			
		||||
+		if (buffer) {
 | 
			
		||||
+			if (size < used) {
 | 
			
		||||
+				used = -ERANGE;
 | 
			
		||||
+				break;
 | 
			
		||||
+			}
 | 
			
		||||
+			memcpy(buffer, xattr->name, len);
 | 
			
		||||
+			buffer += len;
 | 
			
		||||
+		}
 | 
			
		||||
+	}
 | 
			
		||||
+	spin_unlock(&info->lock);
 | 
			
		||||
+
 | 
			
		||||
+	return used;
 | 
			
		||||
+}
 | 
			
		||||
+#endif /* CONFIG_TMPFS_XATTR */
 | 
			
		||||
+
 | 
			
		||||
+static const struct inode_operations shmem_symlink_inline_operations = {
 | 
			
		||||
+	.readlink	= generic_readlink,
 | 
			
		||||
+	.follow_link	= shmem_follow_link_inline,
 | 
			
		||||
+#ifdef CONFIG_TMPFS_XATTR
 | 
			
		||||
+	.setxattr	= shmem_setxattr,
 | 
			
		||||
+	.getxattr	= shmem_getxattr,
 | 
			
		||||
+	.listxattr	= shmem_listxattr,
 | 
			
		||||
+	.removexattr	= shmem_removexattr,
 | 
			
		||||
+#endif
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static const struct inode_operations shmem_symlink_inode_operations = {
 | 
			
		||||
+	.readlink	= generic_readlink,
 | 
			
		||||
+	.follow_link	= shmem_follow_link,
 | 
			
		||||
+	.put_link	= shmem_put_link,
 | 
			
		||||
+#ifdef CONFIG_TMPFS_XATTR
 | 
			
		||||
+	.setxattr	= shmem_setxattr,
 | 
			
		||||
+	.getxattr	= shmem_getxattr,
 | 
			
		||||
+	.listxattr	= shmem_listxattr,
 | 
			
		||||
+	.removexattr	= shmem_removexattr,
 | 
			
		||||
 #endif
 | 
			
		||||
+};
 | 
			
		||||
 
 | 
			
		||||
 static struct dentry *shmem_get_parent(struct dentry *child)
 | 
			
		||||
 {
 | 
			
		||||
@@ -2402,8 +2606,10 @@ int shmem_fill_super(struct super_block 
 | 
			
		||||
 	sb->s_magic = TMPFS_MAGIC;
 | 
			
		||||
 	sb->s_op = &shmem_ops;
 | 
			
		||||
 	sb->s_time_gran = 1;
 | 
			
		||||
-#ifdef CONFIG_TMPFS_POSIX_ACL
 | 
			
		||||
+#ifdef CONFIG_TMPFS_XATTR
 | 
			
		||||
 	sb->s_xattr = shmem_xattr_handlers;
 | 
			
		||||
+#endif
 | 
			
		||||
+#ifdef CONFIG_TMPFS_POSIX_ACL
 | 
			
		||||
 	sb->s_flags |= MS_POSIXACL;
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
@@ -2501,11 +2707,13 @@ static const struct file_operations shme
 | 
			
		||||
 static const struct inode_operations shmem_inode_operations = {
 | 
			
		||||
 	.setattr	= shmem_notify_change,
 | 
			
		||||
 	.truncate_range	= shmem_truncate_range,
 | 
			
		||||
+#ifdef CONFIG_TMPFS_XATTR
 | 
			
		||||
+	.setxattr	= shmem_setxattr,
 | 
			
		||||
+	.getxattr	= shmem_getxattr,
 | 
			
		||||
+	.listxattr	= shmem_listxattr,
 | 
			
		||||
+	.removexattr	= shmem_removexattr,
 | 
			
		||||
+#endif
 | 
			
		||||
 #ifdef CONFIG_TMPFS_POSIX_ACL
 | 
			
		||||
-	.setxattr	= generic_setxattr,
 | 
			
		||||
-	.getxattr	= generic_getxattr,
 | 
			
		||||
-	.listxattr	= generic_listxattr,
 | 
			
		||||
-	.removexattr	= generic_removexattr,
 | 
			
		||||
 	.check_acl	= generic_check_acl,
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
@@ -2523,23 +2731,27 @@ static const struct inode_operations shm
 | 
			
		||||
 	.mknod		= shmem_mknod,
 | 
			
		||||
 	.rename		= shmem_rename,
 | 
			
		||||
 #endif
 | 
			
		||||
+#ifdef CONFIG_TMPFS_XATTR
 | 
			
		||||
+	.setxattr	= shmem_setxattr,
 | 
			
		||||
+	.getxattr	= shmem_getxattr,
 | 
			
		||||
+	.listxattr	= shmem_listxattr,
 | 
			
		||||
+	.removexattr	= shmem_removexattr,
 | 
			
		||||
+#endif
 | 
			
		||||
 #ifdef CONFIG_TMPFS_POSIX_ACL
 | 
			
		||||
 	.setattr	= shmem_notify_change,
 | 
			
		||||
-	.setxattr	= generic_setxattr,
 | 
			
		||||
-	.getxattr	= generic_getxattr,
 | 
			
		||||
-	.listxattr	= generic_listxattr,
 | 
			
		||||
-	.removexattr	= generic_removexattr,
 | 
			
		||||
 	.check_acl	= generic_check_acl,
 | 
			
		||||
 #endif
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 static const struct inode_operations shmem_special_inode_operations = {
 | 
			
		||||
+#ifdef CONFIG_TMPFS_XATTR
 | 
			
		||||
+	.setxattr	= shmem_setxattr,
 | 
			
		||||
+	.getxattr	= shmem_getxattr,
 | 
			
		||||
+	.listxattr	= shmem_listxattr,
 | 
			
		||||
+	.removexattr	= shmem_removexattr,
 | 
			
		||||
+#endif
 | 
			
		||||
 #ifdef CONFIG_TMPFS_POSIX_ACL
 | 
			
		||||
 	.setattr	= shmem_notify_change,
 | 
			
		||||
-	.setxattr	= generic_setxattr,
 | 
			
		||||
-	.getxattr	= generic_getxattr,
 | 
			
		||||
-	.listxattr	= generic_listxattr,
 | 
			
		||||
-	.removexattr	= generic_removexattr,
 | 
			
		||||
 	.check_acl	= generic_check_acl,
 | 
			
		||||
 #endif
 | 
			
		||||
 };
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
--- a/mm/shmem.c
 | 
			
		||||
+++ b/mm/shmem.c
 | 
			
		||||
@@ -2731,6 +2731,16 @@ out:
 | 
			
		||||
@@ -2943,6 +2943,16 @@ out:
 | 
			
		||||
 
 | 
			
		||||
 /* common code */
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@
 | 
			
		||||
 /**
 | 
			
		||||
  * shmem_file_setup - get an unlinked file living in tmpfs
 | 
			
		||||
  * @name: name for dentry (to be seen in /proc/<pid>/maps
 | 
			
		||||
@@ -2808,10 +2818,7 @@ int shmem_zero_setup(struct vm_area_stru
 | 
			
		||||
@@ -3020,10 +3030,7 @@ int shmem_zero_setup(struct vm_area_stru
 | 
			
		||||
 	if (IS_ERR(file))
 | 
			
		||||
 		return PTR_ERR(file);
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user