diff options
author | Andreas Gruenbacher <agruenba@redhat.com> | 2016-09-29 11:48:39 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-10-07 20:10:42 -0400 |
commit | d0a5b995a308347fdb1bb0412df32acd0312523b (patch) | |
tree | 080efa7c4513aa0e42e9e65c75260546f9b303ac | |
parent | b6ba11773d9535fbe068232f2231c99740bb32db (diff) |
vfs: Add IOP_XATTR inode operations flag
The IOP_XATTR inode operations flag in inode->i_opflags indicates that
the inode has xattr support. The flag is automatically set by
new_inode() on filesystems with xattr support (where sb->s_xattr is
defined), and cleared otherwise. Filesystems can explicitly clear it
for inodes that should not have xattr support.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/inode.c | 2 | ||||
-rw-r--r-- | fs/xattr.c | 12 | ||||
-rw-r--r-- | include/linux/fs.h | 1 |
3 files changed, 11 insertions, 4 deletions
diff --git a/fs/inode.c b/fs/inode.c index 7e3ef3af3db9..705f8609fdb8 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -140,6 +140,8 @@ int inode_init_always(struct super_block *sb, struct inode *inode) | |||
140 | inode->i_fop = &no_open_fops; | 140 | inode->i_fop = &no_open_fops; |
141 | inode->__i_nlink = 1; | 141 | inode->__i_nlink = 1; |
142 | inode->i_opflags = 0; | 142 | inode->i_opflags = 0; |
143 | if (sb->s_xattr) | ||
144 | inode->i_opflags |= IOP_XATTR; | ||
143 | i_uid_write(inode, 0); | 145 | i_uid_write(inode, 0); |
144 | i_gid_write(inode, 0); | 146 | i_gid_write(inode, 0); |
145 | atomic_set(&inode->i_writecount, 0); | 147 | atomic_set(&inode->i_writecount, 0); |
diff --git a/fs/xattr.c b/fs/xattr.c index bb3cbbfd982d..38b52a356d1b 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -53,10 +53,13 @@ strcmp_prefix(const char *a, const char *a_prefix) | |||
53 | * Find the xattr_handler with the matching prefix. | 53 | * Find the xattr_handler with the matching prefix. |
54 | */ | 54 | */ |
55 | static const struct xattr_handler * | 55 | static const struct xattr_handler * |
56 | xattr_resolve_name(const struct xattr_handler **handlers, const char **name) | 56 | xattr_resolve_name(struct inode *inode, const char **name) |
57 | { | 57 | { |
58 | const struct xattr_handler **handlers = inode->i_sb->s_xattr; | ||
58 | const struct xattr_handler *handler; | 59 | const struct xattr_handler *handler; |
59 | 60 | ||
61 | if (!(inode->i_opflags & IOP_XATTR)) | ||
62 | return ERR_PTR(-EOPNOTSUPP); | ||
60 | for_each_xattr_handler(handlers, handler) { | 63 | for_each_xattr_handler(handlers, handler) { |
61 | const char *n; | 64 | const char *n; |
62 | 65 | ||
@@ -298,6 +301,7 @@ nolsm: | |||
298 | error = -EOPNOTSUPP; | 301 | error = -EOPNOTSUPP; |
299 | 302 | ||
300 | return error; | 303 | return error; |
304 | |||
301 | } | 305 | } |
302 | EXPORT_SYMBOL_GPL(vfs_getxattr); | 306 | EXPORT_SYMBOL_GPL(vfs_getxattr); |
303 | 307 | ||
@@ -700,7 +704,7 @@ generic_getxattr(struct dentry *dentry, struct inode *inode, | |||
700 | { | 704 | { |
701 | const struct xattr_handler *handler; | 705 | const struct xattr_handler *handler; |
702 | 706 | ||
703 | handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); | 707 | handler = xattr_resolve_name(inode, &name); |
704 | if (IS_ERR(handler)) | 708 | if (IS_ERR(handler)) |
705 | return PTR_ERR(handler); | 709 | return PTR_ERR(handler); |
706 | return handler->get(handler, dentry, inode, | 710 | return handler->get(handler, dentry, inode, |
@@ -755,7 +759,7 @@ generic_setxattr(struct dentry *dentry, struct inode *inode, const char *name, | |||
755 | 759 | ||
756 | if (size == 0) | 760 | if (size == 0) |
757 | value = ""; /* empty EA, do not remove */ | 761 | value = ""; /* empty EA, do not remove */ |
758 | handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); | 762 | handler = xattr_resolve_name(inode, &name); |
759 | if (IS_ERR(handler)) | 763 | if (IS_ERR(handler)) |
760 | return PTR_ERR(handler); | 764 | return PTR_ERR(handler); |
761 | return handler->set(handler, dentry, inode, name, value, size, flags); | 765 | return handler->set(handler, dentry, inode, name, value, size, flags); |
@@ -770,7 +774,7 @@ generic_removexattr(struct dentry *dentry, const char *name) | |||
770 | { | 774 | { |
771 | const struct xattr_handler *handler; | 775 | const struct xattr_handler *handler; |
772 | 776 | ||
773 | handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); | 777 | handler = xattr_resolve_name(d_inode(dentry), &name); |
774 | if (IS_ERR(handler)) | 778 | if (IS_ERR(handler)) |
775 | return PTR_ERR(handler); | 779 | return PTR_ERR(handler); |
776 | return handler->set(handler, dentry, d_inode(dentry), name, NULL, | 780 | return handler->set(handler, dentry, d_inode(dentry), name, NULL, |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 7540e872591a..91a7245e58c7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -591,6 +591,7 @@ is_uncached_acl(struct posix_acl *acl) | |||
591 | #define IOP_FASTPERM 0x0001 | 591 | #define IOP_FASTPERM 0x0001 |
592 | #define IOP_LOOKUP 0x0002 | 592 | #define IOP_LOOKUP 0x0002 |
593 | #define IOP_NOFOLLOW 0x0004 | 593 | #define IOP_NOFOLLOW 0x0004 |
594 | #define IOP_XATTR 0x0008 | ||
594 | 595 | ||
595 | /* | 596 | /* |
596 | * Keep mostly read-only and often accessed (especially for | 597 | * Keep mostly read-only and often accessed (especially for |