int orangefs_init_acl(struct inode *inode, struct inode *dir) { struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); struct posix_acl *default_acl, *acl; umode_t mode = inode->i_mode; int error = 0; ClearModeFlag(orangefs_inode); error = posix_acl_create(dir, &mode, &default_acl, &acl); if (error) return error; if (default_acl) { error = orangefs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); posix_acl_release(default_acl); } if (acl) { if (!error) error = orangefs_set_acl(inode, acl, ACL_TYPE_ACCESS); posix_acl_release(acl); } /* If mode of the inode was changed, then do a forcible ->setattr */ if (mode != inode->i_mode) { SetModeFlag(orangefs_inode); inode->i_mode = mode; orangefs_flush_inode(inode); } return error; }
/* * initialize the ACLs of a new inode. * This needs to be called from pvfs2_get_custom_inode. * Note that for the root of the PVFS2 file system, * dir will be NULL! For all others dir will be non-NULL * However, inode cannot be NULL! * Returns 0 on success and -ve number on failure. */ int pvfs2_init_acl(struct inode *inode, struct inode *dir) { struct posix_acl *acl = NULL; int error = 0; pvfs2_inode_t *pvfs2_inode = PVFS2_I(inode); if (dir == NULL) dir = inode; ClearModeFlag(pvfs2_inode); if (!S_ISLNK(inode->i_mode)) { if (get_acl_flag(inode) == 1) { acl = pvfs2_get_acl(dir, ACL_TYPE_DEFAULT); if (IS_ERR(acl)) { error = PTR_ERR(acl); gossip_err("pvfs2_get_acl (default) failed with error %d\n", error); return error; } } if (!acl && dir != inode) { int old_mode = inode->i_mode; inode->i_mode &= ~current->fs->umask; gossip_debug(GOSSIP_ACL_DEBUG, "inode->i_mode before %o and " "after %o\n", old_mode, inode->i_mode); if (old_mode != inode->i_mode) SetModeFlag(pvfs2_inode); } } if (get_acl_flag(inode) == 1 && acl) { struct posix_acl *clone; mode_t mode; if (S_ISDIR(inode->i_mode)) { error = pvfs2_set_acl(inode, ACL_TYPE_DEFAULT, acl); if (error) { gossip_err("pvfs2_set_acl (default) directory failed with " "error %d\n", error); ClearModeFlag(pvfs2_inode); goto cleanup; } } clone = posix_acl_clone(acl, GFP_KERNEL); error = -ENOMEM; if (!clone) { gossip_err("posix_acl_clone failed with ENOMEM\n"); ClearModeFlag(pvfs2_inode); goto cleanup; } mode = inode->i_mode; error = posix_acl_create_masq(clone, &mode); if (error >= 0) { gossip_debug(GOSSIP_ACL_DEBUG, "posix_acl_create_masq changed mode " "from %o to %o\n", inode->i_mode, mode); /* * Dont do a needless ->setattr() if mode has not changed */ if (inode->i_mode != mode) SetModeFlag(pvfs2_inode); inode->i_mode = mode; /* * if this is an ACL that cannot be captured by * the mode bits, go for the server! */ if (error > 0) { error = pvfs2_set_acl(inode, ACL_TYPE_ACCESS, clone); gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_set_acl (access) returned %d\n", error); } } posix_acl_release(clone); } /* If mode of the inode was changed, then do a forcible ->setattr */ if (ModeFlag(pvfs2_inode)) pvfs2_flush_inode(inode); cleanup: posix_acl_release(acl); return error; }