int zpl_init_acl(struct inode *ip, struct inode *dir) { struct posix_acl *acl = NULL; int error = 0; if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIXACL) return (0); if (!S_ISLNK(ip->i_mode)) { if (ITOZSB(ip)->z_acl_type == ZFS_ACLTYPE_POSIXACL) { acl = zpl_get_acl(dir, ACL_TYPE_DEFAULT); if (IS_ERR(acl)) return (PTR_ERR(acl)); } if (!acl) { ip->i_mode &= ~current_umask(); ip->i_ctime = current_fs_time(ITOZSB(ip)->z_sb); zfs_mark_inode_dirty(ip); return (0); } } if ((ITOZSB(ip)->z_acl_type == ZFS_ACLTYPE_POSIXACL) && acl) { umode_t mode; if (S_ISDIR(ip->i_mode)) { error = zpl_set_acl(ip, ACL_TYPE_DEFAULT, acl); if (error) goto out; } mode = ip->i_mode; error = __posix_acl_create(&acl, GFP_KERNEL, &mode); if (error >= 0) { ip->i_mode = mode; zfs_mark_inode_dirty(ip); if (error > 0) error = zpl_set_acl(ip, ACL_TYPE_ACCESS, acl); } } out: zpl_posix_acl_release(acl); return (error); }
static int zpl_release(struct inode *ip, struct file *filp) { cred_t *cr = CRED(); int error; if (ITOZ(ip)->z_atime_dirty) zfs_mark_inode_dirty(ip); crhold(cr); error = -zfs_close(ip, filp->f_flags, cr); crfree(cr); ASSERT3S(error, <=, 0); return (error); }
int zpl_set_acl(struct inode *ip, int type, struct posix_acl *acl) { struct super_block *sb = ITOZSB(ip)->z_sb; char *name, *value = NULL; int error = 0; size_t size = 0; if (S_ISLNK(ip->i_mode)) return (-EOPNOTSUPP); switch (type) { case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; if (acl) { zpl_equivmode_t mode = ip->i_mode; error = posix_acl_equiv_mode(acl, &mode); if (error < 0) { return (error); } else { /* * The mode bits will have been set by * ->zfs_setattr()->zfs_acl_chmod_setattr() * using the ZFS ACL conversion. If they * differ from the Posix ACL conversion dirty * the inode to write the Posix mode bits. */ if (ip->i_mode != mode) { ip->i_mode = mode; ip->i_ctime = current_fs_time(sb); zfs_mark_inode_dirty(ip); } if (error == 0) acl = NULL; } } break; case ACL_TYPE_DEFAULT: name = POSIX_ACL_XATTR_DEFAULT; if (!S_ISDIR(ip->i_mode)) return (acl ? -EACCES : 0); break; default: return (-EINVAL); } if (acl) { size = posix_acl_xattr_size(acl->a_count); value = kmem_alloc(size, KM_SLEEP); error = zpl_acl_to_xattr(acl, value, size); if (error < 0) { kmem_free(value, size); return (error); } } error = zpl_xattr_set(ip, name, value, size, 0); if (value) kmem_free(value, size); if (!error) { if (acl) zpl_set_cached_acl(ip, type, acl); else zpl_forget_cached_acl(ip, type); } return (error); }