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 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; 210af48b85bSJaegeuk Kim 211af48b85bSJaegeuk Kim switch (type) { 212af48b85bSJaegeuk Kim case ACL_TYPE_ACCESS: 213af48b85bSJaegeuk Kim name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; 214*c925dc16SJaegeuk Kim if (acl && !ipage) { 21507393101SJan Kara error = posix_acl_update_mode(inode, &inode->i_mode, &acl); 21607393101SJan Kara if (error) 217af48b85bSJaegeuk Kim return error; 21891942321SJaegeuk Kim set_acl_inode(inode, inode->i_mode); 219af48b85bSJaegeuk Kim } 220af48b85bSJaegeuk Kim break; 221af48b85bSJaegeuk Kim 222af48b85bSJaegeuk Kim case ACL_TYPE_DEFAULT: 223af48b85bSJaegeuk Kim name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT; 224af48b85bSJaegeuk Kim if (!S_ISDIR(inode->i_mode)) 225af48b85bSJaegeuk Kim return acl ? -EACCES : 0; 226af48b85bSJaegeuk Kim break; 227af48b85bSJaegeuk Kim 228af48b85bSJaegeuk Kim default: 229af48b85bSJaegeuk Kim return -EINVAL; 230af48b85bSJaegeuk Kim } 231af48b85bSJaegeuk Kim 232af48b85bSJaegeuk Kim if (acl) { 2331ecc0c5cSChao Yu value = f2fs_acl_to_disk(F2FS_I_SB(inode), acl, &size); 234af48b85bSJaegeuk Kim if (IS_ERR(value)) { 23591942321SJaegeuk Kim clear_inode_flag(inode, FI_ACL_MODE); 23668390dd9SZhang Shengju return PTR_ERR(value); 237af48b85bSJaegeuk Kim } 238af48b85bSJaegeuk Kim } 239af48b85bSJaegeuk Kim 240c02745efSJaegeuk Kim error = f2fs_setxattr(inode, name_index, "", value, size, ipage, 0); 241af48b85bSJaegeuk Kim 242af48b85bSJaegeuk Kim kfree(value); 243af48b85bSJaegeuk Kim if (!error) 244af48b85bSJaegeuk Kim set_cached_acl(inode, type, acl); 245af48b85bSJaegeuk Kim 24691942321SJaegeuk Kim clear_inode_flag(inode, FI_ACL_MODE); 247af48b85bSJaegeuk Kim return error; 248af48b85bSJaegeuk Kim } 249af48b85bSJaegeuk Kim 250a6dda0e6SChristoph Hellwig int f2fs_set_acl(struct inode *inode, struct posix_acl *acl, int type) 251a6dda0e6SChristoph Hellwig { 252a6dda0e6SChristoph Hellwig return __f2fs_set_acl(inode, type, acl, NULL); 253a6dda0e6SChristoph Hellwig } 254a6dda0e6SChristoph Hellwig 255bce8d112SJaegeuk Kim /* 256bce8d112SJaegeuk Kim * Most part of f2fs_acl_clone, f2fs_acl_create_masq, f2fs_acl_create 257bce8d112SJaegeuk Kim * are copied from posix_acl.c 258bce8d112SJaegeuk Kim */ 259bce8d112SJaegeuk Kim static struct posix_acl *f2fs_acl_clone(const struct posix_acl *acl, 260bce8d112SJaegeuk Kim gfp_t flags) 261af48b85bSJaegeuk Kim { 262bce8d112SJaegeuk Kim struct posix_acl *clone = NULL; 263bce8d112SJaegeuk Kim 264bce8d112SJaegeuk Kim if (acl) { 265bce8d112SJaegeuk Kim int size = sizeof(struct posix_acl) + acl->a_count * 266bce8d112SJaegeuk Kim sizeof(struct posix_acl_entry); 267bce8d112SJaegeuk Kim clone = kmemdup(acl, size, flags); 268bce8d112SJaegeuk Kim if (clone) 269bce8d112SJaegeuk Kim atomic_set(&clone->a_refcount, 1); 270bce8d112SJaegeuk Kim } 271bce8d112SJaegeuk Kim return clone; 272bce8d112SJaegeuk Kim } 273bce8d112SJaegeuk Kim 274bce8d112SJaegeuk Kim static int f2fs_acl_create_masq(struct posix_acl *acl, umode_t *mode_p) 275bce8d112SJaegeuk Kim { 276bce8d112SJaegeuk Kim struct posix_acl_entry *pa, *pe; 277bce8d112SJaegeuk Kim struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL; 278bce8d112SJaegeuk Kim umode_t mode = *mode_p; 279bce8d112SJaegeuk Kim int not_equiv = 0; 280bce8d112SJaegeuk Kim 281bce8d112SJaegeuk Kim /* assert(atomic_read(acl->a_refcount) == 1); */ 282bce8d112SJaegeuk Kim 283bce8d112SJaegeuk Kim FOREACH_ACL_ENTRY(pa, acl, pe) { 284bce8d112SJaegeuk Kim switch(pa->e_tag) { 285bce8d112SJaegeuk Kim case ACL_USER_OBJ: 286bce8d112SJaegeuk Kim pa->e_perm &= (mode >> 6) | ~S_IRWXO; 287bce8d112SJaegeuk Kim mode &= (pa->e_perm << 6) | ~S_IRWXU; 288bce8d112SJaegeuk Kim break; 289bce8d112SJaegeuk Kim 290bce8d112SJaegeuk Kim case ACL_USER: 291bce8d112SJaegeuk Kim case ACL_GROUP: 292bce8d112SJaegeuk Kim not_equiv = 1; 293bce8d112SJaegeuk Kim break; 294bce8d112SJaegeuk Kim 295bce8d112SJaegeuk Kim case ACL_GROUP_OBJ: 296bce8d112SJaegeuk Kim group_obj = pa; 297bce8d112SJaegeuk Kim break; 298bce8d112SJaegeuk Kim 299bce8d112SJaegeuk Kim case ACL_OTHER: 300bce8d112SJaegeuk Kim pa->e_perm &= mode | ~S_IRWXO; 301bce8d112SJaegeuk Kim mode &= pa->e_perm | ~S_IRWXO; 302bce8d112SJaegeuk Kim break; 303bce8d112SJaegeuk Kim 304bce8d112SJaegeuk Kim case ACL_MASK: 305bce8d112SJaegeuk Kim mask_obj = pa; 306bce8d112SJaegeuk Kim not_equiv = 1; 307bce8d112SJaegeuk Kim break; 308bce8d112SJaegeuk Kim 309bce8d112SJaegeuk Kim default: 310bce8d112SJaegeuk Kim return -EIO; 311bce8d112SJaegeuk Kim } 312bce8d112SJaegeuk Kim } 313bce8d112SJaegeuk Kim 314bce8d112SJaegeuk Kim if (mask_obj) { 315bce8d112SJaegeuk Kim mask_obj->e_perm &= (mode >> 3) | ~S_IRWXO; 316bce8d112SJaegeuk Kim mode &= (mask_obj->e_perm << 3) | ~S_IRWXG; 317bce8d112SJaegeuk Kim } else { 318bce8d112SJaegeuk Kim if (!group_obj) 319bce8d112SJaegeuk Kim return -EIO; 320bce8d112SJaegeuk Kim group_obj->e_perm &= (mode >> 3) | ~S_IRWXO; 321bce8d112SJaegeuk Kim mode &= (group_obj->e_perm << 3) | ~S_IRWXG; 322bce8d112SJaegeuk Kim } 323bce8d112SJaegeuk Kim 324bce8d112SJaegeuk Kim *mode_p = (*mode_p & ~S_IRWXUGO) | mode; 325bce8d112SJaegeuk Kim return not_equiv; 326bce8d112SJaegeuk Kim } 327bce8d112SJaegeuk Kim 328bce8d112SJaegeuk Kim static int f2fs_acl_create(struct inode *dir, umode_t *mode, 329bce8d112SJaegeuk Kim struct posix_acl **default_acl, struct posix_acl **acl, 330bce8d112SJaegeuk Kim struct page *dpage) 331bce8d112SJaegeuk Kim { 332bce8d112SJaegeuk Kim struct posix_acl *p; 333272e083fSChao Yu struct posix_acl *clone; 334bce8d112SJaegeuk Kim int ret; 335bce8d112SJaegeuk Kim 336272e083fSChao Yu *acl = NULL; 337272e083fSChao Yu *default_acl = NULL; 338272e083fSChao Yu 339bce8d112SJaegeuk Kim if (S_ISLNK(*mode) || !IS_POSIXACL(dir)) 340272e083fSChao Yu return 0; 341bce8d112SJaegeuk Kim 342bce8d112SJaegeuk Kim p = __f2fs_get_acl(dir, ACL_TYPE_DEFAULT, dpage); 343272e083fSChao Yu if (!p || p == ERR_PTR(-EOPNOTSUPP)) { 344272e083fSChao Yu *mode &= ~current_umask(); 345272e083fSChao Yu return 0; 346bce8d112SJaegeuk Kim } 347272e083fSChao Yu if (IS_ERR(p)) 348272e083fSChao Yu return PTR_ERR(p); 349bce8d112SJaegeuk Kim 350272e083fSChao Yu clone = f2fs_acl_clone(p, GFP_NOFS); 351272e083fSChao Yu if (!clone) 35283dfe53cSChao Yu goto no_mem; 353bce8d112SJaegeuk Kim 354272e083fSChao Yu ret = f2fs_acl_create_masq(clone, mode); 35583dfe53cSChao Yu if (ret < 0) 35683dfe53cSChao Yu goto no_mem_clone; 357bce8d112SJaegeuk Kim 358272e083fSChao Yu if (ret == 0) 359272e083fSChao Yu posix_acl_release(clone); 360272e083fSChao Yu else 361272e083fSChao Yu *acl = clone; 362bce8d112SJaegeuk Kim 363272e083fSChao Yu if (!S_ISDIR(*mode)) 364bce8d112SJaegeuk Kim posix_acl_release(p); 365272e083fSChao Yu else 366bce8d112SJaegeuk Kim *default_acl = p; 367bce8d112SJaegeuk Kim 368bce8d112SJaegeuk Kim return 0; 36983dfe53cSChao Yu 37083dfe53cSChao Yu no_mem_clone: 371272e083fSChao Yu posix_acl_release(clone); 37283dfe53cSChao Yu no_mem: 37383dfe53cSChao Yu posix_acl_release(p); 37483dfe53cSChao Yu return -ENOMEM; 375bce8d112SJaegeuk Kim } 376bce8d112SJaegeuk Kim 377bce8d112SJaegeuk Kim int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage, 378bce8d112SJaegeuk Kim struct page *dpage) 379bce8d112SJaegeuk Kim { 380bce8d112SJaegeuk Kim struct posix_acl *default_acl = NULL, *acl = NULL; 381af48b85bSJaegeuk Kim int error = 0; 382af48b85bSJaegeuk Kim 383bce8d112SJaegeuk Kim error = f2fs_acl_create(dir, &inode->i_mode, &default_acl, &acl, dpage); 384af48b85bSJaegeuk Kim if (error) 385af48b85bSJaegeuk Kim return error; 386b8b60e1aSJaegeuk Kim 3877c45729aSJaegeuk Kim f2fs_mark_inode_dirty_sync(inode, true); 388205b9822SJaegeuk Kim 389a6dda0e6SChristoph Hellwig if (default_acl) { 390a6dda0e6SChristoph Hellwig error = __f2fs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl, 391a6dda0e6SChristoph Hellwig ipage); 392a6dda0e6SChristoph Hellwig posix_acl_release(default_acl); 393af48b85bSJaegeuk Kim } 394af48b85bSJaegeuk Kim if (acl) { 3953b6709b7SKinglong Mee if (!error) 396a6dda0e6SChristoph Hellwig error = __f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, 397a6dda0e6SChristoph Hellwig ipage); 398af48b85bSJaegeuk Kim posix_acl_release(acl); 399a6dda0e6SChristoph Hellwig } 400a6dda0e6SChristoph Hellwig 401af48b85bSJaegeuk Kim return error; 402af48b85bSJaegeuk Kim } 403