17c1a000dSChao Yu // SPDX-License-Identifier: GPL-2.0 20a8165d7SJaegeuk Kim /* 3af48b85bSJaegeuk Kim * fs/f2fs/acl.c 4af48b85bSJaegeuk Kim * 5af48b85bSJaegeuk Kim * Copyright (c) 2012 Samsung Electronics Co., Ltd. 6af48b85bSJaegeuk Kim * http://www.samsung.com/ 7af48b85bSJaegeuk Kim * 8af48b85bSJaegeuk Kim * Portions of this code from linux/fs/ext2/acl.c 9af48b85bSJaegeuk Kim * 10af48b85bSJaegeuk Kim * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> 11af48b85bSJaegeuk Kim */ 12af48b85bSJaegeuk Kim #include <linux/f2fs_fs.h> 13af48b85bSJaegeuk Kim #include "f2fs.h" 14af48b85bSJaegeuk Kim #include "xattr.h" 15af48b85bSJaegeuk Kim #include "acl.h" 16af48b85bSJaegeuk Kim 17af48b85bSJaegeuk Kim static inline size_t f2fs_acl_size(int count) 18af48b85bSJaegeuk Kim { 19af48b85bSJaegeuk Kim if (count <= 4) { 20af48b85bSJaegeuk Kim return sizeof(struct f2fs_acl_header) + 21af48b85bSJaegeuk Kim count * sizeof(struct f2fs_acl_entry_short); 22af48b85bSJaegeuk Kim } else { 23af48b85bSJaegeuk Kim return sizeof(struct f2fs_acl_header) + 24af48b85bSJaegeuk Kim 4 * sizeof(struct f2fs_acl_entry_short) + 25af48b85bSJaegeuk Kim (count - 4) * sizeof(struct f2fs_acl_entry); 26af48b85bSJaegeuk Kim } 27af48b85bSJaegeuk Kim } 28af48b85bSJaegeuk Kim 29af48b85bSJaegeuk Kim static inline int f2fs_acl_count(size_t size) 30af48b85bSJaegeuk Kim { 31af48b85bSJaegeuk Kim ssize_t s; 32af48b85bSJaegeuk Kim size -= sizeof(struct f2fs_acl_header); 33af48b85bSJaegeuk Kim s = size - 4 * sizeof(struct f2fs_acl_entry_short); 34af48b85bSJaegeuk Kim if (s < 0) { 35af48b85bSJaegeuk Kim if (size % sizeof(struct f2fs_acl_entry_short)) 36af48b85bSJaegeuk Kim return -1; 37af48b85bSJaegeuk Kim return size / sizeof(struct f2fs_acl_entry_short); 38af48b85bSJaegeuk Kim } else { 39af48b85bSJaegeuk Kim if (s % sizeof(struct f2fs_acl_entry)) 40af48b85bSJaegeuk Kim return -1; 41af48b85bSJaegeuk Kim return s / sizeof(struct f2fs_acl_entry) + 4; 42af48b85bSJaegeuk Kim } 43af48b85bSJaegeuk Kim } 44af48b85bSJaegeuk Kim 45af48b85bSJaegeuk Kim static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size) 46af48b85bSJaegeuk Kim { 47af48b85bSJaegeuk Kim int i, count; 48af48b85bSJaegeuk Kim struct posix_acl *acl; 49af48b85bSJaegeuk Kim struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value; 50af48b85bSJaegeuk Kim struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1); 51af48b85bSJaegeuk Kim const char *end = value + size; 52af48b85bSJaegeuk Kim 531618e6e2SChengguang Xu if (size < sizeof(struct f2fs_acl_header)) 541618e6e2SChengguang Xu return ERR_PTR(-EINVAL); 551618e6e2SChengguang Xu 56af48b85bSJaegeuk Kim if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION)) 57af48b85bSJaegeuk Kim return ERR_PTR(-EINVAL); 58af48b85bSJaegeuk Kim 59af48b85bSJaegeuk Kim count = f2fs_acl_count(size); 60af48b85bSJaegeuk Kim if (count < 0) 61af48b85bSJaegeuk Kim return ERR_PTR(-EINVAL); 62af48b85bSJaegeuk Kim if (count == 0) 63af48b85bSJaegeuk Kim return NULL; 64af48b85bSJaegeuk Kim 65dd802406SJaegeuk Kim acl = posix_acl_alloc(count, GFP_NOFS); 66af48b85bSJaegeuk Kim if (!acl) 67af48b85bSJaegeuk Kim return ERR_PTR(-ENOMEM); 68af48b85bSJaegeuk Kim 69af48b85bSJaegeuk Kim for (i = 0; i < count; i++) { 70af48b85bSJaegeuk Kim 71af48b85bSJaegeuk Kim if ((char *)entry > end) 72af48b85bSJaegeuk Kim goto fail; 73af48b85bSJaegeuk Kim 74af48b85bSJaegeuk Kim acl->a_entries[i].e_tag = le16_to_cpu(entry->e_tag); 75af48b85bSJaegeuk Kim acl->a_entries[i].e_perm = le16_to_cpu(entry->e_perm); 76af48b85bSJaegeuk Kim 77af48b85bSJaegeuk Kim switch (acl->a_entries[i].e_tag) { 78af48b85bSJaegeuk Kim case ACL_USER_OBJ: 79af48b85bSJaegeuk Kim case ACL_GROUP_OBJ: 80af48b85bSJaegeuk Kim case ACL_MASK: 81af48b85bSJaegeuk Kim case ACL_OTHER: 82af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 83af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry_short)); 84af48b85bSJaegeuk Kim break; 85af48b85bSJaegeuk Kim 86af48b85bSJaegeuk Kim case ACL_USER: 87af48b85bSJaegeuk Kim acl->a_entries[i].e_uid = 88af48b85bSJaegeuk Kim make_kuid(&init_user_ns, 89af48b85bSJaegeuk Kim le32_to_cpu(entry->e_id)); 90af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 91af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry)); 92af48b85bSJaegeuk Kim break; 93af48b85bSJaegeuk Kim case ACL_GROUP: 94af48b85bSJaegeuk Kim acl->a_entries[i].e_gid = 95af48b85bSJaegeuk Kim make_kgid(&init_user_ns, 96af48b85bSJaegeuk Kim le32_to_cpu(entry->e_id)); 97af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 98af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry)); 99af48b85bSJaegeuk Kim break; 100af48b85bSJaegeuk Kim default: 101af48b85bSJaegeuk Kim goto fail; 102af48b85bSJaegeuk Kim } 103af48b85bSJaegeuk Kim } 104af48b85bSJaegeuk Kim if ((char *)entry != end) 105af48b85bSJaegeuk Kim goto fail; 106af48b85bSJaegeuk Kim return acl; 107af48b85bSJaegeuk Kim fail: 108af48b85bSJaegeuk Kim posix_acl_release(acl); 109af48b85bSJaegeuk Kim return ERR_PTR(-EINVAL); 110af48b85bSJaegeuk Kim } 111af48b85bSJaegeuk Kim 1121ecc0c5cSChao Yu static void *f2fs_acl_to_disk(struct f2fs_sb_info *sbi, 1131ecc0c5cSChao Yu const struct posix_acl *acl, size_t *size) 114af48b85bSJaegeuk Kim { 115af48b85bSJaegeuk Kim struct f2fs_acl_header *f2fs_acl; 116af48b85bSJaegeuk Kim struct f2fs_acl_entry *entry; 117af48b85bSJaegeuk Kim int i; 118af48b85bSJaegeuk Kim 1191ecc0c5cSChao Yu f2fs_acl = f2fs_kmalloc(sbi, sizeof(struct f2fs_acl_header) + 1201ecc0c5cSChao Yu acl->a_count * sizeof(struct f2fs_acl_entry), 1211ecc0c5cSChao Yu GFP_NOFS); 122af48b85bSJaegeuk Kim if (!f2fs_acl) 123af48b85bSJaegeuk Kim return ERR_PTR(-ENOMEM); 124af48b85bSJaegeuk Kim 125af48b85bSJaegeuk Kim f2fs_acl->a_version = cpu_to_le32(F2FS_ACL_VERSION); 126af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)(f2fs_acl + 1); 127af48b85bSJaegeuk Kim 128af48b85bSJaegeuk Kim for (i = 0; i < acl->a_count; i++) { 129af48b85bSJaegeuk Kim 130af48b85bSJaegeuk Kim entry->e_tag = cpu_to_le16(acl->a_entries[i].e_tag); 131af48b85bSJaegeuk Kim entry->e_perm = cpu_to_le16(acl->a_entries[i].e_perm); 132af48b85bSJaegeuk Kim 133af48b85bSJaegeuk Kim switch (acl->a_entries[i].e_tag) { 134af48b85bSJaegeuk Kim case ACL_USER: 135af48b85bSJaegeuk Kim entry->e_id = cpu_to_le32( 136af48b85bSJaegeuk Kim from_kuid(&init_user_ns, 137af48b85bSJaegeuk Kim acl->a_entries[i].e_uid)); 138af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 139af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry)); 140af48b85bSJaegeuk Kim break; 141af48b85bSJaegeuk Kim case ACL_GROUP: 142af48b85bSJaegeuk Kim entry->e_id = cpu_to_le32( 143af48b85bSJaegeuk Kim from_kgid(&init_user_ns, 144af48b85bSJaegeuk Kim acl->a_entries[i].e_gid)); 145af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 146af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry)); 147af48b85bSJaegeuk Kim break; 148af48b85bSJaegeuk Kim case ACL_USER_OBJ: 149af48b85bSJaegeuk Kim case ACL_GROUP_OBJ: 150af48b85bSJaegeuk Kim case ACL_MASK: 151af48b85bSJaegeuk Kim case ACL_OTHER: 152af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 153af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry_short)); 154af48b85bSJaegeuk Kim break; 155af48b85bSJaegeuk Kim default: 156af48b85bSJaegeuk Kim goto fail; 157af48b85bSJaegeuk Kim } 158af48b85bSJaegeuk Kim } 159af48b85bSJaegeuk Kim *size = f2fs_acl_size(acl->a_count); 160af48b85bSJaegeuk Kim return (void *)f2fs_acl; 161af48b85bSJaegeuk Kim 162af48b85bSJaegeuk Kim fail: 163af48b85bSJaegeuk Kim kfree(f2fs_acl); 164af48b85bSJaegeuk Kim return ERR_PTR(-EINVAL); 165af48b85bSJaegeuk Kim } 166af48b85bSJaegeuk Kim 167bce8d112SJaegeuk Kim static struct posix_acl *__f2fs_get_acl(struct inode *inode, int type, 168bce8d112SJaegeuk Kim struct page *dpage) 169af48b85bSJaegeuk Kim { 170af48b85bSJaegeuk Kim int name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT; 171af48b85bSJaegeuk Kim void *value = NULL; 172af48b85bSJaegeuk Kim struct posix_acl *acl; 173af48b85bSJaegeuk Kim int retval; 174af48b85bSJaegeuk Kim 175af48b85bSJaegeuk Kim if (type == ACL_TYPE_ACCESS) 176af48b85bSJaegeuk Kim name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; 177af48b85bSJaegeuk Kim 178bce8d112SJaegeuk Kim retval = f2fs_getxattr(inode, name_index, "", NULL, 0, dpage); 179af48b85bSJaegeuk Kim if (retval > 0) { 1801ecc0c5cSChao Yu value = f2fs_kmalloc(F2FS_I_SB(inode), retval, GFP_F2FS_ZERO); 181af48b85bSJaegeuk Kim if (!value) 182af48b85bSJaegeuk Kim return ERR_PTR(-ENOMEM); 183bce8d112SJaegeuk Kim retval = f2fs_getxattr(inode, name_index, "", value, 184bce8d112SJaegeuk Kim retval, dpage); 185af48b85bSJaegeuk Kim } 186af48b85bSJaegeuk Kim 187c1b75eabSJaegeuk Kim if (retval > 0) 188c1b75eabSJaegeuk Kim acl = f2fs_acl_from_disk(value, retval); 189c1b75eabSJaegeuk Kim else if (retval == -ENODATA) 190af48b85bSJaegeuk Kim acl = NULL; 191af48b85bSJaegeuk Kim else 192af48b85bSJaegeuk Kim acl = ERR_PTR(retval); 193af48b85bSJaegeuk Kim kfree(value); 194c1b75eabSJaegeuk Kim 195af48b85bSJaegeuk Kim return acl; 196af48b85bSJaegeuk Kim } 197af48b85bSJaegeuk Kim 198bce8d112SJaegeuk Kim struct posix_acl *f2fs_get_acl(struct inode *inode, int type) 199bce8d112SJaegeuk Kim { 200bce8d112SJaegeuk Kim return __f2fs_get_acl(inode, type, NULL); 201bce8d112SJaegeuk Kim } 202bce8d112SJaegeuk Kim 203a6dda0e6SChristoph Hellwig static int __f2fs_set_acl(struct inode *inode, int type, 2042ed2d5b3SJaegeuk Kim struct posix_acl *acl, struct page *ipage) 205af48b85bSJaegeuk Kim { 206af48b85bSJaegeuk Kim int name_index; 207af48b85bSJaegeuk Kim void *value = NULL; 208af48b85bSJaegeuk Kim size_t size = 0; 209af48b85bSJaegeuk Kim int error; 21014af20fcSErnesto A. Fernández umode_t mode = inode->i_mode; 211af48b85bSJaegeuk Kim 212af48b85bSJaegeuk Kim switch (type) { 213af48b85bSJaegeuk Kim case ACL_TYPE_ACCESS: 214af48b85bSJaegeuk Kim name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; 215c925dc16SJaegeuk Kim if (acl && !ipage) { 21614af20fcSErnesto A. Fernández error = posix_acl_update_mode(inode, &mode, &acl); 21707393101SJan Kara if (error) 218af48b85bSJaegeuk Kim return error; 21914af20fcSErnesto A. Fernández set_acl_inode(inode, mode); 220af48b85bSJaegeuk Kim } 221af48b85bSJaegeuk Kim break; 222af48b85bSJaegeuk Kim 223af48b85bSJaegeuk Kim case ACL_TYPE_DEFAULT: 224af48b85bSJaegeuk Kim name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT; 225af48b85bSJaegeuk Kim if (!S_ISDIR(inode->i_mode)) 226af48b85bSJaegeuk Kim return acl ? -EACCES : 0; 227af48b85bSJaegeuk Kim break; 228af48b85bSJaegeuk Kim 229af48b85bSJaegeuk Kim default: 230af48b85bSJaegeuk Kim return -EINVAL; 231af48b85bSJaegeuk Kim } 232af48b85bSJaegeuk Kim 233af48b85bSJaegeuk Kim if (acl) { 2341ecc0c5cSChao Yu value = f2fs_acl_to_disk(F2FS_I_SB(inode), acl, &size); 235af48b85bSJaegeuk Kim if (IS_ERR(value)) { 23691942321SJaegeuk Kim clear_inode_flag(inode, FI_ACL_MODE); 23768390dd9SZhang Shengju return PTR_ERR(value); 238af48b85bSJaegeuk Kim } 239af48b85bSJaegeuk Kim } 240af48b85bSJaegeuk Kim 241c02745efSJaegeuk Kim error = f2fs_setxattr(inode, name_index, "", value, size, ipage, 0); 242af48b85bSJaegeuk Kim 243af48b85bSJaegeuk Kim kfree(value); 244af48b85bSJaegeuk Kim if (!error) 245af48b85bSJaegeuk Kim set_cached_acl(inode, type, acl); 246af48b85bSJaegeuk Kim 24791942321SJaegeuk Kim clear_inode_flag(inode, FI_ACL_MODE); 248af48b85bSJaegeuk Kim return error; 249af48b85bSJaegeuk Kim } 250af48b85bSJaegeuk Kim 251a6dda0e6SChristoph Hellwig int f2fs_set_acl(struct inode *inode, struct posix_acl *acl, int type) 252a6dda0e6SChristoph Hellwig { 2531f227a3eSJaegeuk Kim if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) 2541f227a3eSJaegeuk Kim return -EIO; 2551f227a3eSJaegeuk Kim 256a6dda0e6SChristoph Hellwig return __f2fs_set_acl(inode, type, acl, NULL); 257a6dda0e6SChristoph Hellwig } 258a6dda0e6SChristoph Hellwig 259bce8d112SJaegeuk Kim /* 260bce8d112SJaegeuk Kim * Most part of f2fs_acl_clone, f2fs_acl_create_masq, f2fs_acl_create 261bce8d112SJaegeuk Kim * are copied from posix_acl.c 262bce8d112SJaegeuk Kim */ 263bce8d112SJaegeuk Kim static struct posix_acl *f2fs_acl_clone(const struct posix_acl *acl, 264bce8d112SJaegeuk Kim gfp_t flags) 265af48b85bSJaegeuk Kim { 266bce8d112SJaegeuk Kim struct posix_acl *clone = NULL; 267bce8d112SJaegeuk Kim 268bce8d112SJaegeuk Kim if (acl) { 269bce8d112SJaegeuk Kim int size = sizeof(struct posix_acl) + acl->a_count * 270bce8d112SJaegeuk Kim sizeof(struct posix_acl_entry); 271bce8d112SJaegeuk Kim clone = kmemdup(acl, size, flags); 272bce8d112SJaegeuk Kim if (clone) 27366717260SElena Reshetova refcount_set(&clone->a_refcount, 1); 274bce8d112SJaegeuk Kim } 275bce8d112SJaegeuk Kim return clone; 276bce8d112SJaegeuk Kim } 277bce8d112SJaegeuk Kim 278bce8d112SJaegeuk Kim static int f2fs_acl_create_masq(struct posix_acl *acl, umode_t *mode_p) 279bce8d112SJaegeuk Kim { 280bce8d112SJaegeuk Kim struct posix_acl_entry *pa, *pe; 281bce8d112SJaegeuk Kim struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL; 282bce8d112SJaegeuk Kim umode_t mode = *mode_p; 283bce8d112SJaegeuk Kim int not_equiv = 0; 284bce8d112SJaegeuk Kim 285bce8d112SJaegeuk Kim /* assert(atomic_read(acl->a_refcount) == 1); */ 286bce8d112SJaegeuk Kim 287bce8d112SJaegeuk Kim FOREACH_ACL_ENTRY(pa, acl, pe) { 288bce8d112SJaegeuk Kim switch(pa->e_tag) { 289bce8d112SJaegeuk Kim case ACL_USER_OBJ: 290bce8d112SJaegeuk Kim pa->e_perm &= (mode >> 6) | ~S_IRWXO; 291bce8d112SJaegeuk Kim mode &= (pa->e_perm << 6) | ~S_IRWXU; 292bce8d112SJaegeuk Kim break; 293bce8d112SJaegeuk Kim 294bce8d112SJaegeuk Kim case ACL_USER: 295bce8d112SJaegeuk Kim case ACL_GROUP: 296bce8d112SJaegeuk Kim not_equiv = 1; 297bce8d112SJaegeuk Kim break; 298bce8d112SJaegeuk Kim 299bce8d112SJaegeuk Kim case ACL_GROUP_OBJ: 300bce8d112SJaegeuk Kim group_obj = pa; 301bce8d112SJaegeuk Kim break; 302bce8d112SJaegeuk Kim 303bce8d112SJaegeuk Kim case ACL_OTHER: 304bce8d112SJaegeuk Kim pa->e_perm &= mode | ~S_IRWXO; 305bce8d112SJaegeuk Kim mode &= pa->e_perm | ~S_IRWXO; 306bce8d112SJaegeuk Kim break; 307bce8d112SJaegeuk Kim 308bce8d112SJaegeuk Kim case ACL_MASK: 309bce8d112SJaegeuk Kim mask_obj = pa; 310bce8d112SJaegeuk Kim not_equiv = 1; 311bce8d112SJaegeuk Kim break; 312bce8d112SJaegeuk Kim 313bce8d112SJaegeuk Kim default: 314bce8d112SJaegeuk Kim return -EIO; 315bce8d112SJaegeuk Kim } 316bce8d112SJaegeuk Kim } 317bce8d112SJaegeuk Kim 318bce8d112SJaegeuk Kim if (mask_obj) { 319bce8d112SJaegeuk Kim mask_obj->e_perm &= (mode >> 3) | ~S_IRWXO; 320bce8d112SJaegeuk Kim mode &= (mask_obj->e_perm << 3) | ~S_IRWXG; 321bce8d112SJaegeuk Kim } else { 322bce8d112SJaegeuk Kim if (!group_obj) 323bce8d112SJaegeuk Kim return -EIO; 324bce8d112SJaegeuk Kim group_obj->e_perm &= (mode >> 3) | ~S_IRWXO; 325bce8d112SJaegeuk Kim mode &= (group_obj->e_perm << 3) | ~S_IRWXG; 326bce8d112SJaegeuk Kim } 327bce8d112SJaegeuk Kim 328bce8d112SJaegeuk Kim *mode_p = (*mode_p & ~S_IRWXUGO) | mode; 329bce8d112SJaegeuk Kim return not_equiv; 330bce8d112SJaegeuk Kim } 331bce8d112SJaegeuk Kim 332bce8d112SJaegeuk Kim static int f2fs_acl_create(struct inode *dir, umode_t *mode, 333bce8d112SJaegeuk Kim struct posix_acl **default_acl, struct posix_acl **acl, 334bce8d112SJaegeuk Kim struct page *dpage) 335bce8d112SJaegeuk Kim { 336bce8d112SJaegeuk Kim struct posix_acl *p; 337272e083fSChao Yu struct posix_acl *clone; 338bce8d112SJaegeuk Kim int ret; 339bce8d112SJaegeuk Kim 340272e083fSChao Yu *acl = NULL; 341272e083fSChao Yu *default_acl = NULL; 342272e083fSChao Yu 343bce8d112SJaegeuk Kim if (S_ISLNK(*mode) || !IS_POSIXACL(dir)) 344272e083fSChao Yu return 0; 345bce8d112SJaegeuk Kim 346bce8d112SJaegeuk Kim p = __f2fs_get_acl(dir, ACL_TYPE_DEFAULT, dpage); 347272e083fSChao Yu if (!p || p == ERR_PTR(-EOPNOTSUPP)) { 348272e083fSChao Yu *mode &= ~current_umask(); 349272e083fSChao Yu return 0; 350bce8d112SJaegeuk Kim } 351272e083fSChao Yu if (IS_ERR(p)) 352272e083fSChao Yu return PTR_ERR(p); 353bce8d112SJaegeuk Kim 354272e083fSChao Yu clone = f2fs_acl_clone(p, GFP_NOFS); 355*f6176473STiezhu Yang if (!clone) { 356*f6176473STiezhu Yang ret = -ENOMEM; 357*f6176473STiezhu Yang goto release_acl; 358*f6176473STiezhu Yang } 359bce8d112SJaegeuk Kim 360272e083fSChao Yu ret = f2fs_acl_create_masq(clone, mode); 36183dfe53cSChao Yu if (ret < 0) 362*f6176473STiezhu Yang goto release_clone; 363bce8d112SJaegeuk Kim 364272e083fSChao Yu if (ret == 0) 365272e083fSChao Yu posix_acl_release(clone); 366272e083fSChao Yu else 367272e083fSChao Yu *acl = clone; 368bce8d112SJaegeuk Kim 369272e083fSChao Yu if (!S_ISDIR(*mode)) 370bce8d112SJaegeuk Kim posix_acl_release(p); 371272e083fSChao Yu else 372bce8d112SJaegeuk Kim *default_acl = p; 373bce8d112SJaegeuk Kim 374bce8d112SJaegeuk Kim return 0; 37583dfe53cSChao Yu 376*f6176473STiezhu Yang release_clone: 377272e083fSChao Yu posix_acl_release(clone); 378*f6176473STiezhu Yang release_acl: 37983dfe53cSChao Yu posix_acl_release(p); 380*f6176473STiezhu Yang return ret; 381bce8d112SJaegeuk Kim } 382bce8d112SJaegeuk Kim 383bce8d112SJaegeuk Kim int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage, 384bce8d112SJaegeuk Kim struct page *dpage) 385bce8d112SJaegeuk Kim { 386bce8d112SJaegeuk Kim struct posix_acl *default_acl = NULL, *acl = NULL; 387af48b85bSJaegeuk Kim int error = 0; 388af48b85bSJaegeuk Kim 389bce8d112SJaegeuk Kim error = f2fs_acl_create(dir, &inode->i_mode, &default_acl, &acl, dpage); 390af48b85bSJaegeuk Kim if (error) 391af48b85bSJaegeuk Kim return error; 392b8b60e1aSJaegeuk Kim 3937c45729aSJaegeuk Kim f2fs_mark_inode_dirty_sync(inode, true); 394205b9822SJaegeuk Kim 395a6dda0e6SChristoph Hellwig if (default_acl) { 396a6dda0e6SChristoph Hellwig error = __f2fs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl, 397a6dda0e6SChristoph Hellwig ipage); 398a6dda0e6SChristoph Hellwig posix_acl_release(default_acl); 399313ed62aSChengguang Xu } else { 400313ed62aSChengguang Xu inode->i_default_acl = NULL; 401af48b85bSJaegeuk Kim } 402af48b85bSJaegeuk Kim if (acl) { 4033b6709b7SKinglong Mee if (!error) 404a6dda0e6SChristoph Hellwig error = __f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, 405a6dda0e6SChristoph Hellwig ipage); 406af48b85bSJaegeuk Kim posix_acl_release(acl); 407313ed62aSChengguang Xu } else { 408313ed62aSChengguang Xu inode->i_acl = NULL; 409a6dda0e6SChristoph Hellwig } 410a6dda0e6SChristoph Hellwig 411af48b85bSJaegeuk Kim return error; 412af48b85bSJaegeuk Kim } 413