diff options
author | Seth Forshee <seth.forshee@canonical.com> | 2016-08-29 08:46:37 -0500 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2016-10-01 07:32:32 +0200 |
commit | 60bcc88ad185d512f5718f2f8dcccb483ea8fb73 (patch) | |
tree | 898d528618e9091ed7a9191ee736b57073b8a1ad /fs/fuse/dir.c | |
parent | 5e940c1dd3c1f7561924954eecee956ec277a79b (diff) | |
download | linux-exynos-60bcc88ad185d512f5718f2f8dcccb483ea8fb73.tar.gz linux-exynos-60bcc88ad185d512f5718f2f8dcccb483ea8fb73.tar.bz2 linux-exynos-60bcc88ad185d512f5718f2f8dcccb483ea8fb73.zip |
fuse: Add posix ACL support
Add a new INIT flag, FUSE_POSIX_ACL, for negotiating ACL support with
userspace. When it is set in the INIT response, ACL support will be
enabled. ACL support also implies "default_permissions".
When ACL support is enabled, the kernel will cache and have responsibility
for enforcing ACLs. ACL xattrs will be passed to userspace, which is
responsible for updating the ACLs in the filesystem, keeping the file mode
in sync, and inheritance of default ACLs when new filesystem nodes are
created.
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/fuse/dir.c')
-rw-r--r-- | fs/fuse/dir.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 7cb68b18eb3f..3076f48d86a6 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -14,6 +14,7 @@ #include <linux/namei.h> #include <linux/slab.h> #include <linux/xattr.h> +#include <linux/posix_acl.h> static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx) { @@ -244,6 +245,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) goto invalid; + forget_all_cached_acls(inode); fuse_change_attributes(inode, &outarg.attr, entry_attr_timeout(&outarg), attr_version); @@ -918,6 +920,7 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat, if (time_before64(fi->i_time, get_jiffies_64())) { r = true; + forget_all_cached_acls(inode); err = fuse_do_getattr(inode, stat, file); } else { r = false; @@ -1065,6 +1068,7 @@ static int fuse_perm_getattr(struct inode *inode, int mask) if (mask & MAY_NOT_BLOCK) return -ECHILD; + forget_all_cached_acls(inode); return fuse_do_getattr(inode, NULL, NULL); } @@ -1234,6 +1238,7 @@ retry: fi->nlookup++; spin_unlock(&fc->lock); + forget_all_cached_acls(inode); fuse_change_attributes(inode, &o->attr, entry_attr_timeout(o), attr_version); @@ -1748,6 +1753,13 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) ret = fuse_do_setattr(inode, attr, file); if (!ret) { + /* + * If filesystem supports acls it may have updated acl xattrs in + * the filesystem, so forget cached acls for the inode. + */ + if (fc->posix_acl) + forget_all_cached_acls(inode); + /* Directory mode changed, may need to revalidate access */ if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE)) fuse_invalidate_entry_cache(entry); @@ -1785,6 +1797,8 @@ static const struct inode_operations fuse_dir_inode_operations = { .getxattr = generic_getxattr, .listxattr = fuse_listxattr, .removexattr = generic_removexattr, + .get_acl = fuse_get_acl, + .set_acl = fuse_set_acl, }; static const struct file_operations fuse_dir_operations = { @@ -1806,6 +1820,8 @@ static const struct inode_operations fuse_common_inode_operations = { .getxattr = generic_getxattr, .listxattr = fuse_listxattr, .removexattr = generic_removexattr, + .get_acl = fuse_get_acl, + .set_acl = fuse_set_acl, }; static const struct inode_operations fuse_symlink_inode_operations = { |