10a8165d7SJaegeuk Kim /* 2af48b85bSJaegeuk Kim * fs/f2fs/acl.c 3af48b85bSJaegeuk Kim * 4af48b85bSJaegeuk Kim * Copyright (c) 2012 Samsung Electronics Co., Ltd. 5af48b85bSJaegeuk Kim * http://www.samsung.com/ 6af48b85bSJaegeuk Kim * 7af48b85bSJaegeuk Kim * Portions of this code from linux/fs/ext2/acl.c 8af48b85bSJaegeuk Kim * 9af48b85bSJaegeuk Kim * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de> 10af48b85bSJaegeuk Kim * 11af48b85bSJaegeuk Kim * This program is free software; you can redistribute it and/or modify 12af48b85bSJaegeuk Kim * it under the terms of the GNU General Public License version 2 as 13af48b85bSJaegeuk Kim * published by the Free Software Foundation. 14af48b85bSJaegeuk Kim */ 15af48b85bSJaegeuk Kim #include <linux/f2fs_fs.h> 16af48b85bSJaegeuk Kim #include "f2fs.h" 17af48b85bSJaegeuk Kim #include "xattr.h" 18af48b85bSJaegeuk Kim #include "acl.h" 19af48b85bSJaegeuk Kim 20af48b85bSJaegeuk Kim static inline size_t f2fs_acl_size(int count) 21af48b85bSJaegeuk Kim { 22af48b85bSJaegeuk Kim if (count <= 4) { 23af48b85bSJaegeuk Kim return sizeof(struct f2fs_acl_header) + 24af48b85bSJaegeuk Kim count * sizeof(struct f2fs_acl_entry_short); 25af48b85bSJaegeuk Kim } else { 26af48b85bSJaegeuk Kim return sizeof(struct f2fs_acl_header) + 27af48b85bSJaegeuk Kim 4 * sizeof(struct f2fs_acl_entry_short) + 28af48b85bSJaegeuk Kim (count - 4) * sizeof(struct f2fs_acl_entry); 29af48b85bSJaegeuk Kim } 30af48b85bSJaegeuk Kim } 31af48b85bSJaegeuk Kim 32af48b85bSJaegeuk Kim static inline int f2fs_acl_count(size_t size) 33af48b85bSJaegeuk Kim { 34af48b85bSJaegeuk Kim ssize_t s; 35af48b85bSJaegeuk Kim size -= sizeof(struct f2fs_acl_header); 36af48b85bSJaegeuk Kim s = size - 4 * sizeof(struct f2fs_acl_entry_short); 37af48b85bSJaegeuk Kim if (s < 0) { 38af48b85bSJaegeuk Kim if (size % sizeof(struct f2fs_acl_entry_short)) 39af48b85bSJaegeuk Kim return -1; 40af48b85bSJaegeuk Kim return size / sizeof(struct f2fs_acl_entry_short); 41af48b85bSJaegeuk Kim } else { 42af48b85bSJaegeuk Kim if (s % sizeof(struct f2fs_acl_entry)) 43af48b85bSJaegeuk Kim return -1; 44af48b85bSJaegeuk Kim return s / sizeof(struct f2fs_acl_entry) + 4; 45af48b85bSJaegeuk Kim } 46af48b85bSJaegeuk Kim } 47af48b85bSJaegeuk Kim 48af48b85bSJaegeuk Kim static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size) 49af48b85bSJaegeuk Kim { 50af48b85bSJaegeuk Kim int i, count; 51af48b85bSJaegeuk Kim struct posix_acl *acl; 52af48b85bSJaegeuk Kim struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value; 53af48b85bSJaegeuk Kim struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1); 54af48b85bSJaegeuk Kim const char *end = value + size; 55af48b85bSJaegeuk Kim 56*1618e6e2SChengguang Xu if (size < sizeof(struct f2fs_acl_header)) 57*1618e6e2SChengguang Xu return ERR_PTR(-EINVAL); 58*1618e6e2SChengguang Xu 59af48b85bSJaegeuk Kim if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION)) 60af48b85bSJaegeuk Kim return ERR_PTR(-EINVAL); 61af48b85bSJaegeuk Kim 62af48b85bSJaegeuk Kim count = f2fs_acl_count(size); 63af48b85bSJaegeuk Kim if (count < 0) 64af48b85bSJaegeuk Kim return ERR_PTR(-EINVAL); 65af48b85bSJaegeuk Kim if (count == 0) 66af48b85bSJaegeuk Kim return NULL; 67af48b85bSJaegeuk Kim 68dd802406SJaegeuk Kim acl = posix_acl_alloc(count, GFP_NOFS); 69af48b85bSJaegeuk Kim if (!acl) 70af48b85bSJaegeuk Kim return ERR_PTR(-ENOMEM); 71af48b85bSJaegeuk Kim 72af48b85bSJaegeuk Kim for (i = 0; i < count; i++) { 73af48b85bSJaegeuk Kim 74af48b85bSJaegeuk Kim if ((char *)entry > end) 75af48b85bSJaegeuk Kim goto fail; 76af48b85bSJaegeuk Kim 77af48b85bSJaegeuk Kim acl->a_entries[i].e_tag = le16_to_cpu(entry->e_tag); 78af48b85bSJaegeuk Kim acl->a_entries[i].e_perm = le16_to_cpu(entry->e_perm); 79af48b85bSJaegeuk Kim 80af48b85bSJaegeuk Kim switch (acl->a_entries[i].e_tag) { 81af48b85bSJaegeuk Kim case ACL_USER_OBJ: 82af48b85bSJaegeuk Kim case ACL_GROUP_OBJ: 83af48b85bSJaegeuk Kim case ACL_MASK: 84af48b85bSJaegeuk Kim case ACL_OTHER: 85af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 86af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry_short)); 87af48b85bSJaegeuk Kim break; 88af48b85bSJaegeuk Kim 89af48b85bSJaegeuk Kim case ACL_USER: 90af48b85bSJaegeuk Kim acl->a_entries[i].e_uid = 91af48b85bSJaegeuk Kim make_kuid(&init_user_ns, 92af48b85bSJaegeuk Kim le32_to_cpu(entry->e_id)); 93af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 94af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry)); 95af48b85bSJaegeuk Kim break; 96af48b85bSJaegeuk Kim case ACL_GROUP: 97af48b85bSJaegeuk Kim acl->a_entries[i].e_gid = 98af48b85bSJaegeuk Kim make_kgid(&init_user_ns, 99af48b85bSJaegeuk Kim le32_to_cpu(entry->e_id)); 100af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 101af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry)); 102af48b85bSJaegeuk Kim break; 103af48b85bSJaegeuk Kim default: 104af48b85bSJaegeuk Kim goto fail; 105af48b85bSJaegeuk Kim } 106af48b85bSJaegeuk Kim } 107af48b85bSJaegeuk Kim if ((char *)entry != end) 108af48b85bSJaegeuk Kim goto fail; 109af48b85bSJaegeuk Kim return acl; 110af48b85bSJaegeuk Kim fail: 111af48b85bSJaegeuk Kim posix_acl_release(acl); 112af48b85bSJaegeuk Kim return ERR_PTR(-EINVAL); 113af48b85bSJaegeuk Kim } 114af48b85bSJaegeuk Kim 1151ecc0c5cSChao Yu static void *f2fs_acl_to_disk(struct f2fs_sb_info *sbi, 1161ecc0c5cSChao Yu const struct posix_acl *acl, size_t *size) 117af48b85bSJaegeuk Kim { 118af48b85bSJaegeuk Kim struct f2fs_acl_header *f2fs_acl; 119af48b85bSJaegeuk Kim struct f2fs_acl_entry *entry; 120af48b85bSJaegeuk Kim int i; 121af48b85bSJaegeuk Kim 1221ecc0c5cSChao Yu f2fs_acl = f2fs_kmalloc(sbi, sizeof(struct f2fs_acl_header) + 1231ecc0c5cSChao Yu acl->a_count * sizeof(struct f2fs_acl_entry), 1241ecc0c5cSChao Yu GFP_NOFS); 125af48b85bSJaegeuk Kim if (!f2fs_acl) 126af48b85bSJaegeuk Kim return ERR_PTR(-ENOMEM); 127af48b85bSJaegeuk Kim 128af48b85bSJaegeuk Kim f2fs_acl->a_version = cpu_to_le32(F2FS_ACL_VERSION); 129af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)(f2fs_acl + 1); 130af48b85bSJaegeuk Kim 131af48b85bSJaegeuk Kim for (i = 0; i < acl->a_count; i++) { 132af48b85bSJaegeuk Kim 133af48b85bSJaegeuk Kim entry->e_tag = cpu_to_le16(acl->a_entries[i].e_tag); 134af48b85bSJaegeuk Kim entry->e_perm = cpu_to_le16(acl->a_entries[i].e_perm); 135af48b85bSJaegeuk Kim 136af48b85bSJaegeuk Kim switch (acl->a_entries[i].e_tag) { 137af48b85bSJaegeuk Kim case ACL_USER: 138af48b85bSJaegeuk Kim entry->e_id = cpu_to_le32( 139af48b85bSJaegeuk Kim from_kuid(&init_user_ns, 140af48b85bSJaegeuk Kim acl->a_entries[i].e_uid)); 141af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 142af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry)); 143af48b85bSJaegeuk Kim break; 144af48b85bSJaegeuk Kim case ACL_GROUP: 145af48b85bSJaegeuk Kim entry->e_id = cpu_to_le32( 146af48b85bSJaegeuk Kim from_kgid(&init_user_ns, 147af48b85bSJaegeuk Kim acl->a_entries[i].e_gid)); 148af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 149af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry)); 150af48b85bSJaegeuk Kim break; 151af48b85bSJaegeuk Kim case ACL_USER_OBJ: 152af48b85bSJaegeuk Kim case ACL_GROUP_OBJ: 153af48b85bSJaegeuk Kim case ACL_MASK: 154af48b85bSJaegeuk Kim case ACL_OTHER: 155af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 156af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry_short)); 157af48b85bSJaegeuk Kim break; 158af48b85bSJaegeuk Kim default: 159af48b85bSJaegeuk Kim goto fail; 160af48b85bSJaegeuk Kim } 161af48b85bSJaegeuk Kim } 162af48b85bSJaegeuk Kim *size = f2fs_acl_size(acl->a_count); 163af48b85bSJaegeuk Kim return (void *)f2fs_acl; 164af48b85bSJaegeuk Kim 165af48b85bSJaegeuk Kim fail: 166af48b85bSJaegeuk Kim kfree(f2fs_acl); 167af48b85bSJaegeuk Kim return ERR_PTR(-EINVAL); 168af48b85bSJaegeuk Kim } 169af48b85bSJaegeuk Kim 170bce8d112SJaegeuk Kim static struct posix_acl *__f2fs_get_acl(struct inode *inode, int type, 171bce8d112SJaegeuk Kim struct page *dpage) 172af48b85bSJaegeuk Kim { 173af48b85bSJaegeuk Kim int name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT; 174af48b85bSJaegeuk Kim void *value = NULL; 175af48b85bSJaegeuk Kim struct posix_acl *acl; 176af48b85bSJaegeuk Kim int retval; 177af48b85bSJaegeuk Kim 178af48b85bSJaegeuk Kim if (type == ACL_TYPE_ACCESS) 179af48b85bSJaegeuk Kim name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; 180af48b85bSJaegeuk Kim 181bce8d112SJaegeuk Kim retval = f2fs_getxattr(inode, name_index, "", NULL, 0, dpage); 182af48b85bSJaegeuk Kim if (retval > 0) { 1831ecc0c5cSChao Yu value = f2fs_kmalloc(F2FS_I_SB(inode), retval, GFP_F2FS_ZERO); 184af48b85bSJaegeuk Kim if (!value) 185af48b85bSJaegeuk Kim return ERR_PTR(-ENOMEM); 186bce8d112SJaegeuk Kim retval = f2fs_getxattr(inode, name_index, "", value, 187bce8d112SJaegeuk Kim retval, dpage); 188af48b85bSJaegeuk Kim } 189af48b85bSJaegeuk Kim 190c1b75eabSJaegeuk Kim if (retval > 0) 191c1b75eabSJaegeuk Kim acl = f2fs_acl_from_disk(value, retval); 192c1b75eabSJaegeuk Kim else if (retval == -ENODATA) 193af48b85bSJaegeuk Kim acl = NULL; 194af48b85bSJaegeuk Kim else 195af48b85bSJaegeuk Kim acl = ERR_PTR(retval); 196af48b85bSJaegeuk Kim kfree(value); 197c1b75eabSJaegeuk Kim 198af48b85bSJaegeuk Kim return acl; 199af48b85bSJaegeuk Kim } 200af48b85bSJaegeuk Kim 201bce8d112SJaegeuk Kim struct posix_acl *f2fs_get_acl(struct inode *inode, int type) 202bce8d112SJaegeuk Kim { 203bce8d112SJaegeuk Kim return __f2fs_get_acl(inode, type, NULL); 204bce8d112SJaegeuk Kim } 205bce8d112SJaegeuk Kim 206a6dda0e6SChristoph Hellwig static int __f2fs_set_acl(struct inode *inode, int type, 2072ed2d5b3SJaegeuk Kim struct posix_acl *acl, struct page *ipage) 208af48b85bSJaegeuk Kim { 209af48b85bSJaegeuk Kim int name_index; 210af48b85bSJaegeuk Kim void *value = NULL; 211af48b85bSJaegeuk Kim size_t size = 0; 212af48b85bSJaegeuk Kim int error; 21314af20fcSErnesto A. Fernández umode_t mode = inode->i_mode; 214af48b85bSJaegeuk Kim 215af48b85bSJaegeuk Kim switch (type) { 216af48b85bSJaegeuk Kim case ACL_TYPE_ACCESS: 217af48b85bSJaegeuk Kim name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; 218c925dc16SJaegeuk Kim if (acl && !ipage) { 21914af20fcSErnesto A. Fernández error = posix_acl_update_mode(inode, &mode, &acl); 22007393101SJan Kara if (error) 221af48b85bSJaegeuk Kim return error; 22214af20fcSErnesto A. Fernández set_acl_inode(inode, mode); 223af48b85bSJaegeuk Kim } 224af48b85bSJaegeuk Kim break; 225af48b85bSJaegeuk Kim 226af48b85bSJaegeuk Kim case ACL_TYPE_DEFAULT: 227af48b85bSJaegeuk Kim name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT; 228af48b85bSJaegeuk Kim if (!S_ISDIR(inode->i_mode)) 229af48b85bSJaegeuk Kim return acl ? -EACCES : 0; 230af48b85bSJaegeuk Kim break; 231af48b85bSJaegeuk Kim 232af48b85bSJaegeuk Kim default: 233af48b85bSJaegeuk Kim return -EINVAL; 234af48b85bSJaegeuk Kim } 235af48b85bSJaegeuk Kim 236af48b85bSJaegeuk Kim if (acl) { 2371ecc0c5cSChao Yu value = f2fs_acl_to_disk(F2FS_I_SB(inode), acl, &size); 238af48b85bSJaegeuk Kim if (IS_ERR(value)) { 23991942321SJaegeuk Kim clear_inode_flag(inode, FI_ACL_MODE); 24068390dd9SZhang Shengju return PTR_ERR(value); 241af48b85bSJaegeuk Kim } 242af48b85bSJaegeuk Kim } 243af48b85bSJaegeuk Kim 244c02745efSJaegeuk Kim error = f2fs_setxattr(inode, name_index, "", value, size, ipage, 0); 245af48b85bSJaegeuk Kim 246af48b85bSJaegeuk Kim kfree(value); 247af48b85bSJaegeuk Kim if (!error) 248af48b85bSJaegeuk Kim set_cached_acl(inode, type, acl); 249af48b85bSJaegeuk Kim 25091942321SJaegeuk Kim clear_inode_flag(inode, FI_ACL_MODE); 251af48b85bSJaegeuk Kim return error; 252af48b85bSJaegeuk Kim } 253af48b85bSJaegeuk Kim 254a6dda0e6SChristoph Hellwig int f2fs_set_acl(struct inode *inode, struct posix_acl *acl, int type) 255a6dda0e6SChristoph Hellwig { 2561f227a3eSJaegeuk Kim if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) 2571f227a3eSJaegeuk Kim return -EIO; 2581f227a3eSJaegeuk Kim 259a6dda0e6SChristoph Hellwig return __f2fs_set_acl(inode, type, acl, NULL); 260a6dda0e6SChristoph Hellwig } 261a6dda0e6SChristoph Hellwig 262bce8d112SJaegeuk Kim /* 263bce8d112SJaegeuk Kim * Most part of f2fs_acl_clone, f2fs_acl_create_masq, f2fs_acl_create 264bce8d112SJaegeuk Kim * are copied from posix_acl.c 265bce8d112SJaegeuk Kim */ 266bce8d112SJaegeuk Kim static struct posix_acl *f2fs_acl_clone(const struct posix_acl *acl, 267bce8d112SJaegeuk Kim gfp_t flags) 268af48b85bSJaegeuk Kim { 269bce8d112SJaegeuk Kim struct posix_acl *clone = NULL; 270bce8d112SJaegeuk Kim 271bce8d112SJaegeuk Kim if (acl) { 272bce8d112SJaegeuk Kim int size = sizeof(struct posix_acl) + acl->a_count * 273bce8d112SJaegeuk Kim sizeof(struct posix_acl_entry); 274bce8d112SJaegeuk Kim clone = kmemdup(acl, size, flags); 275bce8d112SJaegeuk Kim if (clone) 27666717260SElena Reshetova refcount_set(&clone->a_refcount, 1); 277bce8d112SJaegeuk Kim } 278bce8d112SJaegeuk Kim return clone; 279bce8d112SJaegeuk Kim } 280bce8d112SJaegeuk Kim 281bce8d112SJaegeuk Kim static int f2fs_acl_create_masq(struct posix_acl *acl, umode_t *mode_p) 282bce8d112SJaegeuk Kim { 283bce8d112SJaegeuk Kim struct posix_acl_entry *pa, *pe; 284bce8d112SJaegeuk Kim struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL; 285bce8d112SJaegeuk Kim umode_t mode = *mode_p; 286bce8d112SJaegeuk Kim int not_equiv = 0; 287bce8d112SJaegeuk Kim 288bce8d112SJaegeuk Kim /* assert(atomic_read(acl->a_refcount) == 1); */ 289bce8d112SJaegeuk Kim 290bce8d112SJaegeuk Kim FOREACH_ACL_ENTRY(pa, acl, pe) { 291bce8d112SJaegeuk Kim switch(pa->e_tag) { 292bce8d112SJaegeuk Kim case ACL_USER_OBJ: 293bce8d112SJaegeuk Kim pa->e_perm &= (mode >> 6) | ~S_IRWXO; 294bce8d112SJaegeuk Kim mode &= (pa->e_perm << 6) | ~S_IRWXU; 295bce8d112SJaegeuk Kim break; 296bce8d112SJaegeuk Kim 297bce8d112SJaegeuk Kim case ACL_USER: 298bce8d112SJaegeuk Kim case ACL_GROUP: 299bce8d112SJaegeuk Kim not_equiv = 1; 300bce8d112SJaegeuk Kim break; 301bce8d112SJaegeuk Kim 302bce8d112SJaegeuk Kim case ACL_GROUP_OBJ: 303bce8d112SJaegeuk Kim group_obj = pa; 304bce8d112SJaegeuk Kim break; 305bce8d112SJaegeuk Kim 306bce8d112SJaegeuk Kim case ACL_OTHER: 307bce8d112SJaegeuk Kim pa->e_perm &= mode | ~S_IRWXO; 308bce8d112SJaegeuk Kim mode &= pa->e_perm | ~S_IRWXO; 309bce8d112SJaegeuk Kim break; 310bce8d112SJaegeuk Kim 311bce8d112SJaegeuk Kim case ACL_MASK: 312bce8d112SJaegeuk Kim mask_obj = pa; 313bce8d112SJaegeuk Kim not_equiv = 1; 314bce8d112SJaegeuk Kim break; 315bce8d112SJaegeuk Kim 316bce8d112SJaegeuk Kim default: 317bce8d112SJaegeuk Kim return -EIO; 318bce8d112SJaegeuk Kim } 319bce8d112SJaegeuk Kim } 320bce8d112SJaegeuk Kim 321bce8d112SJaegeuk Kim if (mask_obj) { 322bce8d112SJaegeuk Kim mask_obj->e_perm &= (mode >> 3) | ~S_IRWXO; 323bce8d112SJaegeuk Kim mode &= (mask_obj->e_perm << 3) | ~S_IRWXG; 324bce8d112SJaegeuk Kim } else { 325bce8d112SJaegeuk Kim if (!group_obj) 326bce8d112SJaegeuk Kim return -EIO; 327bce8d112SJaegeuk Kim group_obj->e_perm &= (mode >> 3) | ~S_IRWXO; 328bce8d112SJaegeuk Kim mode &= (group_obj->e_perm << 3) | ~S_IRWXG; 329bce8d112SJaegeuk Kim } 330bce8d112SJaegeuk Kim 331bce8d112SJaegeuk Kim *mode_p = (*mode_p & ~S_IRWXUGO) | mode; 332bce8d112SJaegeuk Kim return not_equiv; 333bce8d112SJaegeuk Kim } 334bce8d112SJaegeuk Kim 335bce8d112SJaegeuk Kim static int f2fs_acl_create(struct inode *dir, umode_t *mode, 336bce8d112SJaegeuk Kim struct posix_acl **default_acl, struct posix_acl **acl, 337bce8d112SJaegeuk Kim struct page *dpage) 338bce8d112SJaegeuk Kim { 339bce8d112SJaegeuk Kim struct posix_acl *p; 340272e083fSChao Yu struct posix_acl *clone; 341bce8d112SJaegeuk Kim int ret; 342bce8d112SJaegeuk Kim 343272e083fSChao Yu *acl = NULL; 344272e083fSChao Yu *default_acl = NULL; 345272e083fSChao Yu 346bce8d112SJaegeuk Kim if (S_ISLNK(*mode) || !IS_POSIXACL(dir)) 347272e083fSChao Yu return 0; 348bce8d112SJaegeuk Kim 349bce8d112SJaegeuk Kim p = __f2fs_get_acl(dir, ACL_TYPE_DEFAULT, dpage); 350272e083fSChao Yu if (!p || p == ERR_PTR(-EOPNOTSUPP)) { 351272e083fSChao Yu *mode &= ~current_umask(); 352272e083fSChao Yu return 0; 353bce8d112SJaegeuk Kim } 354272e083fSChao Yu if (IS_ERR(p)) 355272e083fSChao Yu return PTR_ERR(p); 356bce8d112SJaegeuk Kim 357272e083fSChao Yu clone = f2fs_acl_clone(p, GFP_NOFS); 358272e083fSChao Yu if (!clone) 35983dfe53cSChao Yu goto no_mem; 360bce8d112SJaegeuk Kim 361272e083fSChao Yu ret = f2fs_acl_create_masq(clone, mode); 36283dfe53cSChao Yu if (ret < 0) 36383dfe53cSChao Yu goto no_mem_clone; 364bce8d112SJaegeuk Kim 365272e083fSChao Yu if (ret == 0) 366272e083fSChao Yu posix_acl_release(clone); 367272e083fSChao Yu else 368272e083fSChao Yu *acl = clone; 369bce8d112SJaegeuk Kim 370272e083fSChao Yu if (!S_ISDIR(*mode)) 371bce8d112SJaegeuk Kim posix_acl_release(p); 372272e083fSChao Yu else 373bce8d112SJaegeuk Kim *default_acl = p; 374bce8d112SJaegeuk Kim 375bce8d112SJaegeuk Kim return 0; 37683dfe53cSChao Yu 37783dfe53cSChao Yu no_mem_clone: 378272e083fSChao Yu posix_acl_release(clone); 37983dfe53cSChao Yu no_mem: 38083dfe53cSChao Yu posix_acl_release(p); 38183dfe53cSChao Yu return -ENOMEM; 382bce8d112SJaegeuk Kim } 383bce8d112SJaegeuk Kim 384bce8d112SJaegeuk Kim int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage, 385bce8d112SJaegeuk Kim struct page *dpage) 386bce8d112SJaegeuk Kim { 387bce8d112SJaegeuk Kim struct posix_acl *default_acl = NULL, *acl = NULL; 388af48b85bSJaegeuk Kim int error = 0; 389af48b85bSJaegeuk Kim 390bce8d112SJaegeuk Kim error = f2fs_acl_create(dir, &inode->i_mode, &default_acl, &acl, dpage); 391af48b85bSJaegeuk Kim if (error) 392af48b85bSJaegeuk Kim return error; 393b8b60e1aSJaegeuk Kim 3947c45729aSJaegeuk Kim f2fs_mark_inode_dirty_sync(inode, true); 395205b9822SJaegeuk Kim 396a6dda0e6SChristoph Hellwig if (default_acl) { 397a6dda0e6SChristoph Hellwig error = __f2fs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl, 398a6dda0e6SChristoph Hellwig ipage); 399a6dda0e6SChristoph Hellwig posix_acl_release(default_acl); 400af48b85bSJaegeuk Kim } 401af48b85bSJaegeuk Kim if (acl) { 4023b6709b7SKinglong Mee if (!error) 403a6dda0e6SChristoph Hellwig error = __f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, 404a6dda0e6SChristoph Hellwig ipage); 405af48b85bSJaegeuk Kim posix_acl_release(acl); 406a6dda0e6SChristoph Hellwig } 407a6dda0e6SChristoph Hellwig 408af48b85bSJaegeuk Kim return error; 409af48b85bSJaegeuk Kim } 410