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 112af48b85bSJaegeuk Kim static void *f2fs_acl_to_disk(const struct posix_acl *acl, size_t *size) 113af48b85bSJaegeuk Kim { 114af48b85bSJaegeuk Kim struct f2fs_acl_header *f2fs_acl; 115af48b85bSJaegeuk Kim struct f2fs_acl_entry *entry; 116af48b85bSJaegeuk Kim int i; 117af48b85bSJaegeuk Kim 118af48b85bSJaegeuk Kim f2fs_acl = kmalloc(sizeof(struct f2fs_acl_header) + acl->a_count * 119dd802406SJaegeuk Kim sizeof(struct f2fs_acl_entry), GFP_NOFS); 120af48b85bSJaegeuk Kim if (!f2fs_acl) 121af48b85bSJaegeuk Kim return ERR_PTR(-ENOMEM); 122af48b85bSJaegeuk Kim 123af48b85bSJaegeuk Kim f2fs_acl->a_version = cpu_to_le32(F2FS_ACL_VERSION); 124af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)(f2fs_acl + 1); 125af48b85bSJaegeuk Kim 126af48b85bSJaegeuk Kim for (i = 0; i < acl->a_count; i++) { 127af48b85bSJaegeuk Kim 128af48b85bSJaegeuk Kim entry->e_tag = cpu_to_le16(acl->a_entries[i].e_tag); 129af48b85bSJaegeuk Kim entry->e_perm = cpu_to_le16(acl->a_entries[i].e_perm); 130af48b85bSJaegeuk Kim 131af48b85bSJaegeuk Kim switch (acl->a_entries[i].e_tag) { 132af48b85bSJaegeuk Kim case ACL_USER: 133af48b85bSJaegeuk Kim entry->e_id = cpu_to_le32( 134af48b85bSJaegeuk Kim from_kuid(&init_user_ns, 135af48b85bSJaegeuk Kim acl->a_entries[i].e_uid)); 136af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 137af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry)); 138af48b85bSJaegeuk Kim break; 139af48b85bSJaegeuk Kim case ACL_GROUP: 140af48b85bSJaegeuk Kim entry->e_id = cpu_to_le32( 141af48b85bSJaegeuk Kim from_kgid(&init_user_ns, 142af48b85bSJaegeuk Kim acl->a_entries[i].e_gid)); 143af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 144af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry)); 145af48b85bSJaegeuk Kim break; 146af48b85bSJaegeuk Kim case ACL_USER_OBJ: 147af48b85bSJaegeuk Kim case ACL_GROUP_OBJ: 148af48b85bSJaegeuk Kim case ACL_MASK: 149af48b85bSJaegeuk Kim case ACL_OTHER: 150af48b85bSJaegeuk Kim entry = (struct f2fs_acl_entry *)((char *)entry + 151af48b85bSJaegeuk Kim sizeof(struct f2fs_acl_entry_short)); 152af48b85bSJaegeuk Kim break; 153af48b85bSJaegeuk Kim default: 154af48b85bSJaegeuk Kim goto fail; 155af48b85bSJaegeuk Kim } 156af48b85bSJaegeuk Kim } 157af48b85bSJaegeuk Kim *size = f2fs_acl_size(acl->a_count); 158af48b85bSJaegeuk Kim return (void *)f2fs_acl; 159af48b85bSJaegeuk Kim 160af48b85bSJaegeuk Kim fail: 161af48b85bSJaegeuk Kim kfree(f2fs_acl); 162af48b85bSJaegeuk Kim return ERR_PTR(-EINVAL); 163af48b85bSJaegeuk Kim } 164af48b85bSJaegeuk Kim 165bce8d112SJaegeuk Kim static struct posix_acl *__f2fs_get_acl(struct inode *inode, int type, 166bce8d112SJaegeuk Kim struct page *dpage) 167af48b85bSJaegeuk Kim { 168af48b85bSJaegeuk Kim int name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT; 169af48b85bSJaegeuk Kim void *value = NULL; 170af48b85bSJaegeuk Kim struct posix_acl *acl; 171af48b85bSJaegeuk Kim int retval; 172af48b85bSJaegeuk Kim 173af48b85bSJaegeuk Kim if (type == ACL_TYPE_ACCESS) 174af48b85bSJaegeuk Kim name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; 175af48b85bSJaegeuk Kim 176bce8d112SJaegeuk Kim retval = f2fs_getxattr(inode, name_index, "", NULL, 0, dpage); 177af48b85bSJaegeuk Kim if (retval > 0) { 178808a1d74SJaegeuk Kim value = kmalloc(retval, GFP_F2FS_ZERO); 179af48b85bSJaegeuk Kim if (!value) 180af48b85bSJaegeuk Kim return ERR_PTR(-ENOMEM); 181bce8d112SJaegeuk Kim retval = f2fs_getxattr(inode, name_index, "", value, 182bce8d112SJaegeuk Kim retval, dpage); 183af48b85bSJaegeuk Kim } 184af48b85bSJaegeuk Kim 185c1b75eabSJaegeuk Kim if (retval > 0) 186c1b75eabSJaegeuk Kim acl = f2fs_acl_from_disk(value, retval); 187c1b75eabSJaegeuk Kim else if (retval == -ENODATA) 188af48b85bSJaegeuk Kim acl = NULL; 189af48b85bSJaegeuk Kim else 190af48b85bSJaegeuk Kim acl = ERR_PTR(retval); 191af48b85bSJaegeuk Kim kfree(value); 192c1b75eabSJaegeuk Kim 193af48b85bSJaegeuk Kim if (!IS_ERR(acl)) 194af48b85bSJaegeuk Kim set_cached_acl(inode, type, acl); 195af48b85bSJaegeuk Kim 196af48b85bSJaegeuk Kim return acl; 197af48b85bSJaegeuk Kim } 198af48b85bSJaegeuk Kim 199bce8d112SJaegeuk Kim struct posix_acl *f2fs_get_acl(struct inode *inode, int type) 200bce8d112SJaegeuk Kim { 201bce8d112SJaegeuk Kim return __f2fs_get_acl(inode, type, NULL); 202bce8d112SJaegeuk Kim } 203bce8d112SJaegeuk Kim 204a6dda0e6SChristoph Hellwig static int __f2fs_set_acl(struct inode *inode, int type, 2052ed2d5b3SJaegeuk Kim struct posix_acl *acl, struct page *ipage) 206af48b85bSJaegeuk Kim { 207af48b85bSJaegeuk Kim struct f2fs_inode_info *fi = F2FS_I(inode); 208af48b85bSJaegeuk Kim int name_index; 209af48b85bSJaegeuk Kim void *value = NULL; 210af48b85bSJaegeuk Kim size_t size = 0; 211af48b85bSJaegeuk Kim int error; 212af48b85bSJaegeuk Kim 213af48b85bSJaegeuk Kim switch (type) { 214af48b85bSJaegeuk Kim case ACL_TYPE_ACCESS: 215af48b85bSJaegeuk Kim name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; 216af48b85bSJaegeuk Kim if (acl) { 217af48b85bSJaegeuk Kim error = posix_acl_equiv_mode(acl, &inode->i_mode); 218af48b85bSJaegeuk Kim if (error < 0) 219af48b85bSJaegeuk Kim return error; 220af48b85bSJaegeuk Kim set_acl_inode(fi, inode->i_mode); 221af48b85bSJaegeuk Kim if (error == 0) 222af48b85bSJaegeuk Kim acl = NULL; 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) { 237af48b85bSJaegeuk Kim value = f2fs_acl_to_disk(acl, &size); 238af48b85bSJaegeuk Kim if (IS_ERR(value)) { 239fa528722SGu Zheng clear_inode_flag(fi, FI_ACL_MODE); 240af48b85bSJaegeuk Kim return (int)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 250fa528722SGu Zheng clear_inode_flag(fi, 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 { 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) 273bce8d112SJaegeuk Kim atomic_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; 337bce8d112SJaegeuk Kim int ret; 338bce8d112SJaegeuk Kim 339bce8d112SJaegeuk Kim if (S_ISLNK(*mode) || !IS_POSIXACL(dir)) 340bce8d112SJaegeuk Kim goto no_acl; 341bce8d112SJaegeuk Kim 342bce8d112SJaegeuk Kim p = __f2fs_get_acl(dir, ACL_TYPE_DEFAULT, dpage); 343bce8d112SJaegeuk Kim if (IS_ERR(p)) { 344bce8d112SJaegeuk Kim if (p == ERR_PTR(-EOPNOTSUPP)) 345bce8d112SJaegeuk Kim goto apply_umask; 346bce8d112SJaegeuk Kim return PTR_ERR(p); 347bce8d112SJaegeuk Kim } 348bce8d112SJaegeuk Kim 349bce8d112SJaegeuk Kim if (!p) 350bce8d112SJaegeuk Kim goto apply_umask; 351bce8d112SJaegeuk Kim 352bce8d112SJaegeuk Kim *acl = f2fs_acl_clone(p, GFP_NOFS); 353bce8d112SJaegeuk Kim if (!*acl) 354bce8d112SJaegeuk Kim return -ENOMEM; 355bce8d112SJaegeuk Kim 356bce8d112SJaegeuk Kim ret = f2fs_acl_create_masq(*acl, mode); 357bce8d112SJaegeuk Kim if (ret < 0) { 358bce8d112SJaegeuk Kim posix_acl_release(*acl); 359bce8d112SJaegeuk Kim return -ENOMEM; 360bce8d112SJaegeuk Kim } 361bce8d112SJaegeuk Kim 362bce8d112SJaegeuk Kim if (ret == 0) { 363bce8d112SJaegeuk Kim posix_acl_release(*acl); 364bce8d112SJaegeuk Kim *acl = NULL; 365bce8d112SJaegeuk Kim } 366bce8d112SJaegeuk Kim 367bce8d112SJaegeuk Kim if (!S_ISDIR(*mode)) { 368bce8d112SJaegeuk Kim posix_acl_release(p); 369bce8d112SJaegeuk Kim *default_acl = NULL; 370bce8d112SJaegeuk Kim } else { 371bce8d112SJaegeuk Kim *default_acl = p; 372bce8d112SJaegeuk Kim } 373bce8d112SJaegeuk Kim return 0; 374bce8d112SJaegeuk Kim 375bce8d112SJaegeuk Kim apply_umask: 376bce8d112SJaegeuk Kim *mode &= ~current_umask(); 377bce8d112SJaegeuk Kim no_acl: 378bce8d112SJaegeuk Kim *default_acl = NULL; 379bce8d112SJaegeuk Kim *acl = NULL; 380bce8d112SJaegeuk Kim return 0; 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 393a6dda0e6SChristoph Hellwig if (default_acl) { 394a6dda0e6SChristoph Hellwig error = __f2fs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl, 395a6dda0e6SChristoph Hellwig ipage); 396a6dda0e6SChristoph Hellwig posix_acl_release(default_acl); 397af48b85bSJaegeuk Kim } 398af48b85bSJaegeuk Kim if (acl) { 399*3b6709b7SKinglong Mee if (!error) 400a6dda0e6SChristoph Hellwig error = __f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, 401a6dda0e6SChristoph Hellwig ipage); 402af48b85bSJaegeuk Kim posix_acl_release(acl); 403a6dda0e6SChristoph Hellwig } 404a6dda0e6SChristoph Hellwig 405af48b85bSJaegeuk Kim return error; 406af48b85bSJaegeuk Kim } 407