Loading fs/namei.c +6 −11 Original line number Diff line number Diff line Loading @@ -179,19 +179,14 @@ static int check_acl(struct inode *inode, int mask) #ifdef CONFIG_FS_POSIX_ACL struct posix_acl *acl; /* * Under RCU walk, we cannot even do a "get_cached_acl()", * because that involves locking and getting a refcount on * a cached ACL. * * So the only case we handle during RCU walking is the * case of a cached "no ACL at all", which needs no locks * or refcounts. */ if (mask & MAY_NOT_BLOCK) { if (negative_cached_acl(inode, ACL_TYPE_ACCESS)) acl = get_cached_acl_rcu(inode, ACL_TYPE_ACCESS); if (!acl) return -EAGAIN; /* no ->get_acl() calls in RCU mode... */ if (acl == ACL_NOT_CACHED) return -ECHILD; return posix_acl_permission(inode, acl, mask); } acl = get_cached_acl(inode, ACL_TYPE_ACCESS); Loading include/linux/posix_acl.h +9 −9 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ #define __LINUX_POSIX_ACL_H #include <linux/slab.h> #include <linux/rcupdate.h> #define ACL_UNDEFINED_ID (-1) Loading Loading @@ -38,7 +39,10 @@ struct posix_acl_entry { }; struct posix_acl { union { atomic_t a_refcount; struct rcu_head a_rcu; }; unsigned int a_count; struct posix_acl_entry a_entries[0]; }; Loading @@ -65,7 +69,7 @@ static inline void posix_acl_release(struct posix_acl *acl) { if (acl && atomic_dec_and_test(&acl->a_refcount)) kfree(acl); kfree_rcu(acl, a_rcu); } Loading Loading @@ -110,13 +114,9 @@ static inline struct posix_acl *get_cached_acl(struct inode *inode, int type) return acl; } static inline int negative_cached_acl(struct inode *inode, int type) static inline struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type) { struct posix_acl **p = acl_by_type(inode, type); struct posix_acl *acl = ACCESS_ONCE(*p); if (acl) return 0; return 1; return rcu_dereference(*acl_by_type(inode, type)); } static inline void set_cached_acl(struct inode *inode, Loading @@ -127,7 +127,7 @@ static inline void set_cached_acl(struct inode *inode, struct posix_acl *old; spin_lock(&inode->i_lock); old = *p; *p = posix_dup_acl(acl); rcu_assign_pointer(*p, posix_acl_dup(acl)); spin_unlock(&inode->i_lock); if (old != ACL_NOT_CACHED) posix_acl_release(old); Loading Loading
fs/namei.c +6 −11 Original line number Diff line number Diff line Loading @@ -179,19 +179,14 @@ static int check_acl(struct inode *inode, int mask) #ifdef CONFIG_FS_POSIX_ACL struct posix_acl *acl; /* * Under RCU walk, we cannot even do a "get_cached_acl()", * because that involves locking and getting a refcount on * a cached ACL. * * So the only case we handle during RCU walking is the * case of a cached "no ACL at all", which needs no locks * or refcounts. */ if (mask & MAY_NOT_BLOCK) { if (negative_cached_acl(inode, ACL_TYPE_ACCESS)) acl = get_cached_acl_rcu(inode, ACL_TYPE_ACCESS); if (!acl) return -EAGAIN; /* no ->get_acl() calls in RCU mode... */ if (acl == ACL_NOT_CACHED) return -ECHILD; return posix_acl_permission(inode, acl, mask); } acl = get_cached_acl(inode, ACL_TYPE_ACCESS); Loading
include/linux/posix_acl.h +9 −9 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ #define __LINUX_POSIX_ACL_H #include <linux/slab.h> #include <linux/rcupdate.h> #define ACL_UNDEFINED_ID (-1) Loading Loading @@ -38,7 +39,10 @@ struct posix_acl_entry { }; struct posix_acl { union { atomic_t a_refcount; struct rcu_head a_rcu; }; unsigned int a_count; struct posix_acl_entry a_entries[0]; }; Loading @@ -65,7 +69,7 @@ static inline void posix_acl_release(struct posix_acl *acl) { if (acl && atomic_dec_and_test(&acl->a_refcount)) kfree(acl); kfree_rcu(acl, a_rcu); } Loading Loading @@ -110,13 +114,9 @@ static inline struct posix_acl *get_cached_acl(struct inode *inode, int type) return acl; } static inline int negative_cached_acl(struct inode *inode, int type) static inline struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type) { struct posix_acl **p = acl_by_type(inode, type); struct posix_acl *acl = ACCESS_ONCE(*p); if (acl) return 0; return 1; return rcu_dereference(*acl_by_type(inode, type)); } static inline void set_cached_acl(struct inode *inode, Loading @@ -127,7 +127,7 @@ static inline void set_cached_acl(struct inode *inode, struct posix_acl *old; spin_lock(&inode->i_lock); old = *p; *p = posix_dup_acl(acl); rcu_assign_pointer(*p, posix_acl_dup(acl)); spin_unlock(&inode->i_lock); if (old != ACL_NOT_CACHED) posix_acl_release(old); Loading