diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/inode.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index dc812ec551f6..90c23eb28829 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2016,6 +2016,57 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) | |||
2016 | } | 2016 | } |
2017 | 2017 | ||
2018 | /* | 2018 | /* |
2019 | * very simple check to peek ahead in the leaf looking for xattrs. If we | ||
2020 | * don't find any xattrs, we know there can't be any acls. | ||
2021 | * | ||
2022 | * slot is the slot the inode is in, objectid is the objectid of the inode | ||
2023 | */ | ||
2024 | static noinline int acls_after_inode_item(struct extent_buffer *leaf, | ||
2025 | int slot, u64 objectid) | ||
2026 | { | ||
2027 | u32 nritems = btrfs_header_nritems(leaf); | ||
2028 | struct btrfs_key found_key; | ||
2029 | int scanned = 0; | ||
2030 | |||
2031 | slot++; | ||
2032 | while (slot < nritems) { | ||
2033 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | ||
2034 | |||
2035 | /* we found a different objectid, there must not be acls */ | ||
2036 | if (found_key.objectid != objectid) | ||
2037 | return 0; | ||
2038 | |||
2039 | /* we found an xattr, assume we've got an acl */ | ||
2040 | if (found_key.type == BTRFS_XATTR_ITEM_KEY) | ||
2041 | return 1; | ||
2042 | |||
2043 | /* | ||
2044 | * we found a key greater than an xattr key, there can't | ||
2045 | * be any acls later on | ||
2046 | */ | ||
2047 | if (found_key.type > BTRFS_XATTR_ITEM_KEY) | ||
2048 | return 0; | ||
2049 | |||
2050 | slot++; | ||
2051 | scanned++; | ||
2052 | |||
2053 | /* | ||
2054 | * it goes inode, inode backrefs, xattrs, extents, | ||
2055 | * so if there are a ton of hard links to an inode there can | ||
2056 | * be a lot of backrefs. Don't waste time searching too hard, | ||
2057 | * this is just an optimization | ||
2058 | */ | ||
2059 | if (scanned >= 8) | ||
2060 | break; | ||
2061 | } | ||
2062 | /* we hit the end of the leaf before we found an xattr or | ||
2063 | * something larger than an xattr. We have to assume the inode | ||
2064 | * has acls | ||
2065 | */ | ||
2066 | return 1; | ||
2067 | } | ||
2068 | |||
2069 | /* | ||
2019 | * read an inode from the btree into the in-memory inode | 2070 | * read an inode from the btree into the in-memory inode |
2020 | */ | 2071 | */ |
2021 | void btrfs_read_locked_inode(struct inode *inode) | 2072 | void btrfs_read_locked_inode(struct inode *inode) |
@@ -2026,6 +2077,7 @@ void btrfs_read_locked_inode(struct inode *inode) | |||
2026 | struct btrfs_timespec *tspec; | 2077 | struct btrfs_timespec *tspec; |
2027 | struct btrfs_root *root = BTRFS_I(inode)->root; | 2078 | struct btrfs_root *root = BTRFS_I(inode)->root; |
2028 | struct btrfs_key location; | 2079 | struct btrfs_key location; |
2080 | int maybe_acls; | ||
2029 | u64 alloc_group_block; | 2081 | u64 alloc_group_block; |
2030 | u32 rdev; | 2082 | u32 rdev; |
2031 | int ret; | 2083 | int ret; |
@@ -2072,6 +2124,16 @@ void btrfs_read_locked_inode(struct inode *inode) | |||
2072 | 2124 | ||
2073 | alloc_group_block = btrfs_inode_block_group(leaf, inode_item); | 2125 | alloc_group_block = btrfs_inode_block_group(leaf, inode_item); |
2074 | 2126 | ||
2127 | /* | ||
2128 | * try to precache a NULL acl entry for files that don't have | ||
2129 | * any xattrs or acls | ||
2130 | */ | ||
2131 | maybe_acls = acls_after_inode_item(leaf, path->slots[0], inode->i_ino); | ||
2132 | if (!maybe_acls) { | ||
2133 | BTRFS_I(inode)->i_acl = NULL; | ||
2134 | BTRFS_I(inode)->i_default_acl = NULL; | ||
2135 | } | ||
2136 | |||
2075 | BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0, | 2137 | BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0, |
2076 | alloc_group_block, 0); | 2138 | alloc_group_block, 0); |
2077 | btrfs_free_path(path); | 2139 | btrfs_free_path(path); |