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>
This commit is contained in:

committed by
Miklos Szeredi

parent
5e940c1dd3
commit
60bcc88ad1
@@ -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 = {
|
||||
|
Reference in New Issue
Block a user