|
@@ -97,6 +97,61 @@ int v9fs_check_acl(struct inode *inode, int mask)
|
|
|
return -EAGAIN;
|
|
|
}
|
|
|
|
|
|
+static int v9fs_set_acl(struct dentry *dentry, int type, struct posix_acl *acl)
|
|
|
+{
|
|
|
+ int retval;
|
|
|
+ char *name;
|
|
|
+ size_t size;
|
|
|
+ void *buffer;
|
|
|
+ struct inode *inode = dentry->d_inode;
|
|
|
+
|
|
|
+ set_cached_acl(inode, type, acl);
|
|
|
+ /* Set a setxattr request to server */
|
|
|
+ size = posix_acl_xattr_size(acl->a_count);
|
|
|
+ buffer = kmalloc(size, GFP_KERNEL);
|
|
|
+ if (!buffer)
|
|
|
+ return -ENOMEM;
|
|
|
+ retval = posix_acl_to_xattr(acl, buffer, size);
|
|
|
+ if (retval < 0)
|
|
|
+ goto err_free_out;
|
|
|
+ switch (type) {
|
|
|
+ case ACL_TYPE_ACCESS:
|
|
|
+ name = POSIX_ACL_XATTR_ACCESS;
|
|
|
+ break;
|
|
|
+ case ACL_TYPE_DEFAULT:
|
|
|
+ name = POSIX_ACL_XATTR_DEFAULT;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ BUG();
|
|
|
+ }
|
|
|
+ retval = v9fs_xattr_set(dentry, name, buffer, size, 0);
|
|
|
+err_free_out:
|
|
|
+ kfree(buffer);
|
|
|
+ return retval;
|
|
|
+}
|
|
|
+
|
|
|
+int v9fs_acl_chmod(struct dentry *dentry)
|
|
|
+{
|
|
|
+ int retval = 0;
|
|
|
+ struct posix_acl *acl, *clone;
|
|
|
+ struct inode *inode = dentry->d_inode;
|
|
|
+
|
|
|
+ if (S_ISLNK(inode->i_mode))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS);
|
|
|
+ if (acl) {
|
|
|
+ clone = posix_acl_clone(acl, GFP_KERNEL);
|
|
|
+ posix_acl_release(acl);
|
|
|
+ if (!clone)
|
|
|
+ return -ENOMEM;
|
|
|
+ retval = posix_acl_chmod_masq(clone, inode->i_mode);
|
|
|
+ if (!retval)
|
|
|
+ retval = v9fs_set_acl(dentry, ACL_TYPE_ACCESS, clone);
|
|
|
+ posix_acl_release(clone);
|
|
|
+ }
|
|
|
+ return retval;
|
|
|
+}
|
|
|
+
|
|
|
static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
|
|
|
void *buffer, size_t size, int type)
|
|
|
{
|