aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/dir.c
diff options
context:
space:
mode:
authorSeth Forshee <seth.forshee@canonical.com>2016-08-29 08:46:37 -0500
committerMiklos Szeredi <mszeredi@redhat.com>2016-10-01 07:32:32 +0200
commit60bcc88ad185d512f5718f2f8dcccb483ea8fb73 (patch)
tree898d528618e9091ed7a9191ee736b57073b8a1ad /fs/fuse/dir.c
parentfuse: handle killpriv in userspace fs (diff)
downloadlinux-dev-60bcc88ad185d512f5718f2f8dcccb483ea8fb73.tar.xz
linux-dev-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.c16
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 = {