diff options
Diffstat (limited to 'fs/btrfs/acl.c')
| -rw-r--r-- | fs/btrfs/acl.c | 18 | 
1 files changed, 13 insertions, 5 deletions
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 7fdd184a528..cbba000dccb 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -60,15 +60,20 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)  		return ERR_PTR(-EINVAL);  	} +	/* Handle the cached NULL acl case without locking */ +	acl = ACCESS_ONCE(*p_acl); +	if (!acl) +		return acl; +  	spin_lock(&inode->i_lock); -	if (*p_acl != BTRFS_ACL_NOT_CACHED) -		acl = posix_acl_dup(*p_acl); +	acl = *p_acl; +	if (acl != BTRFS_ACL_NOT_CACHED) +		acl = posix_acl_dup(acl);  	spin_unlock(&inode->i_lock); -	if (acl) +	if (acl != BTRFS_ACL_NOT_CACHED)  		return acl; -  	size = __btrfs_getxattr(inode, name, "", 0);  	if (size > 0) {  		value = kzalloc(size, GFP_NOFS); @@ -80,9 +85,12 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)  			btrfs_update_cached_acl(inode, p_acl, acl);  		}  		kfree(value); -	} else if (size == -ENOENT) { +	} else if (size == -ENOENT || size == -ENODATA || size == 0) { +		/* FIXME, who returns -ENOENT?  I think nobody */  		acl = NULL;  		btrfs_update_cached_acl(inode, p_acl, acl); +	} else { +		acl = ERR_PTR(-EIO);  	}  	return acl;  | 
