All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 00/11] Inode security label invalidation
@ 2015-08-20 18:19 ` Andreas Gruenbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	linux-fsdevel, David Quigley, J. Bruce Fields
  Cc: linux-security-module, cluster-devel

Hello,

this patch queue adds an LSM hook for file systems to invalidate inode security
labels.  To allow selinux to revalidate invalid labels, the generic xattr
handlers are cleaned up a bit and a new igetxattr inode operation is
introduced: the getxattr inode operation requires a dentry which selinux
doesn't have in inode_has_perm(); igetxattr instead takes an inode.  Finally,
gfs2 is patched to make use of this new mechanism.

The new igetxattr inode operation currently is *only* used for revalidating
security labels in selinux; it may make sense to use it instead of getxattr
when defined.

Is this approach useful?  An alternative would be to modify selinux so that it
always has a dentry when checking inode security labels; I would guess that
this won't work in all cases, though.


BACKGROUND

Selinux currently assumes that, after initialization, inode->i_security always
represents the current security label of the inode.  This assumption works for
local file systems; any change of the label must go through setxattr (or
removexattr) which updates inode->i_security.

On an nfs mount, other nodes can change the security label; there is no
immediate notification mechanism.  Other nodes will eventually notice a label
change because the label is transmitted as part of the reply of operations like
open. (A timeout for cached labels would help too; I'm not sure if the code
implements that.)

Other file systems have different consistency models. For example, gfs2 inodes
go "invalid" when a node drops the inode's glocks. When such an invalid inode
is accessed again, all the metadata must be read from disk again, including the
security label.

For that case, the file system has no way of updating the security label before
selinux next uses it.  Things also don't fix themselves over time; when selinux
rejects access, the file system never notices.

To fix that, this patch queue adds a mechanism for file systems to invalidate
inode security labels, and for selinux to revalidate them; this is similar to
how the inode acl cache works.

Thanks,
Andreas

Andreas Gruenbacher (11):
  ubifs: Remove unused "security.*" xattr handler
  hfsplus: Remove unused xattr handler list operations
  9p: Simplify the xattr handlers
  xattr handlers: Pass handler to operations instead of flags
  xattr handlers: Some simplifications
  lib: Move strcmp_prefix into string.c
  9p: Stop using the generic xattr_handler infrastructure
  xattr: Pass inodes to xattr handlers instead of dentries
  vfs: Add igetxattr inode operation
  selinux: Allow to invalidate an inode's security label
  gfs2: Invalide security labels of inodes that go invalid

 Documentation/filesystems/Locking |  2 +
 Documentation/filesystems/vfs.txt |  4 ++
 fs/9p/Makefile                    |  5 +--
 fs/9p/acl.c                       | 65 ++++++------------------------
 fs/9p/vfs_super.c                 |  5 +--
 fs/9p/xattr.c                     | 74 +++++++++++++++++++++++++++++++++-
 fs/9p/xattr.h                     | 18 ++++++---
 fs/9p/xattr_security.c            | 80 -------------------------------------
 fs/9p/xattr_trusted.c             | 80 -------------------------------------
 fs/9p/xattr_user.c                | 80 -------------------------------------
 fs/ext2/xattr.c                   |  4 +-
 fs/ext2/xattr_security.c          | 19 +++++----
 fs/ext2/xattr_trusted.c           | 19 +++++----
 fs/ext2/xattr_user.c              | 25 ++++++------
 fs/ext3/xattr.c                   |  5 ++-
 fs/ext3/xattr_security.c          | 19 +++++----
 fs/ext3/xattr_trusted.c           | 19 +++++----
 fs/ext3/xattr_user.c              | 25 ++++++------
 fs/ext4/xattr.c                   |  5 ++-
 fs/ext4/xattr_security.c          | 19 +++++----
 fs/ext4/xattr_trusted.c           | 19 +++++----
 fs/ext4/xattr_user.c              | 25 ++++++------
 fs/f2fs/xattr.c                   | 71 +++++++++++++++------------------
 fs/gfs2/glops.c                   |  2 +
 fs/gfs2/inode.c                   | 16 ++++++--
 fs/gfs2/xattr.c                   | 17 ++++----
 fs/hfsplus/xattr.c                | 33 ++++++----------
 fs/hfsplus/xattr.h                |  4 +-
 fs/hfsplus/xattr_security.c       | 25 ++++--------
 fs/hfsplus/xattr_trusted.c        | 25 ++++--------
 fs/hfsplus/xattr_user.c           | 25 ++++--------
 fs/jffs2/security.c               | 19 +++++----
 fs/jffs2/xattr.c                  |  8 ++--
 fs/jffs2/xattr_trusted.c          | 18 +++++----
 fs/jffs2/xattr_user.c             | 19 +++++----
 fs/nfs/nfs4proc.c                 | 49 ++++++++++++-----------
 fs/ocfs2/xattr.c                  | 63 ++++++++++++++++-------------
 fs/posix_acl.c                    | 37 ++++++++---------
 fs/reiserfs/xattr.c               | 29 ++++++++------
 fs/reiserfs/xattr_security.c      | 24 +++++------
 fs/reiserfs/xattr_trusted.c       | 24 +++++------
 fs/reiserfs/xattr_user.c          | 24 +++++------
 fs/squashfs/xattr.c               | 83 ++++++++++++++-------------------------
 fs/ubifs/super.c                  |  1 -
 fs/ubifs/ubifs.h                  |  1 -
 fs/ubifs/xattr.c                  | 40 -------------------
 fs/xattr.c                        | 37 ++++++++---------
 fs/xfs/xfs_xattr.c                | 16 +++++---
 include/linux/fs.h                |  1 +
 include/linux/lsm_hooks.h         |  6 +++
 include/linux/security.h          |  5 +++
 include/linux/string.h            |  1 +
 include/linux/xattr.h             | 16 ++++----
 lib/string.c                      | 16 ++++++++
 security/selinux/hooks.c          | 47 ++++++++++++++++------
 security/selinux/include/objsec.h |  3 +-
 56 files changed, 620 insertions(+), 801 deletions(-)
 delete mode 100644 fs/9p/xattr_security.c
 delete mode 100644 fs/9p/xattr_trusted.c
 delete mode 100644 fs/9p/xattr_user.c

-- 
2.4.3


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 00/11] Inode security label invalidation
@ 2015-08-20 18:19 ` Andreas Gruenbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Hello,

this patch queue adds an LSM hook for file systems to invalidate inode security
labels.  To allow selinux to revalidate invalid labels, the generic xattr
handlers are cleaned up a bit and a new igetxattr inode operation is
introduced: the getxattr inode operation requires a dentry which selinux
doesn't have in inode_has_perm(); igetxattr instead takes an inode.  Finally,
gfs2 is patched to make use of this new mechanism.

The new igetxattr inode operation currently is *only* used for revalidating
security labels in selinux; it may make sense to use it instead of getxattr
when defined.

Is this approach useful?  An alternative would be to modify selinux so that it
always has a dentry when checking inode security labels; I would guess that
this won't work in all cases, though.


BACKGROUND

Selinux currently assumes that, after initialization, inode->i_security always
represents the current security label of the inode.  This assumption works for
local file systems; any change of the label must go through setxattr (or
removexattr) which updates inode->i_security.

On an nfs mount, other nodes can change the security label; there is no
immediate notification mechanism.  Other nodes will eventually notice a label
change because the label is transmitted as part of the reply of operations like
open. (A timeout for cached labels would help too; I'm not sure if the code
implements that.)

Other file systems have different consistency models. For example, gfs2 inodes
go "invalid" when a node drops the inode's glocks. When such an invalid inode
is accessed again, all the metadata must be read from disk again, including the
security label.

For that case, the file system has no way of updating the security label before
selinux next uses it.  Things also don't fix themselves over time; when selinux
rejects access, the file system never notices.

To fix that, this patch queue adds a mechanism for file systems to invalidate
inode security labels, and for selinux to revalidate them; this is similar to
how the inode acl cache works.

Thanks,
Andreas

Andreas Gruenbacher (11):
  ubifs: Remove unused "security.*" xattr handler
  hfsplus: Remove unused xattr handler list operations
  9p: Simplify the xattr handlers
  xattr handlers: Pass handler to operations instead of flags
  xattr handlers: Some simplifications
  lib: Move strcmp_prefix into string.c
  9p: Stop using the generic xattr_handler infrastructure
  xattr: Pass inodes to xattr handlers instead of dentries
  vfs: Add igetxattr inode operation
  selinux: Allow to invalidate an inode's security label
  gfs2: Invalide security labels of inodes that go invalid

 Documentation/filesystems/Locking |  2 +
 Documentation/filesystems/vfs.txt |  4 ++
 fs/9p/Makefile                    |  5 +--
 fs/9p/acl.c                       | 65 ++++++------------------------
 fs/9p/vfs_super.c                 |  5 +--
 fs/9p/xattr.c                     | 74 +++++++++++++++++++++++++++++++++-
 fs/9p/xattr.h                     | 18 ++++++---
 fs/9p/xattr_security.c            | 80 -------------------------------------
 fs/9p/xattr_trusted.c             | 80 -------------------------------------
 fs/9p/xattr_user.c                | 80 -------------------------------------
 fs/ext2/xattr.c                   |  4 +-
 fs/ext2/xattr_security.c          | 19 +++++----
 fs/ext2/xattr_trusted.c           | 19 +++++----
 fs/ext2/xattr_user.c              | 25 ++++++------
 fs/ext3/xattr.c                   |  5 ++-
 fs/ext3/xattr_security.c          | 19 +++++----
 fs/ext3/xattr_trusted.c           | 19 +++++----
 fs/ext3/xattr_user.c              | 25 ++++++------
 fs/ext4/xattr.c                   |  5 ++-
 fs/ext4/xattr_security.c          | 19 +++++----
 fs/ext4/xattr_trusted.c           | 19 +++++----
 fs/ext4/xattr_user.c              | 25 ++++++------
 fs/f2fs/xattr.c                   | 71 +++++++++++++++------------------
 fs/gfs2/glops.c                   |  2 +
 fs/gfs2/inode.c                   | 16 ++++++--
 fs/gfs2/xattr.c                   | 17 ++++----
 fs/hfsplus/xattr.c                | 33 ++++++----------
 fs/hfsplus/xattr.h                |  4 +-
 fs/hfsplus/xattr_security.c       | 25 ++++--------
 fs/hfsplus/xattr_trusted.c        | 25 ++++--------
 fs/hfsplus/xattr_user.c           | 25 ++++--------
 fs/jffs2/security.c               | 19 +++++----
 fs/jffs2/xattr.c                  |  8 ++--
 fs/jffs2/xattr_trusted.c          | 18 +++++----
 fs/jffs2/xattr_user.c             | 19 +++++----
 fs/nfs/nfs4proc.c                 | 49 ++++++++++++-----------
 fs/ocfs2/xattr.c                  | 63 ++++++++++++++++-------------
 fs/posix_acl.c                    | 37 ++++++++---------
 fs/reiserfs/xattr.c               | 29 ++++++++------
 fs/reiserfs/xattr_security.c      | 24 +++++------
 fs/reiserfs/xattr_trusted.c       | 24 +++++------
 fs/reiserfs/xattr_user.c          | 24 +++++------
 fs/squashfs/xattr.c               | 83 ++++++++++++++-------------------------
 fs/ubifs/super.c                  |  1 -
 fs/ubifs/ubifs.h                  |  1 -
 fs/ubifs/xattr.c                  | 40 -------------------
 fs/xattr.c                        | 37 ++++++++---------
 fs/xfs/xfs_xattr.c                | 16 +++++---
 include/linux/fs.h                |  1 +
 include/linux/lsm_hooks.h         |  6 +++
 include/linux/security.h          |  5 +++
 include/linux/string.h            |  1 +
 include/linux/xattr.h             | 16 ++++----
 lib/string.c                      | 16 ++++++++
 security/selinux/hooks.c          | 47 ++++++++++++++++------
 security/selinux/include/objsec.h |  3 +-
 56 files changed, 620 insertions(+), 801 deletions(-)
 delete mode 100644 fs/9p/xattr_security.c
 delete mode 100644 fs/9p/xattr_trusted.c
 delete mode 100644 fs/9p/xattr_user.c

-- 
2.4.3



^ permalink raw reply	[flat|nested] 40+ messages in thread

* [RFC 01/11] ubifs: Remove unused "security.*" xattr handler
  2015-08-20 18:19 ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  -1 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	linux-fsdevel, David Quigley, J. Bruce Fields
  Cc: linux-security-module, cluster-devel, Subodh Nijsure

Ubifs installs a "security.*" xattr handler in sb->s_xattr but doesn't use the
generic_{get,set,list,remove}xattr inode operations needed for processing this
list of attribute handlers; the handler is never called.  Instead, ubifs uses
its own xattr handlers which also process "security.*" xattrs.

Remove the dead code.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Cc: Subodh Nijsure <snijsure@grid-net.com>
---
 fs/ubifs/super.c |  1 -
 fs/ubifs/ubifs.h |  1 -
 fs/ubifs/xattr.c | 40 ----------------------------------------
 3 files changed, 42 deletions(-)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 9547a278..c71edca 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -2037,7 +2037,6 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
 	if (c->max_inode_sz > MAX_LFS_FILESIZE)
 		sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE;
 	sb->s_op = &ubifs_super_operations;
-	sb->s_xattr = ubifs_xattr_handlers;
 
 	mutex_lock(&c->umount_mutex);
 	err = mount_ubifs(c);
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index de75902..33b6ee7 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1470,7 +1470,6 @@ extern spinlock_t ubifs_infos_lock;
 extern atomic_long_t ubifs_clean_zn_cnt;
 extern struct kmem_cache *ubifs_inode_slab;
 extern const struct super_operations ubifs_super_operations;
-extern const struct xattr_handler *ubifs_xattr_handlers[];
 extern const struct address_space_operations ubifs_file_address_operations;
 extern const struct file_operations ubifs_file_operations;
 extern const struct inode_operations ubifs_file_inode_operations;
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index 96f3448..b512b14 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -582,46 +582,6 @@ out_free:
 	return err;
 }
 
-static size_t security_listxattr(struct dentry *d, char *list, size_t list_size,
-				 const char *name, size_t name_len, int flags)
-{
-	const int prefix_len = XATTR_SECURITY_PREFIX_LEN;
-	const size_t total_len = prefix_len + name_len + 1;
-
-	if (list && total_len <= list_size) {
-		memcpy(list, XATTR_SECURITY_PREFIX, prefix_len);
-		memcpy(list + prefix_len, name, name_len);
-		list[prefix_len + name_len] = '\0';
-	}
-
-	return total_len;
-}
-
-static int security_getxattr(struct dentry *d, const char *name, void *buffer,
-		      size_t size, int flags)
-{
-	return ubifs_getxattr(d, name, buffer, size);
-}
-
-static int security_setxattr(struct dentry *d, const char *name,
-			     const void *value, size_t size, int flags,
-			     int handler_flags)
-{
-	return ubifs_setxattr(d, name, value, size, flags);
-}
-
-static const struct xattr_handler ubifs_xattr_security_handler = {
-	.prefix = XATTR_SECURITY_PREFIX,
-	.list   = security_listxattr,
-	.get    = security_getxattr,
-	.set    = security_setxattr,
-};
-
-const struct xattr_handler *ubifs_xattr_handlers[] = {
-	&ubifs_xattr_security_handler,
-	NULL,
-};
-
 static int init_xattrs(struct inode *inode, const struct xattr *xattr_array,
 		      void *fs_info)
 {
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 01/11] ubifs: Remove unused "security.*" xattr handler
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Ubifs installs a "security.*" xattr handler in sb->s_xattr but doesn't use the
generic_{get,set,list,remove}xattr inode operations needed for processing this
list of attribute handlers; the handler is never called.  Instead, ubifs uses
its own xattr handlers which also process "security.*" xattrs.

Remove the dead code.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Cc: Subodh Nijsure <snijsure@grid-net.com>
---
 fs/ubifs/super.c |  1 -
 fs/ubifs/ubifs.h |  1 -
 fs/ubifs/xattr.c | 40 ----------------------------------------
 3 files changed, 42 deletions(-)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 9547a278..c71edca 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -2037,7 +2037,6 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
 	if (c->max_inode_sz > MAX_LFS_FILESIZE)
 		sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE;
 	sb->s_op = &ubifs_super_operations;
-	sb->s_xattr = ubifs_xattr_handlers;
 
 	mutex_lock(&c->umount_mutex);
 	err = mount_ubifs(c);
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index de75902..33b6ee7 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1470,7 +1470,6 @@ extern spinlock_t ubifs_infos_lock;
 extern atomic_long_t ubifs_clean_zn_cnt;
 extern struct kmem_cache *ubifs_inode_slab;
 extern const struct super_operations ubifs_super_operations;
-extern const struct xattr_handler *ubifs_xattr_handlers[];
 extern const struct address_space_operations ubifs_file_address_operations;
 extern const struct file_operations ubifs_file_operations;
 extern const struct inode_operations ubifs_file_inode_operations;
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index 96f3448..b512b14 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -582,46 +582,6 @@ out_free:
 	return err;
 }
 
-static size_t security_listxattr(struct dentry *d, char *list, size_t list_size,
-				 const char *name, size_t name_len, int flags)
-{
-	const int prefix_len = XATTR_SECURITY_PREFIX_LEN;
-	const size_t total_len = prefix_len + name_len + 1;
-
-	if (list && total_len <= list_size) {
-		memcpy(list, XATTR_SECURITY_PREFIX, prefix_len);
-		memcpy(list + prefix_len, name, name_len);
-		list[prefix_len + name_len] = '\0';
-	}
-
-	return total_len;
-}
-
-static int security_getxattr(struct dentry *d, const char *name, void *buffer,
-		      size_t size, int flags)
-{
-	return ubifs_getxattr(d, name, buffer, size);
-}
-
-static int security_setxattr(struct dentry *d, const char *name,
-			     const void *value, size_t size, int flags,
-			     int handler_flags)
-{
-	return ubifs_setxattr(d, name, value, size, flags);
-}
-
-static const struct xattr_handler ubifs_xattr_security_handler = {
-	.prefix = XATTR_SECURITY_PREFIX,
-	.list   = security_listxattr,
-	.get    = security_getxattr,
-	.set    = security_setxattr,
-};
-
-const struct xattr_handler *ubifs_xattr_handlers[] = {
-	&ubifs_xattr_security_handler,
-	NULL,
-};
-
 static int init_xattrs(struct inode *inode, const struct xattr *xattr_array,
 		      void *fs_info)
 {
-- 
2.4.3



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC 02/11] hfsplus: Remove unused xattr handler list operations
  2015-08-20 18:19 ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  -1 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	linux-fsdevel, David Quigley, J. Bruce Fields
  Cc: linux-security-module, cluster-devel

The list operations can never be called; they are even documented to be unused.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/hfsplus/xattr.c          | 11 -----------
 fs/hfsplus/xattr_security.c | 11 -----------
 fs/hfsplus/xattr_trusted.c  | 11 -----------
 fs/hfsplus/xattr_user.c     | 11 -----------
 4 files changed, 44 deletions(-)

diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
index 416b1db..e898499 100644
--- a/fs/hfsplus/xattr.c
+++ b/fs/hfsplus/xattr.c
@@ -893,19 +893,8 @@ static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
 	return __hfsplus_setxattr(d_inode(dentry), name, buffer, size, flags);
 }
 
-static size_t hfsplus_osx_listxattr(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t name_len, int type)
-{
-	/*
-	 * This method is not used.
-	 * It is used hfsplus_listxattr() instead of generic_listxattr().
-	 */
-	return -EOPNOTSUPP;
-}
-
 const struct xattr_handler hfsplus_xattr_osx_handler = {
 	.prefix	= XATTR_MAC_OSX_PREFIX,
-	.list	= hfsplus_osx_listxattr,
 	.get	= hfsplus_osx_getxattr,
 	.set	= hfsplus_osx_setxattr,
 };
diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c
index aacff00..024e61c 100644
--- a/fs/hfsplus/xattr_security.c
+++ b/fs/hfsplus/xattr_security.c
@@ -29,16 +29,6 @@ static int hfsplus_security_setxattr(struct dentry *dentry, const char *name,
 				XATTR_SECURITY_PREFIX_LEN);
 }
 
-static size_t hfsplus_security_listxattr(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t name_len, int type)
-{
-	/*
-	 * This method is not used.
-	 * It is used hfsplus_listxattr() instead of generic_listxattr().
-	 */
-	return -EOPNOTSUPP;
-}
-
 static int hfsplus_initxattrs(struct inode *inode,
 				const struct xattr *xattr_array,
 				void *fs_info)
@@ -92,7 +82,6 @@ int hfsplus_init_inode_security(struct inode *inode,
 
 const struct xattr_handler hfsplus_xattr_security_handler = {
 	.prefix	= XATTR_SECURITY_PREFIX,
-	.list	= hfsplus_security_listxattr,
 	.get	= hfsplus_security_getxattr,
 	.set	= hfsplus_security_setxattr,
 };
diff --git a/fs/hfsplus/xattr_trusted.c b/fs/hfsplus/xattr_trusted.c
index bcf6508..6186157 100644
--- a/fs/hfsplus/xattr_trusted.c
+++ b/fs/hfsplus/xattr_trusted.c
@@ -26,19 +26,8 @@ static int hfsplus_trusted_setxattr(struct dentry *dentry, const char *name,
 				XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
 }
 
-static size_t hfsplus_trusted_listxattr(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t name_len, int type)
-{
-	/*
-	 * This method is not used.
-	 * It is used hfsplus_listxattr() instead of generic_listxattr().
-	 */
-	return -EOPNOTSUPP;
-}
-
 const struct xattr_handler hfsplus_xattr_trusted_handler = {
 	.prefix	= XATTR_TRUSTED_PREFIX,
-	.list	= hfsplus_trusted_listxattr,
 	.get	= hfsplus_trusted_getxattr,
 	.set	= hfsplus_trusted_setxattr,
 };
diff --git a/fs/hfsplus/xattr_user.c b/fs/hfsplus/xattr_user.c
index 5aa0e6d..3b4caba 100644
--- a/fs/hfsplus/xattr_user.c
+++ b/fs/hfsplus/xattr_user.c
@@ -26,19 +26,8 @@ static int hfsplus_user_setxattr(struct dentry *dentry, const char *name,
 				XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
 }
 
-static size_t hfsplus_user_listxattr(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t name_len, int type)
-{
-	/*
-	 * This method is not used.
-	 * It is used hfsplus_listxattr() instead of generic_listxattr().
-	 */
-	return -EOPNOTSUPP;
-}
-
 const struct xattr_handler hfsplus_xattr_user_handler = {
 	.prefix	= XATTR_USER_PREFIX,
-	.list	= hfsplus_user_listxattr,
 	.get	= hfsplus_user_getxattr,
 	.set	= hfsplus_user_setxattr,
 };
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 02/11] hfsplus: Remove unused xattr handler list operations
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

The list operations can never be called; they are even documented to be unused.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/hfsplus/xattr.c          | 11 -----------
 fs/hfsplus/xattr_security.c | 11 -----------
 fs/hfsplus/xattr_trusted.c  | 11 -----------
 fs/hfsplus/xattr_user.c     | 11 -----------
 4 files changed, 44 deletions(-)

diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
index 416b1db..e898499 100644
--- a/fs/hfsplus/xattr.c
+++ b/fs/hfsplus/xattr.c
@@ -893,19 +893,8 @@ static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
 	return __hfsplus_setxattr(d_inode(dentry), name, buffer, size, flags);
 }
 
-static size_t hfsplus_osx_listxattr(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t name_len, int type)
-{
-	/*
-	 * This method is not used.
-	 * It is used hfsplus_listxattr() instead of generic_listxattr().
-	 */
-	return -EOPNOTSUPP;
-}
-
 const struct xattr_handler hfsplus_xattr_osx_handler = {
 	.prefix	= XATTR_MAC_OSX_PREFIX,
-	.list	= hfsplus_osx_listxattr,
 	.get	= hfsplus_osx_getxattr,
 	.set	= hfsplus_osx_setxattr,
 };
diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c
index aacff00..024e61c 100644
--- a/fs/hfsplus/xattr_security.c
+++ b/fs/hfsplus/xattr_security.c
@@ -29,16 +29,6 @@ static int hfsplus_security_setxattr(struct dentry *dentry, const char *name,
 				XATTR_SECURITY_PREFIX_LEN);
 }
 
-static size_t hfsplus_security_listxattr(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t name_len, int type)
-{
-	/*
-	 * This method is not used.
-	 * It is used hfsplus_listxattr() instead of generic_listxattr().
-	 */
-	return -EOPNOTSUPP;
-}
-
 static int hfsplus_initxattrs(struct inode *inode,
 				const struct xattr *xattr_array,
 				void *fs_info)
@@ -92,7 +82,6 @@ int hfsplus_init_inode_security(struct inode *inode,
 
 const struct xattr_handler hfsplus_xattr_security_handler = {
 	.prefix	= XATTR_SECURITY_PREFIX,
-	.list	= hfsplus_security_listxattr,
 	.get	= hfsplus_security_getxattr,
 	.set	= hfsplus_security_setxattr,
 };
diff --git a/fs/hfsplus/xattr_trusted.c b/fs/hfsplus/xattr_trusted.c
index bcf6508..6186157 100644
--- a/fs/hfsplus/xattr_trusted.c
+++ b/fs/hfsplus/xattr_trusted.c
@@ -26,19 +26,8 @@ static int hfsplus_trusted_setxattr(struct dentry *dentry, const char *name,
 				XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
 }
 
-static size_t hfsplus_trusted_listxattr(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t name_len, int type)
-{
-	/*
-	 * This method is not used.
-	 * It is used hfsplus_listxattr() instead of generic_listxattr().
-	 */
-	return -EOPNOTSUPP;
-}
-
 const struct xattr_handler hfsplus_xattr_trusted_handler = {
 	.prefix	= XATTR_TRUSTED_PREFIX,
-	.list	= hfsplus_trusted_listxattr,
 	.get	= hfsplus_trusted_getxattr,
 	.set	= hfsplus_trusted_setxattr,
 };
diff --git a/fs/hfsplus/xattr_user.c b/fs/hfsplus/xattr_user.c
index 5aa0e6d..3b4caba 100644
--- a/fs/hfsplus/xattr_user.c
+++ b/fs/hfsplus/xattr_user.c
@@ -26,19 +26,8 @@ static int hfsplus_user_setxattr(struct dentry *dentry, const char *name,
 				XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
 }
 
-static size_t hfsplus_user_listxattr(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t name_len, int type)
-{
-	/*
-	 * This method is not used.
-	 * It is used hfsplus_listxattr() instead of generic_listxattr().
-	 */
-	return -EOPNOTSUPP;
-}
-
 const struct xattr_handler hfsplus_xattr_user_handler = {
 	.prefix	= XATTR_USER_PREFIX,
-	.list	= hfsplus_user_listxattr,
 	.get	= hfsplus_user_getxattr,
 	.set	= hfsplus_user_setxattr,
 };
-- 
2.4.3



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC 03/11] 9p: Simplify the xattr handlers
  2015-08-20 18:19 ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  -1 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	linux-fsdevel, David Quigley, J. Bruce Fields
  Cc: linux-security-module, cluster-devel

The generic_{get,set,remove}xattr inode operations use the xattr name prefix to
decide which of the defined xattr handlers to call, then call the appropriate
handler's get or set operation.  The name suffix is passed to the get or set
operations, the prefix is still "there" in the name before the suffix though.
There is no need to recompose the name in a temporary buffer.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/9p/xattr_security.c | 34 ++++------------------------------
 fs/9p/xattr_trusted.c  | 34 ++++------------------------------
 fs/9p/xattr_user.c     | 34 ++++------------------------------
 3 files changed, 12 insertions(+), 90 deletions(-)

diff --git a/fs/9p/xattr_security.c b/fs/9p/xattr_security.c
index cb247a1..2c9b394 100644
--- a/fs/9p/xattr_security.c
+++ b/fs/9p/xattr_security.c
@@ -22,10 +22,7 @@
 static int v9fs_xattr_security_get(struct dentry *dentry, const char *name,
 			void *buffer, size_t size, int type)
 {
-	int retval;
-	char *full_name;
-	size_t name_len;
-	size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
+	const char *full_name = name - XATTR_SECURITY_PREFIX_LEN;
 
 	if (name == NULL)
 		return -EINVAL;
@@ -33,26 +30,13 @@ static int v9fs_xattr_security_get(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	name_len = strlen(name);
-	full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-	if (!full_name)
-		return -ENOMEM;
-	memcpy(full_name, XATTR_SECURITY_PREFIX, prefix_len);
-	memcpy(full_name+prefix_len, name, name_len);
-	full_name[prefix_len + name_len] = '\0';
-
-	retval = v9fs_xattr_get(dentry, full_name, buffer, size);
-	kfree(full_name);
-	return retval;
+	return v9fs_xattr_get(dentry, full_name, buffer, size);
 }
 
 static int v9fs_xattr_security_set(struct dentry *dentry, const char *name,
 			const void *value, size_t size, int flags, int type)
 {
-	int retval;
-	char *full_name;
-	size_t name_len;
-	size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
+	const char *full_name = name - XATTR_SECURITY_PREFIX_LEN;
 
 	if (name == NULL)
 		return -EINVAL;
@@ -60,17 +44,7 @@ static int v9fs_xattr_security_set(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	name_len = strlen(name);
-	full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-	if (!full_name)
-		return -ENOMEM;
-	memcpy(full_name, XATTR_SECURITY_PREFIX, prefix_len);
-	memcpy(full_name + prefix_len, name, name_len);
-	full_name[prefix_len + name_len] = '\0';
-
-	retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
-	kfree(full_name);
-	return retval;
+	return v9fs_xattr_set(dentry, full_name, value, size, flags);
 }
 
 struct xattr_handler v9fs_xattr_security_handler = {
diff --git a/fs/9p/xattr_trusted.c b/fs/9p/xattr_trusted.c
index e30d33b..ee470b6 100644
--- a/fs/9p/xattr_trusted.c
+++ b/fs/9p/xattr_trusted.c
@@ -22,10 +22,7 @@
 static int v9fs_xattr_trusted_get(struct dentry *dentry, const char *name,
 			void *buffer, size_t size, int type)
 {
-	int retval;
-	char *full_name;
-	size_t name_len;
-	size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
+	const char *full_name = name - XATTR_TRUSTED_PREFIX_LEN;
 
 	if (name == NULL)
 		return -EINVAL;
@@ -33,26 +30,13 @@ static int v9fs_xattr_trusted_get(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	name_len = strlen(name);
-	full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-	if (!full_name)
-		return -ENOMEM;
-	memcpy(full_name, XATTR_TRUSTED_PREFIX, prefix_len);
-	memcpy(full_name+prefix_len, name, name_len);
-	full_name[prefix_len + name_len] = '\0';
-
-	retval = v9fs_xattr_get(dentry, full_name, buffer, size);
-	kfree(full_name);
-	return retval;
+	return v9fs_xattr_get(dentry, full_name, buffer, size);
 }
 
 static int v9fs_xattr_trusted_set(struct dentry *dentry, const char *name,
 			const void *value, size_t size, int flags, int type)
 {
-	int retval;
-	char *full_name;
-	size_t name_len;
-	size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
+	const char *full_name = name - XATTR_TRUSTED_PREFIX_LEN;
 
 	if (name == NULL)
 		return -EINVAL;
@@ -60,17 +44,7 @@ static int v9fs_xattr_trusted_set(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	name_len = strlen(name);
-	full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-	if (!full_name)
-		return -ENOMEM;
-	memcpy(full_name, XATTR_TRUSTED_PREFIX, prefix_len);
-	memcpy(full_name + prefix_len, name, name_len);
-	full_name[prefix_len + name_len] = '\0';
-
-	retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
-	kfree(full_name);
-	return retval;
+	return v9fs_xattr_set(dentry, full_name, value, size, flags);
 }
 
 struct xattr_handler v9fs_xattr_trusted_handler = {
diff --git a/fs/9p/xattr_user.c b/fs/9p/xattr_user.c
index d0b701b..4432604 100644
--- a/fs/9p/xattr_user.c
+++ b/fs/9p/xattr_user.c
@@ -22,10 +22,7 @@
 static int v9fs_xattr_user_get(struct dentry *dentry, const char *name,
 			void *buffer, size_t size, int type)
 {
-	int retval;
-	char *full_name;
-	size_t name_len;
-	size_t prefix_len = XATTR_USER_PREFIX_LEN;
+	const char *full_name = name - XATTR_USER_PREFIX_LEN;
 
 	if (name == NULL)
 		return -EINVAL;
@@ -33,26 +30,13 @@ static int v9fs_xattr_user_get(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	name_len = strlen(name);
-	full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-	if (!full_name)
-		return -ENOMEM;
-	memcpy(full_name, XATTR_USER_PREFIX, prefix_len);
-	memcpy(full_name+prefix_len, name, name_len);
-	full_name[prefix_len + name_len] = '\0';
-
-	retval = v9fs_xattr_get(dentry, full_name, buffer, size);
-	kfree(full_name);
-	return retval;
+	return v9fs_xattr_get(dentry, full_name, buffer, size);
 }
 
 static int v9fs_xattr_user_set(struct dentry *dentry, const char *name,
 			const void *value, size_t size, int flags, int type)
 {
-	int retval;
-	char *full_name;
-	size_t name_len;
-	size_t prefix_len = XATTR_USER_PREFIX_LEN;
+	const char *full_name = name - XATTR_USER_PREFIX_LEN;
 
 	if (name == NULL)
 		return -EINVAL;
@@ -60,17 +44,7 @@ static int v9fs_xattr_user_set(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	name_len = strlen(name);
-	full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-	if (!full_name)
-		return -ENOMEM;
-	memcpy(full_name, XATTR_USER_PREFIX, prefix_len);
-	memcpy(full_name + prefix_len, name, name_len);
-	full_name[prefix_len + name_len] = '\0';
-
-	retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
-	kfree(full_name);
-	return retval;
+	return v9fs_xattr_set(dentry, full_name, value, size, flags);
 }
 
 struct xattr_handler v9fs_xattr_user_handler = {
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 03/11] 9p: Simplify the xattr handlers
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

The generic_{get,set,remove}xattr inode operations use the xattr name prefix to
decide which of the defined xattr handlers to call, then call the appropriate
handler's get or set operation.  The name suffix is passed to the get or set
operations, the prefix is still "there" in the name before the suffix though.
There is no need to recompose the name in a temporary buffer.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/9p/xattr_security.c | 34 ++++------------------------------
 fs/9p/xattr_trusted.c  | 34 ++++------------------------------
 fs/9p/xattr_user.c     | 34 ++++------------------------------
 3 files changed, 12 insertions(+), 90 deletions(-)

diff --git a/fs/9p/xattr_security.c b/fs/9p/xattr_security.c
index cb247a1..2c9b394 100644
--- a/fs/9p/xattr_security.c
+++ b/fs/9p/xattr_security.c
@@ -22,10 +22,7 @@
 static int v9fs_xattr_security_get(struct dentry *dentry, const char *name,
 			void *buffer, size_t size, int type)
 {
-	int retval;
-	char *full_name;
-	size_t name_len;
-	size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
+	const char *full_name = name - XATTR_SECURITY_PREFIX_LEN;
 
 	if (name == NULL)
 		return -EINVAL;
@@ -33,26 +30,13 @@ static int v9fs_xattr_security_get(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	name_len = strlen(name);
-	full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-	if (!full_name)
-		return -ENOMEM;
-	memcpy(full_name, XATTR_SECURITY_PREFIX, prefix_len);
-	memcpy(full_name+prefix_len, name, name_len);
-	full_name[prefix_len + name_len] = '\0';
-
-	retval = v9fs_xattr_get(dentry, full_name, buffer, size);
-	kfree(full_name);
-	return retval;
+	return v9fs_xattr_get(dentry, full_name, buffer, size);
 }
 
 static int v9fs_xattr_security_set(struct dentry *dentry, const char *name,
 			const void *value, size_t size, int flags, int type)
 {
-	int retval;
-	char *full_name;
-	size_t name_len;
-	size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
+	const char *full_name = name - XATTR_SECURITY_PREFIX_LEN;
 
 	if (name == NULL)
 		return -EINVAL;
@@ -60,17 +44,7 @@ static int v9fs_xattr_security_set(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	name_len = strlen(name);
-	full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-	if (!full_name)
-		return -ENOMEM;
-	memcpy(full_name, XATTR_SECURITY_PREFIX, prefix_len);
-	memcpy(full_name + prefix_len, name, name_len);
-	full_name[prefix_len + name_len] = '\0';
-
-	retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
-	kfree(full_name);
-	return retval;
+	return v9fs_xattr_set(dentry, full_name, value, size, flags);
 }
 
 struct xattr_handler v9fs_xattr_security_handler = {
diff --git a/fs/9p/xattr_trusted.c b/fs/9p/xattr_trusted.c
index e30d33b..ee470b6 100644
--- a/fs/9p/xattr_trusted.c
+++ b/fs/9p/xattr_trusted.c
@@ -22,10 +22,7 @@
 static int v9fs_xattr_trusted_get(struct dentry *dentry, const char *name,
 			void *buffer, size_t size, int type)
 {
-	int retval;
-	char *full_name;
-	size_t name_len;
-	size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
+	const char *full_name = name - XATTR_TRUSTED_PREFIX_LEN;
 
 	if (name == NULL)
 		return -EINVAL;
@@ -33,26 +30,13 @@ static int v9fs_xattr_trusted_get(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	name_len = strlen(name);
-	full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-	if (!full_name)
-		return -ENOMEM;
-	memcpy(full_name, XATTR_TRUSTED_PREFIX, prefix_len);
-	memcpy(full_name+prefix_len, name, name_len);
-	full_name[prefix_len + name_len] = '\0';
-
-	retval = v9fs_xattr_get(dentry, full_name, buffer, size);
-	kfree(full_name);
-	return retval;
+	return v9fs_xattr_get(dentry, full_name, buffer, size);
 }
 
 static int v9fs_xattr_trusted_set(struct dentry *dentry, const char *name,
 			const void *value, size_t size, int flags, int type)
 {
-	int retval;
-	char *full_name;
-	size_t name_len;
-	size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
+	const char *full_name = name - XATTR_TRUSTED_PREFIX_LEN;
 
 	if (name == NULL)
 		return -EINVAL;
@@ -60,17 +44,7 @@ static int v9fs_xattr_trusted_set(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	name_len = strlen(name);
-	full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-	if (!full_name)
-		return -ENOMEM;
-	memcpy(full_name, XATTR_TRUSTED_PREFIX, prefix_len);
-	memcpy(full_name + prefix_len, name, name_len);
-	full_name[prefix_len + name_len] = '\0';
-
-	retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
-	kfree(full_name);
-	return retval;
+	return v9fs_xattr_set(dentry, full_name, value, size, flags);
 }
 
 struct xattr_handler v9fs_xattr_trusted_handler = {
diff --git a/fs/9p/xattr_user.c b/fs/9p/xattr_user.c
index d0b701b..4432604 100644
--- a/fs/9p/xattr_user.c
+++ b/fs/9p/xattr_user.c
@@ -22,10 +22,7 @@
 static int v9fs_xattr_user_get(struct dentry *dentry, const char *name,
 			void *buffer, size_t size, int type)
 {
-	int retval;
-	char *full_name;
-	size_t name_len;
-	size_t prefix_len = XATTR_USER_PREFIX_LEN;
+	const char *full_name = name - XATTR_USER_PREFIX_LEN;
 
 	if (name == NULL)
 		return -EINVAL;
@@ -33,26 +30,13 @@ static int v9fs_xattr_user_get(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	name_len = strlen(name);
-	full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-	if (!full_name)
-		return -ENOMEM;
-	memcpy(full_name, XATTR_USER_PREFIX, prefix_len);
-	memcpy(full_name+prefix_len, name, name_len);
-	full_name[prefix_len + name_len] = '\0';
-
-	retval = v9fs_xattr_get(dentry, full_name, buffer, size);
-	kfree(full_name);
-	return retval;
+	return v9fs_xattr_get(dentry, full_name, buffer, size);
 }
 
 static int v9fs_xattr_user_set(struct dentry *dentry, const char *name,
 			const void *value, size_t size, int flags, int type)
 {
-	int retval;
-	char *full_name;
-	size_t name_len;
-	size_t prefix_len = XATTR_USER_PREFIX_LEN;
+	const char *full_name = name - XATTR_USER_PREFIX_LEN;
 
 	if (name == NULL)
 		return -EINVAL;
@@ -60,17 +44,7 @@ static int v9fs_xattr_user_set(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	name_len = strlen(name);
-	full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-	if (!full_name)
-		return -ENOMEM;
-	memcpy(full_name, XATTR_USER_PREFIX, prefix_len);
-	memcpy(full_name + prefix_len, name, name_len);
-	full_name[prefix_len + name_len] = '\0';
-
-	retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
-	kfree(full_name);
-	return retval;
+	return v9fs_xattr_set(dentry, full_name, value, size, flags);
 }
 
 struct xattr_handler v9fs_xattr_user_handler = {
-- 
2.4.3



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC 04/11] xattr handlers: Pass handler to operations instead of flags
  2015-08-20 18:19 ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  -1 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	linux-fsdevel, David Quigley, J. Bruce Fields
  Cc: linux-security-module, cluster-devel

The xattr_handler operations are currently all passed a file system specific
flags value which the operations can use to disambiguate between different
handlers; some file systems use that to distinguish the xattr namespace, for
example.  In some oprations, it would be useful to also have access to the
handler prefix.  To allow that, pass a pointer to the handler to operations
instead of the flags value alone.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/9p/acl.c                  | 12 +++++++-----
 fs/9p/xattr_security.c       |  6 ++++--
 fs/9p/xattr_trusted.c        |  6 ++++--
 fs/9p/xattr_user.c           |  6 ++++--
 fs/ext2/xattr.c              |  2 +-
 fs/ext2/xattr_security.c     |  9 ++++++---
 fs/ext2/xattr_trusted.c      |  9 ++++++---
 fs/ext2/xattr_user.c         |  9 ++++++---
 fs/ext3/xattr.c              |  2 +-
 fs/ext3/xattr_security.c     |  9 ++++++---
 fs/ext3/xattr_trusted.c      |  9 ++++++---
 fs/ext3/xattr_user.c         |  9 ++++++---
 fs/ext4/xattr.c              |  2 +-
 fs/ext4/xattr_security.c     |  9 ++++++---
 fs/ext4/xattr_trusted.c      |  9 ++++++---
 fs/ext4/xattr_user.c         |  9 ++++++---
 fs/f2fs/xattr.c              | 32 +++++++++++++++++++-------------
 fs/gfs2/xattr.c              |  9 ++++++---
 fs/hfsplus/xattr.c           |  6 ++++--
 fs/hfsplus/xattr_security.c  |  6 ++++--
 fs/hfsplus/xattr_trusted.c   |  6 ++++--
 fs/hfsplus/xattr_user.c      |  6 ++++--
 fs/jffs2/security.c          |  9 ++++++---
 fs/jffs2/xattr.c             |  4 ++--
 fs/jffs2/xattr_trusted.c     |  8 +++++---
 fs/jffs2/xattr_user.c        |  9 ++++++---
 fs/nfs/nfs4proc.c            | 18 ++++++++++++------
 fs/ocfs2/xattr.c             | 27 ++++++++++++++++++---------
 fs/posix_acl.c               | 17 ++++++++++-------
 fs/reiserfs/xattr.c          | 11 +++++------
 fs/reiserfs/xattr_security.c |  8 +++++---
 fs/reiserfs/xattr_trusted.c  |  8 +++++---
 fs/reiserfs/xattr_user.c     |  8 +++++---
 fs/squashfs/xattr.c          | 16 +++++++++-------
 fs/xattr.c                   | 10 +++++-----
 fs/xfs/xfs_xattr.c           |  8 ++++++--
 include/linux/xattr.h        |  9 +++++----
 37 files changed, 221 insertions(+), 131 deletions(-)

diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index 31c0103..a9e5d72 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -231,10 +231,12 @@ static int v9fs_remote_get_acl(struct dentry *dentry, const char *name,
 }
 
 static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
-			      void *buffer, size_t size, int type)
+			      void *buffer, size_t size,
+			      const struct xattr_handler *handler)
 {
 	struct v9fs_session_info *v9ses;
 	struct posix_acl *acl;
+	int type = handler->flags;
 	int error;
 
 	if (strcmp(name, "") != 0)
@@ -280,7 +282,7 @@ static int v9fs_remote_set_acl(struct dentry *dentry, const char *name,
 
 static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 			      const void *value, size_t size,
-			      int flags, int type)
+			      int flags, const struct xattr_handler *handler)
 {
 	int retval;
 	struct posix_acl *acl;
@@ -297,7 +299,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 	 */
 	if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
 		return v9fs_remote_set_acl(dentry, name,
-					   value, size, flags, type);
+					   value, size, flags, handler->flags);
 
 	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
@@ -316,7 +318,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 	} else
 		acl = NULL;
 
-	switch (type) {
+	switch (handler->flags) {
 	case ACL_TYPE_ACCESS:
 		name = POSIX_ACL_XATTR_ACCESS;
 		if (acl) {
@@ -360,7 +362,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 	}
 	retval = v9fs_xattr_set(dentry, name, value, size, flags);
 	if (!retval)
-		set_cached_acl(inode, type, acl);
+		set_cached_acl(inode, handler->flags, acl);
 err_out:
 	posix_acl_release(acl);
 	return retval;
diff --git a/fs/9p/xattr_security.c b/fs/9p/xattr_security.c
index 2c9b394..1d99c65 100644
--- a/fs/9p/xattr_security.c
+++ b/fs/9p/xattr_security.c
@@ -20,7 +20,8 @@
 #include "xattr.h"
 
 static int v9fs_xattr_security_get(struct dentry *dentry, const char *name,
-			void *buffer, size_t size, int type)
+			void *buffer, size_t size,
+			const struct xattr_handler *handler)
 {
 	const char *full_name = name - XATTR_SECURITY_PREFIX_LEN;
 
@@ -34,7 +35,8 @@ static int v9fs_xattr_security_get(struct dentry *dentry, const char *name,
 }
 
 static int v9fs_xattr_security_set(struct dentry *dentry, const char *name,
-			const void *value, size_t size, int flags, int type)
+			const void *value, size_t size, int flags,
+			const struct xattr_handler *handler)
 {
 	const char *full_name = name - XATTR_SECURITY_PREFIX_LEN;
 
diff --git a/fs/9p/xattr_trusted.c b/fs/9p/xattr_trusted.c
index ee470b6..1a24647 100644
--- a/fs/9p/xattr_trusted.c
+++ b/fs/9p/xattr_trusted.c
@@ -20,7 +20,8 @@
 #include "xattr.h"
 
 static int v9fs_xattr_trusted_get(struct dentry *dentry, const char *name,
-			void *buffer, size_t size, int type)
+			void *buffer, size_t size,
+			const struct xattr_handler *handler)
 {
 	const char *full_name = name - XATTR_TRUSTED_PREFIX_LEN;
 
@@ -34,7 +35,8 @@ static int v9fs_xattr_trusted_get(struct dentry *dentry, const char *name,
 }
 
 static int v9fs_xattr_trusted_set(struct dentry *dentry, const char *name,
-			const void *value, size_t size, int flags, int type)
+			const void *value, size_t size, int flags,
+			const struct xattr_handler *handler)
 {
 	const char *full_name = name - XATTR_TRUSTED_PREFIX_LEN;
 
diff --git a/fs/9p/xattr_user.c b/fs/9p/xattr_user.c
index 4432604..2c35e16 100644
--- a/fs/9p/xattr_user.c
+++ b/fs/9p/xattr_user.c
@@ -20,7 +20,8 @@
 #include "xattr.h"
 
 static int v9fs_xattr_user_get(struct dentry *dentry, const char *name,
-			void *buffer, size_t size, int type)
+			void *buffer, size_t size,
+			const struct xattr_handler *handler)
 {
 	const char *full_name = name - XATTR_USER_PREFIX_LEN;
 
@@ -34,7 +35,8 @@ static int v9fs_xattr_user_get(struct dentry *dentry, const char *name,
 }
 
 static int v9fs_xattr_user_set(struct dentry *dentry, const char *name,
-			const void *value, size_t size, int flags, int type)
+			const void *value, size_t size, int flags,
+			const struct xattr_handler *handler)
 {
 	const char *full_name = name - XATTR_USER_PREFIX_LEN;
 
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index 0b6bfd3..f786688 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -296,7 +296,7 @@ bad_block:	ext2_error(inode->i_sb, "ext2_xattr_list",
 			size_t size = handler->list(dentry, buffer, rest,
 						    entry->e_name,
 						    entry->e_name_len,
-						    handler->flags);
+						    handler);
 			if (buffer) {
 				if (size > rest) {
 					error = -ERANGE;
diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c
index 702fc68..ed9f7a32 100644
--- a/fs/ext2/xattr_security.c
+++ b/fs/ext2/xattr_security.c
@@ -9,7 +9,8 @@
 
 static size_t
 ext2_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
-			 const char *name, size_t name_len, int type)
+			 const char *name, size_t name_len,
+			 const struct xattr_handler *handler)
 {
 	const int prefix_len = XATTR_SECURITY_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -24,7 +25,8 @@ ext2_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext2_xattr_security_get(struct dentry *dentry, const char *name,
-		       void *buffer, size_t size, int type)
+		       void *buffer, size_t size,
+		       const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -34,7 +36,8 @@ ext2_xattr_security_get(struct dentry *dentry, const char *name,
 
 static int
 ext2_xattr_security_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c
index 42b6e98..991676b 100644
--- a/fs/ext2/xattr_trusted.c
+++ b/fs/ext2/xattr_trusted.c
@@ -10,7 +10,8 @@
 
 static size_t
 ext2_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
-		const char *name, size_t name_len, int type)
+		const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	const int prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -28,7 +29,8 @@ ext2_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext2_xattr_trusted_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -38,7 +40,8 @@ ext2_xattr_trusted_get(struct dentry *dentry, const char *name,
 
 static int
 ext2_xattr_trusted_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c
index ecdc460..b8f7c02 100644
--- a/fs/ext2/xattr_user.c
+++ b/fs/ext2/xattr_user.c
@@ -12,7 +12,8 @@
 
 static size_t
 ext2_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
-		const char *name, size_t name_len, int type)
+		const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -30,7 +31,8 @@ ext2_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext2_xattr_user_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -42,7 +44,8 @@ ext2_xattr_user_get(struct dentry *dentry, const char *name,
 
 static int
 ext2_xattr_user_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 7cf3650..4c35ac4 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -340,7 +340,7 @@ ext3_xattr_list_entries(struct dentry *dentry, struct ext3_xattr_entry *entry,
 			size_t size = handler->list(dentry, buffer, rest,
 						    entry->e_name,
 						    entry->e_name_len,
-						    handler->flags);
+						    handler);
 			if (buffer) {
 				if (size > rest)
 					return -ERANGE;
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index c9506d5..c26ebe0 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -9,7 +9,8 @@
 
 static size_t
 ext3_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
-			 const char *name, size_t name_len, int type)
+			 const char *name, size_t name_len,
+			 const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -25,7 +26,8 @@ ext3_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext3_xattr_security_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -35,7 +37,8 @@ ext3_xattr_security_get(struct dentry *dentry, const char *name,
 
 static int
 ext3_xattr_security_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c
index 206cc66..ba3ea56 100644
--- a/fs/ext3/xattr_trusted.c
+++ b/fs/ext3/xattr_trusted.c
@@ -10,7 +10,8 @@
 
 static size_t
 ext3_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
-		const char *name, size_t name_len, int type)
+		const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -28,7 +29,8 @@ ext3_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext3_xattr_trusted_get(struct dentry *dentry, const char *name,
-		       void *buffer, size_t size, int type)
+		       void *buffer, size_t size,
+		       const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -38,7 +40,8 @@ ext3_xattr_trusted_get(struct dentry *dentry, const char *name,
 
 static int
 ext3_xattr_trusted_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
index 021508a..9a5ff25 100644
--- a/fs/ext3/xattr_user.c
+++ b/fs/ext3/xattr_user.c
@@ -10,7 +10,8 @@
 
 static size_t
 ext3_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
-		const char *name, size_t name_len, int type)
+		const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -28,7 +29,8 @@ ext3_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext3_xattr_user_get(struct dentry *dentry, const char *name, void *buffer,
-		size_t size, int type)
+		size_t size,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -40,7 +42,8 @@ ext3_xattr_user_get(struct dentry *dentry, const char *name, void *buffer,
 
 static int
 ext3_xattr_user_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 16e28c0..f5158d9 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -408,7 +408,7 @@ ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
 			size_t size = handler->list(dentry, buffer, rest,
 						    entry->e_name,
 						    entry->e_name_len,
-						    handler->flags);
+						    handler);
 			if (buffer) {
 				if (size > rest)
 					return -ERANGE;
diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c
index 95d90e0..5e5b4e0 100644
--- a/fs/ext4/xattr_security.c
+++ b/fs/ext4/xattr_security.c
@@ -13,7 +13,8 @@
 
 static size_t
 ext4_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
-		const char *name, size_t name_len, int type)
+		const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	const size_t prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -29,7 +30,8 @@ ext4_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext4_xattr_security_get(struct dentry *dentry, const char *name,
-		       void *buffer, size_t size, int type)
+		       void *buffer, size_t size,
+		       const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -39,7 +41,8 @@ ext4_xattr_security_get(struct dentry *dentry, const char *name,
 
 static int
 ext4_xattr_security_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c
index 891ee2d..b298d01 100644
--- a/fs/ext4/xattr_trusted.c
+++ b/fs/ext4/xattr_trusted.c
@@ -14,7 +14,8 @@
 
 static size_t
 ext4_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
-		const char *name, size_t name_len, int type)
+		const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -32,7 +33,8 @@ ext4_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext4_xattr_trusted_get(struct dentry *dentry, const char *name, void *buffer,
-		size_t size, int type)
+		size_t size,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -42,7 +44,8 @@ ext4_xattr_trusted_get(struct dentry *dentry, const char *name, void *buffer,
 
 static int
 ext4_xattr_trusted_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c
index 6ed932b..62085d1 100644
--- a/fs/ext4/xattr_user.c
+++ b/fs/ext4/xattr_user.c
@@ -13,7 +13,8 @@
 
 static size_t
 ext4_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
-		     const char *name, size_t name_len, int type)
+		     const char *name, size_t name_len,
+		     const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -31,7 +32,8 @@ ext4_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext4_xattr_user_get(struct dentry *dentry, const char *name,
-		    void *buffer, size_t size, int type)
+		    void *buffer, size_t size,
+		    const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -43,7 +45,8 @@ ext4_xattr_user_get(struct dentry *dentry, const char *name,
 
 static int
 ext4_xattr_user_set(struct dentry *dentry, const char *name,
-		    const void *value, size_t size, int flags, int type)
+		    const void *value, size_t size, int flags,
+		    const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 07449b98..fdc9849 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -26,13 +26,14 @@
 #include "xattr.h"
 
 static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t len, int type)
+		size_t list_size, const char *name, size_t len,
+		const struct xattr_handler *handler)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
 	int total_len, prefix_len = 0;
 	const char *prefix = NULL;
 
-	switch (type) {
+	switch (handler->flags) {
 	case F2FS_XATTR_INDEX_USER:
 		if (!test_opt(sbi, XATTR_USER))
 			return -EOPNOTSUPP;
@@ -63,11 +64,11 @@ static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
 }
 
 static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size, const struct xattr_handler *handler)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
 
-	switch (type) {
+	switch (handler->flags) {
 	case F2FS_XATTR_INDEX_USER:
 		if (!test_opt(sbi, XATTR_USER))
 			return -EOPNOTSUPP;
@@ -83,15 +84,17 @@ static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
 	}
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return f2fs_getxattr(d_inode(dentry), type, name, buffer, size, NULL);
+	return f2fs_getxattr(d_inode(dentry), handler->flags, name,
+			     buffer, size, NULL);
 }
 
 static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
 
-	switch (type) {
+	switch (handler->flags) {
 	case F2FS_XATTR_INDEX_USER:
 		if (!test_opt(sbi, XATTR_USER))
 			return -EOPNOTSUPP;
@@ -108,17 +111,18 @@ static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	return f2fs_setxattr(d_inode(dentry), type, name,
+	return f2fs_setxattr(d_inode(dentry), handler->flags, name,
 					value, size, NULL, flags);
 }
 
 static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t len, int type)
+		size_t list_size, const char *name, size_t len,
+		const struct xattr_handler *handler)
 {
 	const char *xname = F2FS_SYSTEM_ADVISE_PREFIX;
 	size_t size;
 
-	if (type != F2FS_XATTR_INDEX_ADVISE)
+	if (handler->flags != F2FS_XATTR_INDEX_ADVISE)
 		return 0;
 
 	size = strlen(xname) + 1;
@@ -128,7 +132,8 @@ static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
 }
 
 static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	struct inode *inode = d_inode(dentry);
 
@@ -141,7 +146,8 @@ static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
 }
 
 static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	struct inode *inode = d_inode(dentry);
 
@@ -463,7 +469,7 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 			continue;
 
 		size = handler->list(dentry, buffer, rest, entry->e_name,
-				entry->e_name_len, handler->flags);
+				entry->e_name_len, handler);
 		if (buffer && size > rest) {
 			error = -ERANGE;
 			goto cleanup;
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index 4c096fa..3979c608 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -584,10 +584,12 @@ out:
  * Returns: actual size of data on success, -errno on error
  */
 static int gfs2_xattr_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	struct gfs2_inode *ip = GFS2_I(d_inode(dentry));
 	struct gfs2_ea_location el;
+	int type = handler->flags;
 	int error;
 
 	if (!ip->i_eattr)
@@ -1228,10 +1230,11 @@ int __gfs2_xattr_set(struct inode *inode, const char *name,
 }
 
 static int gfs2_xattr_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	return __gfs2_xattr_set(d_inode(dentry), name, value,
-				size, flags, type);
+				size, flags, handler->flags);
 }
 
 
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
index e898499..65914db 100644
--- a/fs/hfsplus/xattr.c
+++ b/fs/hfsplus/xattr.c
@@ -850,7 +850,8 @@ end_removexattr:
 }
 
 static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
-					void *buffer, size_t size, int type)
+					void *buffer, size_t size,
+					const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
@@ -872,7 +873,8 @@ static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
 }
 
 static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
-		const void *buffer, size_t size, int flags, int type)
+		const void *buffer, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c
index 024e61c..3601ecc 100644
--- a/fs/hfsplus/xattr_security.c
+++ b/fs/hfsplus/xattr_security.c
@@ -14,7 +14,8 @@
 #include "acl.h"
 
 static int hfsplus_security_getxattr(struct dentry *dentry, const char *name,
-					void *buffer, size_t size, int type)
+					void *buffer, size_t size,
+					const struct xattr_handler *handler)
 {
 	return hfsplus_getxattr(dentry, name, buffer, size,
 				XATTR_SECURITY_PREFIX,
@@ -22,7 +23,8 @@ static int hfsplus_security_getxattr(struct dentry *dentry, const char *name,
 }
 
 static int hfsplus_security_setxattr(struct dentry *dentry, const char *name,
-		const void *buffer, size_t size, int flags, int type)
+		const void *buffer, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	return hfsplus_setxattr(dentry, name, buffer, size, flags,
 				XATTR_SECURITY_PREFIX,
diff --git a/fs/hfsplus/xattr_trusted.c b/fs/hfsplus/xattr_trusted.c
index 6186157..123cd8e 100644
--- a/fs/hfsplus/xattr_trusted.c
+++ b/fs/hfsplus/xattr_trusted.c
@@ -12,7 +12,8 @@
 #include "xattr.h"
 
 static int hfsplus_trusted_getxattr(struct dentry *dentry, const char *name,
-					void *buffer, size_t size, int type)
+					void *buffer, size_t size,
+					const struct xattr_handler *handler)
 {
 	return hfsplus_getxattr(dentry, name, buffer, size,
 				XATTR_TRUSTED_PREFIX,
@@ -20,7 +21,8 @@ static int hfsplus_trusted_getxattr(struct dentry *dentry, const char *name,
 }
 
 static int hfsplus_trusted_setxattr(struct dentry *dentry, const char *name,
-		const void *buffer, size_t size, int flags, int type)
+		const void *buffer, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	return hfsplus_setxattr(dentry, name, buffer, size, flags,
 				XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
diff --git a/fs/hfsplus/xattr_user.c b/fs/hfsplus/xattr_user.c
index 3b4caba..2272557 100644
--- a/fs/hfsplus/xattr_user.c
+++ b/fs/hfsplus/xattr_user.c
@@ -12,7 +12,8 @@
 #include "xattr.h"
 
 static int hfsplus_user_getxattr(struct dentry *dentry, const char *name,
-					void *buffer, size_t size, int type)
+					void *buffer, size_t size,
+					const struct xattr_handler *handler)
 {
 
 	return hfsplus_getxattr(dentry, name, buffer, size,
@@ -20,7 +21,8 @@ static int hfsplus_user_getxattr(struct dentry *dentry, const char *name,
 }
 
 static int hfsplus_user_setxattr(struct dentry *dentry, const char *name,
-		const void *buffer, size_t size, int flags, int type)
+		const void *buffer, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	return hfsplus_setxattr(dentry, name, buffer, size, flags,
 				XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
index d4b43fb..8f609e8 100644
--- a/fs/jffs2/security.c
+++ b/fs/jffs2/security.c
@@ -49,7 +49,8 @@ int jffs2_init_security(struct inode *inode, struct inode *dir,
 
 /* ---- XATTR Handler for "security.*" ----------------- */
 static int jffs2_security_getxattr(struct dentry *dentry, const char *name,
-				   void *buffer, size_t size, int type)
+				   void *buffer, size_t size,
+				   const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
@@ -59,7 +60,8 @@ static int jffs2_security_getxattr(struct dentry *dentry, const char *name,
 }
 
 static int jffs2_security_setxattr(struct dentry *dentry, const char *name,
-		const void *buffer, size_t size, int flags, int type)
+		const void *buffer, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
@@ -69,7 +71,8 @@ static int jffs2_security_setxattr(struct dentry *dentry, const char *name,
 }
 
 static size_t jffs2_security_listxattr(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t name_len, int type)
+		size_t list_size, const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1;
 
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index f092fee..8b2305c 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -1002,10 +1002,10 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
 			continue;
 		if (buffer) {
 			rc = xhandle->list(dentry, buffer+len, size-len,
-					   xd->xname, xd->name_len, xd->flags);
+					   xd->xname, xd->name_len, xhandle);
 		} else {
 			rc = xhandle->list(dentry, NULL, 0, xd->xname,
-					   xd->name_len, xd->flags);
+					   xd->name_len, xhandle);
 		}
 		if (rc < 0)
 			goto out;
diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c
index ceaf9c6..afa0e4d 100644
--- a/fs/jffs2/xattr_trusted.c
+++ b/fs/jffs2/xattr_trusted.c
@@ -17,7 +17,7 @@
 #include "nodelist.h"
 
 static int jffs2_trusted_getxattr(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size, const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
@@ -26,7 +26,8 @@ static int jffs2_trusted_getxattr(struct dentry *dentry, const char *name,
 }
 
 static int jffs2_trusted_setxattr(struct dentry *dentry, const char *name,
-		const void *buffer, size_t size, int flags, int type)
+		const void *buffer, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
@@ -35,7 +36,8 @@ static int jffs2_trusted_setxattr(struct dentry *dentry, const char *name,
 }
 
 static size_t jffs2_trusted_listxattr(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t name_len, int type)
+		size_t list_size, const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1;
 
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
index a71391e..4c45567 100644
--- a/fs/jffs2/xattr_user.c
+++ b/fs/jffs2/xattr_user.c
@@ -17,7 +17,8 @@
 #include "nodelist.h"
 
 static int jffs2_user_getxattr(struct dentry *dentry, const char *name,
-			       void *buffer, size_t size, int type)
+			       void *buffer, size_t size,
+			       const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
@@ -26,7 +27,8 @@ static int jffs2_user_getxattr(struct dentry *dentry, const char *name,
 }
 
 static int jffs2_user_setxattr(struct dentry *dentry, const char *name,
-		const void *buffer, size_t size, int flags, int type)
+		const void *buffer, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
@@ -35,7 +37,8 @@ static int jffs2_user_setxattr(struct dentry *dentry, const char *name,
 }
 
 static size_t jffs2_user_listxattr(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t name_len, int type)
+		size_t list_size, const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1;
 
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 3acb1eb..977165e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6203,7 +6203,8 @@ nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
 
 static int nfs4_xattr_set_nfs4_acl(struct dentry *dentry, const char *key,
 				   const void *buf, size_t buflen,
-				   int flags, int type)
+				   int flags,
+				   const struct xattr_handler *handler)
 {
 	if (strcmp(key, "") != 0)
 		return -EINVAL;
@@ -6212,7 +6213,8 @@ static int nfs4_xattr_set_nfs4_acl(struct dentry *dentry, const char *key,
 }
 
 static int nfs4_xattr_get_nfs4_acl(struct dentry *dentry, const char *key,
-				   void *buf, size_t buflen, int type)
+				   void *buf, size_t buflen,
+				   const struct xattr_handler *handler)
 {
 	if (strcmp(key, "") != 0)
 		return -EINVAL;
@@ -6222,7 +6224,8 @@ static int nfs4_xattr_get_nfs4_acl(struct dentry *dentry, const char *key,
 
 static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list,
 				       size_t list_len, const char *name,
-				       size_t name_len, int type)
+				       size_t name_len,
+				       const struct xattr_handler *handler)
 {
 	size_t len = sizeof(XATTR_NAME_NFSV4_ACL);
 
@@ -6242,7 +6245,8 @@ static inline int nfs4_server_supports_labels(struct nfs_server *server)
 
 static int nfs4_xattr_set_nfs4_label(struct dentry *dentry, const char *key,
 				   const void *buf, size_t buflen,
-				   int flags, int type)
+				   int flags,
+				   const struct xattr_handler *handler)
 {
 	if (security_ismaclabel(key))
 		return nfs4_set_security_label(dentry, buf, buflen);
@@ -6251,7 +6255,8 @@ static int nfs4_xattr_set_nfs4_label(struct dentry *dentry, const char *key,
 }
 
 static int nfs4_xattr_get_nfs4_label(struct dentry *dentry, const char *key,
-				   void *buf, size_t buflen, int type)
+				   void *buf, size_t buflen,
+				   const struct xattr_handler *handler)
 {
 	if (security_ismaclabel(key))
 		return nfs4_get_security_label(d_inode(dentry), buf, buflen);
@@ -6260,7 +6265,8 @@ static int nfs4_xattr_get_nfs4_label(struct dentry *dentry, const char *key,
 
 static size_t nfs4_xattr_list_nfs4_label(struct dentry *dentry, char *list,
 				       size_t list_len, const char *name,
-				       size_t name_len, int type)
+				       size_t name_len,
+				       const struct xattr_handler *handler)
 {
 	size_t len = 0;
 
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 889f379..f5ce434 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -7239,7 +7239,8 @@ leave:
  */
 static size_t ocfs2_xattr_security_list(struct dentry *dentry, char *list,
 					size_t list_size, const char *name,
-					size_t name_len, int type)
+					size_t name_len,
+					const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -7253,7 +7254,8 @@ static size_t ocfs2_xattr_security_list(struct dentry *dentry, char *list,
 }
 
 static int ocfs2_xattr_security_get(struct dentry *dentry, const char *name,
-				    void *buffer, size_t size, int type)
+				    void *buffer, size_t size,
+				    const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -7262,7 +7264,8 @@ static int ocfs2_xattr_security_get(struct dentry *dentry, const char *name,
 }
 
 static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -7329,7 +7332,8 @@ const struct xattr_handler ocfs2_xattr_security_handler = {
  */
 static size_t ocfs2_xattr_trusted_list(struct dentry *dentry, char *list,
 				       size_t list_size, const char *name,
-				       size_t name_len, int type)
+				       size_t name_len,
+				       const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -7343,7 +7347,8 @@ static size_t ocfs2_xattr_trusted_list(struct dentry *dentry, char *list,
 }
 
 static int ocfs2_xattr_trusted_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -7352,7 +7357,8 @@ static int ocfs2_xattr_trusted_get(struct dentry *dentry, const char *name,
 }
 
 static int ocfs2_xattr_trusted_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -7373,7 +7379,8 @@ const struct xattr_handler ocfs2_xattr_trusted_handler = {
  */
 static size_t ocfs2_xattr_user_list(struct dentry *dentry, char *list,
 				    size_t list_size, const char *name,
-				    size_t name_len, int type)
+				    size_t name_len,
+				    const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -7391,7 +7398,8 @@ static size_t ocfs2_xattr_user_list(struct dentry *dentry, char *list,
 }
 
 static int ocfs2_xattr_user_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
@@ -7404,7 +7412,8 @@ static int ocfs2_xattr_user_get(struct dentry *dentry, const char *name,
 }
 
 static int ocfs2_xattr_user_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 4fb17de..1c7e94f 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -763,7 +763,8 @@ EXPORT_SYMBOL (posix_acl_to_xattr);
 
 static int
 posix_acl_xattr_get(struct dentry *dentry, const char *name,
-		void *value, size_t size, int type)
+		void *value, size_t size,
+		const struct xattr_handler *handler)
 {
 	struct posix_acl *acl;
 	int error;
@@ -773,7 +774,7 @@ posix_acl_xattr_get(struct dentry *dentry, const char *name,
 	if (d_is_symlink(dentry))
 		return -EOPNOTSUPP;
 
-	acl = get_acl(d_backing_inode(dentry), type);
+	acl = get_acl(d_backing_inode(dentry), handler->flags);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl == NULL)
@@ -787,7 +788,8 @@ posix_acl_xattr_get(struct dentry *dentry, const char *name,
 
 static int
 posix_acl_xattr_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	struct inode *inode = d_backing_inode(dentry);
 	struct posix_acl *acl = NULL;
@@ -798,7 +800,7 @@ posix_acl_xattr_set(struct dentry *dentry, const char *name,
 	if (!inode->i_op->set_acl)
 		return -EOPNOTSUPP;
 
-	if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
+	if (handler->flags == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
 		return value ? -EACCES : 0;
 	if (!inode_owner_or_capable(inode))
 		return -EPERM;
@@ -815,7 +817,7 @@ posix_acl_xattr_set(struct dentry *dentry, const char *name,
 		}
 	}
 
-	ret = inode->i_op->set_acl(inode, acl, type);
+	ret = inode->i_op->set_acl(inode, acl, handler->flags);
 out:
 	posix_acl_release(acl);
 	return ret;
@@ -823,7 +825,8 @@ out:
 
 static size_t
 posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
-		const char *name, size_t name_len, int type)
+		const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	const char *xname;
 	size_t size;
@@ -833,7 +836,7 @@ posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
 	if (d_is_symlink(dentry))
 		return -EOPNOTSUPP;
 
-	if (type == ACL_TYPE_ACCESS)
+	if (handler->flags == ACL_TYPE_ACCESS)
 		xname = POSIX_ACL_XATTR_ACCESS;
 	else
 		xname = POSIX_ACL_XATTR_DEFAULT;
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index e87f9b5..ad6e4bb 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -778,7 +778,7 @@ reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
 	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->get(dentry, name, buffer, size, handler->flags);
+	return handler->get(dentry, name, buffer, size, handler);
 }
 
 /*
@@ -797,7 +797,7 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->set(dentry, name, value, size, flags, handler->flags);
+	return handler->set(dentry, name, value, size, flags, handler);
 }
 
 /*
@@ -814,7 +814,7 @@ int reiserfs_removexattr(struct dentry *dentry, const char *name)
 	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->set(dentry, name, NULL, 0, XATTR_REPLACE, handler->flags);
+	return handler->set(dentry, name, NULL, 0, XATTR_REPLACE, handler);
 }
 
 struct listxattr_buf {
@@ -843,13 +843,12 @@ static int listxattr_filler(struct dir_context *ctx, const char *name,
 			return 0;
 		if (b->buf) {
 			size = handler->list(b->dentry, b->buf + b->pos,
-					 b->size, name, namelen,
-					 handler->flags);
+					 b->size, name, namelen, handler);
 			if (size > b->size)
 				return -ERANGE;
 		} else {
 			size = handler->list(b->dentry, NULL, 0, name,
-					     namelen, handler->flags);
+					     namelen, handler);
 		}
 
 		b->pos += size;
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index 9a3b061..08074f5 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -10,7 +10,7 @@
 
 static int
 security_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
-		int handler_flags)
+	     const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
 		return -EINVAL;
@@ -23,7 +23,8 @@ security_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
 
 static int
 security_set(struct dentry *dentry, const char *name, const void *buffer,
-	     size_t size, int flags, int handler_flags)
+	     size_t size, int flags,
+	     const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
 		return -EINVAL;
@@ -35,7 +36,8 @@ security_set(struct dentry *dentry, const char *name, const void *buffer,
 }
 
 static size_t security_list(struct dentry *dentry, char *list, size_t list_len,
-			    const char *name, size_t namelen, int handler_flags)
+			    const char *name, size_t namelen,
+			    const struct xattr_handler *handler)
 {
 	const size_t len = namelen + 1;
 
diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c
index e4f1343..e3ab346 100644
--- a/fs/reiserfs/xattr_trusted.c
+++ b/fs/reiserfs/xattr_trusted.c
@@ -9,7 +9,7 @@
 
 static int
 trusted_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
-	    int handler_flags)
+	    const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
 		return -EINVAL;
@@ -22,7 +22,8 @@ trusted_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
 
 static int
 trusted_set(struct dentry *dentry, const char *name, const void *buffer,
-	    size_t size, int flags, int handler_flags)
+	    size_t size, int flags,
+	    const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
 		return -EINVAL;
@@ -34,7 +35,8 @@ trusted_set(struct dentry *dentry, const char *name, const void *buffer,
 }
 
 static size_t trusted_list(struct dentry *dentry, char *list, size_t list_size,
-			   const char *name, size_t name_len, int handler_flags)
+			   const char *name, size_t name_len,
+			   const struct xattr_handler *handler)
 {
 	const size_t len = name_len + 1;
 
diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c
index d0b08d3..2c8d466 100644
--- a/fs/reiserfs/xattr_user.c
+++ b/fs/reiserfs/xattr_user.c
@@ -8,7 +8,7 @@
 
 static int
 user_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
-	 int handler_flags)
+	 const struct xattr_handler *handler)
 {
 
 	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
@@ -20,7 +20,8 @@ user_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
 
 static int
 user_set(struct dentry *dentry, const char *name, const void *buffer,
-	 size_t size, int flags, int handler_flags)
+	 size_t size, int flags,
+	 const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
 		return -EINVAL;
@@ -31,7 +32,8 @@ user_set(struct dentry *dentry, const char *name, const void *buffer,
 }
 
 static size_t user_list(struct dentry *dentry, char *list, size_t list_size,
-			const char *name, size_t name_len, int handler_flags)
+			const char *name, size_t name_len,
+			const struct xattr_handler *handler)
 {
 	const size_t len = name_len + 1;
 
diff --git a/fs/squashfs/xattr.c b/fs/squashfs/xattr.c
index e5e0ddf..05ef4b9 100644
--- a/fs/squashfs/xattr.c
+++ b/fs/squashfs/xattr.c
@@ -69,7 +69,7 @@ ssize_t squashfs_listxattr(struct dentry *d, char *buffer,
 		handler = squashfs_xattr_handler(le16_to_cpu(entry.type));
 		if (handler)
 			prefix_size = handler->list(d, buffer, rest, NULL,
-				name_size, handler->flags);
+				name_size, handler);
 		if (prefix_size) {
 			if (buffer) {
 				if (prefix_size + name_size + 1 > rest) {
@@ -216,7 +216,7 @@ failed:
  * User namespace support
  */
 static size_t squashfs_user_list(struct dentry *d, char *list, size_t list_size,
-	const char *name, size_t name_len, int type)
+	const char *name, size_t name_len, const struct xattr_handler *handler)
 {
 	if (list && XATTR_USER_PREFIX_LEN <= list_size)
 		memcpy(list, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
@@ -224,7 +224,7 @@ static size_t squashfs_user_list(struct dentry *d, char *list, size_t list_size,
 }
 
 static int squashfs_user_get(struct dentry *d, const char *name, void *buffer,
-	size_t size, int type)
+	size_t size, const struct xattr_handler *handler)
 {
 	if (name[0] == '\0')
 		return  -EINVAL;
@@ -243,7 +243,8 @@ static const struct xattr_handler squashfs_xattr_user_handler = {
  * Trusted namespace support
  */
 static size_t squashfs_trusted_list(struct dentry *d, char *list,
-	size_t list_size, const char *name, size_t name_len, int type)
+	size_t list_size, const char *name, size_t name_len,
+	const struct xattr_handler *handler)
 {
 	if (!capable(CAP_SYS_ADMIN))
 		return 0;
@@ -254,7 +255,7 @@ static size_t squashfs_trusted_list(struct dentry *d, char *list,
 }
 
 static int squashfs_trusted_get(struct dentry *d, const char *name,
-	void *buffer, size_t size, int type)
+	void *buffer, size_t size, const struct xattr_handler *handler)
 {
 	if (name[0] == '\0')
 		return  -EINVAL;
@@ -273,7 +274,8 @@ static const struct xattr_handler squashfs_xattr_trusted_handler = {
  * Security namespace support
  */
 static size_t squashfs_security_list(struct dentry *d, char *list,
-	size_t list_size, const char *name, size_t name_len, int type)
+	size_t list_size, const char *name, size_t name_len,
+	const struct xattr_handler *handler)
 {
 	if (list && XATTR_SECURITY_PREFIX_LEN <= list_size)
 		memcpy(list, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN);
@@ -281,7 +283,7 @@ static size_t squashfs_security_list(struct dentry *d, char *list,
 }
 
 static int squashfs_security_get(struct dentry *d, const char *name,
-	void *buffer, size_t size, int type)
+	void *buffer, size_t size, const struct xattr_handler *handler)
 {
 	if (name[0] == '\0')
 		return  -EINVAL;
diff --git a/fs/xattr.c b/fs/xattr.c
index 072fee1..efa16ce 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -720,7 +720,7 @@ generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t s
 	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->get(dentry, name, buffer, size, handler->flags);
+	return handler->get(dentry, name, buffer, size, handler);
 }
 
 /*
@@ -736,14 +736,14 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 	if (!buffer) {
 		for_each_xattr_handler(handlers, handler) {
 			size += handler->list(dentry, NULL, 0, NULL, 0,
-					      handler->flags);
+					      handler);
 		}
 	} else {
 		char *buf = buffer;
 
 		for_each_xattr_handler(handlers, handler) {
 			size = handler->list(dentry, buf, buffer_size,
-					     NULL, 0, handler->flags);
+					     NULL, 0, handler);
 			if (size > buffer_size)
 				return -ERANGE;
 			buf += size;
@@ -767,7 +767,7 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz
 	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->set(dentry, name, value, size, flags, handler->flags);
+	return handler->set(dentry, name, value, size, flags, handler);
 }
 
 /*
@@ -783,7 +783,7 @@ generic_removexattr(struct dentry *dentry, const char *name)
 	if (!handler)
 		return -EOPNOTSUPP;
 	return handler->set(dentry, name, NULL, 0,
-			    XATTR_REPLACE, handler->flags);
+			    XATTR_REPLACE, handler);
 }
 
 EXPORT_SYMBOL(generic_getxattr);
diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c
index c0368151..9dace13 100644
--- a/fs/xfs/xfs_xattr.c
+++ b/fs/xfs/xfs_xattr.c
@@ -33,8 +33,10 @@
 
 static int
 xfs_xattr_get(struct dentry *dentry, const char *name,
-		void *value, size_t size, int xflags)
+		void *value, size_t size,
+		const struct xattr_handler *handler)
 {
+	int xflags = handler->flags;
 	struct xfs_inode *ip = XFS_I(d_inode(dentry));
 	int error, asize = size;
 
@@ -55,8 +57,10 @@ xfs_xattr_get(struct dentry *dentry, const char *name,
 
 static int
 xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
-		size_t size, int flags, int xflags)
+		size_t size, int flags,
+		const struct xattr_handler *handler)
 {
+	int xflags = handler->flags;
 	struct xfs_inode *ip = XFS_I(d_inode(dentry));
 
 	if (strcmp(name, "") == 0)
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 91b0a68..8fd287d 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -21,13 +21,14 @@ struct dentry;
 
 struct xattr_handler {
 	const char *prefix;
-	int flags;	/* fs private flags passed back to the handlers */
+	int flags;      /* fs private flags */
 	size_t (*list)(struct dentry *dentry, char *list, size_t list_size,
-		       const char *name, size_t name_len, int handler_flags);
+		       const char *name, size_t name_len,
+		       const struct xattr_handler *);
 	int (*get)(struct dentry *dentry, const char *name, void *buffer,
-		   size_t size, int handler_flags);
+		   size_t size, const struct xattr_handler *);
 	int (*set)(struct dentry *dentry, const char *name, const void *buffer,
-		   size_t size, int flags, int handler_flags);
+		   size_t size, int flags, const struct xattr_handler *);
 };
 
 struct xattr {
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 04/11] xattr handlers: Pass handler to operations instead of flags
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

The xattr_handler operations are currently all passed a file system specific
flags value which the operations can use to disambiguate between different
handlers; some file systems use that to distinguish the xattr namespace, for
example.  In some oprations, it would be useful to also have access to the
handler prefix.  To allow that, pass a pointer to the handler to operations
instead of the flags value alone.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/9p/acl.c                  | 12 +++++++-----
 fs/9p/xattr_security.c       |  6 ++++--
 fs/9p/xattr_trusted.c        |  6 ++++--
 fs/9p/xattr_user.c           |  6 ++++--
 fs/ext2/xattr.c              |  2 +-
 fs/ext2/xattr_security.c     |  9 ++++++---
 fs/ext2/xattr_trusted.c      |  9 ++++++---
 fs/ext2/xattr_user.c         |  9 ++++++---
 fs/ext3/xattr.c              |  2 +-
 fs/ext3/xattr_security.c     |  9 ++++++---
 fs/ext3/xattr_trusted.c      |  9 ++++++---
 fs/ext3/xattr_user.c         |  9 ++++++---
 fs/ext4/xattr.c              |  2 +-
 fs/ext4/xattr_security.c     |  9 ++++++---
 fs/ext4/xattr_trusted.c      |  9 ++++++---
 fs/ext4/xattr_user.c         |  9 ++++++---
 fs/f2fs/xattr.c              | 32 +++++++++++++++++++-------------
 fs/gfs2/xattr.c              |  9 ++++++---
 fs/hfsplus/xattr.c           |  6 ++++--
 fs/hfsplus/xattr_security.c  |  6 ++++--
 fs/hfsplus/xattr_trusted.c   |  6 ++++--
 fs/hfsplus/xattr_user.c      |  6 ++++--
 fs/jffs2/security.c          |  9 ++++++---
 fs/jffs2/xattr.c             |  4 ++--
 fs/jffs2/xattr_trusted.c     |  8 +++++---
 fs/jffs2/xattr_user.c        |  9 ++++++---
 fs/nfs/nfs4proc.c            | 18 ++++++++++++------
 fs/ocfs2/xattr.c             | 27 ++++++++++++++++++---------
 fs/posix_acl.c               | 17 ++++++++++-------
 fs/reiserfs/xattr.c          | 11 +++++------
 fs/reiserfs/xattr_security.c |  8 +++++---
 fs/reiserfs/xattr_trusted.c  |  8 +++++---
 fs/reiserfs/xattr_user.c     |  8 +++++---
 fs/squashfs/xattr.c          | 16 +++++++++-------
 fs/xattr.c                   | 10 +++++-----
 fs/xfs/xfs_xattr.c           |  8 ++++++--
 include/linux/xattr.h        |  9 +++++----
 37 files changed, 221 insertions(+), 131 deletions(-)

diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index 31c0103..a9e5d72 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -231,10 +231,12 @@ static int v9fs_remote_get_acl(struct dentry *dentry, const char *name,
 }
 
 static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
-			      void *buffer, size_t size, int type)
+			      void *buffer, size_t size,
+			      const struct xattr_handler *handler)
 {
 	struct v9fs_session_info *v9ses;
 	struct posix_acl *acl;
+	int type = handler->flags;
 	int error;
 
 	if (strcmp(name, "") != 0)
@@ -280,7 +282,7 @@ static int v9fs_remote_set_acl(struct dentry *dentry, const char *name,
 
 static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 			      const void *value, size_t size,
-			      int flags, int type)
+			      int flags, const struct xattr_handler *handler)
 {
 	int retval;
 	struct posix_acl *acl;
@@ -297,7 +299,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 	 */
 	if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
 		return v9fs_remote_set_acl(dentry, name,
-					   value, size, flags, type);
+					   value, size, flags, handler->flags);
 
 	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
@@ -316,7 +318,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 	} else
 		acl = NULL;
 
-	switch (type) {
+	switch (handler->flags) {
 	case ACL_TYPE_ACCESS:
 		name = POSIX_ACL_XATTR_ACCESS;
 		if (acl) {
@@ -360,7 +362,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 	}
 	retval = v9fs_xattr_set(dentry, name, value, size, flags);
 	if (!retval)
-		set_cached_acl(inode, type, acl);
+		set_cached_acl(inode, handler->flags, acl);
 err_out:
 	posix_acl_release(acl);
 	return retval;
diff --git a/fs/9p/xattr_security.c b/fs/9p/xattr_security.c
index 2c9b394..1d99c65 100644
--- a/fs/9p/xattr_security.c
+++ b/fs/9p/xattr_security.c
@@ -20,7 +20,8 @@
 #include "xattr.h"
 
 static int v9fs_xattr_security_get(struct dentry *dentry, const char *name,
-			void *buffer, size_t size, int type)
+			void *buffer, size_t size,
+			const struct xattr_handler *handler)
 {
 	const char *full_name = name - XATTR_SECURITY_PREFIX_LEN;
 
@@ -34,7 +35,8 @@ static int v9fs_xattr_security_get(struct dentry *dentry, const char *name,
 }
 
 static int v9fs_xattr_security_set(struct dentry *dentry, const char *name,
-			const void *value, size_t size, int flags, int type)
+			const void *value, size_t size, int flags,
+			const struct xattr_handler *handler)
 {
 	const char *full_name = name - XATTR_SECURITY_PREFIX_LEN;
 
diff --git a/fs/9p/xattr_trusted.c b/fs/9p/xattr_trusted.c
index ee470b6..1a24647 100644
--- a/fs/9p/xattr_trusted.c
+++ b/fs/9p/xattr_trusted.c
@@ -20,7 +20,8 @@
 #include "xattr.h"
 
 static int v9fs_xattr_trusted_get(struct dentry *dentry, const char *name,
-			void *buffer, size_t size, int type)
+			void *buffer, size_t size,
+			const struct xattr_handler *handler)
 {
 	const char *full_name = name - XATTR_TRUSTED_PREFIX_LEN;
 
@@ -34,7 +35,8 @@ static int v9fs_xattr_trusted_get(struct dentry *dentry, const char *name,
 }
 
 static int v9fs_xattr_trusted_set(struct dentry *dentry, const char *name,
-			const void *value, size_t size, int flags, int type)
+			const void *value, size_t size, int flags,
+			const struct xattr_handler *handler)
 {
 	const char *full_name = name - XATTR_TRUSTED_PREFIX_LEN;
 
diff --git a/fs/9p/xattr_user.c b/fs/9p/xattr_user.c
index 4432604..2c35e16 100644
--- a/fs/9p/xattr_user.c
+++ b/fs/9p/xattr_user.c
@@ -20,7 +20,8 @@
 #include "xattr.h"
 
 static int v9fs_xattr_user_get(struct dentry *dentry, const char *name,
-			void *buffer, size_t size, int type)
+			void *buffer, size_t size,
+			const struct xattr_handler *handler)
 {
 	const char *full_name = name - XATTR_USER_PREFIX_LEN;
 
@@ -34,7 +35,8 @@ static int v9fs_xattr_user_get(struct dentry *dentry, const char *name,
 }
 
 static int v9fs_xattr_user_set(struct dentry *dentry, const char *name,
-			const void *value, size_t size, int flags, int type)
+			const void *value, size_t size, int flags,
+			const struct xattr_handler *handler)
 {
 	const char *full_name = name - XATTR_USER_PREFIX_LEN;
 
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index 0b6bfd3..f786688 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -296,7 +296,7 @@ bad_block:	ext2_error(inode->i_sb, "ext2_xattr_list",
 			size_t size = handler->list(dentry, buffer, rest,
 						    entry->e_name,
 						    entry->e_name_len,
-						    handler->flags);
+						    handler);
 			if (buffer) {
 				if (size > rest) {
 					error = -ERANGE;
diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c
index 702fc68..ed9f7a32 100644
--- a/fs/ext2/xattr_security.c
+++ b/fs/ext2/xattr_security.c
@@ -9,7 +9,8 @@
 
 static size_t
 ext2_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
-			 const char *name, size_t name_len, int type)
+			 const char *name, size_t name_len,
+			 const struct xattr_handler *handler)
 {
 	const int prefix_len = XATTR_SECURITY_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -24,7 +25,8 @@ ext2_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext2_xattr_security_get(struct dentry *dentry, const char *name,
-		       void *buffer, size_t size, int type)
+		       void *buffer, size_t size,
+		       const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -34,7 +36,8 @@ ext2_xattr_security_get(struct dentry *dentry, const char *name,
 
 static int
 ext2_xattr_security_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c
index 42b6e98..991676b 100644
--- a/fs/ext2/xattr_trusted.c
+++ b/fs/ext2/xattr_trusted.c
@@ -10,7 +10,8 @@
 
 static size_t
 ext2_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
-		const char *name, size_t name_len, int type)
+		const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	const int prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -28,7 +29,8 @@ ext2_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext2_xattr_trusted_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -38,7 +40,8 @@ ext2_xattr_trusted_get(struct dentry *dentry, const char *name,
 
 static int
 ext2_xattr_trusted_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c
index ecdc460..b8f7c02 100644
--- a/fs/ext2/xattr_user.c
+++ b/fs/ext2/xattr_user.c
@@ -12,7 +12,8 @@
 
 static size_t
 ext2_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
-		const char *name, size_t name_len, int type)
+		const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -30,7 +31,8 @@ ext2_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext2_xattr_user_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -42,7 +44,8 @@ ext2_xattr_user_get(struct dentry *dentry, const char *name,
 
 static int
 ext2_xattr_user_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 7cf3650..4c35ac4 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -340,7 +340,7 @@ ext3_xattr_list_entries(struct dentry *dentry, struct ext3_xattr_entry *entry,
 			size_t size = handler->list(dentry, buffer, rest,
 						    entry->e_name,
 						    entry->e_name_len,
-						    handler->flags);
+						    handler);
 			if (buffer) {
 				if (size > rest)
 					return -ERANGE;
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index c9506d5..c26ebe0 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -9,7 +9,8 @@
 
 static size_t
 ext3_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
-			 const char *name, size_t name_len, int type)
+			 const char *name, size_t name_len,
+			 const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -25,7 +26,8 @@ ext3_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext3_xattr_security_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -35,7 +37,8 @@ ext3_xattr_security_get(struct dentry *dentry, const char *name,
 
 static int
 ext3_xattr_security_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c
index 206cc66..ba3ea56 100644
--- a/fs/ext3/xattr_trusted.c
+++ b/fs/ext3/xattr_trusted.c
@@ -10,7 +10,8 @@
 
 static size_t
 ext3_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
-		const char *name, size_t name_len, int type)
+		const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -28,7 +29,8 @@ ext3_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext3_xattr_trusted_get(struct dentry *dentry, const char *name,
-		       void *buffer, size_t size, int type)
+		       void *buffer, size_t size,
+		       const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -38,7 +40,8 @@ ext3_xattr_trusted_get(struct dentry *dentry, const char *name,
 
 static int
 ext3_xattr_trusted_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
index 021508a..9a5ff25 100644
--- a/fs/ext3/xattr_user.c
+++ b/fs/ext3/xattr_user.c
@@ -10,7 +10,8 @@
 
 static size_t
 ext3_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
-		const char *name, size_t name_len, int type)
+		const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -28,7 +29,8 @@ ext3_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext3_xattr_user_get(struct dentry *dentry, const char *name, void *buffer,
-		size_t size, int type)
+		size_t size,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -40,7 +42,8 @@ ext3_xattr_user_get(struct dentry *dentry, const char *name, void *buffer,
 
 static int
 ext3_xattr_user_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 16e28c0..f5158d9 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -408,7 +408,7 @@ ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
 			size_t size = handler->list(dentry, buffer, rest,
 						    entry->e_name,
 						    entry->e_name_len,
-						    handler->flags);
+						    handler);
 			if (buffer) {
 				if (size > rest)
 					return -ERANGE;
diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c
index 95d90e0..5e5b4e0 100644
--- a/fs/ext4/xattr_security.c
+++ b/fs/ext4/xattr_security.c
@@ -13,7 +13,8 @@
 
 static size_t
 ext4_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
-		const char *name, size_t name_len, int type)
+		const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	const size_t prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -29,7 +30,8 @@ ext4_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext4_xattr_security_get(struct dentry *dentry, const char *name,
-		       void *buffer, size_t size, int type)
+		       void *buffer, size_t size,
+		       const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -39,7 +41,8 @@ ext4_xattr_security_get(struct dentry *dentry, const char *name,
 
 static int
 ext4_xattr_security_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c
index 891ee2d..b298d01 100644
--- a/fs/ext4/xattr_trusted.c
+++ b/fs/ext4/xattr_trusted.c
@@ -14,7 +14,8 @@
 
 static size_t
 ext4_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
-		const char *name, size_t name_len, int type)
+		const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -32,7 +33,8 @@ ext4_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext4_xattr_trusted_get(struct dentry *dentry, const char *name, void *buffer,
-		size_t size, int type)
+		size_t size,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -42,7 +44,8 @@ ext4_xattr_trusted_get(struct dentry *dentry, const char *name, void *buffer,
 
 static int
 ext4_xattr_trusted_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c
index 6ed932b..62085d1 100644
--- a/fs/ext4/xattr_user.c
+++ b/fs/ext4/xattr_user.c
@@ -13,7 +13,8 @@
 
 static size_t
 ext4_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
-		     const char *name, size_t name_len, int type)
+		     const char *name, size_t name_len,
+		     const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -31,7 +32,8 @@ ext4_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
 
 static int
 ext4_xattr_user_get(struct dentry *dentry, const char *name,
-		    void *buffer, size_t size, int type)
+		    void *buffer, size_t size,
+		    const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -43,7 +45,8 @@ ext4_xattr_user_get(struct dentry *dentry, const char *name,
 
 static int
 ext4_xattr_user_set(struct dentry *dentry, const char *name,
-		    const void *value, size_t size, int flags, int type)
+		    const void *value, size_t size, int flags,
+		    const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 07449b98..fdc9849 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -26,13 +26,14 @@
 #include "xattr.h"
 
 static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t len, int type)
+		size_t list_size, const char *name, size_t len,
+		const struct xattr_handler *handler)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
 	int total_len, prefix_len = 0;
 	const char *prefix = NULL;
 
-	switch (type) {
+	switch (handler->flags) {
 	case F2FS_XATTR_INDEX_USER:
 		if (!test_opt(sbi, XATTR_USER))
 			return -EOPNOTSUPP;
@@ -63,11 +64,11 @@ static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
 }
 
 static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size, const struct xattr_handler *handler)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
 
-	switch (type) {
+	switch (handler->flags) {
 	case F2FS_XATTR_INDEX_USER:
 		if (!test_opt(sbi, XATTR_USER))
 			return -EOPNOTSUPP;
@@ -83,15 +84,17 @@ static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
 	}
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return f2fs_getxattr(d_inode(dentry), type, name, buffer, size, NULL);
+	return f2fs_getxattr(d_inode(dentry), handler->flags, name,
+			     buffer, size, NULL);
 }
 
 static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
 
-	switch (type) {
+	switch (handler->flags) {
 	case F2FS_XATTR_INDEX_USER:
 		if (!test_opt(sbi, XATTR_USER))
 			return -EOPNOTSUPP;
@@ -108,17 +111,18 @@ static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	return f2fs_setxattr(d_inode(dentry), type, name,
+	return f2fs_setxattr(d_inode(dentry), handler->flags, name,
 					value, size, NULL, flags);
 }
 
 static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t len, int type)
+		size_t list_size, const char *name, size_t len,
+		const struct xattr_handler *handler)
 {
 	const char *xname = F2FS_SYSTEM_ADVISE_PREFIX;
 	size_t size;
 
-	if (type != F2FS_XATTR_INDEX_ADVISE)
+	if (handler->flags != F2FS_XATTR_INDEX_ADVISE)
 		return 0;
 
 	size = strlen(xname) + 1;
@@ -128,7 +132,8 @@ static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
 }
 
 static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	struct inode *inode = d_inode(dentry);
 
@@ -141,7 +146,8 @@ static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
 }
 
 static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	struct inode *inode = d_inode(dentry);
 
@@ -463,7 +469,7 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 			continue;
 
 		size = handler->list(dentry, buffer, rest, entry->e_name,
-				entry->e_name_len, handler->flags);
+				entry->e_name_len, handler);
 		if (buffer && size > rest) {
 			error = -ERANGE;
 			goto cleanup;
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index 4c096fa..3979c608 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -584,10 +584,12 @@ out:
  * Returns: actual size of data on success, -errno on error
  */
 static int gfs2_xattr_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	struct gfs2_inode *ip = GFS2_I(d_inode(dentry));
 	struct gfs2_ea_location el;
+	int type = handler->flags;
 	int error;
 
 	if (!ip->i_eattr)
@@ -1228,10 +1230,11 @@ int __gfs2_xattr_set(struct inode *inode, const char *name,
 }
 
 static int gfs2_xattr_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	return __gfs2_xattr_set(d_inode(dentry), name, value,
-				size, flags, type);
+				size, flags, handler->flags);
 }
 
 
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
index e898499..65914db 100644
--- a/fs/hfsplus/xattr.c
+++ b/fs/hfsplus/xattr.c
@@ -850,7 +850,8 @@ end_removexattr:
 }
 
 static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
-					void *buffer, size_t size, int type)
+					void *buffer, size_t size,
+					const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
@@ -872,7 +873,8 @@ static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
 }
 
 static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
-		const void *buffer, size_t size, int flags, int type)
+		const void *buffer, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c
index 024e61c..3601ecc 100644
--- a/fs/hfsplus/xattr_security.c
+++ b/fs/hfsplus/xattr_security.c
@@ -14,7 +14,8 @@
 #include "acl.h"
 
 static int hfsplus_security_getxattr(struct dentry *dentry, const char *name,
-					void *buffer, size_t size, int type)
+					void *buffer, size_t size,
+					const struct xattr_handler *handler)
 {
 	return hfsplus_getxattr(dentry, name, buffer, size,
 				XATTR_SECURITY_PREFIX,
@@ -22,7 +23,8 @@ static int hfsplus_security_getxattr(struct dentry *dentry, const char *name,
 }
 
 static int hfsplus_security_setxattr(struct dentry *dentry, const char *name,
-		const void *buffer, size_t size, int flags, int type)
+		const void *buffer, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	return hfsplus_setxattr(dentry, name, buffer, size, flags,
 				XATTR_SECURITY_PREFIX,
diff --git a/fs/hfsplus/xattr_trusted.c b/fs/hfsplus/xattr_trusted.c
index 6186157..123cd8e 100644
--- a/fs/hfsplus/xattr_trusted.c
+++ b/fs/hfsplus/xattr_trusted.c
@@ -12,7 +12,8 @@
 #include "xattr.h"
 
 static int hfsplus_trusted_getxattr(struct dentry *dentry, const char *name,
-					void *buffer, size_t size, int type)
+					void *buffer, size_t size,
+					const struct xattr_handler *handler)
 {
 	return hfsplus_getxattr(dentry, name, buffer, size,
 				XATTR_TRUSTED_PREFIX,
@@ -20,7 +21,8 @@ static int hfsplus_trusted_getxattr(struct dentry *dentry, const char *name,
 }
 
 static int hfsplus_trusted_setxattr(struct dentry *dentry, const char *name,
-		const void *buffer, size_t size, int flags, int type)
+		const void *buffer, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	return hfsplus_setxattr(dentry, name, buffer, size, flags,
 				XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
diff --git a/fs/hfsplus/xattr_user.c b/fs/hfsplus/xattr_user.c
index 3b4caba..2272557 100644
--- a/fs/hfsplus/xattr_user.c
+++ b/fs/hfsplus/xattr_user.c
@@ -12,7 +12,8 @@
 #include "xattr.h"
 
 static int hfsplus_user_getxattr(struct dentry *dentry, const char *name,
-					void *buffer, size_t size, int type)
+					void *buffer, size_t size,
+					const struct xattr_handler *handler)
 {
 
 	return hfsplus_getxattr(dentry, name, buffer, size,
@@ -20,7 +21,8 @@ static int hfsplus_user_getxattr(struct dentry *dentry, const char *name,
 }
 
 static int hfsplus_user_setxattr(struct dentry *dentry, const char *name,
-		const void *buffer, size_t size, int flags, int type)
+		const void *buffer, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	return hfsplus_setxattr(dentry, name, buffer, size, flags,
 				XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
index d4b43fb..8f609e8 100644
--- a/fs/jffs2/security.c
+++ b/fs/jffs2/security.c
@@ -49,7 +49,8 @@ int jffs2_init_security(struct inode *inode, struct inode *dir,
 
 /* ---- XATTR Handler for "security.*" ----------------- */
 static int jffs2_security_getxattr(struct dentry *dentry, const char *name,
-				   void *buffer, size_t size, int type)
+				   void *buffer, size_t size,
+				   const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
@@ -59,7 +60,8 @@ static int jffs2_security_getxattr(struct dentry *dentry, const char *name,
 }
 
 static int jffs2_security_setxattr(struct dentry *dentry, const char *name,
-		const void *buffer, size_t size, int flags, int type)
+		const void *buffer, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
@@ -69,7 +71,8 @@ static int jffs2_security_setxattr(struct dentry *dentry, const char *name,
 }
 
 static size_t jffs2_security_listxattr(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t name_len, int type)
+		size_t list_size, const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1;
 
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index f092fee..8b2305c 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -1002,10 +1002,10 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
 			continue;
 		if (buffer) {
 			rc = xhandle->list(dentry, buffer+len, size-len,
-					   xd->xname, xd->name_len, xd->flags);
+					   xd->xname, xd->name_len, xhandle);
 		} else {
 			rc = xhandle->list(dentry, NULL, 0, xd->xname,
-					   xd->name_len, xd->flags);
+					   xd->name_len, xhandle);
 		}
 		if (rc < 0)
 			goto out;
diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c
index ceaf9c6..afa0e4d 100644
--- a/fs/jffs2/xattr_trusted.c
+++ b/fs/jffs2/xattr_trusted.c
@@ -17,7 +17,7 @@
 #include "nodelist.h"
 
 static int jffs2_trusted_getxattr(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size, const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
@@ -26,7 +26,8 @@ static int jffs2_trusted_getxattr(struct dentry *dentry, const char *name,
 }
 
 static int jffs2_trusted_setxattr(struct dentry *dentry, const char *name,
-		const void *buffer, size_t size, int flags, int type)
+		const void *buffer, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
@@ -35,7 +36,8 @@ static int jffs2_trusted_setxattr(struct dentry *dentry, const char *name,
 }
 
 static size_t jffs2_trusted_listxattr(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t name_len, int type)
+		size_t list_size, const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1;
 
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
index a71391e..4c45567 100644
--- a/fs/jffs2/xattr_user.c
+++ b/fs/jffs2/xattr_user.c
@@ -17,7 +17,8 @@
 #include "nodelist.h"
 
 static int jffs2_user_getxattr(struct dentry *dentry, const char *name,
-			       void *buffer, size_t size, int type)
+			       void *buffer, size_t size,
+			       const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
@@ -26,7 +27,8 @@ static int jffs2_user_getxattr(struct dentry *dentry, const char *name,
 }
 
 static int jffs2_user_setxattr(struct dentry *dentry, const char *name,
-		const void *buffer, size_t size, int flags, int type)
+		const void *buffer, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
@@ -35,7 +37,8 @@ static int jffs2_user_setxattr(struct dentry *dentry, const char *name,
 }
 
 static size_t jffs2_user_listxattr(struct dentry *dentry, char *list,
-		size_t list_size, const char *name, size_t name_len, int type)
+		size_t list_size, const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1;
 
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 3acb1eb..977165e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6203,7 +6203,8 @@ nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
 
 static int nfs4_xattr_set_nfs4_acl(struct dentry *dentry, const char *key,
 				   const void *buf, size_t buflen,
-				   int flags, int type)
+				   int flags,
+				   const struct xattr_handler *handler)
 {
 	if (strcmp(key, "") != 0)
 		return -EINVAL;
@@ -6212,7 +6213,8 @@ static int nfs4_xattr_set_nfs4_acl(struct dentry *dentry, const char *key,
 }
 
 static int nfs4_xattr_get_nfs4_acl(struct dentry *dentry, const char *key,
-				   void *buf, size_t buflen, int type)
+				   void *buf, size_t buflen,
+				   const struct xattr_handler *handler)
 {
 	if (strcmp(key, "") != 0)
 		return -EINVAL;
@@ -6222,7 +6224,8 @@ static int nfs4_xattr_get_nfs4_acl(struct dentry *dentry, const char *key,
 
 static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list,
 				       size_t list_len, const char *name,
-				       size_t name_len, int type)
+				       size_t name_len,
+				       const struct xattr_handler *handler)
 {
 	size_t len = sizeof(XATTR_NAME_NFSV4_ACL);
 
@@ -6242,7 +6245,8 @@ static inline int nfs4_server_supports_labels(struct nfs_server *server)
 
 static int nfs4_xattr_set_nfs4_label(struct dentry *dentry, const char *key,
 				   const void *buf, size_t buflen,
-				   int flags, int type)
+				   int flags,
+				   const struct xattr_handler *handler)
 {
 	if (security_ismaclabel(key))
 		return nfs4_set_security_label(dentry, buf, buflen);
@@ -6251,7 +6255,8 @@ static int nfs4_xattr_set_nfs4_label(struct dentry *dentry, const char *key,
 }
 
 static int nfs4_xattr_get_nfs4_label(struct dentry *dentry, const char *key,
-				   void *buf, size_t buflen, int type)
+				   void *buf, size_t buflen,
+				   const struct xattr_handler *handler)
 {
 	if (security_ismaclabel(key))
 		return nfs4_get_security_label(d_inode(dentry), buf, buflen);
@@ -6260,7 +6265,8 @@ static int nfs4_xattr_get_nfs4_label(struct dentry *dentry, const char *key,
 
 static size_t nfs4_xattr_list_nfs4_label(struct dentry *dentry, char *list,
 				       size_t list_len, const char *name,
-				       size_t name_len, int type)
+				       size_t name_len,
+				       const struct xattr_handler *handler)
 {
 	size_t len = 0;
 
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 889f379..f5ce434 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -7239,7 +7239,8 @@ leave:
  */
 static size_t ocfs2_xattr_security_list(struct dentry *dentry, char *list,
 					size_t list_size, const char *name,
-					size_t name_len, int type)
+					size_t name_len,
+					const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -7253,7 +7254,8 @@ static size_t ocfs2_xattr_security_list(struct dentry *dentry, char *list,
 }
 
 static int ocfs2_xattr_security_get(struct dentry *dentry, const char *name,
-				    void *buffer, size_t size, int type)
+				    void *buffer, size_t size,
+				    const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -7262,7 +7264,8 @@ static int ocfs2_xattr_security_get(struct dentry *dentry, const char *name,
 }
 
 static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -7329,7 +7332,8 @@ const struct xattr_handler ocfs2_xattr_security_handler = {
  */
 static size_t ocfs2_xattr_trusted_list(struct dentry *dentry, char *list,
 				       size_t list_size, const char *name,
-				       size_t name_len, int type)
+				       size_t name_len,
+				       const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -7343,7 +7347,8 @@ static size_t ocfs2_xattr_trusted_list(struct dentry *dentry, char *list,
 }
 
 static int ocfs2_xattr_trusted_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -7352,7 +7357,8 @@ static int ocfs2_xattr_trusted_get(struct dentry *dentry, const char *name,
 }
 
 static int ocfs2_xattr_trusted_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -7373,7 +7379,8 @@ const struct xattr_handler ocfs2_xattr_trusted_handler = {
  */
 static size_t ocfs2_xattr_user_list(struct dentry *dentry, char *list,
 				    size_t list_size, const char *name,
-				    size_t name_len, int type)
+				    size_t name_len,
+				    const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -7391,7 +7398,8 @@ static size_t ocfs2_xattr_user_list(struct dentry *dentry, char *list,
 }
 
 static int ocfs2_xattr_user_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, int type)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
@@ -7404,7 +7412,8 @@ static int ocfs2_xattr_user_get(struct dentry *dentry, const char *name,
 }
 
 static int ocfs2_xattr_user_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 4fb17de..1c7e94f 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -763,7 +763,8 @@ EXPORT_SYMBOL (posix_acl_to_xattr);
 
 static int
 posix_acl_xattr_get(struct dentry *dentry, const char *name,
-		void *value, size_t size, int type)
+		void *value, size_t size,
+		const struct xattr_handler *handler)
 {
 	struct posix_acl *acl;
 	int error;
@@ -773,7 +774,7 @@ posix_acl_xattr_get(struct dentry *dentry, const char *name,
 	if (d_is_symlink(dentry))
 		return -EOPNOTSUPP;
 
-	acl = get_acl(d_backing_inode(dentry), type);
+	acl = get_acl(d_backing_inode(dentry), handler->flags);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl == NULL)
@@ -787,7 +788,8 @@ posix_acl_xattr_get(struct dentry *dentry, const char *name,
 
 static int
 posix_acl_xattr_set(struct dentry *dentry, const char *name,
-		const void *value, size_t size, int flags, int type)
+		const void *value, size_t size, int flags,
+		const struct xattr_handler *handler)
 {
 	struct inode *inode = d_backing_inode(dentry);
 	struct posix_acl *acl = NULL;
@@ -798,7 +800,7 @@ posix_acl_xattr_set(struct dentry *dentry, const char *name,
 	if (!inode->i_op->set_acl)
 		return -EOPNOTSUPP;
 
-	if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
+	if (handler->flags == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
 		return value ? -EACCES : 0;
 	if (!inode_owner_or_capable(inode))
 		return -EPERM;
@@ -815,7 +817,7 @@ posix_acl_xattr_set(struct dentry *dentry, const char *name,
 		}
 	}
 
-	ret = inode->i_op->set_acl(inode, acl, type);
+	ret = inode->i_op->set_acl(inode, acl, handler->flags);
 out:
 	posix_acl_release(acl);
 	return ret;
@@ -823,7 +825,8 @@ out:
 
 static size_t
 posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
-		const char *name, size_t name_len, int type)
+		const char *name, size_t name_len,
+		const struct xattr_handler *handler)
 {
 	const char *xname;
 	size_t size;
@@ -833,7 +836,7 @@ posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
 	if (d_is_symlink(dentry))
 		return -EOPNOTSUPP;
 
-	if (type == ACL_TYPE_ACCESS)
+	if (handler->flags == ACL_TYPE_ACCESS)
 		xname = POSIX_ACL_XATTR_ACCESS;
 	else
 		xname = POSIX_ACL_XATTR_DEFAULT;
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index e87f9b5..ad6e4bb 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -778,7 +778,7 @@ reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
 	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->get(dentry, name, buffer, size, handler->flags);
+	return handler->get(dentry, name, buffer, size, handler);
 }
 
 /*
@@ -797,7 +797,7 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->set(dentry, name, value, size, flags, handler->flags);
+	return handler->set(dentry, name, value, size, flags, handler);
 }
 
 /*
@@ -814,7 +814,7 @@ int reiserfs_removexattr(struct dentry *dentry, const char *name)
 	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->set(dentry, name, NULL, 0, XATTR_REPLACE, handler->flags);
+	return handler->set(dentry, name, NULL, 0, XATTR_REPLACE, handler);
 }
 
 struct listxattr_buf {
@@ -843,13 +843,12 @@ static int listxattr_filler(struct dir_context *ctx, const char *name,
 			return 0;
 		if (b->buf) {
 			size = handler->list(b->dentry, b->buf + b->pos,
-					 b->size, name, namelen,
-					 handler->flags);
+					 b->size, name, namelen, handler);
 			if (size > b->size)
 				return -ERANGE;
 		} else {
 			size = handler->list(b->dentry, NULL, 0, name,
-					     namelen, handler->flags);
+					     namelen, handler);
 		}
 
 		b->pos += size;
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index 9a3b061..08074f5 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -10,7 +10,7 @@
 
 static int
 security_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
-		int handler_flags)
+	     const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
 		return -EINVAL;
@@ -23,7 +23,8 @@ security_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
 
 static int
 security_set(struct dentry *dentry, const char *name, const void *buffer,
-	     size_t size, int flags, int handler_flags)
+	     size_t size, int flags,
+	     const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
 		return -EINVAL;
@@ -35,7 +36,8 @@ security_set(struct dentry *dentry, const char *name, const void *buffer,
 }
 
 static size_t security_list(struct dentry *dentry, char *list, size_t list_len,
-			    const char *name, size_t namelen, int handler_flags)
+			    const char *name, size_t namelen,
+			    const struct xattr_handler *handler)
 {
 	const size_t len = namelen + 1;
 
diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c
index e4f1343..e3ab346 100644
--- a/fs/reiserfs/xattr_trusted.c
+++ b/fs/reiserfs/xattr_trusted.c
@@ -9,7 +9,7 @@
 
 static int
 trusted_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
-	    int handler_flags)
+	    const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
 		return -EINVAL;
@@ -22,7 +22,8 @@ trusted_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
 
 static int
 trusted_set(struct dentry *dentry, const char *name, const void *buffer,
-	    size_t size, int flags, int handler_flags)
+	    size_t size, int flags,
+	    const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
 		return -EINVAL;
@@ -34,7 +35,8 @@ trusted_set(struct dentry *dentry, const char *name, const void *buffer,
 }
 
 static size_t trusted_list(struct dentry *dentry, char *list, size_t list_size,
-			   const char *name, size_t name_len, int handler_flags)
+			   const char *name, size_t name_len,
+			   const struct xattr_handler *handler)
 {
 	const size_t len = name_len + 1;
 
diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c
index d0b08d3..2c8d466 100644
--- a/fs/reiserfs/xattr_user.c
+++ b/fs/reiserfs/xattr_user.c
@@ -8,7 +8,7 @@
 
 static int
 user_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
-	 int handler_flags)
+	 const struct xattr_handler *handler)
 {
 
 	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
@@ -20,7 +20,8 @@ user_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
 
 static int
 user_set(struct dentry *dentry, const char *name, const void *buffer,
-	 size_t size, int flags, int handler_flags)
+	 size_t size, int flags,
+	 const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
 		return -EINVAL;
@@ -31,7 +32,8 @@ user_set(struct dentry *dentry, const char *name, const void *buffer,
 }
 
 static size_t user_list(struct dentry *dentry, char *list, size_t list_size,
-			const char *name, size_t name_len, int handler_flags)
+			const char *name, size_t name_len,
+			const struct xattr_handler *handler)
 {
 	const size_t len = name_len + 1;
 
diff --git a/fs/squashfs/xattr.c b/fs/squashfs/xattr.c
index e5e0ddf..05ef4b9 100644
--- a/fs/squashfs/xattr.c
+++ b/fs/squashfs/xattr.c
@@ -69,7 +69,7 @@ ssize_t squashfs_listxattr(struct dentry *d, char *buffer,
 		handler = squashfs_xattr_handler(le16_to_cpu(entry.type));
 		if (handler)
 			prefix_size = handler->list(d, buffer, rest, NULL,
-				name_size, handler->flags);
+				name_size, handler);
 		if (prefix_size) {
 			if (buffer) {
 				if (prefix_size + name_size + 1 > rest) {
@@ -216,7 +216,7 @@ failed:
  * User namespace support
  */
 static size_t squashfs_user_list(struct dentry *d, char *list, size_t list_size,
-	const char *name, size_t name_len, int type)
+	const char *name, size_t name_len, const struct xattr_handler *handler)
 {
 	if (list && XATTR_USER_PREFIX_LEN <= list_size)
 		memcpy(list, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
@@ -224,7 +224,7 @@ static size_t squashfs_user_list(struct dentry *d, char *list, size_t list_size,
 }
 
 static int squashfs_user_get(struct dentry *d, const char *name, void *buffer,
-	size_t size, int type)
+	size_t size, const struct xattr_handler *handler)
 {
 	if (name[0] == '\0')
 		return  -EINVAL;
@@ -243,7 +243,8 @@ static const struct xattr_handler squashfs_xattr_user_handler = {
  * Trusted namespace support
  */
 static size_t squashfs_trusted_list(struct dentry *d, char *list,
-	size_t list_size, const char *name, size_t name_len, int type)
+	size_t list_size, const char *name, size_t name_len,
+	const struct xattr_handler *handler)
 {
 	if (!capable(CAP_SYS_ADMIN))
 		return 0;
@@ -254,7 +255,7 @@ static size_t squashfs_trusted_list(struct dentry *d, char *list,
 }
 
 static int squashfs_trusted_get(struct dentry *d, const char *name,
-	void *buffer, size_t size, int type)
+	void *buffer, size_t size, const struct xattr_handler *handler)
 {
 	if (name[0] == '\0')
 		return  -EINVAL;
@@ -273,7 +274,8 @@ static const struct xattr_handler squashfs_xattr_trusted_handler = {
  * Security namespace support
  */
 static size_t squashfs_security_list(struct dentry *d, char *list,
-	size_t list_size, const char *name, size_t name_len, int type)
+	size_t list_size, const char *name, size_t name_len,
+	const struct xattr_handler *handler)
 {
 	if (list && XATTR_SECURITY_PREFIX_LEN <= list_size)
 		memcpy(list, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN);
@@ -281,7 +283,7 @@ static size_t squashfs_security_list(struct dentry *d, char *list,
 }
 
 static int squashfs_security_get(struct dentry *d, const char *name,
-	void *buffer, size_t size, int type)
+	void *buffer, size_t size, const struct xattr_handler *handler)
 {
 	if (name[0] == '\0')
 		return  -EINVAL;
diff --git a/fs/xattr.c b/fs/xattr.c
index 072fee1..efa16ce 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -720,7 +720,7 @@ generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t s
 	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->get(dentry, name, buffer, size, handler->flags);
+	return handler->get(dentry, name, buffer, size, handler);
 }
 
 /*
@@ -736,14 +736,14 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 	if (!buffer) {
 		for_each_xattr_handler(handlers, handler) {
 			size += handler->list(dentry, NULL, 0, NULL, 0,
-					      handler->flags);
+					      handler);
 		}
 	} else {
 		char *buf = buffer;
 
 		for_each_xattr_handler(handlers, handler) {
 			size = handler->list(dentry, buf, buffer_size,
-					     NULL, 0, handler->flags);
+					     NULL, 0, handler);
 			if (size > buffer_size)
 				return -ERANGE;
 			buf += size;
@@ -767,7 +767,7 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz
 	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->set(dentry, name, value, size, flags, handler->flags);
+	return handler->set(dentry, name, value, size, flags, handler);
 }
 
 /*
@@ -783,7 +783,7 @@ generic_removexattr(struct dentry *dentry, const char *name)
 	if (!handler)
 		return -EOPNOTSUPP;
 	return handler->set(dentry, name, NULL, 0,
-			    XATTR_REPLACE, handler->flags);
+			    XATTR_REPLACE, handler);
 }
 
 EXPORT_SYMBOL(generic_getxattr);
diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c
index c0368151..9dace13 100644
--- a/fs/xfs/xfs_xattr.c
+++ b/fs/xfs/xfs_xattr.c
@@ -33,8 +33,10 @@
 
 static int
 xfs_xattr_get(struct dentry *dentry, const char *name,
-		void *value, size_t size, int xflags)
+		void *value, size_t size,
+		const struct xattr_handler *handler)
 {
+	int xflags = handler->flags;
 	struct xfs_inode *ip = XFS_I(d_inode(dentry));
 	int error, asize = size;
 
@@ -55,8 +57,10 @@ xfs_xattr_get(struct dentry *dentry, const char *name,
 
 static int
 xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
-		size_t size, int flags, int xflags)
+		size_t size, int flags,
+		const struct xattr_handler *handler)
 {
+	int xflags = handler->flags;
 	struct xfs_inode *ip = XFS_I(d_inode(dentry));
 
 	if (strcmp(name, "") == 0)
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 91b0a68..8fd287d 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -21,13 +21,14 @@ struct dentry;
 
 struct xattr_handler {
 	const char *prefix;
-	int flags;	/* fs private flags passed back to the handlers */
+	int flags;      /* fs private flags */
 	size_t (*list)(struct dentry *dentry, char *list, size_t list_size,
-		       const char *name, size_t name_len, int handler_flags);
+		       const char *name, size_t name_len,
+		       const struct xattr_handler *);
 	int (*get)(struct dentry *dentry, const char *name, void *buffer,
-		   size_t size, int handler_flags);
+		   size_t size, const struct xattr_handler *);
 	int (*set)(struct dentry *dentry, const char *name, const void *buffer,
-		   size_t size, int flags, int handler_flags);
+		   size_t size, int flags, const struct xattr_handler *);
 };
 
 struct xattr {
-- 
2.4.3



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC 05/11] xattr handlers: Some simplifications
  2015-08-20 18:19 ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  -1 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	linux-fsdevel, David Quigley, J. Bruce Fields
  Cc: linux-security-module, cluster-devel

We have access to struct xattr_handler inside the list/get/set operations now,
so simplify some of the xattr code.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/9p/Makefile         |  5 +---
 fs/9p/acl.c            | 51 ++++-----------------------------
 fs/9p/xattr.c          | 42 +++++++++++++++++++++++++++
 fs/9p/xattr.h          |  3 --
 fs/9p/xattr_security.c | 56 ------------------------------------
 fs/9p/xattr_trusted.c  | 56 ------------------------------------
 fs/9p/xattr_user.c     | 56 ------------------------------------
 fs/f2fs/xattr.c        | 18 ++++--------
 fs/posix_acl.c         |  7 +----
 fs/squashfs/xattr.c    | 77 +++++++++++++++++---------------------------------
 10 files changed, 80 insertions(+), 291 deletions(-)
 delete mode 100644 fs/9p/xattr_security.c
 delete mode 100644 fs/9p/xattr_trusted.c
 delete mode 100644 fs/9p/xattr_user.c

diff --git a/fs/9p/Makefile b/fs/9p/Makefile
index ff7be98..9619cca 100644
--- a/fs/9p/Makefile
+++ b/fs/9p/Makefile
@@ -10,10 +10,7 @@ obj-$(CONFIG_9P_FS) := 9p.o
 	vfs_dentry.o \
 	v9fs.o \
 	fid.o  \
-	xattr.o \
-	xattr_user.o \
-	xattr_trusted.o
+	xattr.o
 
 9p-$(CONFIG_9P_FSCACHE) += cache.o
 9p-$(CONFIG_9P_FS_POSIX_ACL) += acl.o
-9p-$(CONFIG_9P_FS_SECURITY) += xattr_security.o
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index a9e5d72..5325304 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -212,31 +212,12 @@ int v9fs_acl_mode(struct inode *dir, umode_t *modep,
 	return 0;
 }
 
-static int v9fs_remote_get_acl(struct dentry *dentry, const char *name,
-			       void *buffer, size_t size, int type)
-{
-	char *full_name;
-
-	switch (type) {
-	case ACL_TYPE_ACCESS:
-		full_name =  POSIX_ACL_XATTR_ACCESS;
-		break;
-	case ACL_TYPE_DEFAULT:
-		full_name = POSIX_ACL_XATTR_DEFAULT;
-		break;
-	default:
-		BUG();
-	}
-	return v9fs_xattr_get(dentry, full_name, buffer, size);
-}
-
 static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
 			      void *buffer, size_t size,
 			      const struct xattr_handler *handler)
 {
 	struct v9fs_session_info *v9ses;
 	struct posix_acl *acl;
-	int type = handler->flags;
 	int error;
 
 	if (strcmp(name, "") != 0)
@@ -247,9 +228,9 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
 	 * We allow set/get/list of acl when access=client is not specified
 	 */
 	if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
-		return v9fs_remote_get_acl(dentry, name, buffer, size, type);
+		return v9fs_xattr_get(dentry, handler->prefix, buffer, size);
 
-	acl = v9fs_get_cached_acl(d_inode(dentry), type);
+	acl = v9fs_get_cached_acl(d_inode(dentry), handler->flags);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl == NULL)
@@ -260,26 +241,6 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
 	return error;
 }
 
-static int v9fs_remote_set_acl(struct dentry *dentry, const char *name,
-			      const void *value, size_t size,
-			      int flags, int type)
-{
-	char *full_name;
-
-	switch (type) {
-	case ACL_TYPE_ACCESS:
-		full_name =  POSIX_ACL_XATTR_ACCESS;
-		break;
-	case ACL_TYPE_DEFAULT:
-		full_name = POSIX_ACL_XATTR_DEFAULT;
-		break;
-	default:
-		BUG();
-	}
-	return v9fs_xattr_set(dentry, full_name, value, size, flags);
-}
-
-
 static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 			      const void *value, size_t size,
 			      int flags, const struct xattr_handler *handler)
@@ -298,8 +259,8 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 	 * xattr value. We leave it to the server to validate
 	 */
 	if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
-		return v9fs_remote_set_acl(dentry, name,
-					   value, size, flags, handler->flags);
+		return v9fs_xattr_set(dentry, handler->prefix,
+				      value, size, flags);
 
 	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
@@ -320,7 +281,6 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 
 	switch (handler->flags) {
 	case ACL_TYPE_ACCESS:
-		name = POSIX_ACL_XATTR_ACCESS;
 		if (acl) {
 			umode_t mode = inode->i_mode;
 			retval = posix_acl_equiv_mode(acl, &mode);
@@ -351,7 +311,6 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 		}
 		break;
 	case ACL_TYPE_DEFAULT:
-		name = POSIX_ACL_XATTR_DEFAULT;
 		if (!S_ISDIR(inode->i_mode)) {
 			retval = acl ? -EINVAL : 0;
 			goto err_out;
@@ -360,7 +319,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 	default:
 		BUG();
 	}
-	retval = v9fs_xattr_set(dentry, name, value, size, flags);
+	retval = v9fs_xattr_set(dentry, handler->prefix, value, size, flags);
 	if (!retval)
 		set_cached_acl(inode, handler->flags, acl);
 err_out:
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
index 0cf44b6..00b28f4 100644
--- a/fs/9p/xattr.c
+++ b/fs/9p/xattr.c
@@ -137,6 +137,48 @@ ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 	return v9fs_xattr_get(dentry, NULL, buffer, buffer_size);
 }
 
+static int v9fs_xattr_handler_get(struct dentry *dentry, const char *name,
+				  void *buffer, size_t size,
+				  const struct xattr_handler *handler)
+{
+	int prefix_len = strlen(handler->prefix);
+
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return v9fs_xattr_get(dentry, name - prefix_len, buffer, size);
+}
+
+static int v9fs_xattr_handler_set(struct dentry *dentry, const char *name,
+				  const void *value, size_t size, int flags,
+				  const struct xattr_handler *handler)
+{
+	int prefix_len = strlen(handler->prefix);
+
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return v9fs_xattr_set(dentry, name - prefix_len, value, size, flags);
+}
+
+static struct xattr_handler v9fs_xattr_user_handler = {
+	.prefix	= XATTR_USER_PREFIX,
+	.get	= v9fs_xattr_handler_get,
+	.set	= v9fs_xattr_handler_set,
+};
+
+static struct xattr_handler v9fs_xattr_trusted_handler = {
+	.prefix	= XATTR_TRUSTED_PREFIX,
+	.get	= v9fs_xattr_handler_get,
+	.set	= v9fs_xattr_handler_set,
+};
+
+#ifdef CONFIG_9P_FS_SECURITY
+static struct xattr_handler v9fs_xattr_security_handler = {
+	.prefix	= XATTR_SECURITY_PREFIX,
+	.get	= v9fs_xattr_handler_get,
+	.set	= v9fs_xattr_handler_set,
+};
+#endif
+
 const struct xattr_handler *v9fs_xattr_handlers[] = {
 	&v9fs_xattr_user_handler,
 	&v9fs_xattr_trusted_handler,
diff --git a/fs/9p/xattr.h b/fs/9p/xattr.h
index d3e2ea3..c63c3be 100644
--- a/fs/9p/xattr.h
+++ b/fs/9p/xattr.h
@@ -19,9 +19,6 @@
 #include <net/9p/client.h>
 
 extern const struct xattr_handler *v9fs_xattr_handlers[];
-extern struct xattr_handler v9fs_xattr_user_handler;
-extern struct xattr_handler v9fs_xattr_trusted_handler;
-extern struct xattr_handler v9fs_xattr_security_handler;
 extern const struct xattr_handler v9fs_xattr_acl_access_handler;
 extern const struct xattr_handler v9fs_xattr_acl_default_handler;
 
diff --git a/fs/9p/xattr_security.c b/fs/9p/xattr_security.c
deleted file mode 100644
index 1d99c65..0000000
--- a/fs/9p/xattr_security.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright IBM Corporation, 2010
- * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include "xattr.h"
-
-static int v9fs_xattr_security_get(struct dentry *dentry, const char *name,
-			void *buffer, size_t size,
-			const struct xattr_handler *handler)
-{
-	const char *full_name = name - XATTR_SECURITY_PREFIX_LEN;
-
-	if (name == NULL)
-		return -EINVAL;
-
-	if (strcmp(name, "") == 0)
-		return -EINVAL;
-
-	return v9fs_xattr_get(dentry, full_name, buffer, size);
-}
-
-static int v9fs_xattr_security_set(struct dentry *dentry, const char *name,
-			const void *value, size_t size, int flags,
-			const struct xattr_handler *handler)
-{
-	const char *full_name = name - XATTR_SECURITY_PREFIX_LEN;
-
-	if (name == NULL)
-		return -EINVAL;
-
-	if (strcmp(name, "") == 0)
-		return -EINVAL;
-
-	return v9fs_xattr_set(dentry, full_name, value, size, flags);
-}
-
-struct xattr_handler v9fs_xattr_security_handler = {
-	.prefix	= XATTR_SECURITY_PREFIX,
-	.get	= v9fs_xattr_security_get,
-	.set	= v9fs_xattr_security_set,
-};
diff --git a/fs/9p/xattr_trusted.c b/fs/9p/xattr_trusted.c
deleted file mode 100644
index 1a24647..0000000
--- a/fs/9p/xattr_trusted.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright IBM Corporation, 2010
- * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include "xattr.h"
-
-static int v9fs_xattr_trusted_get(struct dentry *dentry, const char *name,
-			void *buffer, size_t size,
-			const struct xattr_handler *handler)
-{
-	const char *full_name = name - XATTR_TRUSTED_PREFIX_LEN;
-
-	if (name == NULL)
-		return -EINVAL;
-
-	if (strcmp(name, "") == 0)
-		return -EINVAL;
-
-	return v9fs_xattr_get(dentry, full_name, buffer, size);
-}
-
-static int v9fs_xattr_trusted_set(struct dentry *dentry, const char *name,
-			const void *value, size_t size, int flags,
-			const struct xattr_handler *handler)
-{
-	const char *full_name = name - XATTR_TRUSTED_PREFIX_LEN;
-
-	if (name == NULL)
-		return -EINVAL;
-
-	if (strcmp(name, "") == 0)
-		return -EINVAL;
-
-	return v9fs_xattr_set(dentry, full_name, value, size, flags);
-}
-
-struct xattr_handler v9fs_xattr_trusted_handler = {
-	.prefix	= XATTR_TRUSTED_PREFIX,
-	.get	= v9fs_xattr_trusted_get,
-	.set	= v9fs_xattr_trusted_set,
-};
diff --git a/fs/9p/xattr_user.c b/fs/9p/xattr_user.c
deleted file mode 100644
index 2c35e16..0000000
--- a/fs/9p/xattr_user.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright IBM Corporation, 2010
- * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include "xattr.h"
-
-static int v9fs_xattr_user_get(struct dentry *dentry, const char *name,
-			void *buffer, size_t size,
-			const struct xattr_handler *handler)
-{
-	const char *full_name = name - XATTR_USER_PREFIX_LEN;
-
-	if (name == NULL)
-		return -EINVAL;
-
-	if (strcmp(name, "") == 0)
-		return -EINVAL;
-
-	return v9fs_xattr_get(dentry, full_name, buffer, size);
-}
-
-static int v9fs_xattr_user_set(struct dentry *dentry, const char *name,
-			const void *value, size_t size, int flags,
-			const struct xattr_handler *handler)
-{
-	const char *full_name = name - XATTR_USER_PREFIX_LEN;
-
-	if (name == NULL)
-		return -EINVAL;
-
-	if (strcmp(name, "") == 0)
-		return -EINVAL;
-
-	return v9fs_xattr_set(dentry, full_name, value, size, flags);
-}
-
-struct xattr_handler v9fs_xattr_user_handler = {
-	.prefix	= XATTR_USER_PREFIX,
-	.get	= v9fs_xattr_user_get,
-	.set	= v9fs_xattr_user_set,
-};
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index fdc9849..1c3e5e7 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -30,33 +30,27 @@ static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
 		const struct xattr_handler *handler)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
-	int total_len, prefix_len = 0;
-	const char *prefix = NULL;
+	int total_len, prefix_len;
 
 	switch (handler->flags) {
 	case F2FS_XATTR_INDEX_USER:
 		if (!test_opt(sbi, XATTR_USER))
 			return -EOPNOTSUPP;
-		prefix = XATTR_USER_PREFIX;
-		prefix_len = XATTR_USER_PREFIX_LEN;
 		break;
 	case F2FS_XATTR_INDEX_TRUSTED:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		prefix = XATTR_TRUSTED_PREFIX;
-		prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 		break;
 	case F2FS_XATTR_INDEX_SECURITY:
-		prefix = XATTR_SECURITY_PREFIX;
-		prefix_len = XATTR_SECURITY_PREFIX_LEN;
 		break;
 	default:
 		return -EINVAL;
 	}
 
+	prefix_len = strlen(handler->prefix);
 	total_len = prefix_len + len + 1;
 	if (list && total_len <= list_size) {
-		memcpy(list, prefix, prefix_len);
+		memcpy(list, handler->prefix, prefix_len);
 		memcpy(list + prefix_len, name, len);
 		list[prefix_len + len] = '\0';
 	}
@@ -64,7 +58,8 @@ static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
 }
 
 static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, const struct xattr_handler *handler)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
 
@@ -122,9 +117,6 @@ static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
 	const char *xname = F2FS_SYSTEM_ADVISE_PREFIX;
 	size_t size;
 
-	if (handler->flags != F2FS_XATTR_INDEX_ADVISE)
-		return 0;
-
 	size = strlen(xname) + 1;
 	if (list && size <= list_size)
 		memcpy(list, xname, size);
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 1c7e94f..cea22e6 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -828,7 +828,7 @@ posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
-	const char *xname;
+	const char *xname = handler->prefix;
 	size_t size;
 
 	if (!IS_POSIXACL(d_backing_inode(dentry)))
@@ -836,11 +836,6 @@ posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
 	if (d_is_symlink(dentry))
 		return -EOPNOTSUPP;
 
-	if (handler->flags == ACL_TYPE_ACCESS)
-		xname = POSIX_ACL_XATTR_ACCESS;
-	else
-		xname = POSIX_ACL_XATTR_DEFAULT;
-
 	size = strlen(xname) + 1;
 	if (list && size <= list_size)
 		memcpy(list, xname, size);
diff --git a/fs/squashfs/xattr.c b/fs/squashfs/xattr.c
index 05ef4b9..268e25b 100644
--- a/fs/squashfs/xattr.c
+++ b/fs/squashfs/xattr.c
@@ -212,90 +212,65 @@ failed:
 }
 
 
-/*
- * User namespace support
- */
-static size_t squashfs_user_list(struct dentry *d, char *list, size_t list_size,
-	const char *name, size_t name_len, const struct xattr_handler *handler)
+static size_t squashfs_xattr_handler_list(struct dentry *d, char *list,
+	size_t list_size, const char *name, size_t name_len,
+	const struct xattr_handler *handler)
 {
-	if (list && XATTR_USER_PREFIX_LEN <= list_size)
-		memcpy(list, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
-	return XATTR_USER_PREFIX_LEN;
+	int len = strlen(handler->prefix);
+
+	if (list && len <= list_size)
+		memcpy(list, handler->prefix, len);
+	return len;
 }
 
-static int squashfs_user_get(struct dentry *d, const char *name, void *buffer,
-	size_t size, const struct xattr_handler *handler)
+static int squashfs_xattr_handler_get(struct dentry *d, const char *name,
+	void *buffer, size_t size, const struct xattr_handler *handler)
 {
 	if (name[0] == '\0')
 		return  -EINVAL;
 
-	return squashfs_xattr_get(d_inode(d), SQUASHFS_XATTR_USER, name,
+	return squashfs_xattr_get(d_inode(d), handler->flags, name,
 		buffer, size);
 }
 
+/*
+ * User namespace support
+ */
 static const struct xattr_handler squashfs_xattr_user_handler = {
 	.prefix	= XATTR_USER_PREFIX,
-	.list	= squashfs_user_list,
-	.get	= squashfs_user_get
+	.flags	= SQUASHFS_XATTR_USER,
+	.list	= squashfs_xattr_handler_list,
+	.get	= squashfs_xattr_handler_get
 };
 
 /*
  * Trusted namespace support
  */
-static size_t squashfs_trusted_list(struct dentry *d, char *list,
+static size_t squashfs_trusted_xattr_handler_list(struct dentry *d, char *list,
 	size_t list_size, const char *name, size_t name_len,
 	const struct xattr_handler *handler)
 {
 	if (!capable(CAP_SYS_ADMIN))
 		return 0;
-
-	if (list && XATTR_TRUSTED_PREFIX_LEN <= list_size)
-		memcpy(list, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
-	return XATTR_TRUSTED_PREFIX_LEN;
-}
-
-static int squashfs_trusted_get(struct dentry *d, const char *name,
-	void *buffer, size_t size, const struct xattr_handler *handler)
-{
-	if (name[0] == '\0')
-		return  -EINVAL;
-
-	return squashfs_xattr_get(d_inode(d), SQUASHFS_XATTR_TRUSTED, name,
-		buffer, size);
+	return squashfs_xattr_handler_list(d, list, list_size, name, name_len,
+		handler);
 }
 
 static const struct xattr_handler squashfs_xattr_trusted_handler = {
 	.prefix	= XATTR_TRUSTED_PREFIX,
-	.list	= squashfs_trusted_list,
-	.get	= squashfs_trusted_get
+	.flags	= SQUASHFS_XATTR_TRUSTED,
+	.list	= squashfs_trusted_xattr_handler_list,
+	.get	= squashfs_xattr_handler_get
 };
 
 /*
  * Security namespace support
  */
-static size_t squashfs_security_list(struct dentry *d, char *list,
-	size_t list_size, const char *name, size_t name_len,
-	const struct xattr_handler *handler)
-{
-	if (list && XATTR_SECURITY_PREFIX_LEN <= list_size)
-		memcpy(list, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN);
-	return XATTR_SECURITY_PREFIX_LEN;
-}
-
-static int squashfs_security_get(struct dentry *d, const char *name,
-	void *buffer, size_t size, const struct xattr_handler *handler)
-{
-	if (name[0] == '\0')
-		return  -EINVAL;
-
-	return squashfs_xattr_get(d_inode(d), SQUASHFS_XATTR_SECURITY, name,
-		buffer, size);
-}
-
 static const struct xattr_handler squashfs_xattr_security_handler = {
 	.prefix	= XATTR_SECURITY_PREFIX,
-	.list	= squashfs_security_list,
-	.get	= squashfs_security_get
+	.flags	= SQUASHFS_XATTR_SECURITY,
+	.list	= squashfs_xattr_handler_list,
+	.get	= squashfs_xattr_handler_get
 };
 
 static const struct xattr_handler *squashfs_xattr_handler(int type)
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 05/11] xattr handlers: Some simplifications
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

We have access to struct xattr_handler inside the list/get/set operations now,
so simplify some of the xattr code.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/9p/Makefile         |  5 +---
 fs/9p/acl.c            | 51 ++++-----------------------------
 fs/9p/xattr.c          | 42 +++++++++++++++++++++++++++
 fs/9p/xattr.h          |  3 --
 fs/9p/xattr_security.c | 56 ------------------------------------
 fs/9p/xattr_trusted.c  | 56 ------------------------------------
 fs/9p/xattr_user.c     | 56 ------------------------------------
 fs/f2fs/xattr.c        | 18 ++++--------
 fs/posix_acl.c         |  7 +----
 fs/squashfs/xattr.c    | 77 +++++++++++++++++---------------------------------
 10 files changed, 80 insertions(+), 291 deletions(-)
 delete mode 100644 fs/9p/xattr_security.c
 delete mode 100644 fs/9p/xattr_trusted.c
 delete mode 100644 fs/9p/xattr_user.c

diff --git a/fs/9p/Makefile b/fs/9p/Makefile
index ff7be98..9619cca 100644
--- a/fs/9p/Makefile
+++ b/fs/9p/Makefile
@@ -10,10 +10,7 @@ obj-$(CONFIG_9P_FS) := 9p.o
 	vfs_dentry.o \
 	v9fs.o \
 	fid.o  \
-	xattr.o \
-	xattr_user.o \
-	xattr_trusted.o
+	xattr.o
 
 9p-$(CONFIG_9P_FSCACHE) += cache.o
 9p-$(CONFIG_9P_FS_POSIX_ACL) += acl.o
-9p-$(CONFIG_9P_FS_SECURITY) += xattr_security.o
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index a9e5d72..5325304 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -212,31 +212,12 @@ int v9fs_acl_mode(struct inode *dir, umode_t *modep,
 	return 0;
 }
 
-static int v9fs_remote_get_acl(struct dentry *dentry, const char *name,
-			       void *buffer, size_t size, int type)
-{
-	char *full_name;
-
-	switch (type) {
-	case ACL_TYPE_ACCESS:
-		full_name =  POSIX_ACL_XATTR_ACCESS;
-		break;
-	case ACL_TYPE_DEFAULT:
-		full_name = POSIX_ACL_XATTR_DEFAULT;
-		break;
-	default:
-		BUG();
-	}
-	return v9fs_xattr_get(dentry, full_name, buffer, size);
-}
-
 static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
 			      void *buffer, size_t size,
 			      const struct xattr_handler *handler)
 {
 	struct v9fs_session_info *v9ses;
 	struct posix_acl *acl;
-	int type = handler->flags;
 	int error;
 
 	if (strcmp(name, "") != 0)
@@ -247,9 +228,9 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
 	 * We allow set/get/list of acl when access=client is not specified
 	 */
 	if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
-		return v9fs_remote_get_acl(dentry, name, buffer, size, type);
+		return v9fs_xattr_get(dentry, handler->prefix, buffer, size);
 
-	acl = v9fs_get_cached_acl(d_inode(dentry), type);
+	acl = v9fs_get_cached_acl(d_inode(dentry), handler->flags);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl == NULL)
@@ -260,26 +241,6 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
 	return error;
 }
 
-static int v9fs_remote_set_acl(struct dentry *dentry, const char *name,
-			      const void *value, size_t size,
-			      int flags, int type)
-{
-	char *full_name;
-
-	switch (type) {
-	case ACL_TYPE_ACCESS:
-		full_name =  POSIX_ACL_XATTR_ACCESS;
-		break;
-	case ACL_TYPE_DEFAULT:
-		full_name = POSIX_ACL_XATTR_DEFAULT;
-		break;
-	default:
-		BUG();
-	}
-	return v9fs_xattr_set(dentry, full_name, value, size, flags);
-}
-
-
 static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 			      const void *value, size_t size,
 			      int flags, const struct xattr_handler *handler)
@@ -298,8 +259,8 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 	 * xattr value. We leave it to the server to validate
 	 */
 	if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
-		return v9fs_remote_set_acl(dentry, name,
-					   value, size, flags, handler->flags);
+		return v9fs_xattr_set(dentry, handler->prefix,
+				      value, size, flags);
 
 	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
@@ -320,7 +281,6 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 
 	switch (handler->flags) {
 	case ACL_TYPE_ACCESS:
-		name = POSIX_ACL_XATTR_ACCESS;
 		if (acl) {
 			umode_t mode = inode->i_mode;
 			retval = posix_acl_equiv_mode(acl, &mode);
@@ -351,7 +311,6 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 		}
 		break;
 	case ACL_TYPE_DEFAULT:
-		name = POSIX_ACL_XATTR_DEFAULT;
 		if (!S_ISDIR(inode->i_mode)) {
 			retval = acl ? -EINVAL : 0;
 			goto err_out;
@@ -360,7 +319,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 	default:
 		BUG();
 	}
-	retval = v9fs_xattr_set(dentry, name, value, size, flags);
+	retval = v9fs_xattr_set(dentry, handler->prefix, value, size, flags);
 	if (!retval)
 		set_cached_acl(inode, handler->flags, acl);
 err_out:
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
index 0cf44b6..00b28f4 100644
--- a/fs/9p/xattr.c
+++ b/fs/9p/xattr.c
@@ -137,6 +137,48 @@ ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 	return v9fs_xattr_get(dentry, NULL, buffer, buffer_size);
 }
 
+static int v9fs_xattr_handler_get(struct dentry *dentry, const char *name,
+				  void *buffer, size_t size,
+				  const struct xattr_handler *handler)
+{
+	int prefix_len = strlen(handler->prefix);
+
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return v9fs_xattr_get(dentry, name - prefix_len, buffer, size);
+}
+
+static int v9fs_xattr_handler_set(struct dentry *dentry, const char *name,
+				  const void *value, size_t size, int flags,
+				  const struct xattr_handler *handler)
+{
+	int prefix_len = strlen(handler->prefix);
+
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return v9fs_xattr_set(dentry, name - prefix_len, value, size, flags);
+}
+
+static struct xattr_handler v9fs_xattr_user_handler = {
+	.prefix	= XATTR_USER_PREFIX,
+	.get	= v9fs_xattr_handler_get,
+	.set	= v9fs_xattr_handler_set,
+};
+
+static struct xattr_handler v9fs_xattr_trusted_handler = {
+	.prefix	= XATTR_TRUSTED_PREFIX,
+	.get	= v9fs_xattr_handler_get,
+	.set	= v9fs_xattr_handler_set,
+};
+
+#ifdef CONFIG_9P_FS_SECURITY
+static struct xattr_handler v9fs_xattr_security_handler = {
+	.prefix	= XATTR_SECURITY_PREFIX,
+	.get	= v9fs_xattr_handler_get,
+	.set	= v9fs_xattr_handler_set,
+};
+#endif
+
 const struct xattr_handler *v9fs_xattr_handlers[] = {
 	&v9fs_xattr_user_handler,
 	&v9fs_xattr_trusted_handler,
diff --git a/fs/9p/xattr.h b/fs/9p/xattr.h
index d3e2ea3..c63c3be 100644
--- a/fs/9p/xattr.h
+++ b/fs/9p/xattr.h
@@ -19,9 +19,6 @@
 #include <net/9p/client.h>
 
 extern const struct xattr_handler *v9fs_xattr_handlers[];
-extern struct xattr_handler v9fs_xattr_user_handler;
-extern struct xattr_handler v9fs_xattr_trusted_handler;
-extern struct xattr_handler v9fs_xattr_security_handler;
 extern const struct xattr_handler v9fs_xattr_acl_access_handler;
 extern const struct xattr_handler v9fs_xattr_acl_default_handler;
 
diff --git a/fs/9p/xattr_security.c b/fs/9p/xattr_security.c
deleted file mode 100644
index 1d99c65..0000000
--- a/fs/9p/xattr_security.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright IBM Corporation, 2010
- * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include "xattr.h"
-
-static int v9fs_xattr_security_get(struct dentry *dentry, const char *name,
-			void *buffer, size_t size,
-			const struct xattr_handler *handler)
-{
-	const char *full_name = name - XATTR_SECURITY_PREFIX_LEN;
-
-	if (name == NULL)
-		return -EINVAL;
-
-	if (strcmp(name, "") == 0)
-		return -EINVAL;
-
-	return v9fs_xattr_get(dentry, full_name, buffer, size);
-}
-
-static int v9fs_xattr_security_set(struct dentry *dentry, const char *name,
-			const void *value, size_t size, int flags,
-			const struct xattr_handler *handler)
-{
-	const char *full_name = name - XATTR_SECURITY_PREFIX_LEN;
-
-	if (name == NULL)
-		return -EINVAL;
-
-	if (strcmp(name, "") == 0)
-		return -EINVAL;
-
-	return v9fs_xattr_set(dentry, full_name, value, size, flags);
-}
-
-struct xattr_handler v9fs_xattr_security_handler = {
-	.prefix	= XATTR_SECURITY_PREFIX,
-	.get	= v9fs_xattr_security_get,
-	.set	= v9fs_xattr_security_set,
-};
diff --git a/fs/9p/xattr_trusted.c b/fs/9p/xattr_trusted.c
deleted file mode 100644
index 1a24647..0000000
--- a/fs/9p/xattr_trusted.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright IBM Corporation, 2010
- * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include "xattr.h"
-
-static int v9fs_xattr_trusted_get(struct dentry *dentry, const char *name,
-			void *buffer, size_t size,
-			const struct xattr_handler *handler)
-{
-	const char *full_name = name - XATTR_TRUSTED_PREFIX_LEN;
-
-	if (name == NULL)
-		return -EINVAL;
-
-	if (strcmp(name, "") == 0)
-		return -EINVAL;
-
-	return v9fs_xattr_get(dentry, full_name, buffer, size);
-}
-
-static int v9fs_xattr_trusted_set(struct dentry *dentry, const char *name,
-			const void *value, size_t size, int flags,
-			const struct xattr_handler *handler)
-{
-	const char *full_name = name - XATTR_TRUSTED_PREFIX_LEN;
-
-	if (name == NULL)
-		return -EINVAL;
-
-	if (strcmp(name, "") == 0)
-		return -EINVAL;
-
-	return v9fs_xattr_set(dentry, full_name, value, size, flags);
-}
-
-struct xattr_handler v9fs_xattr_trusted_handler = {
-	.prefix	= XATTR_TRUSTED_PREFIX,
-	.get	= v9fs_xattr_trusted_get,
-	.set	= v9fs_xattr_trusted_set,
-};
diff --git a/fs/9p/xattr_user.c b/fs/9p/xattr_user.c
deleted file mode 100644
index 2c35e16..0000000
--- a/fs/9p/xattr_user.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright IBM Corporation, 2010
- * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include "xattr.h"
-
-static int v9fs_xattr_user_get(struct dentry *dentry, const char *name,
-			void *buffer, size_t size,
-			const struct xattr_handler *handler)
-{
-	const char *full_name = name - XATTR_USER_PREFIX_LEN;
-
-	if (name == NULL)
-		return -EINVAL;
-
-	if (strcmp(name, "") == 0)
-		return -EINVAL;
-
-	return v9fs_xattr_get(dentry, full_name, buffer, size);
-}
-
-static int v9fs_xattr_user_set(struct dentry *dentry, const char *name,
-			const void *value, size_t size, int flags,
-			const struct xattr_handler *handler)
-{
-	const char *full_name = name - XATTR_USER_PREFIX_LEN;
-
-	if (name == NULL)
-		return -EINVAL;
-
-	if (strcmp(name, "") == 0)
-		return -EINVAL;
-
-	return v9fs_xattr_set(dentry, full_name, value, size, flags);
-}
-
-struct xattr_handler v9fs_xattr_user_handler = {
-	.prefix	= XATTR_USER_PREFIX,
-	.get	= v9fs_xattr_user_get,
-	.set	= v9fs_xattr_user_set,
-};
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index fdc9849..1c3e5e7 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -30,33 +30,27 @@ static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
 		const struct xattr_handler *handler)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
-	int total_len, prefix_len = 0;
-	const char *prefix = NULL;
+	int total_len, prefix_len;
 
 	switch (handler->flags) {
 	case F2FS_XATTR_INDEX_USER:
 		if (!test_opt(sbi, XATTR_USER))
 			return -EOPNOTSUPP;
-		prefix = XATTR_USER_PREFIX;
-		prefix_len = XATTR_USER_PREFIX_LEN;
 		break;
 	case F2FS_XATTR_INDEX_TRUSTED:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		prefix = XATTR_TRUSTED_PREFIX;
-		prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 		break;
 	case F2FS_XATTR_INDEX_SECURITY:
-		prefix = XATTR_SECURITY_PREFIX;
-		prefix_len = XATTR_SECURITY_PREFIX_LEN;
 		break;
 	default:
 		return -EINVAL;
 	}
 
+	prefix_len = strlen(handler->prefix);
 	total_len = prefix_len + len + 1;
 	if (list && total_len <= list_size) {
-		memcpy(list, prefix, prefix_len);
+		memcpy(list, handler->prefix, prefix_len);
 		memcpy(list + prefix_len, name, len);
 		list[prefix_len + len] = '\0';
 	}
@@ -64,7 +58,8 @@ static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
 }
 
 static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
-		void *buffer, size_t size, const struct xattr_handler *handler)
+		void *buffer, size_t size,
+		const struct xattr_handler *handler)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
 
@@ -122,9 +117,6 @@ static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
 	const char *xname = F2FS_SYSTEM_ADVISE_PREFIX;
 	size_t size;
 
-	if (handler->flags != F2FS_XATTR_INDEX_ADVISE)
-		return 0;
-
 	size = strlen(xname) + 1;
 	if (list && size <= list_size)
 		memcpy(list, xname, size);
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 1c7e94f..cea22e6 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -828,7 +828,7 @@ posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
-	const char *xname;
+	const char *xname = handler->prefix;
 	size_t size;
 
 	if (!IS_POSIXACL(d_backing_inode(dentry)))
@@ -836,11 +836,6 @@ posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
 	if (d_is_symlink(dentry))
 		return -EOPNOTSUPP;
 
-	if (handler->flags == ACL_TYPE_ACCESS)
-		xname = POSIX_ACL_XATTR_ACCESS;
-	else
-		xname = POSIX_ACL_XATTR_DEFAULT;
-
 	size = strlen(xname) + 1;
 	if (list && size <= list_size)
 		memcpy(list, xname, size);
diff --git a/fs/squashfs/xattr.c b/fs/squashfs/xattr.c
index 05ef4b9..268e25b 100644
--- a/fs/squashfs/xattr.c
+++ b/fs/squashfs/xattr.c
@@ -212,90 +212,65 @@ failed:
 }
 
 
-/*
- * User namespace support
- */
-static size_t squashfs_user_list(struct dentry *d, char *list, size_t list_size,
-	const char *name, size_t name_len, const struct xattr_handler *handler)
+static size_t squashfs_xattr_handler_list(struct dentry *d, char *list,
+	size_t list_size, const char *name, size_t name_len,
+	const struct xattr_handler *handler)
 {
-	if (list && XATTR_USER_PREFIX_LEN <= list_size)
-		memcpy(list, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
-	return XATTR_USER_PREFIX_LEN;
+	int len = strlen(handler->prefix);
+
+	if (list && len <= list_size)
+		memcpy(list, handler->prefix, len);
+	return len;
 }
 
-static int squashfs_user_get(struct dentry *d, const char *name, void *buffer,
-	size_t size, const struct xattr_handler *handler)
+static int squashfs_xattr_handler_get(struct dentry *d, const char *name,
+	void *buffer, size_t size, const struct xattr_handler *handler)
 {
 	if (name[0] == '\0')
 		return  -EINVAL;
 
-	return squashfs_xattr_get(d_inode(d), SQUASHFS_XATTR_USER, name,
+	return squashfs_xattr_get(d_inode(d), handler->flags, name,
 		buffer, size);
 }
 
+/*
+ * User namespace support
+ */
 static const struct xattr_handler squashfs_xattr_user_handler = {
 	.prefix	= XATTR_USER_PREFIX,
-	.list	= squashfs_user_list,
-	.get	= squashfs_user_get
+	.flags	= SQUASHFS_XATTR_USER,
+	.list	= squashfs_xattr_handler_list,
+	.get	= squashfs_xattr_handler_get
 };
 
 /*
  * Trusted namespace support
  */
-static size_t squashfs_trusted_list(struct dentry *d, char *list,
+static size_t squashfs_trusted_xattr_handler_list(struct dentry *d, char *list,
 	size_t list_size, const char *name, size_t name_len,
 	const struct xattr_handler *handler)
 {
 	if (!capable(CAP_SYS_ADMIN))
 		return 0;
-
-	if (list && XATTR_TRUSTED_PREFIX_LEN <= list_size)
-		memcpy(list, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
-	return XATTR_TRUSTED_PREFIX_LEN;
-}
-
-static int squashfs_trusted_get(struct dentry *d, const char *name,
-	void *buffer, size_t size, const struct xattr_handler *handler)
-{
-	if (name[0] == '\0')
-		return  -EINVAL;
-
-	return squashfs_xattr_get(d_inode(d), SQUASHFS_XATTR_TRUSTED, name,
-		buffer, size);
+	return squashfs_xattr_handler_list(d, list, list_size, name, name_len,
+		handler);
 }
 
 static const struct xattr_handler squashfs_xattr_trusted_handler = {
 	.prefix	= XATTR_TRUSTED_PREFIX,
-	.list	= squashfs_trusted_list,
-	.get	= squashfs_trusted_get
+	.flags	= SQUASHFS_XATTR_TRUSTED,
+	.list	= squashfs_trusted_xattr_handler_list,
+	.get	= squashfs_xattr_handler_get
 };
 
 /*
  * Security namespace support
  */
-static size_t squashfs_security_list(struct dentry *d, char *list,
-	size_t list_size, const char *name, size_t name_len,
-	const struct xattr_handler *handler)
-{
-	if (list && XATTR_SECURITY_PREFIX_LEN <= list_size)
-		memcpy(list, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN);
-	return XATTR_SECURITY_PREFIX_LEN;
-}
-
-static int squashfs_security_get(struct dentry *d, const char *name,
-	void *buffer, size_t size, const struct xattr_handler *handler)
-{
-	if (name[0] == '\0')
-		return  -EINVAL;
-
-	return squashfs_xattr_get(d_inode(d), SQUASHFS_XATTR_SECURITY, name,
-		buffer, size);
-}
-
 static const struct xattr_handler squashfs_xattr_security_handler = {
 	.prefix	= XATTR_SECURITY_PREFIX,
-	.list	= squashfs_security_list,
-	.get	= squashfs_security_get
+	.flags	= SQUASHFS_XATTR_SECURITY,
+	.list	= squashfs_xattr_handler_list,
+	.get	= squashfs_xattr_handler_get
 };
 
 static const struct xattr_handler *squashfs_xattr_handler(int type)
-- 
2.4.3



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC 06/11] lib: Move strcmp_prefix into string.c
  2015-08-20 18:19 ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  -1 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	linux-fsdevel, David Quigley, J. Bruce Fields
  Cc: linux-security-module, cluster-devel

Move strcmp_prefix from fs/xattr.c into lib/string.h to make it available
elsewhere; export it to modules.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/xattr.c             | 11 -----------
 include/linux/string.h |  1 +
 lib/string.c           | 16 ++++++++++++++++
 3 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/fs/xattr.c b/fs/xattr.c
index efa16ce..9584808 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -663,17 +663,6 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
 	return error;
 }
 
-
-static const char *
-strcmp_prefix(const char *a, const char *a_prefix)
-{
-	while (*a_prefix && *a == *a_prefix) {
-		a++;
-		a_prefix++;
-	}
-	return *a_prefix ? NULL : a;
-}
-
 /*
  * In order to implement different sets of xattr operations for each xattr
  * prefix with the generic xattr API, a filesystem should create a
diff --git a/include/linux/string.h b/include/linux/string.h
index a8d90db..edc155d 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -37,6 +37,7 @@ extern size_t strlcat(char *, const char *, __kernel_size_t);
 #ifndef __HAVE_ARCH_STRCMP
 extern int strcmp(const char *,const char *);
 #endif
+extern const char *strcmp_prefix(const char *, const char *);
 #ifndef __HAVE_ARCH_STRNCMP
 extern int strncmp(const char *,const char *,__kernel_size_t);
 #endif
diff --git a/lib/string.c b/lib/string.c
index 13d1e84..697572d 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -246,6 +246,22 @@ int strcmp(const char *cs, const char *ct)
 EXPORT_SYMBOL(strcmp);
 #endif
 
+/**
+ * strcmp_prefix  -  check string for given prefix
+ *
+ * Returns @str + strlen(@prefix) if @str has the given @prefix, and NULL
+ * otherwise.
+ */
+const char *strcmp_prefix(const char *str, const char *prefix)
+{
+	while (*prefix && *str == *prefix) {
+		str++;
+		prefix++;
+	}
+	return *prefix ? NULL : str;
+}
+EXPORT_SYMBOL(strcmp_prefix);
+
 #ifndef __HAVE_ARCH_STRNCMP
 /**
  * strncmp - Compare two length-limited strings
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 06/11] lib: Move strcmp_prefix into string.c
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Move strcmp_prefix from fs/xattr.c into lib/string.h to make it available
elsewhere; export it to modules.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/xattr.c             | 11 -----------
 include/linux/string.h |  1 +
 lib/string.c           | 16 ++++++++++++++++
 3 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/fs/xattr.c b/fs/xattr.c
index efa16ce..9584808 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -663,17 +663,6 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
 	return error;
 }
 
-
-static const char *
-strcmp_prefix(const char *a, const char *a_prefix)
-{
-	while (*a_prefix && *a == *a_prefix) {
-		a++;
-		a_prefix++;
-	}
-	return *a_prefix ? NULL : a;
-}
-
 /*
  * In order to implement different sets of xattr operations for each xattr
  * prefix with the generic xattr API, a filesystem should create a
diff --git a/include/linux/string.h b/include/linux/string.h
index a8d90db..edc155d 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -37,6 +37,7 @@ extern size_t strlcat(char *, const char *, __kernel_size_t);
 #ifndef __HAVE_ARCH_STRCMP
 extern int strcmp(const char *,const char *);
 #endif
+extern const char *strcmp_prefix(const char *, const char *);
 #ifndef __HAVE_ARCH_STRNCMP
 extern int strncmp(const char *,const char *,__kernel_size_t);
 #endif
diff --git a/lib/string.c b/lib/string.c
index 13d1e84..697572d 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -246,6 +246,22 @@ int strcmp(const char *cs, const char *ct)
 EXPORT_SYMBOL(strcmp);
 #endif
 
+/**
+ * strcmp_prefix  -  check string for given prefix
+ *
+ * Returns @str + strlen(@prefix) if @str has the given @prefix, and NULL
+ * otherwise.
+ */
+const char *strcmp_prefix(const char *str, const char *prefix)
+{
+	while (*prefix && *str == *prefix) {
+		str++;
+		prefix++;
+	}
+	return *prefix ? NULL : str;
+}
+EXPORT_SYMBOL(strcmp_prefix);
+
 #ifndef __HAVE_ARCH_STRNCMP
 /**
  * strncmp - Compare two length-limited strings
-- 
2.4.3



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC 07/11] 9p: Stop using the generic xattr_handler infrastructure
  2015-08-20 18:19 ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  -1 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	linux-fsdevel, David Quigley, J. Bruce Fields
  Cc: linux-security-module, cluster-devel

Of all the file systems that use the generic xattr handler infrastructure, 9p
is the only one that needs dentries inside the xattr file system code.  Open
code the xattr handling code in 9p so that we can then convert the generic code
to pass down inodes instead of dentries; this actually takes only little
additional code.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/9p/acl.c       | 12 ++++++------
 fs/9p/vfs_super.c |  5 ++---
 fs/9p/xattr.c     | 46 ++++++++++++++++++++++++++++++++++++++--------
 fs/9p/xattr.h     | 15 ++++++++++++---
 4 files changed, 58 insertions(+), 20 deletions(-)

diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index 5325304..d6a02e0 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -212,9 +212,9 @@ int v9fs_acl_mode(struct inode *dir, umode_t *modep,
 	return 0;
 }
 
-static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
-			      void *buffer, size_t size,
-			      const struct xattr_handler *handler)
+static ssize_t v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
+				  void *buffer, size_t size,
+				  const struct v9fs_xattr_handler *handler)
 {
 	struct v9fs_session_info *v9ses;
 	struct posix_acl *acl;
@@ -243,7 +243,7 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
 
 static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 			      const void *value, size_t size,
-			      int flags, const struct xattr_handler *handler)
+			      int flags, const struct v9fs_xattr_handler *handler)
 {
 	int retval;
 	struct posix_acl *acl;
@@ -327,14 +327,14 @@ err_out:
 	return retval;
 }
 
-const struct xattr_handler v9fs_xattr_acl_access_handler = {
+const struct v9fs_xattr_handler v9fs_xattr_acl_access_handler = {
 	.prefix	= POSIX_ACL_XATTR_ACCESS,
 	.flags	= ACL_TYPE_ACCESS,
 	.get	= v9fs_xattr_get_acl,
 	.set	= v9fs_xattr_set_acl,
 };
 
-const struct xattr_handler v9fs_xattr_acl_default_handler = {
+const struct v9fs_xattr_handler v9fs_xattr_acl_default_handler = {
 	.prefix	= POSIX_ACL_XATTR_DEFAULT,
 	.flags	= ACL_TYPE_DEFAULT,
 	.get	= v9fs_xattr_get_acl,
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index bf495ce..7914544 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -80,10 +80,9 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
 	sb->s_blocksize_bits = fls(v9ses->maxdata - 1);
 	sb->s_blocksize = 1 << sb->s_blocksize_bits;
 	sb->s_magic = V9FS_MAGIC;
-	if (v9fs_proto_dotl(v9ses)) {
+	if (v9fs_proto_dotl(v9ses))
 		sb->s_op = &v9fs_super_ops_dotl;
-		sb->s_xattr = v9fs_xattr_handlers;
-	} else
+	else
 		sb->s_op = &v9fs_super_ops;
 	sb->s_bdi = &v9ses->bdi;
 	if (v9ses->cache)
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
index 00b28f4..64ffd00 100644
--- a/fs/9p/xattr.c
+++ b/fs/9p/xattr.c
@@ -132,14 +132,44 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
 	return retval;
 }
 
+ssize_t v9fs_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
+{
+	const struct v9fs_xattr_handler **handlers = v9fs_xattr_handlers;
+
+	for (; *handlers != NULL; handlers++) {
+		const struct v9fs_xattr_handler *handler = *handlers;
+		const char *suffix = strcmp_prefix(name, handler->prefix);
+
+		if (suffix)
+			return handler->get(dentry, suffix, buffer, size, handler);
+	}
+	return -EOPNOTSUPP;
+}
+
+int v9fs_setxattr(struct dentry *dentry, const char *name, const void *value,
+		  size_t size, int flags)
+{
+	const struct v9fs_xattr_handler **handlers = v9fs_xattr_handlers;
+
+	for (; *handlers != NULL; handlers++) {
+		const struct v9fs_xattr_handler *handler = *handlers;
+		const char *suffix = strcmp_prefix(name, handler->prefix);
+
+		if (suffix)
+			return handler->set(dentry, name, value, size, flags,
+					    handler);
+	}
+	return -EOPNOTSUPP;
+}
+
 ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
 	return v9fs_xattr_get(dentry, NULL, buffer, buffer_size);
 }
 
-static int v9fs_xattr_handler_get(struct dentry *dentry, const char *name,
-				  void *buffer, size_t size,
-				  const struct xattr_handler *handler)
+static ssize_t v9fs_xattr_handler_get(struct dentry *dentry, const char *name,
+				      void *buffer, size_t size,
+				      const struct v9fs_xattr_handler *handler)
 {
 	int prefix_len = strlen(handler->prefix);
 
@@ -150,7 +180,7 @@ static int v9fs_xattr_handler_get(struct dentry *dentry, const char *name,
 
 static int v9fs_xattr_handler_set(struct dentry *dentry, const char *name,
 				  const void *value, size_t size, int flags,
-				  const struct xattr_handler *handler)
+				  const struct v9fs_xattr_handler *handler)
 {
 	int prefix_len = strlen(handler->prefix);
 
@@ -159,27 +189,27 @@ static int v9fs_xattr_handler_set(struct dentry *dentry, const char *name,
 	return v9fs_xattr_set(dentry, name - prefix_len, value, size, flags);
 }
 
-static struct xattr_handler v9fs_xattr_user_handler = {
+static struct v9fs_xattr_handler v9fs_xattr_user_handler = {
 	.prefix	= XATTR_USER_PREFIX,
 	.get	= v9fs_xattr_handler_get,
 	.set	= v9fs_xattr_handler_set,
 };
 
-static struct xattr_handler v9fs_xattr_trusted_handler = {
+static struct v9fs_xattr_handler v9fs_xattr_trusted_handler = {
 	.prefix	= XATTR_TRUSTED_PREFIX,
 	.get	= v9fs_xattr_handler_get,
 	.set	= v9fs_xattr_handler_set,
 };
 
 #ifdef CONFIG_9P_FS_SECURITY
-static struct xattr_handler v9fs_xattr_security_handler = {
+static struct v9fs_xattr_handler v9fs_xattr_security_handler = {
 	.prefix	= XATTR_SECURITY_PREFIX,
 	.get	= v9fs_xattr_handler_get,
 	.set	= v9fs_xattr_handler_set,
 };
 #endif
 
-const struct xattr_handler *v9fs_xattr_handlers[] = {
+const struct v9fs_xattr_handler *v9fs_xattr_handlers[] = {
 	&v9fs_xattr_user_handler,
 	&v9fs_xattr_trusted_handler,
 #ifdef CONFIG_9P_FS_POSIX_ACL
diff --git a/fs/9p/xattr.h b/fs/9p/xattr.h
index c63c3be..488ad6d 100644
--- a/fs/9p/xattr.h
+++ b/fs/9p/xattr.h
@@ -18,9 +18,18 @@
 #include <net/9p/9p.h>
 #include <net/9p/client.h>
 
-extern const struct xattr_handler *v9fs_xattr_handlers[];
-extern const struct xattr_handler v9fs_xattr_acl_access_handler;
-extern const struct xattr_handler v9fs_xattr_acl_default_handler;
+struct v9fs_xattr_handler {
+	const char *prefix;
+	int flags;
+	ssize_t (*get)(struct dentry *, const char *, void *, size_t,
+		       const struct v9fs_xattr_handler *);
+	int (*set)(struct dentry *, const char *, const void *, size_t, int,
+		   const struct v9fs_xattr_handler *);
+};
+
+extern const struct v9fs_xattr_handler *v9fs_xattr_handlers[];
+extern const struct v9fs_xattr_handler v9fs_xattr_acl_access_handler;
+extern const struct v9fs_xattr_handler v9fs_xattr_acl_default_handler;
 
 extern ssize_t v9fs_fid_xattr_get(struct p9_fid *, const char *,
 				  void *, size_t);
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 07/11] 9p: Stop using the generic xattr_handler infrastructure
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Of all the file systems that use the generic xattr handler infrastructure, 9p
is the only one that needs dentries inside the xattr file system code.  Open
code the xattr handling code in 9p so that we can then convert the generic code
to pass down inodes instead of dentries; this actually takes only little
additional code.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/9p/acl.c       | 12 ++++++------
 fs/9p/vfs_super.c |  5 ++---
 fs/9p/xattr.c     | 46 ++++++++++++++++++++++++++++++++++++++--------
 fs/9p/xattr.h     | 15 ++++++++++++---
 4 files changed, 58 insertions(+), 20 deletions(-)

diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index 5325304..d6a02e0 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -212,9 +212,9 @@ int v9fs_acl_mode(struct inode *dir, umode_t *modep,
 	return 0;
 }
 
-static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
-			      void *buffer, size_t size,
-			      const struct xattr_handler *handler)
+static ssize_t v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
+				  void *buffer, size_t size,
+				  const struct v9fs_xattr_handler *handler)
 {
 	struct v9fs_session_info *v9ses;
 	struct posix_acl *acl;
@@ -243,7 +243,7 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
 
 static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 			      const void *value, size_t size,
-			      int flags, const struct xattr_handler *handler)
+			      int flags, const struct v9fs_xattr_handler *handler)
 {
 	int retval;
 	struct posix_acl *acl;
@@ -327,14 +327,14 @@ err_out:
 	return retval;
 }
 
-const struct xattr_handler v9fs_xattr_acl_access_handler = {
+const struct v9fs_xattr_handler v9fs_xattr_acl_access_handler = {
 	.prefix	= POSIX_ACL_XATTR_ACCESS,
 	.flags	= ACL_TYPE_ACCESS,
 	.get	= v9fs_xattr_get_acl,
 	.set	= v9fs_xattr_set_acl,
 };
 
-const struct xattr_handler v9fs_xattr_acl_default_handler = {
+const struct v9fs_xattr_handler v9fs_xattr_acl_default_handler = {
 	.prefix	= POSIX_ACL_XATTR_DEFAULT,
 	.flags	= ACL_TYPE_DEFAULT,
 	.get	= v9fs_xattr_get_acl,
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index bf495ce..7914544 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -80,10 +80,9 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
 	sb->s_blocksize_bits = fls(v9ses->maxdata - 1);
 	sb->s_blocksize = 1 << sb->s_blocksize_bits;
 	sb->s_magic = V9FS_MAGIC;
-	if (v9fs_proto_dotl(v9ses)) {
+	if (v9fs_proto_dotl(v9ses))
 		sb->s_op = &v9fs_super_ops_dotl;
-		sb->s_xattr = v9fs_xattr_handlers;
-	} else
+	else
 		sb->s_op = &v9fs_super_ops;
 	sb->s_bdi = &v9ses->bdi;
 	if (v9ses->cache)
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
index 00b28f4..64ffd00 100644
--- a/fs/9p/xattr.c
+++ b/fs/9p/xattr.c
@@ -132,14 +132,44 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
 	return retval;
 }
 
+ssize_t v9fs_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
+{
+	const struct v9fs_xattr_handler **handlers = v9fs_xattr_handlers;
+
+	for (; *handlers != NULL; handlers++) {
+		const struct v9fs_xattr_handler *handler = *handlers;
+		const char *suffix = strcmp_prefix(name, handler->prefix);
+
+		if (suffix)
+			return handler->get(dentry, suffix, buffer, size, handler);
+	}
+	return -EOPNOTSUPP;
+}
+
+int v9fs_setxattr(struct dentry *dentry, const char *name, const void *value,
+		  size_t size, int flags)
+{
+	const struct v9fs_xattr_handler **handlers = v9fs_xattr_handlers;
+
+	for (; *handlers != NULL; handlers++) {
+		const struct v9fs_xattr_handler *handler = *handlers;
+		const char *suffix = strcmp_prefix(name, handler->prefix);
+
+		if (suffix)
+			return handler->set(dentry, name, value, size, flags,
+					    handler);
+	}
+	return -EOPNOTSUPP;
+}
+
 ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
 	return v9fs_xattr_get(dentry, NULL, buffer, buffer_size);
 }
 
-static int v9fs_xattr_handler_get(struct dentry *dentry, const char *name,
-				  void *buffer, size_t size,
-				  const struct xattr_handler *handler)
+static ssize_t v9fs_xattr_handler_get(struct dentry *dentry, const char *name,
+				      void *buffer, size_t size,
+				      const struct v9fs_xattr_handler *handler)
 {
 	int prefix_len = strlen(handler->prefix);
 
@@ -150,7 +180,7 @@ static int v9fs_xattr_handler_get(struct dentry *dentry, const char *name,
 
 static int v9fs_xattr_handler_set(struct dentry *dentry, const char *name,
 				  const void *value, size_t size, int flags,
-				  const struct xattr_handler *handler)
+				  const struct v9fs_xattr_handler *handler)
 {
 	int prefix_len = strlen(handler->prefix);
 
@@ -159,27 +189,27 @@ static int v9fs_xattr_handler_set(struct dentry *dentry, const char *name,
 	return v9fs_xattr_set(dentry, name - prefix_len, value, size, flags);
 }
 
-static struct xattr_handler v9fs_xattr_user_handler = {
+static struct v9fs_xattr_handler v9fs_xattr_user_handler = {
 	.prefix	= XATTR_USER_PREFIX,
 	.get	= v9fs_xattr_handler_get,
 	.set	= v9fs_xattr_handler_set,
 };
 
-static struct xattr_handler v9fs_xattr_trusted_handler = {
+static struct v9fs_xattr_handler v9fs_xattr_trusted_handler = {
 	.prefix	= XATTR_TRUSTED_PREFIX,
 	.get	= v9fs_xattr_handler_get,
 	.set	= v9fs_xattr_handler_set,
 };
 
 #ifdef CONFIG_9P_FS_SECURITY
-static struct xattr_handler v9fs_xattr_security_handler = {
+static struct v9fs_xattr_handler v9fs_xattr_security_handler = {
 	.prefix	= XATTR_SECURITY_PREFIX,
 	.get	= v9fs_xattr_handler_get,
 	.set	= v9fs_xattr_handler_set,
 };
 #endif
 
-const struct xattr_handler *v9fs_xattr_handlers[] = {
+const struct v9fs_xattr_handler *v9fs_xattr_handlers[] = {
 	&v9fs_xattr_user_handler,
 	&v9fs_xattr_trusted_handler,
 #ifdef CONFIG_9P_FS_POSIX_ACL
diff --git a/fs/9p/xattr.h b/fs/9p/xattr.h
index c63c3be..488ad6d 100644
--- a/fs/9p/xattr.h
+++ b/fs/9p/xattr.h
@@ -18,9 +18,18 @@
 #include <net/9p/9p.h>
 #include <net/9p/client.h>
 
-extern const struct xattr_handler *v9fs_xattr_handlers[];
-extern const struct xattr_handler v9fs_xattr_acl_access_handler;
-extern const struct xattr_handler v9fs_xattr_acl_default_handler;
+struct v9fs_xattr_handler {
+	const char *prefix;
+	int flags;
+	ssize_t (*get)(struct dentry *, const char *, void *, size_t,
+		       const struct v9fs_xattr_handler *);
+	int (*set)(struct dentry *, const char *, const void *, size_t, int,
+		   const struct v9fs_xattr_handler *);
+};
+
+extern const struct v9fs_xattr_handler *v9fs_xattr_handlers[];
+extern const struct v9fs_xattr_handler v9fs_xattr_acl_access_handler;
+extern const struct v9fs_xattr_handler v9fs_xattr_acl_default_handler;
 
 extern ssize_t v9fs_fid_xattr_get(struct p9_fid *, const char *,
 				  void *, size_t);
-- 
2.4.3



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC 08/11] xattr: Pass inodes to xattr handlers instead of dentries
  2015-08-20 18:19 ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  -1 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	linux-fsdevel, David Quigley, J. Bruce Fields
  Cc: linux-security-module, cluster-devel

All remaining file systems that use the generic xattr_handler infrastructure
only access dentry->d_inode and do nothing else with the dentry, so pass down
the inode instead of the dentry to the xattr_handler operations.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/ext2/xattr.c              |  2 +-
 fs/ext2/xattr_security.c     | 10 +++++-----
 fs/ext2/xattr_trusted.c      | 10 +++++-----
 fs/ext2/xattr_user.c         | 16 ++++++++--------
 fs/ext3/xattr.c              |  3 ++-
 fs/ext3/xattr_security.c     | 10 +++++-----
 fs/ext3/xattr_trusted.c      | 10 +++++-----
 fs/ext3/xattr_user.c         | 16 ++++++++--------
 fs/ext4/xattr.c              |  3 ++-
 fs/ext4/xattr_security.c     | 10 +++++-----
 fs/ext4/xattr_trusted.c      | 10 +++++-----
 fs/ext4/xattr_user.c         | 16 ++++++++--------
 fs/f2fs/xattr.c              | 31 +++++++++++++------------------
 fs/gfs2/xattr.c              |  8 ++++----
 fs/hfsplus/xattr.c           | 16 ++++++++--------
 fs/hfsplus/xattr.h           |  4 ++--
 fs/hfsplus/xattr_security.c  |  8 ++++----
 fs/hfsplus/xattr_trusted.c   |  8 ++++----
 fs/hfsplus/xattr_user.c      |  8 ++++----
 fs/jffs2/security.c          | 10 +++++-----
 fs/jffs2/xattr.c             |  4 ++--
 fs/jffs2/xattr_trusted.c     | 10 +++++-----
 fs/jffs2/xattr_user.c        | 10 +++++-----
 fs/nfs/nfs4proc.c            | 31 +++++++++++++++----------------
 fs/ocfs2/xattr.c             | 36 ++++++++++++++++++------------------
 fs/posix_acl.c               | 17 ++++++++---------
 fs/reiserfs/xattr.c          | 28 ++++++++++++++++------------
 fs/reiserfs/xattr_security.c | 16 ++++++++--------
 fs/reiserfs/xattr_trusted.c  | 16 ++++++++--------
 fs/reiserfs/xattr_user.c     | 16 ++++++++--------
 fs/squashfs/xattr.c          | 12 ++++++------
 fs/xattr.c                   | 12 ++++++------
 fs/xfs/xfs_xattr.c           |  8 ++++----
 include/linux/xattr.h        |  6 +++---
 34 files changed, 215 insertions(+), 216 deletions(-)

diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index f786688..b42d1cd 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -293,7 +293,7 @@ bad_block:	ext2_error(inode->i_sb, "ext2_xattr_list",
 			ext2_xattr_handler(entry->e_name_index);
 
 		if (handler) {
-			size_t size = handler->list(dentry, buffer, rest,
+			size_t size = handler->list(inode, buffer, rest,
 						    entry->e_name,
 						    entry->e_name_len,
 						    handler);
diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c
index ed9f7a32..94fe3a9 100644
--- a/fs/ext2/xattr_security.c
+++ b/fs/ext2/xattr_security.c
@@ -8,7 +8,7 @@
 #include "xattr.h"
 
 static size_t
-ext2_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
+ext2_xattr_security_list(struct inode *inode, char *list, size_t list_size,
 			 const char *name, size_t name_len,
 			 const struct xattr_handler *handler)
 {
@@ -24,24 +24,24 @@ ext2_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext2_xattr_security_get(struct dentry *dentry, const char *name,
+ext2_xattr_security_get(struct inode *inode, const char *name,
 		       void *buffer, size_t size,
 		       const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name,
+	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_SECURITY, name,
 			      buffer, size);
 }
 
 static int
-ext2_xattr_security_set(struct dentry *dentry, const char *name,
+ext2_xattr_security_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name,
+	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, name,
 			      value, size, flags);
 }
 
diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c
index 991676b..ce5e33f 100644
--- a/fs/ext2/xattr_trusted.c
+++ b/fs/ext2/xattr_trusted.c
@@ -9,7 +9,7 @@
 #include "xattr.h"
 
 static size_t
-ext2_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
+ext2_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
@@ -28,24 +28,24 @@ ext2_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext2_xattr_trusted_get(struct dentry *dentry, const char *name,
+ext2_xattr_trusted_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name,
+	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_TRUSTED, name,
 			      buffer, size);
 }
 
 static int
-ext2_xattr_trusted_set(struct dentry *dentry, const char *name,
+ext2_xattr_trusted_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name,
+	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_TRUSTED, name,
 			      value, size, flags);
 }
 
diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c
index b8f7c02..06adb5b 100644
--- a/fs/ext2/xattr_user.c
+++ b/fs/ext2/xattr_user.c
@@ -11,14 +11,14 @@
 #include "xattr.h"
 
 static size_t
-ext2_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
+ext2_xattr_user_list(struct inode *inode, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
 
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return 0;
 
 	if (list && total_len <= list_size) {
@@ -30,29 +30,29 @@ ext2_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext2_xattr_user_get(struct dentry *dentry, const char *name,
+ext2_xattr_user_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_USER,
+	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER,
 			      name, buffer, size);
 }
 
 static int
-ext2_xattr_user_set(struct dentry *dentry, const char *name,
+ext2_xattr_user_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
 
-	return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_USER,
+	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER,
 			      name, value, size, flags);
 }
 
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 4c35ac4..392ef8b 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -330,6 +330,7 @@ static int
 ext3_xattr_list_entries(struct dentry *dentry, struct ext3_xattr_entry *entry,
 			char *buffer, size_t buffer_size)
 {
+	struct inode *inode = d_inode(dentry);
 	size_t rest = buffer_size;
 
 	for (; !IS_LAST_ENTRY(entry); entry = EXT3_XATTR_NEXT(entry)) {
@@ -337,7 +338,7 @@ ext3_xattr_list_entries(struct dentry *dentry, struct ext3_xattr_entry *entry,
 			ext3_xattr_handler(entry->e_name_index);
 
 		if (handler) {
-			size_t size = handler->list(dentry, buffer, rest,
+			size_t size = handler->list(inode, buffer, rest,
 						    entry->e_name,
 						    entry->e_name_len,
 						    handler);
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index c26ebe0..05fa7e7 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -8,7 +8,7 @@
 #include "xattr.h"
 
 static size_t
-ext3_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
+ext3_xattr_security_list(struct inode *inode, char *list, size_t list_size,
 			 const char *name, size_t name_len,
 			 const struct xattr_handler *handler)
 {
@@ -25,24 +25,24 @@ ext3_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext3_xattr_security_get(struct dentry *dentry, const char *name,
+ext3_xattr_security_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext3_xattr_get(d_inode(dentry), EXT3_XATTR_INDEX_SECURITY,
+	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_SECURITY,
 			      name, buffer, size);
 }
 
 static int
-ext3_xattr_security_set(struct dentry *dentry, const char *name,
+ext3_xattr_security_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext3_xattr_set(d_inode(dentry), EXT3_XATTR_INDEX_SECURITY,
+	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_SECURITY,
 			      name, value, size, flags);
 }
 
diff --git a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c
index ba3ea56..1b25c3d 100644
--- a/fs/ext3/xattr_trusted.c
+++ b/fs/ext3/xattr_trusted.c
@@ -9,7 +9,7 @@
 #include "xattr.h"
 
 static size_t
-ext3_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
+ext3_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
@@ -28,24 +28,24 @@ ext3_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext3_xattr_trusted_get(struct dentry *dentry, const char *name,
+ext3_xattr_trusted_get(struct inode *inode, const char *name,
 		       void *buffer, size_t size,
 		       const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext3_xattr_get(d_inode(dentry), EXT3_XATTR_INDEX_TRUSTED,
+	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED,
 			      name, buffer, size);
 }
 
 static int
-ext3_xattr_trusted_set(struct dentry *dentry, const char *name,
+ext3_xattr_trusted_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext3_xattr_set(d_inode(dentry), EXT3_XATTR_INDEX_TRUSTED, name,
+	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name,
 			      value, size, flags);
 }
 
diff --git a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
index 9a5ff25..437b489 100644
--- a/fs/ext3/xattr_user.c
+++ b/fs/ext3/xattr_user.c
@@ -9,14 +9,14 @@
 #include "xattr.h"
 
 static size_t
-ext3_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
+ext3_xattr_user_list(struct inode *inode, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
 
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return 0;
 
 	if (list && total_len <= list_size) {
@@ -28,28 +28,28 @@ ext3_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext3_xattr_user_get(struct dentry *dentry, const char *name, void *buffer,
+ext3_xattr_user_get(struct inode *inode, const char *name, void *buffer,
 		size_t size,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext3_xattr_get(d_inode(dentry), EXT3_XATTR_INDEX_USER,
+	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER,
 			      name, buffer, size);
 }
 
 static int
-ext3_xattr_user_set(struct dentry *dentry, const char *name,
+ext3_xattr_user_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext3_xattr_set(d_inode(dentry), EXT3_XATTR_INDEX_USER,
+	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER,
 			      name, value, size, flags);
 }
 
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index f5158d9..89a0938 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -398,6 +398,7 @@ static int
 ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
 			char *buffer, size_t buffer_size)
 {
+	struct inode *inode = d_inode(dentry);
 	size_t rest = buffer_size;
 
 	for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
@@ -405,7 +406,7 @@ ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
 			ext4_xattr_handler(entry->e_name_index);
 
 		if (handler) {
-			size_t size = handler->list(dentry, buffer, rest,
+			size_t size = handler->list(inode, buffer, rest,
 						    entry->e_name,
 						    entry->e_name_len,
 						    handler);
diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c
index 5e5b4e0..eabcafb 100644
--- a/fs/ext4/xattr_security.c
+++ b/fs/ext4/xattr_security.c
@@ -12,7 +12,7 @@
 #include "xattr.h"
 
 static size_t
-ext4_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
+ext4_xattr_security_list(struct inode *inode, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
@@ -29,24 +29,24 @@ ext4_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext4_xattr_security_get(struct dentry *dentry, const char *name,
+ext4_xattr_security_get(struct inode *inode, const char *name,
 		       void *buffer, size_t size,
 		       const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY,
+	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_SECURITY,
 			      name, buffer, size);
 }
 
 static int
-ext4_xattr_security_set(struct dentry *dentry, const char *name,
+ext4_xattr_security_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY,
+	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_SECURITY,
 			      name, value, size, flags);
 }
 
diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c
index b298d01..3e0590a 100644
--- a/fs/ext4/xattr_trusted.c
+++ b/fs/ext4/xattr_trusted.c
@@ -13,7 +13,7 @@
 #include "xattr.h"
 
 static size_t
-ext4_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
+ext4_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
@@ -32,24 +32,24 @@ ext4_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext4_xattr_trusted_get(struct dentry *dentry, const char *name, void *buffer,
+ext4_xattr_trusted_get(struct inode *inode, const char *name, void *buffer,
 		size_t size,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED,
+	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_TRUSTED,
 			      name, buffer, size);
 }
 
 static int
-ext4_xattr_trusted_set(struct dentry *dentry, const char *name,
+ext4_xattr_trusted_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED,
+	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_TRUSTED,
 			      name, value, size, flags);
 }
 
diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c
index 62085d1..77d329d 100644
--- a/fs/ext4/xattr_user.c
+++ b/fs/ext4/xattr_user.c
@@ -12,14 +12,14 @@
 #include "xattr.h"
 
 static size_t
-ext4_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
+ext4_xattr_user_list(struct inode *inode, char *list, size_t list_size,
 		     const char *name, size_t name_len,
 		     const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
 
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return 0;
 
 	if (list && total_len <= list_size) {
@@ -31,28 +31,28 @@ ext4_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext4_xattr_user_get(struct dentry *dentry, const char *name,
+ext4_xattr_user_get(struct inode *inode, const char *name,
 		    void *buffer, size_t size,
 		    const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_USER,
+	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_USER,
 			      name, buffer, size);
 }
 
 static int
-ext4_xattr_user_set(struct dentry *dentry, const char *name,
+ext4_xattr_user_set(struct inode *inode, const char *name,
 		    const void *value, size_t size, int flags,
 		    const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_USER,
+	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_USER,
 			      name, value, size, flags);
 }
 
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 1c3e5e7..3659a3d 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -25,11 +25,11 @@
 #include "f2fs.h"
 #include "xattr.h"
 
-static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
+static size_t f2fs_xattr_generic_list(struct inode *inode, char *list,
 		size_t list_size, const char *name, size_t len,
 		const struct xattr_handler *handler)
 {
-	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 	int total_len, prefix_len;
 
 	switch (handler->flags) {
@@ -57,11 +57,11 @@ static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
 	return total_len;
 }
 
-static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
+static int f2fs_xattr_generic_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
-	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 
 	switch (handler->flags) {
 	case F2FS_XATTR_INDEX_USER:
@@ -79,15 +79,14 @@ static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
 	}
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return f2fs_getxattr(d_inode(dentry), handler->flags, name,
-			     buffer, size, NULL);
+	return f2fs_getxattr(inode, handler->flags, name, buffer, size, NULL);
 }
 
-static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
+static int f2fs_xattr_generic_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 
 	switch (handler->flags) {
 	case F2FS_XATTR_INDEX_USER:
@@ -106,11 +105,11 @@ static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	return f2fs_setxattr(d_inode(dentry), handler->flags, name,
-					value, size, NULL, flags);
+	return f2fs_setxattr(inode, handler->flags, name, value, size, NULL,
+			     flags);
 }
 
-static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
+static size_t f2fs_xattr_advise_list(struct inode *inode, char *list,
 		size_t list_size, const char *name, size_t len,
 		const struct xattr_handler *handler)
 {
@@ -123,12 +122,10 @@ static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
 	return size;
 }
 
-static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
+static int f2fs_xattr_advise_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
-	struct inode *inode = d_inode(dentry);
-
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
 
@@ -137,12 +134,10 @@ static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
 	return sizeof(char);
 }
 
-static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name,
+static int f2fs_xattr_advise_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	struct inode *inode = d_inode(dentry);
-
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
 	if (!inode_owner_or_capable(inode))
@@ -460,7 +455,7 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 		if (!handler)
 			continue;
 
-		size = handler->list(dentry, buffer, rest, entry->e_name,
+		size = handler->list(inode, buffer, rest, entry->e_name,
 				entry->e_name_len, handler);
 		if (buffer && size > rest) {
 			error = -ERANGE;
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index 3979c608..71e0495 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -583,11 +583,11 @@ out:
  *
  * Returns: actual size of data on success, -errno on error
  */
-static int gfs2_xattr_get(struct dentry *dentry, const char *name,
+static int gfs2_xattr_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
-	struct gfs2_inode *ip = GFS2_I(d_inode(dentry));
+	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_ea_location el;
 	int type = handler->flags;
 	int error;
@@ -1229,11 +1229,11 @@ int __gfs2_xattr_set(struct inode *inode, const char *name,
 	return error;
 }
 
-static int gfs2_xattr_set(struct dentry *dentry, const char *name,
+static int gfs2_xattr_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	return __gfs2_xattr_set(d_inode(dentry), name, value,
+	return __gfs2_xattr_set(inode, name, value,
 				size, flags, handler->flags);
 }
 
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
index 65914db..2ba308c 100644
--- a/fs/hfsplus/xattr.c
+++ b/fs/hfsplus/xattr.c
@@ -424,7 +424,7 @@ static int copy_name(char *buffer, const char *xattr_name, int name_len)
 	return len;
 }
 
-int hfsplus_setxattr(struct dentry *dentry, const char *name,
+int hfsplus_setxattr(struct inode *inode, const char *name,
 		     const void *value, size_t size, int flags,
 		     const char *prefix, size_t prefixlen)
 {
@@ -440,7 +440,7 @@ int hfsplus_setxattr(struct dentry *dentry, const char *name,
 		return -ENOMEM;
 	strcpy(xattr_name, prefix);
 	strcpy(xattr_name + prefixlen, name);
-	res = __hfsplus_setxattr(d_inode(dentry), xattr_name, value, size,
+	res = __hfsplus_setxattr(inode, xattr_name, value, size,
 				 flags);
 	kfree(xattr_name);
 	return res;
@@ -582,7 +582,7 @@ failed_getxattr_init:
 	return res;
 }
 
-ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
+ssize_t hfsplus_getxattr(struct inode *inode, const char *name,
 			 void *value, size_t size,
 			 const char *prefix, size_t prefixlen)
 {
@@ -600,7 +600,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
 	strcpy(xattr_name, prefix);
 	strcpy(xattr_name + prefixlen, name);
 
-	res = __hfsplus_getxattr(d_inode(dentry), xattr_name, value, size);
+	res = __hfsplus_getxattr(inode, xattr_name, value, size);
 	kfree(xattr_name);
 	return res;
 
@@ -849,7 +849,7 @@ end_removexattr:
 	return err;
 }
 
-static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
+static int hfsplus_osx_getxattr(struct inode *inode, const char *name,
 					void *buffer, size_t size,
 					const struct xattr_handler *handler)
 {
@@ -869,10 +869,10 @@ static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
 	 * creates), so we pass the name through unmodified (after
 	 * ensuring it doesn't conflict with another namespace).
 	 */
-	return __hfsplus_getxattr(d_inode(dentry), name, buffer, size);
+	return __hfsplus_getxattr(inode, name, buffer, size);
 }
 
-static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
+static int hfsplus_osx_setxattr(struct inode *inode, const char *name,
 		const void *buffer, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
@@ -892,7 +892,7 @@ static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
 	 * creates), so we pass the name through unmodified (after
 	 * ensuring it doesn't conflict with another namespace).
 	 */
-	return __hfsplus_setxattr(d_inode(dentry), name, buffer, size, flags);
+	return __hfsplus_setxattr(inode, name, buffer, size, flags);
 }
 
 const struct xattr_handler hfsplus_xattr_osx_handler = {
diff --git a/fs/hfsplus/xattr.h b/fs/hfsplus/xattr.h
index f9b0955..68f6b53 100644
--- a/fs/hfsplus/xattr.h
+++ b/fs/hfsplus/xattr.h
@@ -21,14 +21,14 @@ extern const struct xattr_handler *hfsplus_xattr_handlers[];
 int __hfsplus_setxattr(struct inode *inode, const char *name,
 			const void *value, size_t size, int flags);
 
-int hfsplus_setxattr(struct dentry *dentry, const char *name,
+int hfsplus_setxattr(struct inode *inode, const char *name,
 				   const void *value, size_t size, int flags,
 				   const char *prefix, size_t prefixlen);
 
 ssize_t __hfsplus_getxattr(struct inode *inode, const char *name,
 			   void *value, size_t size);
 
-ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
+ssize_t hfsplus_getxattr(struct inode *inode, const char *name,
 			 void *value, size_t size,
 			 const char *prefix, size_t prefixlen);
 
diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c
index 3601ecc..aefd82f 100644
--- a/fs/hfsplus/xattr_security.c
+++ b/fs/hfsplus/xattr_security.c
@@ -13,20 +13,20 @@
 #include "xattr.h"
 #include "acl.h"
 
-static int hfsplus_security_getxattr(struct dentry *dentry, const char *name,
+static int hfsplus_security_getxattr(struct inode *inode, const char *name,
 					void *buffer, size_t size,
 					const struct xattr_handler *handler)
 {
-	return hfsplus_getxattr(dentry, name, buffer, size,
+	return hfsplus_getxattr(inode, name, buffer, size,
 				XATTR_SECURITY_PREFIX,
 				XATTR_SECURITY_PREFIX_LEN);
 }
 
-static int hfsplus_security_setxattr(struct dentry *dentry, const char *name,
+static int hfsplus_security_setxattr(struct inode *inode, const char *name,
 		const void *buffer, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	return hfsplus_setxattr(dentry, name, buffer, size, flags,
+	return hfsplus_setxattr(inode, name, buffer, size, flags,
 				XATTR_SECURITY_PREFIX,
 				XATTR_SECURITY_PREFIX_LEN);
 }
diff --git a/fs/hfsplus/xattr_trusted.c b/fs/hfsplus/xattr_trusted.c
index 123cd8e..077e26c 100644
--- a/fs/hfsplus/xattr_trusted.c
+++ b/fs/hfsplus/xattr_trusted.c
@@ -11,20 +11,20 @@
 #include "hfsplus_fs.h"
 #include "xattr.h"
 
-static int hfsplus_trusted_getxattr(struct dentry *dentry, const char *name,
+static int hfsplus_trusted_getxattr(struct inode *inode, const char *name,
 					void *buffer, size_t size,
 					const struct xattr_handler *handler)
 {
-	return hfsplus_getxattr(dentry, name, buffer, size,
+	return hfsplus_getxattr(inode, name, buffer, size,
 				XATTR_TRUSTED_PREFIX,
 				XATTR_TRUSTED_PREFIX_LEN);
 }
 
-static int hfsplus_trusted_setxattr(struct dentry *dentry, const char *name,
+static int hfsplus_trusted_setxattr(struct inode *inode, const char *name,
 		const void *buffer, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	return hfsplus_setxattr(dentry, name, buffer, size, flags,
+	return hfsplus_setxattr(inode, name, buffer, size, flags,
 				XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
 }
 
diff --git a/fs/hfsplus/xattr_user.c b/fs/hfsplus/xattr_user.c
index 2272557..1554304 100644
--- a/fs/hfsplus/xattr_user.c
+++ b/fs/hfsplus/xattr_user.c
@@ -11,20 +11,20 @@
 #include "hfsplus_fs.h"
 #include "xattr.h"
 
-static int hfsplus_user_getxattr(struct dentry *dentry, const char *name,
+static int hfsplus_user_getxattr(struct inode *inode, const char *name,
 					void *buffer, size_t size,
 					const struct xattr_handler *handler)
 {
 
-	return hfsplus_getxattr(dentry, name, buffer, size,
+	return hfsplus_getxattr(inode, name, buffer, size,
 				XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
 }
 
-static int hfsplus_user_setxattr(struct dentry *dentry, const char *name,
+static int hfsplus_user_setxattr(struct inode *inode, const char *name,
 		const void *buffer, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	return hfsplus_setxattr(dentry, name, buffer, size, flags,
+	return hfsplus_setxattr(inode, name, buffer, size, flags,
 				XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
 }
 
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
index 8f609e8..8496955 100644
--- a/fs/jffs2/security.c
+++ b/fs/jffs2/security.c
@@ -48,29 +48,29 @@ int jffs2_init_security(struct inode *inode, struct inode *dir,
 }
 
 /* ---- XATTR Handler for "security.*" ----------------- */
-static int jffs2_security_getxattr(struct dentry *dentry, const char *name,
+static int jffs2_security_getxattr(struct inode *inode, const char *name,
 				   void *buffer, size_t size,
 				   const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
 
-	return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY,
+	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY,
 				 name, buffer, size);
 }
 
-static int jffs2_security_setxattr(struct dentry *dentry, const char *name,
+static int jffs2_security_setxattr(struct inode *inode, const char *name,
 		const void *buffer, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
 
-	return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY,
+	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY,
 				 name, buffer, size, flags);
 }
 
-static size_t jffs2_security_listxattr(struct dentry *dentry, char *list,
+static size_t jffs2_security_listxattr(struct inode *inode, char *list,
 		size_t list_size, const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 8b2305c..67db313 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -1001,10 +1001,10 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
 		if (!xhandle)
 			continue;
 		if (buffer) {
-			rc = xhandle->list(dentry, buffer+len, size-len,
+			rc = xhandle->list(inode, buffer+len, size-len,
 					   xd->xname, xd->name_len, xhandle);
 		} else {
-			rc = xhandle->list(dentry, NULL, 0, xd->xname,
+			rc = xhandle->list(inode, NULL, 0, xd->xname,
 					   xd->name_len, xhandle);
 		}
 		if (rc < 0)
diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c
index afa0e4d..fab079d 100644
--- a/fs/jffs2/xattr_trusted.c
+++ b/fs/jffs2/xattr_trusted.c
@@ -16,26 +16,26 @@
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 
-static int jffs2_trusted_getxattr(struct dentry *dentry, const char *name,
+static int jffs2_trusted_getxattr(struct inode *inode, const char *name,
 		void *buffer, size_t size, const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
-	return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED,
+	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED,
 				 name, buffer, size);
 }
 
-static int jffs2_trusted_setxattr(struct dentry *dentry, const char *name,
+static int jffs2_trusted_setxattr(struct inode *inode, const char *name,
 		const void *buffer, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
-	return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED,
+	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_TRUSTED,
 				 name, buffer, size, flags);
 }
 
-static size_t jffs2_trusted_listxattr(struct dentry *dentry, char *list,
+static size_t jffs2_trusted_listxattr(struct inode *inode, char *list,
 		size_t list_size, const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
index 4c45567..33dab9b 100644
--- a/fs/jffs2/xattr_user.c
+++ b/fs/jffs2/xattr_user.c
@@ -16,27 +16,27 @@
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 
-static int jffs2_user_getxattr(struct dentry *dentry, const char *name,
+static int jffs2_user_getxattr(struct inode *inode, const char *name,
 			       void *buffer, size_t size,
 			       const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
-	return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_USER,
+	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER,
 				 name, buffer, size);
 }
 
-static int jffs2_user_setxattr(struct dentry *dentry, const char *name,
+static int jffs2_user_setxattr(struct inode *inode, const char *name,
 		const void *buffer, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
-	return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_USER,
+	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_USER,
 				 name, buffer, size, flags);
 }
 
-static size_t jffs2_user_listxattr(struct dentry *dentry, char *list,
+static size_t jffs2_user_listxattr(struct inode *inode, char *list,
 		size_t list_size, const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 977165e..9c5a015 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4841,12 +4841,11 @@ static int nfs4_do_set_security_label(struct inode *inode,
 }
 
 static int
-nfs4_set_security_label(struct dentry *dentry, const void *buf, size_t buflen)
+nfs4_set_security_label(struct inode *inode, const void *buf, size_t buflen)
 {
 	struct nfs4_label ilabel, *olabel = NULL;
 	struct nfs_fattr fattr;
 	struct rpc_cred *cred;
-	struct inode *inode = d_inode(dentry);
 	int status;
 
 	if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL))
@@ -6201,7 +6200,7 @@ nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
 
 #define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
 
-static int nfs4_xattr_set_nfs4_acl(struct dentry *dentry, const char *key,
+static int nfs4_xattr_set_nfs4_acl(struct inode *inode, const char *key,
 				   const void *buf, size_t buflen,
 				   int flags,
 				   const struct xattr_handler *handler)
@@ -6209,27 +6208,27 @@ static int nfs4_xattr_set_nfs4_acl(struct dentry *dentry, const char *key,
 	if (strcmp(key, "") != 0)
 		return -EINVAL;
 
-	return nfs4_proc_set_acl(d_inode(dentry), buf, buflen);
+	return nfs4_proc_set_acl(inode, buf, buflen);
 }
 
-static int nfs4_xattr_get_nfs4_acl(struct dentry *dentry, const char *key,
+static int nfs4_xattr_get_nfs4_acl(struct inode *inode, const char *key,
 				   void *buf, size_t buflen,
 				   const struct xattr_handler *handler)
 {
 	if (strcmp(key, "") != 0)
 		return -EINVAL;
 
-	return nfs4_proc_get_acl(d_inode(dentry), buf, buflen);
+	return nfs4_proc_get_acl(inode, buf, buflen);
 }
 
-static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list,
+static size_t nfs4_xattr_list_nfs4_acl(struct inode *inode, char *list,
 				       size_t list_len, const char *name,
 				       size_t name_len,
 				       const struct xattr_handler *handler)
 {
 	size_t len = sizeof(XATTR_NAME_NFSV4_ACL);
 
-	if (!nfs4_server_supports_acls(NFS_SERVER(d_inode(dentry))))
+	if (!nfs4_server_supports_acls(NFS_SERVER(inode)))
 		return 0;
 
 	if (list && len <= list_len)
@@ -6243,37 +6242,37 @@ static inline int nfs4_server_supports_labels(struct nfs_server *server)
 	return server->caps & NFS_CAP_SECURITY_LABEL;
 }
 
-static int nfs4_xattr_set_nfs4_label(struct dentry *dentry, const char *key,
+static int nfs4_xattr_set_nfs4_label(struct inode *inode, const char *key,
 				   const void *buf, size_t buflen,
 				   int flags,
 				   const struct xattr_handler *handler)
 {
 	if (security_ismaclabel(key))
-		return nfs4_set_security_label(dentry, buf, buflen);
+		return nfs4_set_security_label(inode, buf, buflen);
 
 	return -EOPNOTSUPP;
 }
 
-static int nfs4_xattr_get_nfs4_label(struct dentry *dentry, const char *key,
+static int nfs4_xattr_get_nfs4_label(struct inode *inode, const char *key,
 				   void *buf, size_t buflen,
 				   const struct xattr_handler *handler)
 {
 	if (security_ismaclabel(key))
-		return nfs4_get_security_label(d_inode(dentry), buf, buflen);
+		return nfs4_get_security_label(inode, buf, buflen);
 	return -EOPNOTSUPP;
 }
 
-static size_t nfs4_xattr_list_nfs4_label(struct dentry *dentry, char *list,
+static size_t nfs4_xattr_list_nfs4_label(struct inode *inode, char *list,
 				       size_t list_len, const char *name,
 				       size_t name_len,
 				       const struct xattr_handler *handler)
 {
 	size_t len = 0;
 
-	if (nfs_server_capable(d_inode(dentry), NFS_CAP_SECURITY_LABEL)) {
-		len = security_inode_listsecurity(d_inode(dentry), NULL, 0);
+	if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) {
+		len = security_inode_listsecurity(inode, NULL, 0);
 		if (list && len <= list_len)
-			security_inode_listsecurity(d_inode(dentry), list, len);
+			security_inode_listsecurity(inode, list, len);
 	}
 	return len;
 }
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index f5ce434..6cdbd35 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -7237,7 +7237,7 @@ leave:
 /*
  * 'security' attributes support
  */
-static size_t ocfs2_xattr_security_list(struct dentry *dentry, char *list,
+static size_t ocfs2_xattr_security_list(struct inode *inode, char *list,
 					size_t list_size, const char *name,
 					size_t name_len,
 					const struct xattr_handler *handler)
@@ -7253,24 +7253,24 @@ static size_t ocfs2_xattr_security_list(struct dentry *dentry, char *list,
 	return total_len;
 }
 
-static int ocfs2_xattr_security_get(struct dentry *dentry, const char *name,
+static int ocfs2_xattr_security_get(struct inode *inode, const char *name,
 				    void *buffer, size_t size,
 				    const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY,
+	return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_SECURITY,
 			       name, buffer, size);
 }
 
-static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,
+static int ocfs2_xattr_security_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY,
+	return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
 			       name, value, size, flags);
 }
 
@@ -7330,7 +7330,7 @@ const struct xattr_handler ocfs2_xattr_security_handler = {
 /*
  * 'trusted' attributes support
  */
-static size_t ocfs2_xattr_trusted_list(struct dentry *dentry, char *list,
+static size_t ocfs2_xattr_trusted_list(struct inode *inode, char *list,
 				       size_t list_size, const char *name,
 				       size_t name_len,
 				       const struct xattr_handler *handler)
@@ -7346,24 +7346,24 @@ static size_t ocfs2_xattr_trusted_list(struct dentry *dentry, char *list,
 	return total_len;
 }
 
-static int ocfs2_xattr_trusted_get(struct dentry *dentry, const char *name,
+static int ocfs2_xattr_trusted_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED,
+	return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_TRUSTED,
 			       name, buffer, size);
 }
 
-static int ocfs2_xattr_trusted_set(struct dentry *dentry, const char *name,
+static int ocfs2_xattr_trusted_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED,
+	return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_TRUSTED,
 			       name, value, size, flags);
 }
 
@@ -7377,14 +7377,14 @@ const struct xattr_handler ocfs2_xattr_trusted_handler = {
 /*
  * 'user' attributes support
  */
-static size_t ocfs2_xattr_user_list(struct dentry *dentry, char *list,
+static size_t ocfs2_xattr_user_list(struct inode *inode, char *list,
 				    size_t list_size, const char *name,
 				    size_t name_len,
 				    const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
-	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
 		return 0;
@@ -7397,32 +7397,32 @@ static size_t ocfs2_xattr_user_list(struct dentry *dentry, char *list,
 	return total_len;
 }
 
-static int ocfs2_xattr_user_get(struct dentry *dentry, const char *name,
+static int ocfs2_xattr_user_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
-	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
 		return -EOPNOTSUPP;
-	return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_USER, name,
+	return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_USER, name,
 			       buffer, size);
 }
 
-static int ocfs2_xattr_user_set(struct dentry *dentry, const char *name,
+static int ocfs2_xattr_user_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
 		return -EOPNOTSUPP;
 
-	return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_USER,
+	return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_USER,
 			       name, value, size, flags);
 }
 
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index cea22e6..8d9b8d8 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -762,19 +762,19 @@ posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
 EXPORT_SYMBOL (posix_acl_to_xattr);
 
 static int
-posix_acl_xattr_get(struct dentry *dentry, const char *name,
+posix_acl_xattr_get(struct inode *inode, const char *name,
 		void *value, size_t size,
 		const struct xattr_handler *handler)
 {
 	struct posix_acl *acl;
 	int error;
 
-	if (!IS_POSIXACL(d_backing_inode(dentry)))
+	if (!IS_POSIXACL(inode))
 		return -EOPNOTSUPP;
-	if (d_is_symlink(dentry))
+	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
 
-	acl = get_acl(d_backing_inode(dentry), handler->flags);
+	acl = get_acl(inode, handler->flags);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl == NULL)
@@ -787,11 +787,10 @@ posix_acl_xattr_get(struct dentry *dentry, const char *name,
 }
 
 static int
-posix_acl_xattr_set(struct dentry *dentry, const char *name,
+posix_acl_xattr_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	struct inode *inode = d_backing_inode(dentry);
 	struct posix_acl *acl = NULL;
 	int ret;
 
@@ -824,16 +823,16 @@ out:
 }
 
 static size_t
-posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
+posix_acl_xattr_list(struct inode *inode, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
 	const char *xname = handler->prefix;
 	size_t size;
 
-	if (!IS_POSIXACL(d_backing_inode(dentry)))
+	if (!IS_POSIXACL(inode))
 		return -EOPNOTSUPP;
-	if (d_is_symlink(dentry))
+	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
 
 	size = strlen(xname) + 1;
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index ad6e4bb..5b58dea 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -771,50 +771,53 @@ ssize_t
 reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
 		  size_t size)
 {
+	struct inode *inode = d_inode(dentry);
 	const struct xattr_handler *handler;
 
 	handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
+	if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->get(dentry, name, buffer, size, handler);
+	return handler->get(inode, name, buffer, size, handler);
 }
 
 /*
  * Inode operation setxattr()
  *
- * d_inode(dentry)->i_mutex down
+ * inode->i_mutex down
  */
 int
 reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 		  size_t size, int flags)
 {
+	struct inode *inode = d_inode(dentry);
 	const struct xattr_handler *handler;
 
 	handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
+	if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->set(dentry, name, value, size, flags, handler);
+	return handler->set(inode, name, value, size, flags, handler);
 }
 
 /*
  * Inode operation removexattr()
  *
- * d_inode(dentry)->i_mutex down
+ * inode->i_mutex down
  */
 int reiserfs_removexattr(struct dentry *dentry, const char *name)
 {
+	struct inode *inode = d_inode(dentry);
 	const struct xattr_handler *handler;
 
 	handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
+	if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->set(dentry, name, NULL, 0, XATTR_REPLACE, handler);
+	return handler->set(inode, name, NULL, 0, XATTR_REPLACE, handler);
 }
 
 struct listxattr_buf {
@@ -835,6 +838,7 @@ static int listxattr_filler(struct dir_context *ctx, const char *name,
 
 	if (name[0] != '.' ||
 	    (namelen != 1 && (name[1] != '.' || namelen != 2))) {
+		struct inode *inode = d_inode(b->dentry);
 		const struct xattr_handler *handler;
 
 		handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr,
@@ -842,13 +846,13 @@ static int listxattr_filler(struct dir_context *ctx, const char *name,
 		if (!handler)	/* Unsupported xattr name */
 			return 0;
 		if (b->buf) {
-			size = handler->list(b->dentry, b->buf + b->pos,
-					 b->size, name, namelen, handler);
+			size = handler->list(inode, b->buf + b->pos, b->size,
+					     name, namelen, handler);
 			if (size > b->size)
 				return -ERANGE;
 		} else {
-			size = handler->list(b->dentry, NULL, 0, name,
-					     namelen, handler);
+			size = handler->list(inode, NULL, 0,
+					     name, namelen, handler);
 		}
 
 		b->pos += size;
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index 08074f5..579c3b2 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -9,39 +9,39 @@
 #include <linux/uaccess.h>
 
 static int
-security_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
+security_get(struct inode *inode, const char *name, void *buffer, size_t size,
 	     const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
 		return -EINVAL;
 
-	if (IS_PRIVATE(d_inode(dentry)))
+	if (IS_PRIVATE(inode))
 		return -EPERM;
 
-	return reiserfs_xattr_get(d_inode(dentry), name, buffer, size);
+	return reiserfs_xattr_get(inode, name, buffer, size);
 }
 
 static int
-security_set(struct dentry *dentry, const char *name, const void *buffer,
+security_set(struct inode *inode, const char *name, const void *buffer,
 	     size_t size, int flags,
 	     const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
 		return -EINVAL;
 
-	if (IS_PRIVATE(d_inode(dentry)))
+	if (IS_PRIVATE(inode))
 		return -EPERM;
 
-	return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
+	return reiserfs_xattr_set(inode, name, buffer, size, flags);
 }
 
-static size_t security_list(struct dentry *dentry, char *list, size_t list_len,
+static size_t security_list(struct inode *inode, char *list, size_t list_len,
 			    const char *name, size_t namelen,
 			    const struct xattr_handler *handler)
 {
 	const size_t len = namelen + 1;
 
-	if (IS_PRIVATE(d_inode(dentry)))
+	if (IS_PRIVATE(inode))
 		return 0;
 
 	if (list && len <= list_len) {
diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c
index e3ab346..ac2c9ae 100644
--- a/fs/reiserfs/xattr_trusted.c
+++ b/fs/reiserfs/xattr_trusted.c
@@ -8,39 +8,39 @@
 #include <linux/uaccess.h>
 
 static int
-trusted_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
+trusted_get(struct inode *inode, const char *name, void *buffer, size_t size,
 	    const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
 		return -EINVAL;
 
-	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry)))
+	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
 		return -EPERM;
 
-	return reiserfs_xattr_get(d_inode(dentry), name, buffer, size);
+	return reiserfs_xattr_get(inode, name, buffer, size);
 }
 
 static int
-trusted_set(struct dentry *dentry, const char *name, const void *buffer,
+trusted_set(struct inode *inode, const char *name, const void *buffer,
 	    size_t size, int flags,
 	    const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
 		return -EINVAL;
 
-	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry)))
+	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
 		return -EPERM;
 
-	return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
+	return reiserfs_xattr_set(inode, name, buffer, size, flags);
 }
 
-static size_t trusted_list(struct dentry *dentry, char *list, size_t list_size,
+static size_t trusted_list(struct inode *inode, char *list, size_t list_size,
 			   const char *name, size_t name_len,
 			   const struct xattr_handler *handler)
 {
 	const size_t len = name_len + 1;
 
-	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry)))
+	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
 		return 0;
 
 	if (list && len <= list_size) {
diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c
index 2c8d466..712fdeb 100644
--- a/fs/reiserfs/xattr_user.c
+++ b/fs/reiserfs/xattr_user.c
@@ -7,37 +7,37 @@
 #include <linux/uaccess.h>
 
 static int
-user_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
+user_get(struct inode *inode, const char *name, void *buffer, size_t size,
 	 const struct xattr_handler *handler)
 {
 
 	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
 		return -EINVAL;
-	if (!reiserfs_xattrs_user(dentry->d_sb))
+	if (!reiserfs_xattrs_user(inode->i_sb))
 		return -EOPNOTSUPP;
-	return reiserfs_xattr_get(d_inode(dentry), name, buffer, size);
+	return reiserfs_xattr_get(inode, name, buffer, size);
 }
 
 static int
-user_set(struct dentry *dentry, const char *name, const void *buffer,
+user_set(struct inode *inode, const char *name, const void *buffer,
 	 size_t size, int flags,
 	 const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
 		return -EINVAL;
 
-	if (!reiserfs_xattrs_user(dentry->d_sb))
+	if (!reiserfs_xattrs_user(inode->i_sb))
 		return -EOPNOTSUPP;
-	return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
+	return reiserfs_xattr_set(inode, name, buffer, size, flags);
 }
 
-static size_t user_list(struct dentry *dentry, char *list, size_t list_size,
+static size_t user_list(struct inode *inode, char *list, size_t list_size,
 			const char *name, size_t name_len,
 			const struct xattr_handler *handler)
 {
 	const size_t len = name_len + 1;
 
-	if (!reiserfs_xattrs_user(dentry->d_sb))
+	if (!reiserfs_xattrs_user(inode->i_sb))
 		return 0;
 	if (list && len <= list_size) {
 		memcpy(list, name, name_len);
diff --git a/fs/squashfs/xattr.c b/fs/squashfs/xattr.c
index 268e25b..38d1b13 100644
--- a/fs/squashfs/xattr.c
+++ b/fs/squashfs/xattr.c
@@ -68,7 +68,7 @@ ssize_t squashfs_listxattr(struct dentry *d, char *buffer,
 		name_size = le16_to_cpu(entry.size);
 		handler = squashfs_xattr_handler(le16_to_cpu(entry.type));
 		if (handler)
-			prefix_size = handler->list(d, buffer, rest, NULL,
+			prefix_size = handler->list(inode, buffer, rest, NULL,
 				name_size, handler);
 		if (prefix_size) {
 			if (buffer) {
@@ -212,7 +212,7 @@ failed:
 }
 
 
-static size_t squashfs_xattr_handler_list(struct dentry *d, char *list,
+static size_t squashfs_xattr_handler_list(struct inode *inode, char *list,
 	size_t list_size, const char *name, size_t name_len,
 	const struct xattr_handler *handler)
 {
@@ -223,13 +223,13 @@ static size_t squashfs_xattr_handler_list(struct dentry *d, char *list,
 	return len;
 }
 
-static int squashfs_xattr_handler_get(struct dentry *d, const char *name,
+static int squashfs_xattr_handler_get(struct inode *inode, const char *name,
 	void *buffer, size_t size, const struct xattr_handler *handler)
 {
 	if (name[0] == '\0')
 		return  -EINVAL;
 
-	return squashfs_xattr_get(d_inode(d), handler->flags, name,
+	return squashfs_xattr_get(inode, handler->flags, name,
 		buffer, size);
 }
 
@@ -246,13 +246,13 @@ static const struct xattr_handler squashfs_xattr_user_handler = {
 /*
  * Trusted namespace support
  */
-static size_t squashfs_trusted_xattr_handler_list(struct dentry *d, char *list,
+static size_t squashfs_trusted_xattr_handler_list(struct inode *inode, char *list,
 	size_t list_size, const char *name, size_t name_len,
 	const struct xattr_handler *handler)
 {
 	if (!capable(CAP_SYS_ADMIN))
 		return 0;
-	return squashfs_xattr_handler_list(d, list, list_size, name, name_len,
+	return squashfs_xattr_handler_list(inode, list, list_size, name, name_len,
 		handler);
 }
 
diff --git a/fs/xattr.c b/fs/xattr.c
index 9584808..c45db57 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -709,7 +709,7 @@ generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t s
 	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->get(dentry, name, buffer, size, handler);
+	return handler->get(dentry->d_inode, name, buffer, size, handler);
 }
 
 /*
@@ -720,18 +720,18 @@ ssize_t
 generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
 	const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
+	struct inode *inode = dentry->d_inode;
 	unsigned int size = 0;
 
 	if (!buffer) {
 		for_each_xattr_handler(handlers, handler) {
-			size += handler->list(dentry, NULL, 0, NULL, 0,
-					      handler);
+			size += handler->list(inode, NULL, 0, NULL, 0, handler);
 		}
 	} else {
 		char *buf = buffer;
 
 		for_each_xattr_handler(handlers, handler) {
-			size = handler->list(dentry, buf, buffer_size,
+			size = handler->list(inode, buf, buffer_size,
 					     NULL, 0, handler);
 			if (size > buffer_size)
 				return -ERANGE;
@@ -756,7 +756,7 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz
 	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->set(dentry, name, value, size, flags, handler);
+	return handler->set(dentry->d_inode, name, value, size, flags, handler);
 }
 
 /*
@@ -771,7 +771,7 @@ generic_removexattr(struct dentry *dentry, const char *name)
 	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->set(dentry, name, NULL, 0,
+	return handler->set(dentry->d_inode, name, NULL, 0,
 			    XATTR_REPLACE, handler);
 }
 
diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c
index 9dace13..1fd52f9 100644
--- a/fs/xfs/xfs_xattr.c
+++ b/fs/xfs/xfs_xattr.c
@@ -32,12 +32,12 @@
 
 
 static int
-xfs_xattr_get(struct dentry *dentry, const char *name,
+xfs_xattr_get(struct inode *inode, const char *name,
 		void *value, size_t size,
 		const struct xattr_handler *handler)
 {
 	int xflags = handler->flags;
-	struct xfs_inode *ip = XFS_I(d_inode(dentry));
+	struct xfs_inode *ip = XFS_I(inode);
 	int error, asize = size;
 
 	if (strcmp(name, "") == 0)
@@ -56,12 +56,12 @@ xfs_xattr_get(struct dentry *dentry, const char *name,
 }
 
 static int
-xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
+xfs_xattr_set(struct inode *inode, const char *name, const void *value,
 		size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	int xflags = handler->flags;
-	struct xfs_inode *ip = XFS_I(d_inode(dentry));
+	struct xfs_inode *ip = XFS_I(inode);
 
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 8fd287d..0a0539e 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -22,12 +22,12 @@ struct dentry;
 struct xattr_handler {
 	const char *prefix;
 	int flags;      /* fs private flags */
-	size_t (*list)(struct dentry *dentry, char *list, size_t list_size,
+	size_t (*list)(struct inode *inode, char *list, size_t list_size,
 		       const char *name, size_t name_len,
 		       const struct xattr_handler *);
-	int (*get)(struct dentry *dentry, const char *name, void *buffer,
+	int (*get)(struct inode *inode, const char *name, void *buffer,
 		   size_t size, const struct xattr_handler *);
-	int (*set)(struct dentry *dentry, const char *name, const void *buffer,
+	int (*set)(struct inode *inode, const char *name, const void *buffer,
 		   size_t size, int flags, const struct xattr_handler *);
 };
 
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 08/11] xattr: Pass inodes to xattr handlers instead of dentries
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

All remaining file systems that use the generic xattr_handler infrastructure
only access dentry->d_inode and do nothing else with the dentry, so pass down
the inode instead of the dentry to the xattr_handler operations.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/ext2/xattr.c              |  2 +-
 fs/ext2/xattr_security.c     | 10 +++++-----
 fs/ext2/xattr_trusted.c      | 10 +++++-----
 fs/ext2/xattr_user.c         | 16 ++++++++--------
 fs/ext3/xattr.c              |  3 ++-
 fs/ext3/xattr_security.c     | 10 +++++-----
 fs/ext3/xattr_trusted.c      | 10 +++++-----
 fs/ext3/xattr_user.c         | 16 ++++++++--------
 fs/ext4/xattr.c              |  3 ++-
 fs/ext4/xattr_security.c     | 10 +++++-----
 fs/ext4/xattr_trusted.c      | 10 +++++-----
 fs/ext4/xattr_user.c         | 16 ++++++++--------
 fs/f2fs/xattr.c              | 31 +++++++++++++------------------
 fs/gfs2/xattr.c              |  8 ++++----
 fs/hfsplus/xattr.c           | 16 ++++++++--------
 fs/hfsplus/xattr.h           |  4 ++--
 fs/hfsplus/xattr_security.c  |  8 ++++----
 fs/hfsplus/xattr_trusted.c   |  8 ++++----
 fs/hfsplus/xattr_user.c      |  8 ++++----
 fs/jffs2/security.c          | 10 +++++-----
 fs/jffs2/xattr.c             |  4 ++--
 fs/jffs2/xattr_trusted.c     | 10 +++++-----
 fs/jffs2/xattr_user.c        | 10 +++++-----
 fs/nfs/nfs4proc.c            | 31 +++++++++++++++----------------
 fs/ocfs2/xattr.c             | 36 ++++++++++++++++++------------------
 fs/posix_acl.c               | 17 ++++++++---------
 fs/reiserfs/xattr.c          | 28 ++++++++++++++++------------
 fs/reiserfs/xattr_security.c | 16 ++++++++--------
 fs/reiserfs/xattr_trusted.c  | 16 ++++++++--------
 fs/reiserfs/xattr_user.c     | 16 ++++++++--------
 fs/squashfs/xattr.c          | 12 ++++++------
 fs/xattr.c                   | 12 ++++++------
 fs/xfs/xfs_xattr.c           |  8 ++++----
 include/linux/xattr.h        |  6 +++---
 34 files changed, 215 insertions(+), 216 deletions(-)

diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index f786688..b42d1cd 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -293,7 +293,7 @@ bad_block:	ext2_error(inode->i_sb, "ext2_xattr_list",
 			ext2_xattr_handler(entry->e_name_index);
 
 		if (handler) {
-			size_t size = handler->list(dentry, buffer, rest,
+			size_t size = handler->list(inode, buffer, rest,
 						    entry->e_name,
 						    entry->e_name_len,
 						    handler);
diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c
index ed9f7a32..94fe3a9 100644
--- a/fs/ext2/xattr_security.c
+++ b/fs/ext2/xattr_security.c
@@ -8,7 +8,7 @@
 #include "xattr.h"
 
 static size_t
-ext2_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
+ext2_xattr_security_list(struct inode *inode, char *list, size_t list_size,
 			 const char *name, size_t name_len,
 			 const struct xattr_handler *handler)
 {
@@ -24,24 +24,24 @@ ext2_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext2_xattr_security_get(struct dentry *dentry, const char *name,
+ext2_xattr_security_get(struct inode *inode, const char *name,
 		       void *buffer, size_t size,
 		       const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name,
+	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_SECURITY, name,
 			      buffer, size);
 }
 
 static int
-ext2_xattr_security_set(struct dentry *dentry, const char *name,
+ext2_xattr_security_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name,
+	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, name,
 			      value, size, flags);
 }
 
diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c
index 991676b..ce5e33f 100644
--- a/fs/ext2/xattr_trusted.c
+++ b/fs/ext2/xattr_trusted.c
@@ -9,7 +9,7 @@
 #include "xattr.h"
 
 static size_t
-ext2_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
+ext2_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
@@ -28,24 +28,24 @@ ext2_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext2_xattr_trusted_get(struct dentry *dentry, const char *name,
+ext2_xattr_trusted_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name,
+	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_TRUSTED, name,
 			      buffer, size);
 }
 
 static int
-ext2_xattr_trusted_set(struct dentry *dentry, const char *name,
+ext2_xattr_trusted_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name,
+	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_TRUSTED, name,
 			      value, size, flags);
 }
 
diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c
index b8f7c02..06adb5b 100644
--- a/fs/ext2/xattr_user.c
+++ b/fs/ext2/xattr_user.c
@@ -11,14 +11,14 @@
 #include "xattr.h"
 
 static size_t
-ext2_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
+ext2_xattr_user_list(struct inode *inode, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
 
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return 0;
 
 	if (list && total_len <= list_size) {
@@ -30,29 +30,29 @@ ext2_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext2_xattr_user_get(struct dentry *dentry, const char *name,
+ext2_xattr_user_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_USER,
+	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER,
 			      name, buffer, size);
 }
 
 static int
-ext2_xattr_user_set(struct dentry *dentry, const char *name,
+ext2_xattr_user_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
 
-	return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_USER,
+	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER,
 			      name, value, size, flags);
 }
 
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 4c35ac4..392ef8b 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -330,6 +330,7 @@ static int
 ext3_xattr_list_entries(struct dentry *dentry, struct ext3_xattr_entry *entry,
 			char *buffer, size_t buffer_size)
 {
+	struct inode *inode = d_inode(dentry);
 	size_t rest = buffer_size;
 
 	for (; !IS_LAST_ENTRY(entry); entry = EXT3_XATTR_NEXT(entry)) {
@@ -337,7 +338,7 @@ ext3_xattr_list_entries(struct dentry *dentry, struct ext3_xattr_entry *entry,
 			ext3_xattr_handler(entry->e_name_index);
 
 		if (handler) {
-			size_t size = handler->list(dentry, buffer, rest,
+			size_t size = handler->list(inode, buffer, rest,
 						    entry->e_name,
 						    entry->e_name_len,
 						    handler);
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index c26ebe0..05fa7e7 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -8,7 +8,7 @@
 #include "xattr.h"
 
 static size_t
-ext3_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
+ext3_xattr_security_list(struct inode *inode, char *list, size_t list_size,
 			 const char *name, size_t name_len,
 			 const struct xattr_handler *handler)
 {
@@ -25,24 +25,24 @@ ext3_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext3_xattr_security_get(struct dentry *dentry, const char *name,
+ext3_xattr_security_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext3_xattr_get(d_inode(dentry), EXT3_XATTR_INDEX_SECURITY,
+	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_SECURITY,
 			      name, buffer, size);
 }
 
 static int
-ext3_xattr_security_set(struct dentry *dentry, const char *name,
+ext3_xattr_security_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext3_xattr_set(d_inode(dentry), EXT3_XATTR_INDEX_SECURITY,
+	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_SECURITY,
 			      name, value, size, flags);
 }
 
diff --git a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c
index ba3ea56..1b25c3d 100644
--- a/fs/ext3/xattr_trusted.c
+++ b/fs/ext3/xattr_trusted.c
@@ -9,7 +9,7 @@
 #include "xattr.h"
 
 static size_t
-ext3_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
+ext3_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
@@ -28,24 +28,24 @@ ext3_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext3_xattr_trusted_get(struct dentry *dentry, const char *name,
+ext3_xattr_trusted_get(struct inode *inode, const char *name,
 		       void *buffer, size_t size,
 		       const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext3_xattr_get(d_inode(dentry), EXT3_XATTR_INDEX_TRUSTED,
+	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED,
 			      name, buffer, size);
 }
 
 static int
-ext3_xattr_trusted_set(struct dentry *dentry, const char *name,
+ext3_xattr_trusted_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext3_xattr_set(d_inode(dentry), EXT3_XATTR_INDEX_TRUSTED, name,
+	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name,
 			      value, size, flags);
 }
 
diff --git a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
index 9a5ff25..437b489 100644
--- a/fs/ext3/xattr_user.c
+++ b/fs/ext3/xattr_user.c
@@ -9,14 +9,14 @@
 #include "xattr.h"
 
 static size_t
-ext3_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
+ext3_xattr_user_list(struct inode *inode, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
 
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return 0;
 
 	if (list && total_len <= list_size) {
@@ -28,28 +28,28 @@ ext3_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext3_xattr_user_get(struct dentry *dentry, const char *name, void *buffer,
+ext3_xattr_user_get(struct inode *inode, const char *name, void *buffer,
 		size_t size,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext3_xattr_get(d_inode(dentry), EXT3_XATTR_INDEX_USER,
+	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER,
 			      name, buffer, size);
 }
 
 static int
-ext3_xattr_user_set(struct dentry *dentry, const char *name,
+ext3_xattr_user_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext3_xattr_set(d_inode(dentry), EXT3_XATTR_INDEX_USER,
+	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER,
 			      name, value, size, flags);
 }
 
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index f5158d9..89a0938 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -398,6 +398,7 @@ static int
 ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
 			char *buffer, size_t buffer_size)
 {
+	struct inode *inode = d_inode(dentry);
 	size_t rest = buffer_size;
 
 	for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
@@ -405,7 +406,7 @@ ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
 			ext4_xattr_handler(entry->e_name_index);
 
 		if (handler) {
-			size_t size = handler->list(dentry, buffer, rest,
+			size_t size = handler->list(inode, buffer, rest,
 						    entry->e_name,
 						    entry->e_name_len,
 						    handler);
diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c
index 5e5b4e0..eabcafb 100644
--- a/fs/ext4/xattr_security.c
+++ b/fs/ext4/xattr_security.c
@@ -12,7 +12,7 @@
 #include "xattr.h"
 
 static size_t
-ext4_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
+ext4_xattr_security_list(struct inode *inode, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
@@ -29,24 +29,24 @@ ext4_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext4_xattr_security_get(struct dentry *dentry, const char *name,
+ext4_xattr_security_get(struct inode *inode, const char *name,
 		       void *buffer, size_t size,
 		       const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY,
+	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_SECURITY,
 			      name, buffer, size);
 }
 
 static int
-ext4_xattr_security_set(struct dentry *dentry, const char *name,
+ext4_xattr_security_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY,
+	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_SECURITY,
 			      name, value, size, flags);
 }
 
diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c
index b298d01..3e0590a 100644
--- a/fs/ext4/xattr_trusted.c
+++ b/fs/ext4/xattr_trusted.c
@@ -13,7 +13,7 @@
 #include "xattr.h"
 
 static size_t
-ext4_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
+ext4_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
@@ -32,24 +32,24 @@ ext4_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext4_xattr_trusted_get(struct dentry *dentry, const char *name, void *buffer,
+ext4_xattr_trusted_get(struct inode *inode, const char *name, void *buffer,
 		size_t size,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED,
+	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_TRUSTED,
 			      name, buffer, size);
 }
 
 static int
-ext4_xattr_trusted_set(struct dentry *dentry, const char *name,
+ext4_xattr_trusted_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED,
+	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_TRUSTED,
 			      name, value, size, flags);
 }
 
diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c
index 62085d1..77d329d 100644
--- a/fs/ext4/xattr_user.c
+++ b/fs/ext4/xattr_user.c
@@ -12,14 +12,14 @@
 #include "xattr.h"
 
 static size_t
-ext4_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
+ext4_xattr_user_list(struct inode *inode, char *list, size_t list_size,
 		     const char *name, size_t name_len,
 		     const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
 
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return 0;
 
 	if (list && total_len <= list_size) {
@@ -31,28 +31,28 @@ ext4_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext4_xattr_user_get(struct dentry *dentry, const char *name,
+ext4_xattr_user_get(struct inode *inode, const char *name,
 		    void *buffer, size_t size,
 		    const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_USER,
+	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_USER,
 			      name, buffer, size);
 }
 
 static int
-ext4_xattr_user_set(struct dentry *dentry, const char *name,
+ext4_xattr_user_set(struct inode *inode, const char *name,
 		    const void *value, size_t size, int flags,
 		    const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(dentry->d_sb, XATTR_USER))
+	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_USER,
+	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_USER,
 			      name, value, size, flags);
 }
 
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 1c3e5e7..3659a3d 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -25,11 +25,11 @@
 #include "f2fs.h"
 #include "xattr.h"
 
-static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
+static size_t f2fs_xattr_generic_list(struct inode *inode, char *list,
 		size_t list_size, const char *name, size_t len,
 		const struct xattr_handler *handler)
 {
-	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 	int total_len, prefix_len;
 
 	switch (handler->flags) {
@@ -57,11 +57,11 @@ static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
 	return total_len;
 }
 
-static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
+static int f2fs_xattr_generic_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
-	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 
 	switch (handler->flags) {
 	case F2FS_XATTR_INDEX_USER:
@@ -79,15 +79,14 @@ static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
 	}
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return f2fs_getxattr(d_inode(dentry), handler->flags, name,
-			     buffer, size, NULL);
+	return f2fs_getxattr(inode, handler->flags, name, buffer, size, NULL);
 }
 
-static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
+static int f2fs_xattr_generic_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 
 	switch (handler->flags) {
 	case F2FS_XATTR_INDEX_USER:
@@ -106,11 +105,11 @@ static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	return f2fs_setxattr(d_inode(dentry), handler->flags, name,
-					value, size, NULL, flags);
+	return f2fs_setxattr(inode, handler->flags, name, value, size, NULL,
+			     flags);
 }
 
-static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
+static size_t f2fs_xattr_advise_list(struct inode *inode, char *list,
 		size_t list_size, const char *name, size_t len,
 		const struct xattr_handler *handler)
 {
@@ -123,12 +122,10 @@ static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
 	return size;
 }
 
-static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
+static int f2fs_xattr_advise_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
-	struct inode *inode = d_inode(dentry);
-
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
 
@@ -137,12 +134,10 @@ static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
 	return sizeof(char);
 }
 
-static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name,
+static int f2fs_xattr_advise_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	struct inode *inode = d_inode(dentry);
-
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
 	if (!inode_owner_or_capable(inode))
@@ -460,7 +455,7 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 		if (!handler)
 			continue;
 
-		size = handler->list(dentry, buffer, rest, entry->e_name,
+		size = handler->list(inode, buffer, rest, entry->e_name,
 				entry->e_name_len, handler);
 		if (buffer && size > rest) {
 			error = -ERANGE;
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index 3979c608..71e0495 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -583,11 +583,11 @@ out:
  *
  * Returns: actual size of data on success, -errno on error
  */
-static int gfs2_xattr_get(struct dentry *dentry, const char *name,
+static int gfs2_xattr_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
-	struct gfs2_inode *ip = GFS2_I(d_inode(dentry));
+	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_ea_location el;
 	int type = handler->flags;
 	int error;
@@ -1229,11 +1229,11 @@ int __gfs2_xattr_set(struct inode *inode, const char *name,
 	return error;
 }
 
-static int gfs2_xattr_set(struct dentry *dentry, const char *name,
+static int gfs2_xattr_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	return __gfs2_xattr_set(d_inode(dentry), name, value,
+	return __gfs2_xattr_set(inode, name, value,
 				size, flags, handler->flags);
 }
 
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
index 65914db..2ba308c 100644
--- a/fs/hfsplus/xattr.c
+++ b/fs/hfsplus/xattr.c
@@ -424,7 +424,7 @@ static int copy_name(char *buffer, const char *xattr_name, int name_len)
 	return len;
 }
 
-int hfsplus_setxattr(struct dentry *dentry, const char *name,
+int hfsplus_setxattr(struct inode *inode, const char *name,
 		     const void *value, size_t size, int flags,
 		     const char *prefix, size_t prefixlen)
 {
@@ -440,7 +440,7 @@ int hfsplus_setxattr(struct dentry *dentry, const char *name,
 		return -ENOMEM;
 	strcpy(xattr_name, prefix);
 	strcpy(xattr_name + prefixlen, name);
-	res = __hfsplus_setxattr(d_inode(dentry), xattr_name, value, size,
+	res = __hfsplus_setxattr(inode, xattr_name, value, size,
 				 flags);
 	kfree(xattr_name);
 	return res;
@@ -582,7 +582,7 @@ failed_getxattr_init:
 	return res;
 }
 
-ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
+ssize_t hfsplus_getxattr(struct inode *inode, const char *name,
 			 void *value, size_t size,
 			 const char *prefix, size_t prefixlen)
 {
@@ -600,7 +600,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
 	strcpy(xattr_name, prefix);
 	strcpy(xattr_name + prefixlen, name);
 
-	res = __hfsplus_getxattr(d_inode(dentry), xattr_name, value, size);
+	res = __hfsplus_getxattr(inode, xattr_name, value, size);
 	kfree(xattr_name);
 	return res;
 
@@ -849,7 +849,7 @@ end_removexattr:
 	return err;
 }
 
-static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
+static int hfsplus_osx_getxattr(struct inode *inode, const char *name,
 					void *buffer, size_t size,
 					const struct xattr_handler *handler)
 {
@@ -869,10 +869,10 @@ static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
 	 * creates), so we pass the name through unmodified (after
 	 * ensuring it doesn't conflict with another namespace).
 	 */
-	return __hfsplus_getxattr(d_inode(dentry), name, buffer, size);
+	return __hfsplus_getxattr(inode, name, buffer, size);
 }
 
-static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
+static int hfsplus_osx_setxattr(struct inode *inode, const char *name,
 		const void *buffer, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
@@ -892,7 +892,7 @@ static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
 	 * creates), so we pass the name through unmodified (after
 	 * ensuring it doesn't conflict with another namespace).
 	 */
-	return __hfsplus_setxattr(d_inode(dentry), name, buffer, size, flags);
+	return __hfsplus_setxattr(inode, name, buffer, size, flags);
 }
 
 const struct xattr_handler hfsplus_xattr_osx_handler = {
diff --git a/fs/hfsplus/xattr.h b/fs/hfsplus/xattr.h
index f9b0955..68f6b53 100644
--- a/fs/hfsplus/xattr.h
+++ b/fs/hfsplus/xattr.h
@@ -21,14 +21,14 @@ extern const struct xattr_handler *hfsplus_xattr_handlers[];
 int __hfsplus_setxattr(struct inode *inode, const char *name,
 			const void *value, size_t size, int flags);
 
-int hfsplus_setxattr(struct dentry *dentry, const char *name,
+int hfsplus_setxattr(struct inode *inode, const char *name,
 				   const void *value, size_t size, int flags,
 				   const char *prefix, size_t prefixlen);
 
 ssize_t __hfsplus_getxattr(struct inode *inode, const char *name,
 			   void *value, size_t size);
 
-ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
+ssize_t hfsplus_getxattr(struct inode *inode, const char *name,
 			 void *value, size_t size,
 			 const char *prefix, size_t prefixlen);
 
diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c
index 3601ecc..aefd82f 100644
--- a/fs/hfsplus/xattr_security.c
+++ b/fs/hfsplus/xattr_security.c
@@ -13,20 +13,20 @@
 #include "xattr.h"
 #include "acl.h"
 
-static int hfsplus_security_getxattr(struct dentry *dentry, const char *name,
+static int hfsplus_security_getxattr(struct inode *inode, const char *name,
 					void *buffer, size_t size,
 					const struct xattr_handler *handler)
 {
-	return hfsplus_getxattr(dentry, name, buffer, size,
+	return hfsplus_getxattr(inode, name, buffer, size,
 				XATTR_SECURITY_PREFIX,
 				XATTR_SECURITY_PREFIX_LEN);
 }
 
-static int hfsplus_security_setxattr(struct dentry *dentry, const char *name,
+static int hfsplus_security_setxattr(struct inode *inode, const char *name,
 		const void *buffer, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	return hfsplus_setxattr(dentry, name, buffer, size, flags,
+	return hfsplus_setxattr(inode, name, buffer, size, flags,
 				XATTR_SECURITY_PREFIX,
 				XATTR_SECURITY_PREFIX_LEN);
 }
diff --git a/fs/hfsplus/xattr_trusted.c b/fs/hfsplus/xattr_trusted.c
index 123cd8e..077e26c 100644
--- a/fs/hfsplus/xattr_trusted.c
+++ b/fs/hfsplus/xattr_trusted.c
@@ -11,20 +11,20 @@
 #include "hfsplus_fs.h"
 #include "xattr.h"
 
-static int hfsplus_trusted_getxattr(struct dentry *dentry, const char *name,
+static int hfsplus_trusted_getxattr(struct inode *inode, const char *name,
 					void *buffer, size_t size,
 					const struct xattr_handler *handler)
 {
-	return hfsplus_getxattr(dentry, name, buffer, size,
+	return hfsplus_getxattr(inode, name, buffer, size,
 				XATTR_TRUSTED_PREFIX,
 				XATTR_TRUSTED_PREFIX_LEN);
 }
 
-static int hfsplus_trusted_setxattr(struct dentry *dentry, const char *name,
+static int hfsplus_trusted_setxattr(struct inode *inode, const char *name,
 		const void *buffer, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	return hfsplus_setxattr(dentry, name, buffer, size, flags,
+	return hfsplus_setxattr(inode, name, buffer, size, flags,
 				XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
 }
 
diff --git a/fs/hfsplus/xattr_user.c b/fs/hfsplus/xattr_user.c
index 2272557..1554304 100644
--- a/fs/hfsplus/xattr_user.c
+++ b/fs/hfsplus/xattr_user.c
@@ -11,20 +11,20 @@
 #include "hfsplus_fs.h"
 #include "xattr.h"
 
-static int hfsplus_user_getxattr(struct dentry *dentry, const char *name,
+static int hfsplus_user_getxattr(struct inode *inode, const char *name,
 					void *buffer, size_t size,
 					const struct xattr_handler *handler)
 {
 
-	return hfsplus_getxattr(dentry, name, buffer, size,
+	return hfsplus_getxattr(inode, name, buffer, size,
 				XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
 }
 
-static int hfsplus_user_setxattr(struct dentry *dentry, const char *name,
+static int hfsplus_user_setxattr(struct inode *inode, const char *name,
 		const void *buffer, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	return hfsplus_setxattr(dentry, name, buffer, size, flags,
+	return hfsplus_setxattr(inode, name, buffer, size, flags,
 				XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
 }
 
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
index 8f609e8..8496955 100644
--- a/fs/jffs2/security.c
+++ b/fs/jffs2/security.c
@@ -48,29 +48,29 @@ int jffs2_init_security(struct inode *inode, struct inode *dir,
 }
 
 /* ---- XATTR Handler for "security.*" ----------------- */
-static int jffs2_security_getxattr(struct dentry *dentry, const char *name,
+static int jffs2_security_getxattr(struct inode *inode, const char *name,
 				   void *buffer, size_t size,
 				   const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
 
-	return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY,
+	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY,
 				 name, buffer, size);
 }
 
-static int jffs2_security_setxattr(struct dentry *dentry, const char *name,
+static int jffs2_security_setxattr(struct inode *inode, const char *name,
 		const void *buffer, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
 
-	return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY,
+	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY,
 				 name, buffer, size, flags);
 }
 
-static size_t jffs2_security_listxattr(struct dentry *dentry, char *list,
+static size_t jffs2_security_listxattr(struct inode *inode, char *list,
 		size_t list_size, const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 8b2305c..67db313 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -1001,10 +1001,10 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
 		if (!xhandle)
 			continue;
 		if (buffer) {
-			rc = xhandle->list(dentry, buffer+len, size-len,
+			rc = xhandle->list(inode, buffer+len, size-len,
 					   xd->xname, xd->name_len, xhandle);
 		} else {
-			rc = xhandle->list(dentry, NULL, 0, xd->xname,
+			rc = xhandle->list(inode, NULL, 0, xd->xname,
 					   xd->name_len, xhandle);
 		}
 		if (rc < 0)
diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c
index afa0e4d..fab079d 100644
--- a/fs/jffs2/xattr_trusted.c
+++ b/fs/jffs2/xattr_trusted.c
@@ -16,26 +16,26 @@
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 
-static int jffs2_trusted_getxattr(struct dentry *dentry, const char *name,
+static int jffs2_trusted_getxattr(struct inode *inode, const char *name,
 		void *buffer, size_t size, const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
-	return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED,
+	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED,
 				 name, buffer, size);
 }
 
-static int jffs2_trusted_setxattr(struct dentry *dentry, const char *name,
+static int jffs2_trusted_setxattr(struct inode *inode, const char *name,
 		const void *buffer, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
-	return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED,
+	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_TRUSTED,
 				 name, buffer, size, flags);
 }
 
-static size_t jffs2_trusted_listxattr(struct dentry *dentry, char *list,
+static size_t jffs2_trusted_listxattr(struct inode *inode, char *list,
 		size_t list_size, const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
index 4c45567..33dab9b 100644
--- a/fs/jffs2/xattr_user.c
+++ b/fs/jffs2/xattr_user.c
@@ -16,27 +16,27 @@
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 
-static int jffs2_user_getxattr(struct dentry *dentry, const char *name,
+static int jffs2_user_getxattr(struct inode *inode, const char *name,
 			       void *buffer, size_t size,
 			       const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
-	return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_USER,
+	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER,
 				 name, buffer, size);
 }
 
-static int jffs2_user_setxattr(struct dentry *dentry, const char *name,
+static int jffs2_user_setxattr(struct inode *inode, const char *name,
 		const void *buffer, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
-	return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_USER,
+	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_USER,
 				 name, buffer, size, flags);
 }
 
-static size_t jffs2_user_listxattr(struct dentry *dentry, char *list,
+static size_t jffs2_user_listxattr(struct inode *inode, char *list,
 		size_t list_size, const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 977165e..9c5a015 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4841,12 +4841,11 @@ static int nfs4_do_set_security_label(struct inode *inode,
 }
 
 static int
-nfs4_set_security_label(struct dentry *dentry, const void *buf, size_t buflen)
+nfs4_set_security_label(struct inode *inode, const void *buf, size_t buflen)
 {
 	struct nfs4_label ilabel, *olabel = NULL;
 	struct nfs_fattr fattr;
 	struct rpc_cred *cred;
-	struct inode *inode = d_inode(dentry);
 	int status;
 
 	if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL))
@@ -6201,7 +6200,7 @@ nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
 
 #define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
 
-static int nfs4_xattr_set_nfs4_acl(struct dentry *dentry, const char *key,
+static int nfs4_xattr_set_nfs4_acl(struct inode *inode, const char *key,
 				   const void *buf, size_t buflen,
 				   int flags,
 				   const struct xattr_handler *handler)
@@ -6209,27 +6208,27 @@ static int nfs4_xattr_set_nfs4_acl(struct dentry *dentry, const char *key,
 	if (strcmp(key, "") != 0)
 		return -EINVAL;
 
-	return nfs4_proc_set_acl(d_inode(dentry), buf, buflen);
+	return nfs4_proc_set_acl(inode, buf, buflen);
 }
 
-static int nfs4_xattr_get_nfs4_acl(struct dentry *dentry, const char *key,
+static int nfs4_xattr_get_nfs4_acl(struct inode *inode, const char *key,
 				   void *buf, size_t buflen,
 				   const struct xattr_handler *handler)
 {
 	if (strcmp(key, "") != 0)
 		return -EINVAL;
 
-	return nfs4_proc_get_acl(d_inode(dentry), buf, buflen);
+	return nfs4_proc_get_acl(inode, buf, buflen);
 }
 
-static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list,
+static size_t nfs4_xattr_list_nfs4_acl(struct inode *inode, char *list,
 				       size_t list_len, const char *name,
 				       size_t name_len,
 				       const struct xattr_handler *handler)
 {
 	size_t len = sizeof(XATTR_NAME_NFSV4_ACL);
 
-	if (!nfs4_server_supports_acls(NFS_SERVER(d_inode(dentry))))
+	if (!nfs4_server_supports_acls(NFS_SERVER(inode)))
 		return 0;
 
 	if (list && len <= list_len)
@@ -6243,37 +6242,37 @@ static inline int nfs4_server_supports_labels(struct nfs_server *server)
 	return server->caps & NFS_CAP_SECURITY_LABEL;
 }
 
-static int nfs4_xattr_set_nfs4_label(struct dentry *dentry, const char *key,
+static int nfs4_xattr_set_nfs4_label(struct inode *inode, const char *key,
 				   const void *buf, size_t buflen,
 				   int flags,
 				   const struct xattr_handler *handler)
 {
 	if (security_ismaclabel(key))
-		return nfs4_set_security_label(dentry, buf, buflen);
+		return nfs4_set_security_label(inode, buf, buflen);
 
 	return -EOPNOTSUPP;
 }
 
-static int nfs4_xattr_get_nfs4_label(struct dentry *dentry, const char *key,
+static int nfs4_xattr_get_nfs4_label(struct inode *inode, const char *key,
 				   void *buf, size_t buflen,
 				   const struct xattr_handler *handler)
 {
 	if (security_ismaclabel(key))
-		return nfs4_get_security_label(d_inode(dentry), buf, buflen);
+		return nfs4_get_security_label(inode, buf, buflen);
 	return -EOPNOTSUPP;
 }
 
-static size_t nfs4_xattr_list_nfs4_label(struct dentry *dentry, char *list,
+static size_t nfs4_xattr_list_nfs4_label(struct inode *inode, char *list,
 				       size_t list_len, const char *name,
 				       size_t name_len,
 				       const struct xattr_handler *handler)
 {
 	size_t len = 0;
 
-	if (nfs_server_capable(d_inode(dentry), NFS_CAP_SECURITY_LABEL)) {
-		len = security_inode_listsecurity(d_inode(dentry), NULL, 0);
+	if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) {
+		len = security_inode_listsecurity(inode, NULL, 0);
 		if (list && len <= list_len)
-			security_inode_listsecurity(d_inode(dentry), list, len);
+			security_inode_listsecurity(inode, list, len);
 	}
 	return len;
 }
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index f5ce434..6cdbd35 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -7237,7 +7237,7 @@ leave:
 /*
  * 'security' attributes support
  */
-static size_t ocfs2_xattr_security_list(struct dentry *dentry, char *list,
+static size_t ocfs2_xattr_security_list(struct inode *inode, char *list,
 					size_t list_size, const char *name,
 					size_t name_len,
 					const struct xattr_handler *handler)
@@ -7253,24 +7253,24 @@ static size_t ocfs2_xattr_security_list(struct dentry *dentry, char *list,
 	return total_len;
 }
 
-static int ocfs2_xattr_security_get(struct dentry *dentry, const char *name,
+static int ocfs2_xattr_security_get(struct inode *inode, const char *name,
 				    void *buffer, size_t size,
 				    const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY,
+	return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_SECURITY,
 			       name, buffer, size);
 }
 
-static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,
+static int ocfs2_xattr_security_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY,
+	return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
 			       name, value, size, flags);
 }
 
@@ -7330,7 +7330,7 @@ const struct xattr_handler ocfs2_xattr_security_handler = {
 /*
  * 'trusted' attributes support
  */
-static size_t ocfs2_xattr_trusted_list(struct dentry *dentry, char *list,
+static size_t ocfs2_xattr_trusted_list(struct inode *inode, char *list,
 				       size_t list_size, const char *name,
 				       size_t name_len,
 				       const struct xattr_handler *handler)
@@ -7346,24 +7346,24 @@ static size_t ocfs2_xattr_trusted_list(struct dentry *dentry, char *list,
 	return total_len;
 }
 
-static int ocfs2_xattr_trusted_get(struct dentry *dentry, const char *name,
+static int ocfs2_xattr_trusted_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED,
+	return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_TRUSTED,
 			       name, buffer, size);
 }
 
-static int ocfs2_xattr_trusted_set(struct dentry *dentry, const char *name,
+static int ocfs2_xattr_trusted_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED,
+	return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_TRUSTED,
 			       name, value, size, flags);
 }
 
@@ -7377,14 +7377,14 @@ const struct xattr_handler ocfs2_xattr_trusted_handler = {
 /*
  * 'user' attributes support
  */
-static size_t ocfs2_xattr_user_list(struct dentry *dentry, char *list,
+static size_t ocfs2_xattr_user_list(struct inode *inode, char *list,
 				    size_t list_size, const char *name,
 				    size_t name_len,
 				    const struct xattr_handler *handler)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
-	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
 		return 0;
@@ -7397,32 +7397,32 @@ static size_t ocfs2_xattr_user_list(struct dentry *dentry, char *list,
 	return total_len;
 }
 
-static int ocfs2_xattr_user_get(struct dentry *dentry, const char *name,
+static int ocfs2_xattr_user_get(struct inode *inode, const char *name,
 		void *buffer, size_t size,
 		const struct xattr_handler *handler)
 {
-	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
 		return -EOPNOTSUPP;
-	return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_USER, name,
+	return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_USER, name,
 			       buffer, size);
 }
 
-static int ocfs2_xattr_user_set(struct dentry *dentry, const char *name,
+static int ocfs2_xattr_user_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
 		return -EOPNOTSUPP;
 
-	return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_USER,
+	return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_USER,
 			       name, value, size, flags);
 }
 
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index cea22e6..8d9b8d8 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -762,19 +762,19 @@ posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
 EXPORT_SYMBOL (posix_acl_to_xattr);
 
 static int
-posix_acl_xattr_get(struct dentry *dentry, const char *name,
+posix_acl_xattr_get(struct inode *inode, const char *name,
 		void *value, size_t size,
 		const struct xattr_handler *handler)
 {
 	struct posix_acl *acl;
 	int error;
 
-	if (!IS_POSIXACL(d_backing_inode(dentry)))
+	if (!IS_POSIXACL(inode))
 		return -EOPNOTSUPP;
-	if (d_is_symlink(dentry))
+	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
 
-	acl = get_acl(d_backing_inode(dentry), handler->flags);
+	acl = get_acl(inode, handler->flags);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl == NULL)
@@ -787,11 +787,10 @@ posix_acl_xattr_get(struct dentry *dentry, const char *name,
 }
 
 static int
-posix_acl_xattr_set(struct dentry *dentry, const char *name,
+posix_acl_xattr_set(struct inode *inode, const char *name,
 		const void *value, size_t size, int flags,
 		const struct xattr_handler *handler)
 {
-	struct inode *inode = d_backing_inode(dentry);
 	struct posix_acl *acl = NULL;
 	int ret;
 
@@ -824,16 +823,16 @@ out:
 }
 
 static size_t
-posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
+posix_acl_xattr_list(struct inode *inode, char *list, size_t list_size,
 		const char *name, size_t name_len,
 		const struct xattr_handler *handler)
 {
 	const char *xname = handler->prefix;
 	size_t size;
 
-	if (!IS_POSIXACL(d_backing_inode(dentry)))
+	if (!IS_POSIXACL(inode))
 		return -EOPNOTSUPP;
-	if (d_is_symlink(dentry))
+	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
 
 	size = strlen(xname) + 1;
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index ad6e4bb..5b58dea 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -771,50 +771,53 @@ ssize_t
 reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
 		  size_t size)
 {
+	struct inode *inode = d_inode(dentry);
 	const struct xattr_handler *handler;
 
 	handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
+	if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->get(dentry, name, buffer, size, handler);
+	return handler->get(inode, name, buffer, size, handler);
 }
 
 /*
  * Inode operation setxattr()
  *
- * d_inode(dentry)->i_mutex down
+ * inode->i_mutex down
  */
 int
 reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 		  size_t size, int flags)
 {
+	struct inode *inode = d_inode(dentry);
 	const struct xattr_handler *handler;
 
 	handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
+	if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->set(dentry, name, value, size, flags, handler);
+	return handler->set(inode, name, value, size, flags, handler);
 }
 
 /*
  * Inode operation removexattr()
  *
- * d_inode(dentry)->i_mutex down
+ * inode->i_mutex down
  */
 int reiserfs_removexattr(struct dentry *dentry, const char *name)
 {
+	struct inode *inode = d_inode(dentry);
 	const struct xattr_handler *handler;
 
 	handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-	if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
+	if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->set(dentry, name, NULL, 0, XATTR_REPLACE, handler);
+	return handler->set(inode, name, NULL, 0, XATTR_REPLACE, handler);
 }
 
 struct listxattr_buf {
@@ -835,6 +838,7 @@ static int listxattr_filler(struct dir_context *ctx, const char *name,
 
 	if (name[0] != '.' ||
 	    (namelen != 1 && (name[1] != '.' || namelen != 2))) {
+		struct inode *inode = d_inode(b->dentry);
 		const struct xattr_handler *handler;
 
 		handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr,
@@ -842,13 +846,13 @@ static int listxattr_filler(struct dir_context *ctx, const char *name,
 		if (!handler)	/* Unsupported xattr name */
 			return 0;
 		if (b->buf) {
-			size = handler->list(b->dentry, b->buf + b->pos,
-					 b->size, name, namelen, handler);
+			size = handler->list(inode, b->buf + b->pos, b->size,
+					     name, namelen, handler);
 			if (size > b->size)
 				return -ERANGE;
 		} else {
-			size = handler->list(b->dentry, NULL, 0, name,
-					     namelen, handler);
+			size = handler->list(inode, NULL, 0,
+					     name, namelen, handler);
 		}
 
 		b->pos += size;
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index 08074f5..579c3b2 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -9,39 +9,39 @@
 #include <linux/uaccess.h>
 
 static int
-security_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
+security_get(struct inode *inode, const char *name, void *buffer, size_t size,
 	     const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
 		return -EINVAL;
 
-	if (IS_PRIVATE(d_inode(dentry)))
+	if (IS_PRIVATE(inode))
 		return -EPERM;
 
-	return reiserfs_xattr_get(d_inode(dentry), name, buffer, size);
+	return reiserfs_xattr_get(inode, name, buffer, size);
 }
 
 static int
-security_set(struct dentry *dentry, const char *name, const void *buffer,
+security_set(struct inode *inode, const char *name, const void *buffer,
 	     size_t size, int flags,
 	     const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
 		return -EINVAL;
 
-	if (IS_PRIVATE(d_inode(dentry)))
+	if (IS_PRIVATE(inode))
 		return -EPERM;
 
-	return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
+	return reiserfs_xattr_set(inode, name, buffer, size, flags);
 }
 
-static size_t security_list(struct dentry *dentry, char *list, size_t list_len,
+static size_t security_list(struct inode *inode, char *list, size_t list_len,
 			    const char *name, size_t namelen,
 			    const struct xattr_handler *handler)
 {
 	const size_t len = namelen + 1;
 
-	if (IS_PRIVATE(d_inode(dentry)))
+	if (IS_PRIVATE(inode))
 		return 0;
 
 	if (list && len <= list_len) {
diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c
index e3ab346..ac2c9ae 100644
--- a/fs/reiserfs/xattr_trusted.c
+++ b/fs/reiserfs/xattr_trusted.c
@@ -8,39 +8,39 @@
 #include <linux/uaccess.h>
 
 static int
-trusted_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
+trusted_get(struct inode *inode, const char *name, void *buffer, size_t size,
 	    const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
 		return -EINVAL;
 
-	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry)))
+	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
 		return -EPERM;
 
-	return reiserfs_xattr_get(d_inode(dentry), name, buffer, size);
+	return reiserfs_xattr_get(inode, name, buffer, size);
 }
 
 static int
-trusted_set(struct dentry *dentry, const char *name, const void *buffer,
+trusted_set(struct inode *inode, const char *name, const void *buffer,
 	    size_t size, int flags,
 	    const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
 		return -EINVAL;
 
-	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry)))
+	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
 		return -EPERM;
 
-	return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
+	return reiserfs_xattr_set(inode, name, buffer, size, flags);
 }
 
-static size_t trusted_list(struct dentry *dentry, char *list, size_t list_size,
+static size_t trusted_list(struct inode *inode, char *list, size_t list_size,
 			   const char *name, size_t name_len,
 			   const struct xattr_handler *handler)
 {
 	const size_t len = name_len + 1;
 
-	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry)))
+	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
 		return 0;
 
 	if (list && len <= list_size) {
diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c
index 2c8d466..712fdeb 100644
--- a/fs/reiserfs/xattr_user.c
+++ b/fs/reiserfs/xattr_user.c
@@ -7,37 +7,37 @@
 #include <linux/uaccess.h>
 
 static int
-user_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
+user_get(struct inode *inode, const char *name, void *buffer, size_t size,
 	 const struct xattr_handler *handler)
 {
 
 	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
 		return -EINVAL;
-	if (!reiserfs_xattrs_user(dentry->d_sb))
+	if (!reiserfs_xattrs_user(inode->i_sb))
 		return -EOPNOTSUPP;
-	return reiserfs_xattr_get(d_inode(dentry), name, buffer, size);
+	return reiserfs_xattr_get(inode, name, buffer, size);
 }
 
 static int
-user_set(struct dentry *dentry, const char *name, const void *buffer,
+user_set(struct inode *inode, const char *name, const void *buffer,
 	 size_t size, int flags,
 	 const struct xattr_handler *handler)
 {
 	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
 		return -EINVAL;
 
-	if (!reiserfs_xattrs_user(dentry->d_sb))
+	if (!reiserfs_xattrs_user(inode->i_sb))
 		return -EOPNOTSUPP;
-	return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
+	return reiserfs_xattr_set(inode, name, buffer, size, flags);
 }
 
-static size_t user_list(struct dentry *dentry, char *list, size_t list_size,
+static size_t user_list(struct inode *inode, char *list, size_t list_size,
 			const char *name, size_t name_len,
 			const struct xattr_handler *handler)
 {
 	const size_t len = name_len + 1;
 
-	if (!reiserfs_xattrs_user(dentry->d_sb))
+	if (!reiserfs_xattrs_user(inode->i_sb))
 		return 0;
 	if (list && len <= list_size) {
 		memcpy(list, name, name_len);
diff --git a/fs/squashfs/xattr.c b/fs/squashfs/xattr.c
index 268e25b..38d1b13 100644
--- a/fs/squashfs/xattr.c
+++ b/fs/squashfs/xattr.c
@@ -68,7 +68,7 @@ ssize_t squashfs_listxattr(struct dentry *d, char *buffer,
 		name_size = le16_to_cpu(entry.size);
 		handler = squashfs_xattr_handler(le16_to_cpu(entry.type));
 		if (handler)
-			prefix_size = handler->list(d, buffer, rest, NULL,
+			prefix_size = handler->list(inode, buffer, rest, NULL,
 				name_size, handler);
 		if (prefix_size) {
 			if (buffer) {
@@ -212,7 +212,7 @@ failed:
 }
 
 
-static size_t squashfs_xattr_handler_list(struct dentry *d, char *list,
+static size_t squashfs_xattr_handler_list(struct inode *inode, char *list,
 	size_t list_size, const char *name, size_t name_len,
 	const struct xattr_handler *handler)
 {
@@ -223,13 +223,13 @@ static size_t squashfs_xattr_handler_list(struct dentry *d, char *list,
 	return len;
 }
 
-static int squashfs_xattr_handler_get(struct dentry *d, const char *name,
+static int squashfs_xattr_handler_get(struct inode *inode, const char *name,
 	void *buffer, size_t size, const struct xattr_handler *handler)
 {
 	if (name[0] == '\0')
 		return  -EINVAL;
 
-	return squashfs_xattr_get(d_inode(d), handler->flags, name,
+	return squashfs_xattr_get(inode, handler->flags, name,
 		buffer, size);
 }
 
@@ -246,13 +246,13 @@ static const struct xattr_handler squashfs_xattr_user_handler = {
 /*
  * Trusted namespace support
  */
-static size_t squashfs_trusted_xattr_handler_list(struct dentry *d, char *list,
+static size_t squashfs_trusted_xattr_handler_list(struct inode *inode, char *list,
 	size_t list_size, const char *name, size_t name_len,
 	const struct xattr_handler *handler)
 {
 	if (!capable(CAP_SYS_ADMIN))
 		return 0;
-	return squashfs_xattr_handler_list(d, list, list_size, name, name_len,
+	return squashfs_xattr_handler_list(inode, list, list_size, name, name_len,
 		handler);
 }
 
diff --git a/fs/xattr.c b/fs/xattr.c
index 9584808..c45db57 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -709,7 +709,7 @@ generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t s
 	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->get(dentry, name, buffer, size, handler);
+	return handler->get(dentry->d_inode, name, buffer, size, handler);
 }
 
 /*
@@ -720,18 +720,18 @@ ssize_t
 generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
 	const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
+	struct inode *inode = dentry->d_inode;
 	unsigned int size = 0;
 
 	if (!buffer) {
 		for_each_xattr_handler(handlers, handler) {
-			size += handler->list(dentry, NULL, 0, NULL, 0,
-					      handler);
+			size += handler->list(inode, NULL, 0, NULL, 0, handler);
 		}
 	} else {
 		char *buf = buffer;
 
 		for_each_xattr_handler(handlers, handler) {
-			size = handler->list(dentry, buf, buffer_size,
+			size = handler->list(inode, buf, buffer_size,
 					     NULL, 0, handler);
 			if (size > buffer_size)
 				return -ERANGE;
@@ -756,7 +756,7 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz
 	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->set(dentry, name, value, size, flags, handler);
+	return handler->set(dentry->d_inode, name, value, size, flags, handler);
 }
 
 /*
@@ -771,7 +771,7 @@ generic_removexattr(struct dentry *dentry, const char *name)
 	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->set(dentry, name, NULL, 0,
+	return handler->set(dentry->d_inode, name, NULL, 0,
 			    XATTR_REPLACE, handler);
 }
 
diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c
index 9dace13..1fd52f9 100644
--- a/fs/xfs/xfs_xattr.c
+++ b/fs/xfs/xfs_xattr.c
@@ -32,12 +32,12 @@
 
 
 static int
-xfs_xattr_get(struct dentry *dentry, const char *name,
+xfs_xattr_get(struct inode *inode, const char *name,
 		void *value, size_t size,
 		const struct xattr_handler *handler)
 {
 	int xflags = handler->flags;
-	struct xfs_inode *ip = XFS_I(d_inode(dentry));
+	struct xfs_inode *ip = XFS_I(inode);
 	int error, asize = size;
 
 	if (strcmp(name, "") == 0)
@@ -56,12 +56,12 @@ xfs_xattr_get(struct dentry *dentry, const char *name,
 }
 
 static int
-xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
+xfs_xattr_set(struct inode *inode, const char *name, const void *value,
 		size_t size, int flags,
 		const struct xattr_handler *handler)
 {
 	int xflags = handler->flags;
-	struct xfs_inode *ip = XFS_I(d_inode(dentry));
+	struct xfs_inode *ip = XFS_I(inode);
 
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 8fd287d..0a0539e 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -22,12 +22,12 @@ struct dentry;
 struct xattr_handler {
 	const char *prefix;
 	int flags;      /* fs private flags */
-	size_t (*list)(struct dentry *dentry, char *list, size_t list_size,
+	size_t (*list)(struct inode *inode, char *list, size_t list_size,
 		       const char *name, size_t name_len,
 		       const struct xattr_handler *);
-	int (*get)(struct dentry *dentry, const char *name, void *buffer,
+	int (*get)(struct inode *inode, const char *name, void *buffer,
 		   size_t size, const struct xattr_handler *);
-	int (*set)(struct dentry *dentry, const char *name, const void *buffer,
+	int (*set)(struct inode *inode, const char *name, const void *buffer,
 		   size_t size, int flags, const struct xattr_handler *);
 };
 
-- 
2.4.3



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC 09/11] vfs: Add igetxattr inode operation
  2015-08-20 18:19 ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  -1 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	linux-fsdevel, David Quigley, J. Bruce Fields
  Cc: linux-security-module, cluster-devel

Add an igetxattr inode operation that behaves as getxattr but operates on
inodes instead of dentries.  File systems that support this operation can
implement igetxattr for reading xattrs in contexts where a dentry is not
available, such as within SELinux inode security checks.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 Documentation/filesystems/Locking |  2 ++
 Documentation/filesystems/vfs.txt |  4 ++++
 fs/xattr.c                        | 12 +++++++++---
 include/linux/fs.h                |  1 +
 include/linux/xattr.h             |  1 +
 5 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 6a34a0f..77d6d50 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -58,6 +58,7 @@ prototypes:
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
+	ssize_t (*igetxattr) (struct inode *, const char *, void *, size_t);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	int (*removexattr) (struct dentry *, const char *);
@@ -90,6 +91,7 @@ permission:	no (may not block if called in rcu-walk mode)
 get_acl:	no
 getattr:	no
 setxattr:	yes
+igetxattr:	no
 getxattr:	no
 listxattr:	no
 removexattr:	yes
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 5eb8456..4c9512e 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -357,6 +357,7 @@ struct inode_operations {
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
+	ssize_t (*igetxattr) (struct inode *, const char *, void *, size_t);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	int (*removexattr) (struct dentry *, const char *);
@@ -473,6 +474,9 @@ otherwise noted.
   	attribute name. This method is called by getxattr(2) function
   	call.
 
+  igetxattr: retrieve the value of an extended attribute name of an
+	inode; otherwise identical to getxattr which takes a dentry.
+
   listxattr: called by the VFS to list all extended attributes for a
   	given file. This method is called by listxattr(2) system call.
 
diff --git a/fs/xattr.c b/fs/xattr.c
index c45db57..e706e6b 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -702,14 +702,20 @@ xattr_resolve_name(const struct xattr_handler **handlers, const char **name)
  * Find the handler for the prefix and dispatch its get() operation.
  */
 ssize_t
-generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
+generic_igetxattr(struct inode *inode, const char *name, void *buffer, size_t size)
 {
 	const struct xattr_handler *handler;
 
-	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
+	handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->get(dentry->d_inode, name, buffer, size, handler);
+	return handler->get(inode, name, buffer, size, handler);
+}
+
+ssize_t
+generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
+{
+	return generic_igetxattr(dentry->d_inode, name, buffer, size);
 }
 
 /*
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 84b783f..dbca464 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1657,6 +1657,7 @@ struct inode_operations {
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
+	ssize_t (*igetxattr) (struct inode *, const char *, void *, size_t);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	int (*removexattr) (struct dentry *, const char *);
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 0a0539e..9762025 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -44,6 +44,7 @@ int __vfs_setxattr_noperm(struct dentry *, const char *, const void *, size_t, i
 int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
 int vfs_removexattr(struct dentry *, const char *);
 
+ssize_t generic_igetxattr(struct inode *inode, const char *name, void *buffer, size_t size);
 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);
 int generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 09/11] vfs: Add igetxattr inode operation
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Add an igetxattr inode operation that behaves as getxattr but operates on
inodes instead of dentries.  File systems that support this operation can
implement igetxattr for reading xattrs in contexts where a dentry is not
available, such as within SELinux inode security checks.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 Documentation/filesystems/Locking |  2 ++
 Documentation/filesystems/vfs.txt |  4 ++++
 fs/xattr.c                        | 12 +++++++++---
 include/linux/fs.h                |  1 +
 include/linux/xattr.h             |  1 +
 5 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 6a34a0f..77d6d50 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -58,6 +58,7 @@ prototypes:
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
+	ssize_t (*igetxattr) (struct inode *, const char *, void *, size_t);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	int (*removexattr) (struct dentry *, const char *);
@@ -90,6 +91,7 @@ permission:	no (may not block if called in rcu-walk mode)
 get_acl:	no
 getattr:	no
 setxattr:	yes
+igetxattr:	no
 getxattr:	no
 listxattr:	no
 removexattr:	yes
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 5eb8456..4c9512e 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -357,6 +357,7 @@ struct inode_operations {
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
+	ssize_t (*igetxattr) (struct inode *, const char *, void *, size_t);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	int (*removexattr) (struct dentry *, const char *);
@@ -473,6 +474,9 @@ otherwise noted.
   	attribute name. This method is called by getxattr(2) function
   	call.
 
+  igetxattr: retrieve the value of an extended attribute name of an
+	inode; otherwise identical to getxattr which takes a dentry.
+
   listxattr: called by the VFS to list all extended attributes for a
   	given file. This method is called by listxattr(2) system call.
 
diff --git a/fs/xattr.c b/fs/xattr.c
index c45db57..e706e6b 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -702,14 +702,20 @@ xattr_resolve_name(const struct xattr_handler **handlers, const char **name)
  * Find the handler for the prefix and dispatch its get() operation.
  */
 ssize_t
-generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
+generic_igetxattr(struct inode *inode, const char *name, void *buffer, size_t size)
 {
 	const struct xattr_handler *handler;
 
-	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
+	handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->get(dentry->d_inode, name, buffer, size, handler);
+	return handler->get(inode, name, buffer, size, handler);
+}
+
+ssize_t
+generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
+{
+	return generic_igetxattr(dentry->d_inode, name, buffer, size);
 }
 
 /*
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 84b783f..dbca464 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1657,6 +1657,7 @@ struct inode_operations {
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
+	ssize_t (*igetxattr) (struct inode *, const char *, void *, size_t);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	int (*removexattr) (struct dentry *, const char *);
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 0a0539e..9762025 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -44,6 +44,7 @@ int __vfs_setxattr_noperm(struct dentry *, const char *, const void *, size_t, i
 int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
 int vfs_removexattr(struct dentry *, const char *);
 
+ssize_t generic_igetxattr(struct inode *inode, const char *name, void *buffer, size_t size);
 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);
 int generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);
-- 
2.4.3



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC 10/11] selinux: Allow to invalidate an inode's security label
  2015-08-20 18:19 ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  -1 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	linux-fsdevel, David Quigley, J. Bruce Fields
  Cc: linux-security-module, cluster-devel

Add the LSM and SELinux infrastructure for invalidating inode->i_security and
for re-initializing it from inode_has_perm when necessary.  In inode_has_perm,
we don't have access to a dentry, so file systems must implement iop->igetxattr
in order to be able to invalidate security labels.

Alternatively, we could add an inode operation called by inode_has_perm to
revalidate the security label of the inode on each call, but inode_has_perm is
called so frequently that the overhead seems excessive.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 include/linux/lsm_hooks.h         |  6 +++++
 include/linux/security.h          |  5 +++++
 security/selinux/hooks.c          | 47 ++++++++++++++++++++++++++++++---------
 security/selinux/include/objsec.h |  3 ++-
 4 files changed, 49 insertions(+), 12 deletions(-)

diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 9429f05..9fe99d6 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1261,6 +1261,10 @@
  *	audit_rule_init.
  *	@rule contains the allocated rule
  *
+ * @inode_invalidate_secctx:
+ *	Notify the security module that it must revalidate the security context
+ *	of an inode before the next access.
+ *
  * @inode_notifysecctx:
  *	Notify the security module of what the security context of an inode
  *	should be.  Initializes the incore security context managed by the
@@ -1516,6 +1520,7 @@ union security_list_options {
 	int (*secctx_to_secid)(const char *secdata, u32 seclen, u32 *secid);
 	void (*release_secctx)(char *secdata, u32 seclen);
 
+	void (*inode_invalidate_secctx)(struct inode *inode);
 	int (*inode_notifysecctx)(struct inode *inode, void *ctx, u32 ctxlen);
 	int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen);
 	int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen);
@@ -1757,6 +1762,7 @@ struct security_hook_heads {
 	struct list_head secid_to_secctx;
 	struct list_head secctx_to_secid;
 	struct list_head release_secctx;
+	struct list_head inode_invalidate_secctx;
 	struct list_head inode_notifysecctx;
 	struct list_head inode_setsecctx;
 	struct list_head inode_getsecctx;
diff --git a/include/linux/security.h b/include/linux/security.h
index 79d85dd..f50587d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -353,6 +353,7 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
 int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
 void security_release_secctx(char *secdata, u32 seclen);
 
+int security_inode_invalidate_secctx(struct inode *inode);
 int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
 int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
 int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
@@ -1093,6 +1094,10 @@ static inline void security_release_secctx(char *secdata, u32 seclen)
 {
 }
 
+static inline void security_inode_invalidate_secctx(struct inode *inode)
+{
+}
+
 static inline int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
 {
 	return -EOPNOTSUPP;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 564079c..e80fcda 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -430,7 +430,7 @@ static int sb_finish_set_opts(struct super_block *sb)
 			rc = -EOPNOTSUPP;
 			goto out;
 		}
-		rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
+		rc = selinux_getxattr(root_inode, root, NULL, 0);
 		if (rc < 0 && rc != -ENODATA) {
 			if (rc == -EOPNOTSUPP)
 				printk(KERN_WARNING "SELinux: (dev %s, type "
@@ -1270,6 +1270,19 @@ static int selinux_genfs_get_sid(struct dentry *dentry,
 	return rc;
 }
 
+static int selinux_getxattr(struct inode *inode, struct dentry *dentry,
+		       char *context, unsigned int len)
+{
+	if (dentry)
+		return inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
+					     context, len);
+	else if (inode && inode->i_op->igetxattr)
+		return inode->i_op->igetxattr(inode, XATTR_NAME_SELINUX,
+					      context, len);
+	else
+		return -EOPNOTSUPP;
+}
+
 /* The inode's security attributes must be initialized before first use. */
 static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
 {
@@ -1282,11 +1295,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 	unsigned len = 0;
 	int rc = 0;
 
-	if (isec->initialized)
+	if (isec->initialized == 1)
 		goto out;
 
 	mutex_lock(&isec->lock);
-	if (isec->initialized)
+	if (isec->initialized == 1)
 		goto out_unlock;
 
 	sbsec = inode->i_sb->s_security;
@@ -1319,7 +1332,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 			/* Called from selinux_complete_init, try to find a dentry. */
 			dentry = d_find_alias(inode);
 		}
-		if (!dentry) {
+		if (!dentry && !inode->i_op->igetxattr) {
 			/*
 			 * this is can be hit on boot when a file is accessed
 			 * before the policy is loaded.  When we load policy we
@@ -1340,14 +1353,12 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 			goto out_unlock;
 		}
 		context[len] = '\0';
-		rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
-					   context, len);
+		rc = selinux_getxattr(inode, dentry, context, len);
 		if (rc == -ERANGE) {
 			kfree(context);
 
 			/* Need a larger buffer.  Query for the right size. */
-			rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
-						   NULL, 0);
+			rc = selinux_getxattr(inode, dentry, NULL, 0);
 			if (rc < 0) {
 				dput(dentry);
 				goto out_unlock;
@@ -1360,9 +1371,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 				goto out_unlock;
 			}
 			context[len] = '\0';
-			rc = inode->i_op->getxattr(dentry,
-						   XATTR_NAME_SELINUX,
-						   context, len);
+			rc = selinux_getxattr(inode, dentry, context, len);
 		}
 		dput(dentry);
 		if (rc < 0) {
@@ -1614,6 +1623,12 @@ static int inode_has_perm(const struct cred *cred,
 	sid = cred_sid(cred);
 	isec = inode->i_security;
 
+	if (isec->initialized == 2) {
+		inode_doinit(inode);
+		if (isec->initialized == 2)
+			return -EACCES;
+	}
+
 	return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
 }
 
@@ -5715,6 +5730,15 @@ static void selinux_release_secctx(char *secdata, u32 seclen)
 	kfree(secdata);
 }
 
+static void selinux_inode_invalidate_secctx(struct inode *inode)
+{
+	struct inode_security_struct *isec = inode->i_security;
+
+	mutex_lock(&isec->lock);
+	isec->initialized = 2;
+	mutex_unlock(&isec->lock);
+}
+
 /*
  *	called with inode->i_mutex locked
  */
@@ -5946,6 +5970,7 @@ static struct security_hook_list selinux_hooks[] = {
 	LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
 	LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
 	LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
+	LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
 	LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
 	LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
 	LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 81fa718..5b13732 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -46,7 +46,8 @@ struct inode_security_struct {
 	u32 task_sid;		/* SID of creating task */
 	u32 sid;		/* SID of this object */
 	u16 sclass;		/* security class of this object */
-	unsigned char initialized;	/* initialization flag */
+	unsigned char initialized;	/* 0: not initialized, 1: initialized,
+					   2: needs revalidation */
 	struct mutex lock;
 };
 
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 10/11] selinux: Allow to invalidate an inode's security label
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Add the LSM and SELinux infrastructure for invalidating inode->i_security and
for re-initializing it from inode_has_perm when necessary.  In inode_has_perm,
we don't have access to a dentry, so file systems must implement iop->igetxattr
in order to be able to invalidate security labels.

Alternatively, we could add an inode operation called by inode_has_perm to
revalidate the security label of the inode on each call, but inode_has_perm is
called so frequently that the overhead seems excessive.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 include/linux/lsm_hooks.h         |  6 +++++
 include/linux/security.h          |  5 +++++
 security/selinux/hooks.c          | 47 ++++++++++++++++++++++++++++++---------
 security/selinux/include/objsec.h |  3 ++-
 4 files changed, 49 insertions(+), 12 deletions(-)

diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 9429f05..9fe99d6 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1261,6 +1261,10 @@
  *	audit_rule_init.
  *	@rule contains the allocated rule
  *
+ * @inode_invalidate_secctx:
+ *	Notify the security module that it must revalidate the security context
+ *	of an inode before the next access.
+ *
  * @inode_notifysecctx:
  *	Notify the security module of what the security context of an inode
  *	should be.  Initializes the incore security context managed by the
@@ -1516,6 +1520,7 @@ union security_list_options {
 	int (*secctx_to_secid)(const char *secdata, u32 seclen, u32 *secid);
 	void (*release_secctx)(char *secdata, u32 seclen);
 
+	void (*inode_invalidate_secctx)(struct inode *inode);
 	int (*inode_notifysecctx)(struct inode *inode, void *ctx, u32 ctxlen);
 	int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen);
 	int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen);
@@ -1757,6 +1762,7 @@ struct security_hook_heads {
 	struct list_head secid_to_secctx;
 	struct list_head secctx_to_secid;
 	struct list_head release_secctx;
+	struct list_head inode_invalidate_secctx;
 	struct list_head inode_notifysecctx;
 	struct list_head inode_setsecctx;
 	struct list_head inode_getsecctx;
diff --git a/include/linux/security.h b/include/linux/security.h
index 79d85dd..f50587d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -353,6 +353,7 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
 int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
 void security_release_secctx(char *secdata, u32 seclen);
 
+int security_inode_invalidate_secctx(struct inode *inode);
 int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
 int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
 int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
@@ -1093,6 +1094,10 @@ static inline void security_release_secctx(char *secdata, u32 seclen)
 {
 }
 
+static inline void security_inode_invalidate_secctx(struct inode *inode)
+{
+}
+
 static inline int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
 {
 	return -EOPNOTSUPP;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 564079c..e80fcda 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -430,7 +430,7 @@ static int sb_finish_set_opts(struct super_block *sb)
 			rc = -EOPNOTSUPP;
 			goto out;
 		}
-		rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
+		rc = selinux_getxattr(root_inode, root, NULL, 0);
 		if (rc < 0 && rc != -ENODATA) {
 			if (rc == -EOPNOTSUPP)
 				printk(KERN_WARNING "SELinux: (dev %s, type "
@@ -1270,6 +1270,19 @@ static int selinux_genfs_get_sid(struct dentry *dentry,
 	return rc;
 }
 
+static int selinux_getxattr(struct inode *inode, struct dentry *dentry,
+		       char *context, unsigned int len)
+{
+	if (dentry)
+		return inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
+					     context, len);
+	else if (inode && inode->i_op->igetxattr)
+		return inode->i_op->igetxattr(inode, XATTR_NAME_SELINUX,
+					      context, len);
+	else
+		return -EOPNOTSUPP;
+}
+
 /* The inode's security attributes must be initialized before first use. */
 static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
 {
@@ -1282,11 +1295,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 	unsigned len = 0;
 	int rc = 0;
 
-	if (isec->initialized)
+	if (isec->initialized == 1)
 		goto out;
 
 	mutex_lock(&isec->lock);
-	if (isec->initialized)
+	if (isec->initialized == 1)
 		goto out_unlock;
 
 	sbsec = inode->i_sb->s_security;
@@ -1319,7 +1332,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 			/* Called from selinux_complete_init, try to find a dentry. */
 			dentry = d_find_alias(inode);
 		}
-		if (!dentry) {
+		if (!dentry && !inode->i_op->igetxattr) {
 			/*
 			 * this is can be hit on boot when a file is accessed
 			 * before the policy is loaded.  When we load policy we
@@ -1340,14 +1353,12 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 			goto out_unlock;
 		}
 		context[len] = '\0';
-		rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
-					   context, len);
+		rc = selinux_getxattr(inode, dentry, context, len);
 		if (rc == -ERANGE) {
 			kfree(context);
 
 			/* Need a larger buffer.  Query for the right size. */
-			rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
-						   NULL, 0);
+			rc = selinux_getxattr(inode, dentry, NULL, 0);
 			if (rc < 0) {
 				dput(dentry);
 				goto out_unlock;
@@ -1360,9 +1371,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 				goto out_unlock;
 			}
 			context[len] = '\0';
-			rc = inode->i_op->getxattr(dentry,
-						   XATTR_NAME_SELINUX,
-						   context, len);
+			rc = selinux_getxattr(inode, dentry, context, len);
 		}
 		dput(dentry);
 		if (rc < 0) {
@@ -1614,6 +1623,12 @@ static int inode_has_perm(const struct cred *cred,
 	sid = cred_sid(cred);
 	isec = inode->i_security;
 
+	if (isec->initialized == 2) {
+		inode_doinit(inode);
+		if (isec->initialized == 2)
+			return -EACCES;
+	}
+
 	return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
 }
 
@@ -5715,6 +5730,15 @@ static void selinux_release_secctx(char *secdata, u32 seclen)
 	kfree(secdata);
 }
 
+static void selinux_inode_invalidate_secctx(struct inode *inode)
+{
+	struct inode_security_struct *isec = inode->i_security;
+
+	mutex_lock(&isec->lock);
+	isec->initialized = 2;
+	mutex_unlock(&isec->lock);
+}
+
 /*
  *	called with inode->i_mutex locked
  */
@@ -5946,6 +5970,7 @@ static struct security_hook_list selinux_hooks[] = {
 	LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
 	LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
 	LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
+	LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
 	LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
 	LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
 	LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 81fa718..5b13732 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -46,7 +46,8 @@ struct inode_security_struct {
 	u32 task_sid;		/* SID of creating task */
 	u32 sid;		/* SID of this object */
 	u16 sclass;		/* security class of this object */
-	unsigned char initialized;	/* initialization flag */
+	unsigned char initialized;	/* 0: not initialized, 1: initialized,
+					   2: needs revalidation */
 	struct mutex lock;
 };
 
-- 
2.4.3



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC 11/11] gfs2: Invalide security labels of inodes that go invalid
  2015-08-20 18:19 ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  -1 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	linux-fsdevel, David Quigley, J. Bruce Fields
  Cc: linux-security-module, cluster-devel

Invalide security labels of inodes when they go invalid.  SELinux will reload
the "security.selinux" xattr via iop->igetxattr on the next access.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/gfs2/glops.c |  2 ++
 fs/gfs2/inode.c | 16 ++++++++++++----
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index fa3fa5e..29be6d3 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -13,6 +13,7 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/bio.h>
 #include <linux/posix_acl.h>
+#include <linux/security.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -260,6 +261,7 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
 		if (ip) {
 			set_bit(GIF_INVALID, &ip->i_flags);
 			forget_all_cached_acls(&ip->i_inode);
+			security_inode_invalidate_secctx(&ip->i_inode);
 			gfs2_dir_hash_inval(ip);
 		}
 	}
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 063fdfc..3474976 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -2011,28 +2011,33 @@ static int gfs2_setxattr(struct dentry *dentry, const char *name,
 	return ret;
 }
 
-static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name,
+static ssize_t gfs2_igetxattr(struct inode *inode, const char *name,
 			     void *data, size_t size)
 {
-	struct inode *inode = d_inode(dentry);
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_holder gh;
 	int ret;
 
 	/* For selinux during lookup */
 	if (gfs2_glock_is_locked_by_me(ip->i_gl))
-		return generic_getxattr(dentry, name, data, size);
+		return generic_igetxattr(inode, name, data, size);
 
 	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
 	ret = gfs2_glock_nq(&gh);
 	if (ret == 0) {
-		ret = generic_getxattr(dentry, name, data, size);
+		ret = generic_igetxattr(inode, name, data, size);
 		gfs2_glock_dq(&gh);
 	}
 	gfs2_holder_uninit(&gh);
 	return ret;
 }
 
+static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name,
+			     void *data, size_t size)
+{
+	return gfs2_igetxattr(d_inode(dentry), name, data, size);
+}
+
 static int gfs2_removexattr(struct dentry *dentry, const char *name)
 {
 	struct inode *inode = d_inode(dentry);
@@ -2099,6 +2104,7 @@ const struct inode_operations gfs2_file_iops = {
 	.setattr = gfs2_setattr,
 	.getattr = gfs2_getattr,
 	.setxattr = gfs2_setxattr,
+	.igetxattr = gfs2_igetxattr,
 	.getxattr = gfs2_getxattr,
 	.listxattr = gfs2_listxattr,
 	.removexattr = gfs2_removexattr,
@@ -2121,6 +2127,7 @@ const struct inode_operations gfs2_dir_iops = {
 	.setattr = gfs2_setattr,
 	.getattr = gfs2_getattr,
 	.setxattr = gfs2_setxattr,
+	.igetxattr = gfs2_igetxattr,
 	.getxattr = gfs2_getxattr,
 	.listxattr = gfs2_listxattr,
 	.removexattr = gfs2_removexattr,
@@ -2138,6 +2145,7 @@ const struct inode_operations gfs2_symlink_iops = {
 	.setattr = gfs2_setattr,
 	.getattr = gfs2_getattr,
 	.setxattr = gfs2_setxattr,
+	.igetxattr = gfs2_igetxattr,
 	.getxattr = gfs2_getxattr,
 	.listxattr = gfs2_listxattr,
 	.removexattr = gfs2_removexattr,
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 11/11] gfs2: Invalide security labels of inodes that go invalid
@ 2015-08-20 18:19   ` Andreas Gruenbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-20 18:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Invalide security labels of inodes when they go invalid.  SELinux will reload
the "security.selinux" xattr via iop->igetxattr on the next access.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/gfs2/glops.c |  2 ++
 fs/gfs2/inode.c | 16 ++++++++++++----
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index fa3fa5e..29be6d3 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -13,6 +13,7 @@
 #include <linux/gfs2_ondisk.h>
 #include <linux/bio.h>
 #include <linux/posix_acl.h>
+#include <linux/security.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -260,6 +261,7 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
 		if (ip) {
 			set_bit(GIF_INVALID, &ip->i_flags);
 			forget_all_cached_acls(&ip->i_inode);
+			security_inode_invalidate_secctx(&ip->i_inode);
 			gfs2_dir_hash_inval(ip);
 		}
 	}
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 063fdfc..3474976 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -2011,28 +2011,33 @@ static int gfs2_setxattr(struct dentry *dentry, const char *name,
 	return ret;
 }
 
-static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name,
+static ssize_t gfs2_igetxattr(struct inode *inode, const char *name,
 			     void *data, size_t size)
 {
-	struct inode *inode = d_inode(dentry);
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_holder gh;
 	int ret;
 
 	/* For selinux during lookup */
 	if (gfs2_glock_is_locked_by_me(ip->i_gl))
-		return generic_getxattr(dentry, name, data, size);
+		return generic_igetxattr(inode, name, data, size);
 
 	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
 	ret = gfs2_glock_nq(&gh);
 	if (ret == 0) {
-		ret = generic_getxattr(dentry, name, data, size);
+		ret = generic_igetxattr(inode, name, data, size);
 		gfs2_glock_dq(&gh);
 	}
 	gfs2_holder_uninit(&gh);
 	return ret;
 }
 
+static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name,
+			     void *data, size_t size)
+{
+	return gfs2_igetxattr(d_inode(dentry), name, data, size);
+}
+
 static int gfs2_removexattr(struct dentry *dentry, const char *name)
 {
 	struct inode *inode = d_inode(dentry);
@@ -2099,6 +2104,7 @@ const struct inode_operations gfs2_file_iops = {
 	.setattr = gfs2_setattr,
 	.getattr = gfs2_getattr,
 	.setxattr = gfs2_setxattr,
+	.igetxattr = gfs2_igetxattr,
 	.getxattr = gfs2_getxattr,
 	.listxattr = gfs2_listxattr,
 	.removexattr = gfs2_removexattr,
@@ -2121,6 +2127,7 @@ const struct inode_operations gfs2_dir_iops = {
 	.setattr = gfs2_setattr,
 	.getattr = gfs2_getattr,
 	.setxattr = gfs2_setxattr,
+	.igetxattr = gfs2_igetxattr,
 	.getxattr = gfs2_getxattr,
 	.listxattr = gfs2_listxattr,
 	.removexattr = gfs2_removexattr,
@@ -2138,6 +2145,7 @@ const struct inode_operations gfs2_symlink_iops = {
 	.setattr = gfs2_setattr,
 	.getattr = gfs2_getattr,
 	.setxattr = gfs2_setxattr,
+	.igetxattr = gfs2_igetxattr,
 	.getxattr = gfs2_getxattr,
 	.listxattr = gfs2_listxattr,
 	.removexattr = gfs2_removexattr,
-- 
2.4.3



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [RFC 07/11] 9p: Stop using the generic xattr_handler infrastructure
  2015-08-20 18:19   ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-21  6:46     ` Christoph Hellwig
  -1 siblings, 0 replies; 40+ messages in thread
From: Christoph Hellwig @ 2015-08-21  6:46 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	linux-fsdevel, David Quigley, J. Bruce Fields,
	linux-security-module, cluster-devel

On Thu, Aug 20, 2015 at 08:19:54PM +0200, Andreas Gruenbacher wrote:
> Of all the file systems that use the generic xattr handler infrastructure, 9p
> is the only one that needs dentries inside the xattr file system code.  Open
> code the xattr handling code in 9p so that we can then convert the generic code
> to pass down inodes instead of dentries; this actually takes only little
> additional code.

NAK.  The rest of the series looks somewhat sensible but this is wrong.

We need want to converge to one interface, probably more similar to the
handlers, so we need to decided if we want to pass dentries or inodes to
both of them.

Personally I'm in favor of inodes, and that's how it used to be, but
that makes life more complicated for path based file systems like cifs
or 9p.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 07/11] 9p: Stop using the generic xattr_handler infrastructure
@ 2015-08-21  6:46     ` Christoph Hellwig
  0 siblings, 0 replies; 40+ messages in thread
From: Christoph Hellwig @ 2015-08-21  6:46 UTC (permalink / raw)
  To: cluster-devel.redhat.com

On Thu, Aug 20, 2015 at 08:19:54PM +0200, Andreas Gruenbacher wrote:
> Of all the file systems that use the generic xattr handler infrastructure, 9p
> is the only one that needs dentries inside the xattr file system code.  Open
> code the xattr handling code in 9p so that we can then convert the generic code
> to pass down inodes instead of dentries; this actually takes only little
> additional code.

NAK.  The rest of the series looks somewhat sensible but this is wrong.

We need want to converge to one interface, probably more similar to the
handlers, so we need to decided if we want to pass dentries or inodes to
both of them.

Personally I'm in favor of inodes, and that's how it used to be, but
that makes life more complicated for path based file systems like cifs
or 9p.



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [RFC 09/11] vfs: Add igetxattr inode operation
  2015-08-20 18:19   ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-21  6:48     ` Christoph Hellwig
  -1 siblings, 0 replies; 40+ messages in thread
From: Christoph Hellwig @ 2015-08-21  6:48 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	linux-fsdevel, David Quigley, J. Bruce Fields,
	linux-security-module, cluster-devel

On Thu, Aug 20, 2015 at 08:19:56PM +0200, Andreas Gruenbacher wrote:
> Add an igetxattr inode operation that behaves as getxattr but operates on
> inodes instead of dentries.  File systems that support this operation can
> implement igetxattr for reading xattrs in contexts where a dentry is not
> available, such as within SELinux inode security checks.

And this is even worse - we should not have two operations doing the
same thing.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 09/11] vfs: Add igetxattr inode operation
@ 2015-08-21  6:48     ` Christoph Hellwig
  0 siblings, 0 replies; 40+ messages in thread
From: Christoph Hellwig @ 2015-08-21  6:48 UTC (permalink / raw)
  To: cluster-devel.redhat.com

On Thu, Aug 20, 2015 at 08:19:56PM +0200, Andreas Gruenbacher wrote:
> Add an igetxattr inode operation that behaves as getxattr but operates on
> inodes instead of dentries.  File systems that support this operation can
> implement igetxattr for reading xattrs in contexts where a dentry is not
> available, such as within SELinux inode security checks.

And this is even worse - we should not have two operations doing the
same thing.



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [RFC 11/11] gfs2: Invalide security labels of inodes that go invalid
  2015-08-20 18:19   ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-21  6:49     ` Christoph Hellwig
  -1 siblings, 0 replies; 40+ messages in thread
From: Christoph Hellwig @ 2015-08-21  6:49 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Alexander Viro, Eric Paris, Aneesh Kumar K.V, linux-fsdevel,
	David Quigley, J. Bruce Fields, linux-security-module,
	cluster-devel

On Thu, Aug 20, 2015 at 08:19:58PM +0200, Andreas Gruenbacher wrote:
> Invalide security labels of inodes when they go invalid.  SELinux will reload
> the "security.selinux" xattr via iop->igetxattr on the next access.

And if that's all that you needed just skip the detour trough the VFS
interfaces.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 11/11] gfs2: Invalide security labels of inodes that go invalid
@ 2015-08-21  6:49     ` Christoph Hellwig
  0 siblings, 0 replies; 40+ messages in thread
From: Christoph Hellwig @ 2015-08-21  6:49 UTC (permalink / raw)
  To: cluster-devel.redhat.com

On Thu, Aug 20, 2015 at 08:19:58PM +0200, Andreas Gruenbacher wrote:
> Invalide security labels of inodes when they go invalid.  SELinux will reload
> the "security.selinux" xattr via iop->igetxattr on the next access.

And if that's all that you needed just skip the detour trough the VFS
interfaces.



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [Cluster-devel] [RFC 07/11] 9p: Stop using the generic xattr_handler infrastructure
  2015-08-21  6:46     ` [Cluster-devel] " Christoph Hellwig
@ 2015-08-21  8:35       ` Steven Whitehouse
  -1 siblings, 0 replies; 40+ messages in thread
From: Steven Whitehouse @ 2015-08-21  8:35 UTC (permalink / raw)
  To: Christoph Hellwig, Andreas Gruenbacher
  Cc: J. Bruce Fields, cluster-devel, David Quigley, Eric Paris,
	linux-security-module, Alexander Viro, linux-fsdevel,
	Aneesh Kumar K.V

Hi,

On 21/08/15 07:46, Christoph Hellwig wrote:
> On Thu, Aug 20, 2015 at 08:19:54PM +0200, Andreas Gruenbacher wrote:
>> Of all the file systems that use the generic xattr handler infrastructure, 9p
>> is the only one that needs dentries inside the xattr file system code.  Open
>> code the xattr handling code in 9p so that we can then convert the generic code
>> to pass down inodes instead of dentries; this actually takes only little
>> additional code.
> NAK.  The rest of the series looks somewhat sensible but this is wrong.
>
> We need want to converge to one interface, probably more similar to the
> handlers, so we need to decided if we want to pass dentries or inodes to
> both of them.
>
> Personally I'm in favor of inodes, and that's how it used to be, but
> that makes life more complicated for path based file systems like cifs
> or 9p.
>

We did look at this in detail some time ago, and Al came to the 
conclusion that 9p and CIFS both required the dentries and that it would 
not be possible to pass just an inode. In the SELinux refresh case, the 
dentry is not always available, and I don't think we have any choice 
about that.

I know it is a bit of a mess, so if there is a better way to do it, then 
that would be good. At the moment though, it is not clear quite how we 
could get around this issue,

Steve.


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 07/11] 9p: Stop using the generic xattr_handler infrastructure
@ 2015-08-21  8:35       ` Steven Whitehouse
  0 siblings, 0 replies; 40+ messages in thread
From: Steven Whitehouse @ 2015-08-21  8:35 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Hi,

On 21/08/15 07:46, Christoph Hellwig wrote:
> On Thu, Aug 20, 2015 at 08:19:54PM +0200, Andreas Gruenbacher wrote:
>> Of all the file systems that use the generic xattr handler infrastructure, 9p
>> is the only one that needs dentries inside the xattr file system code.  Open
>> code the xattr handling code in 9p so that we can then convert the generic code
>> to pass down inodes instead of dentries; this actually takes only little
>> additional code.
> NAK.  The rest of the series looks somewhat sensible but this is wrong.
>
> We need want to converge to one interface, probably more similar to the
> handlers, so we need to decided if we want to pass dentries or inodes to
> both of them.
>
> Personally I'm in favor of inodes, and that's how it used to be, but
> that makes life more complicated for path based file systems like cifs
> or 9p.
>

We did look at this in detail some time ago, and Al came to the 
conclusion that 9p and CIFS both required the dentries and that it would 
not be possible to pass just an inode. In the SELinux refresh case, the 
dentry is not always available, and I don't think we have any choice 
about that.

I know it is a bit of a mess, so if there is a better way to do it, then 
that would be good. At the moment though, it is not clear quite how we 
could get around this issue,

Steve.



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [Cluster-devel] [RFC 11/11] gfs2: Invalide security labels of inodes that go invalid
  2015-08-21  6:49     ` [Cluster-devel] " Christoph Hellwig
@ 2015-08-21  9:25       ` Andreas Gruenbacher
  -1 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-21  9:25 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Andreas Gruenbacher, cluster-devel, David Quigley, Eric Paris,
	J. Bruce Fields, linux-security-module, Alexander Viro,
	linux-fsdevel, Aneesh Kumar K.V

Christoph,

thanks for your review.

2015-08-21 8:49 GMT+02:00 Christoph Hellwig <hch@infradead.org>:
> On Thu, Aug 20, 2015 at 08:19:58PM +0200, Andreas Gruenbacher wrote:
>> Invalide security labels of inodes when they go invalid.  SELinux will reload
>> the "security.selinux" xattr via iop->igetxattr on the next access.
>
> And if that's all that you needed just skip the detour trough the VFS
> interfaces.

We have more than one file system that has a similar consistency model
as gfs2 so it's not really a one-off hack, and we have selinux as well
as smack, with several different xattr names.

Assuming that selinux or smack only have an inode available, how would
they (re)load an inode's security label other than going through the
vfs?

I could imagine bypassing the xattr handler abstraction in the
affected file systems, but that doesn't seem much better either.

Thanks,
Andreas

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 11/11] gfs2: Invalide security labels of inodes that go invalid
@ 2015-08-21  9:25       ` Andreas Gruenbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Gruenbacher @ 2015-08-21  9:25 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Christoph,

thanks for your review.

2015-08-21 8:49 GMT+02:00 Christoph Hellwig <hch@infradead.org>:
> On Thu, Aug 20, 2015 at 08:19:58PM +0200, Andreas Gruenbacher wrote:
>> Invalide security labels of inodes when they go invalid.  SELinux will reload
>> the "security.selinux" xattr via iop->igetxattr on the next access.
>
> And if that's all that you needed just skip the detour trough the VFS
> interfaces.

We have more than one file system that has a similar consistency model
as gfs2 so it's not really a one-off hack, and we have selinux as well
as smack, with several different xattr names.

Assuming that selinux or smack only have an inode available, how would
they (re)load an inode's security label other than going through the
vfs?

I could imagine bypassing the xattr handler abstraction in the
affected file systems, but that doesn't seem much better either.

Thanks,
Andreas



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [RFC 00/11] Inode security label invalidation
  2015-08-20 18:19 ` [Cluster-devel] " Andreas Gruenbacher
@ 2015-08-24 17:42   ` Stephen Smalley
  -1 siblings, 0 replies; 40+ messages in thread
From: Stephen Smalley @ 2015-08-24 17:42 UTC (permalink / raw)
  To: Andreas Gruenbacher, Alexander Viro, Christoph Hellwig,
	Eric Paris, Aneesh Kumar K.V, linux-fsdevel, David Quigley,
	J. Bruce Fields
  Cc: linux-security-module, cluster-devel

On 08/20/2015 02:19 PM, Andreas Gruenbacher wrote:
> Hello,
> 
> this patch queue adds an LSM hook for file systems to invalidate inode security
> labels.  To allow selinux to revalidate invalid labels, the generic xattr
> handlers are cleaned up a bit and a new igetxattr inode operation is
> introduced: the getxattr inode operation requires a dentry which selinux
> doesn't have in inode_has_perm(); igetxattr instead takes an inode.  Finally,
> gfs2 is patched to make use of this new mechanism.
> 
> The new igetxattr inode operation currently is *only* used for revalidating
> security labels in selinux; it may make sense to use it instead of getxattr
> when defined.
> 
> Is this approach useful?  An alternative would be to modify selinux so that it
> always has a dentry when checking inode security labels; I would guess that
> this won't work in all cases, though.
> 
> 
> BACKGROUND
> 
> Selinux currently assumes that, after initialization, inode->i_security always
> represents the current security label of the inode.  This assumption works for
> local file systems; any change of the label must go through setxattr (or
> removexattr) which updates inode->i_security.
> 
> On an nfs mount, other nodes can change the security label; there is no
> immediate notification mechanism.  Other nodes will eventually notice a label
> change because the label is transmitted as part of the reply of operations like
> open. (A timeout for cached labels would help too; I'm not sure if the code
> implements that.)
> 
> Other file systems have different consistency models. For example, gfs2 inodes
> go "invalid" when a node drops the inode's glocks. When such an invalid inode
> is accessed again, all the metadata must be read from disk again, including the
> security label.
> 
> For that case, the file system has no way of updating the security label before
> selinux next uses it.  Things also don't fix themselves over time; when selinux
> rejects access, the file system never notices.

The current NFSv4 model is to call security_inode_notifysecctx() to
notify the security module of the new label.  Does that not work for
gfs2 or others?  It is up to the filesystem client side code to actually
detect the change and fetch the new value, then push it to the security
module via the security_inode_notifysecctx() hook.

> 
> To fix that, this patch queue adds a mechanism for file systems to invalidate
> inode security labels, and for selinux to revalidate them; this is similar to
> how the inode acl cache works.


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 00/11] Inode security label invalidation
@ 2015-08-24 17:42   ` Stephen Smalley
  0 siblings, 0 replies; 40+ messages in thread
From: Stephen Smalley @ 2015-08-24 17:42 UTC (permalink / raw)
  To: cluster-devel.redhat.com

On 08/20/2015 02:19 PM, Andreas Gruenbacher wrote:
> Hello,
> 
> this patch queue adds an LSM hook for file systems to invalidate inode security
> labels.  To allow selinux to revalidate invalid labels, the generic xattr
> handlers are cleaned up a bit and a new igetxattr inode operation is
> introduced: the getxattr inode operation requires a dentry which selinux
> doesn't have in inode_has_perm(); igetxattr instead takes an inode.  Finally,
> gfs2 is patched to make use of this new mechanism.
> 
> The new igetxattr inode operation currently is *only* used for revalidating
> security labels in selinux; it may make sense to use it instead of getxattr
> when defined.
> 
> Is this approach useful?  An alternative would be to modify selinux so that it
> always has a dentry when checking inode security labels; I would guess that
> this won't work in all cases, though.
> 
> 
> BACKGROUND
> 
> Selinux currently assumes that, after initialization, inode->i_security always
> represents the current security label of the inode.  This assumption works for
> local file systems; any change of the label must go through setxattr (or
> removexattr) which updates inode->i_security.
> 
> On an nfs mount, other nodes can change the security label; there is no
> immediate notification mechanism.  Other nodes will eventually notice a label
> change because the label is transmitted as part of the reply of operations like
> open. (A timeout for cached labels would help too; I'm not sure if the code
> implements that.)
> 
> Other file systems have different consistency models. For example, gfs2 inodes
> go "invalid" when a node drops the inode's glocks. When such an invalid inode
> is accessed again, all the metadata must be read from disk again, including the
> security label.
> 
> For that case, the file system has no way of updating the security label before
> selinux next uses it.  Things also don't fix themselves over time; when selinux
> rejects access, the file system never notices.

The current NFSv4 model is to call security_inode_notifysecctx() to
notify the security module of the new label.  Does that not work for
gfs2 or others?  It is up to the filesystem client side code to actually
detect the change and fetch the new value, then push it to the security
module via the security_inode_notifysecctx() hook.

> 
> To fix that, this patch queue adds a mechanism for file systems to invalidate
> inode security labels, and for selinux to revalidate them; this is similar to
> how the inode acl cache works.



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [RFC 00/11] Inode security label invalidation
  2015-08-24 17:42   ` [Cluster-devel] " Stephen Smalley
@ 2015-08-24 19:13     ` Andreas Grünbacher
  -1 siblings, 0 replies; 40+ messages in thread
From: Andreas Grünbacher @ 2015-08-24 19:13 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Alexander Viro, Christoph Hellwig, Eric Paris, Aneesh Kumar K.V,
	Linux FS-devel Mailing List, David Quigley, J. Bruce Fields,
	linux-security-module, cluster-devel

Stephen,

2015-08-24 19:42 GMT+02:00 Stephen Smalley <sds@tycho.nsa.gov>:
>> BACKGROUND
>>
>> Selinux currently assumes that, after initialization, inode->i_security always
>> represents the current security label of the inode.  This assumption works for
>> local file systems; any change of the label must go through setxattr (or
>> removexattr) which updates inode->i_security.
>>
>> On an nfs mount, other nodes can change the security label; there is no
>> immediate notification mechanism.  Other nodes will eventually notice a label
>> change because the label is transmitted as part of the reply of operations like
>> open. (A timeout for cached labels would help too; I'm not sure if the code
>> implements that.)
>>
>> Other file systems have different consistency models. For example, gfs2 inodes
>> go "invalid" when a node drops the inode's glocks. When such an invalid inode
>> is accessed again, all the metadata must be read from disk again, including the
>> security label.
>>
>> For that case, the file system has no way of updating the security label before
>> selinux next uses it.  Things also don't fix themselves over time; when selinux
>> rejects access, the file system never notices.
>
> The current NFSv4 model is to call security_inode_notifysecctx() to
> notify the security module of the new label.  Does that not work for
> gfs2 or others?

Unfortunately not. In fact, NFS also cannot work fully correctly with
this infrastructure alone because it cannot invalidate cached security
labels once they expire.

> It is up to the filesystem client side code to actually
> detect the change and fetch the new value, then push it to the security
> module via the security_inode_notifysecctx() hook.

That is unfortunately not how non-local file systems work. Clients
don't normally get notified of changes performed by other nodes.
Instead, they do one of the following:

 * On NFS, inode attributes are cached opportunistically for a
   duration determined by the client. When they are needed
   and it turns out that the cached values have expired, they
   are re-fetched from the server. (See cache_validity and
   revalidate_inode in fs/nfs/; RFC 7530, Section 1.5: Client
   Caching and Delegation and Section 10: Client-Side
   Caching.)

   This is not true for security labels though; security labels currently
   won't be expired.

 * GFS2 and some other file systems grab locks on inodes before
   caching data or metadata. When the locks on an inode are
   released, the cached data and metadata become invalid
   and must no longer be used.

File system clients can't actively poll their servers about metadata
changes; that would be way too costly. We really need a way to
invalidate security labels, and selinux needs to reload invalid
security labels when they are needed.

Thanks,
Andreas

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 00/11] Inode security label invalidation
@ 2015-08-24 19:13     ` Andreas Grünbacher
  0 siblings, 0 replies; 40+ messages in thread
From: Andreas Grünbacher @ 2015-08-24 19:13 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Stephen,

2015-08-24 19:42 GMT+02:00 Stephen Smalley <sds@tycho.nsa.gov>:
>> BACKGROUND
>>
>> Selinux currently assumes that, after initialization, inode->i_security always
>> represents the current security label of the inode.  This assumption works for
>> local file systems; any change of the label must go through setxattr (or
>> removexattr) which updates inode->i_security.
>>
>> On an nfs mount, other nodes can change the security label; there is no
>> immediate notification mechanism.  Other nodes will eventually notice a label
>> change because the label is transmitted as part of the reply of operations like
>> open. (A timeout for cached labels would help too; I'm not sure if the code
>> implements that.)
>>
>> Other file systems have different consistency models. For example, gfs2 inodes
>> go "invalid" when a node drops the inode's glocks. When such an invalid inode
>> is accessed again, all the metadata must be read from disk again, including the
>> security label.
>>
>> For that case, the file system has no way of updating the security label before
>> selinux next uses it.  Things also don't fix themselves over time; when selinux
>> rejects access, the file system never notices.
>
> The current NFSv4 model is to call security_inode_notifysecctx() to
> notify the security module of the new label.  Does that not work for
> gfs2 or others?

Unfortunately not. In fact, NFS also cannot work fully correctly with
this infrastructure alone because it cannot invalidate cached security
labels once they expire.

> It is up to the filesystem client side code to actually
> detect the change and fetch the new value, then push it to the security
> module via the security_inode_notifysecctx() hook.

That is unfortunately not how non-local file systems work. Clients
don't normally get notified of changes performed by other nodes.
Instead, they do one of the following:

 * On NFS, inode attributes are cached opportunistically for a
   duration determined by the client. When they are needed
   and it turns out that the cached values have expired, they
   are re-fetched from the server. (See cache_validity and
   revalidate_inode in fs/nfs/; RFC 7530, Section 1.5: Client
   Caching and Delegation and Section 10: Client-Side
   Caching.)

   This is not true for security labels though; security labels currently
   won't be expired.

 * GFS2 and some other file systems grab locks on inodes before
   caching data or metadata. When the locks on an inode are
   released, the cached data and metadata become invalid
   and must no longer be used.

File system clients can't actively poll their servers about metadata
changes; that would be way too costly. We really need a way to
invalidate security labels, and selinux needs to reload invalid
security labels when they are needed.

Thanks,
Andreas



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [RFC 00/11] Inode security label invalidation
  2015-08-24 17:42   ` [Cluster-devel] " Stephen Smalley
@ 2015-08-24 20:47     ` Eric Paris
  -1 siblings, 0 replies; 40+ messages in thread
From: Eric Paris @ 2015-08-24 20:47 UTC (permalink / raw)
  To: Stephen Smalley, Andreas Gruenbacher, Alexander Viro,
	Christoph Hellwig, Aneesh Kumar K.V, linux-fsdevel,
	David Quigley, J. Bruce Fields
  Cc: linux-security-module, cluster-devel

On Mon, 2015-08-24 at 13:42 -0400, Stephen Smalley wrote:
> On 08/20/2015 02:19 PM, Andreas Gruenbacher wrote:

> > For that case, the file system has no way of updating the security
> > label before
> > selinux next uses it.  Things also don't fix themselves over time;
> > when selinux
> > rejects access, the file system never notices.
> 
> The current NFSv4 model is to call security_inode_notifysecctx() to
> notify the security module of the new label.  Does that not work for
> gfs2 or others?  It is up to the filesystem client side code to
> actually
> detect the change and fetch the new value, then push it to the
> security
> module via the security_inode_notifysecctx() hook.

I'm told that most of these filesystems have NO push to clients about
changes. Only clients 'pull'.

Image the inode has the label "no_access". I try to access it on node1.
We pull the inode into core and set the isec to no_access and then get
denied. Now on node2 I relabel to "yes_access". There is no push
mechanism for node1 to find out. Now on node1 if I call access() I
"should" have access, but the VFS/LSM will never call the filesystem
code, so fs never knows to call security_inode_notifysecctx().

Somehow we have to get into the FS function so the FS can tell us that
it is invalid...

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [Cluster-devel] [RFC 00/11] Inode security label invalidation
@ 2015-08-24 20:47     ` Eric Paris
  0 siblings, 0 replies; 40+ messages in thread
From: Eric Paris @ 2015-08-24 20:47 UTC (permalink / raw)
  To: cluster-devel.redhat.com

On Mon, 2015-08-24 at 13:42 -0400, Stephen Smalley wrote:
> On 08/20/2015 02:19 PM, Andreas Gruenbacher wrote:

> > For that case, the file system has no way of updating the security
> > label before
> > selinux next uses it.  Things also don't fix themselves over time;
> > when selinux
> > rejects access, the file system never notices.
> 
> The current NFSv4 model is to call security_inode_notifysecctx() to
> notify the security module of the new label.  Does that not work for
> gfs2 or others?  It is up to the filesystem client side code to
> actually
> detect the change and fetch the new value, then push it to the
> security
> module via the security_inode_notifysecctx() hook.

I'm told that most of these filesystems have NO push to clients about
changes. Only clients 'pull'.

Image the inode has the label "no_access". I try to access it on node1.
We pull the inode into core and set the isec to no_access and then get
denied. Now on node2 I relabel to "yes_access". There is no push
mechanism for node1 to find out. Now on node1 if I call access() I
"should" have access, but the VFS/LSM will never call the filesystem
code, so fs never knows to call security_inode_notifysecctx().

Somehow we have to get into the FS function so the FS can tell us that
it is invalid...



^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2015-08-24 20:48 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-20 18:19 [RFC 00/11] Inode security label invalidation Andreas Gruenbacher
2015-08-20 18:19 ` [Cluster-devel] " Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 01/11] ubifs: Remove unused "security.*" xattr handler Andreas Gruenbacher
2015-08-20 18:19   ` [Cluster-devel] " Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 02/11] hfsplus: Remove unused xattr handler list operations Andreas Gruenbacher
2015-08-20 18:19   ` [Cluster-devel] " Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 03/11] 9p: Simplify the xattr handlers Andreas Gruenbacher
2015-08-20 18:19   ` [Cluster-devel] " Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 04/11] xattr handlers: Pass handler to operations instead of flags Andreas Gruenbacher
2015-08-20 18:19   ` [Cluster-devel] " Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 05/11] xattr handlers: Some simplifications Andreas Gruenbacher
2015-08-20 18:19   ` [Cluster-devel] " Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 06/11] lib: Move strcmp_prefix into string.c Andreas Gruenbacher
2015-08-20 18:19   ` [Cluster-devel] " Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 07/11] 9p: Stop using the generic xattr_handler infrastructure Andreas Gruenbacher
2015-08-20 18:19   ` [Cluster-devel] " Andreas Gruenbacher
2015-08-21  6:46   ` Christoph Hellwig
2015-08-21  6:46     ` [Cluster-devel] " Christoph Hellwig
2015-08-21  8:35     ` Steven Whitehouse
2015-08-21  8:35       ` Steven Whitehouse
2015-08-20 18:19 ` [RFC 08/11] xattr: Pass inodes to xattr handlers instead of dentries Andreas Gruenbacher
2015-08-20 18:19   ` [Cluster-devel] " Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 09/11] vfs: Add igetxattr inode operation Andreas Gruenbacher
2015-08-20 18:19   ` [Cluster-devel] " Andreas Gruenbacher
2015-08-21  6:48   ` Christoph Hellwig
2015-08-21  6:48     ` [Cluster-devel] " Christoph Hellwig
2015-08-20 18:19 ` [RFC 10/11] selinux: Allow to invalidate an inode's security label Andreas Gruenbacher
2015-08-20 18:19   ` [Cluster-devel] " Andreas Gruenbacher
2015-08-20 18:19 ` [RFC 11/11] gfs2: Invalide security labels of inodes that go invalid Andreas Gruenbacher
2015-08-20 18:19   ` [Cluster-devel] " Andreas Gruenbacher
2015-08-21  6:49   ` Christoph Hellwig
2015-08-21  6:49     ` [Cluster-devel] " Christoph Hellwig
2015-08-21  9:25     ` Andreas Gruenbacher
2015-08-21  9:25       ` Andreas Gruenbacher
2015-08-24 17:42 ` [RFC 00/11] Inode security label invalidation Stephen Smalley
2015-08-24 17:42   ` [Cluster-devel] " Stephen Smalley
2015-08-24 19:13   ` Andreas Grünbacher
2015-08-24 19:13     ` [Cluster-devel] " Andreas Grünbacher
2015-08-24 20:47   ` Eric Paris
2015-08-24 20:47     ` [Cluster-devel] " Eric Paris

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.