diff options
author | Tahsin Erdogan <tahsin@google.com> | 2017-06-22 10:26:31 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2017-06-22 10:26:31 -0400 |
commit | 0421a189bc8cdefa18a34aee962ac0558679b944 (patch) | |
tree | 3e701dfeeca3c987d1c815e8fa1461ea979bf8b8 | |
parent | c1a5d5f6ab21eb7e6ff8cb99489d9001cf2a2850 (diff) |
ext4: modify ext4_xattr_ino_array to hold struct inode *
Tracking struct inode * rather than the inode number eliminates the
repeated ext4_xattr_inode_iget() call later. The second call cannot
fail in practice but still requires explanation when it wants to ignore
the return value. Avoid the trouble and make things simple.
Signed-off-by: Tahsin Erdogan <tahsin@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r-- | fs/ext4/ext4.h | 6 | ||||
-rw-r--r-- | fs/ext4/inode.c | 8 | ||||
-rw-r--r-- | fs/ext4/xattr.c | 93 | ||||
-rw-r--r-- | fs/ext4/xattr.h | 5 |
4 files changed, 53 insertions, 59 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 9b6a10e1bf18..144a2863ba27 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -2243,9 +2243,9 @@ struct mmpd_data { | |||
2243 | # define ATTRIB_NORET __attribute__((noreturn)) | 2243 | # define ATTRIB_NORET __attribute__((noreturn)) |
2244 | # define NORET_AND noreturn, | 2244 | # define NORET_AND noreturn, |
2245 | 2245 | ||
2246 | struct ext4_xattr_ino_array { | 2246 | struct ext4_xattr_inode_array { |
2247 | unsigned int xia_count; /* # of used item in the array */ | 2247 | unsigned int count; /* # of used items in the array */ |
2248 | unsigned int xia_inodes[0]; | 2248 | struct inode *inodes[0]; |
2249 | }; | 2249 | }; |
2250 | /* bitmap.c */ | 2250 | /* bitmap.c */ |
2251 | extern unsigned int ext4_count_free(char *bitmap, unsigned numchars); | 2251 | extern unsigned int ext4_count_free(char *bitmap, unsigned numchars); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index fda70fedf56d..1b2a68c5ea42 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -188,7 +188,7 @@ void ext4_evict_inode(struct inode *inode) | |||
188 | handle_t *handle; | 188 | handle_t *handle; |
189 | int err; | 189 | int err; |
190 | int extra_credits = 3; | 190 | int extra_credits = 3; |
191 | struct ext4_xattr_ino_array *lea_ino_array = NULL; | 191 | struct ext4_xattr_inode_array *ea_inode_array = NULL; |
192 | 192 | ||
193 | trace_ext4_evict_inode(inode); | 193 | trace_ext4_evict_inode(inode); |
194 | 194 | ||
@@ -257,7 +257,7 @@ void ext4_evict_inode(struct inode *inode) | |||
257 | /* | 257 | /* |
258 | * Delete xattr inode before deleting the main inode. | 258 | * Delete xattr inode before deleting the main inode. |
259 | */ | 259 | */ |
260 | err = ext4_xattr_delete_inode(handle, inode, &lea_ino_array); | 260 | err = ext4_xattr_delete_inode(handle, inode, &ea_inode_array); |
261 | if (err) { | 261 | if (err) { |
262 | ext4_warning(inode->i_sb, | 262 | ext4_warning(inode->i_sb, |
263 | "couldn't delete inode's xattr (err %d)", err); | 263 | "couldn't delete inode's xattr (err %d)", err); |
@@ -345,9 +345,7 @@ void ext4_evict_inode(struct inode *inode) | |||
345 | 345 | ||
346 | ext4_journal_stop(handle); | 346 | ext4_journal_stop(handle); |
347 | sb_end_intwrite(inode->i_sb); | 347 | sb_end_intwrite(inode->i_sb); |
348 | 348 | ext4_xattr_inode_array_free(ea_inode_array); | |
349 | if (lea_ino_array != NULL) | ||
350 | ext4_xattr_inode_array_free(inode, lea_ino_array); | ||
351 | return; | 349 | return; |
352 | no_delete: | 350 | no_delete: |
353 | ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ | 351 | ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ |
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 43a2c075aa1f..fed54001c9e6 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -1940,44 +1940,44 @@ cleanup: | |||
1940 | 1940 | ||
1941 | #define EIA_INCR 16 /* must be 2^n */ | 1941 | #define EIA_INCR 16 /* must be 2^n */ |
1942 | #define EIA_MASK (EIA_INCR - 1) | 1942 | #define EIA_MASK (EIA_INCR - 1) |
1943 | /* Add the large xattr @ino into @lea_ino_array for later deletion. | 1943 | /* Add the large xattr @inode into @ea_inode_array for later deletion. |
1944 | * If @lea_ino_array is new or full it will be grown and the old | 1944 | * If @ea_inode_array is new or full it will be grown and the old |
1945 | * contents copied over. | 1945 | * contents copied over. |
1946 | */ | 1946 | */ |
1947 | static int | 1947 | static int |
1948 | ext4_expand_ino_array(struct ext4_xattr_ino_array **lea_ino_array, __u32 ino) | 1948 | ext4_expand_inode_array(struct ext4_xattr_inode_array **ea_inode_array, |
1949 | struct inode *inode) | ||
1949 | { | 1950 | { |
1950 | if (*lea_ino_array == NULL) { | 1951 | if (*ea_inode_array == NULL) { |
1951 | /* | 1952 | /* |
1952 | * Start with 15 inodes, so it fits into a power-of-two size. | 1953 | * Start with 15 inodes, so it fits into a power-of-two size. |
1953 | * If *lea_ino_array is NULL, this is essentially offsetof() | 1954 | * If *ea_inode_array is NULL, this is essentially offsetof() |
1954 | */ | 1955 | */ |
1955 | (*lea_ino_array) = | 1956 | (*ea_inode_array) = |
1956 | kmalloc(offsetof(struct ext4_xattr_ino_array, | 1957 | kmalloc(offsetof(struct ext4_xattr_inode_array, |
1957 | xia_inodes[EIA_MASK]), | 1958 | inodes[EIA_MASK]), |
1958 | GFP_NOFS); | 1959 | GFP_NOFS); |
1959 | if (*lea_ino_array == NULL) | 1960 | if (*ea_inode_array == NULL) |
1960 | return -ENOMEM; | 1961 | return -ENOMEM; |
1961 | (*lea_ino_array)->xia_count = 0; | 1962 | (*ea_inode_array)->count = 0; |
1962 | } else if (((*lea_ino_array)->xia_count & EIA_MASK) == EIA_MASK) { | 1963 | } else if (((*ea_inode_array)->count & EIA_MASK) == EIA_MASK) { |
1963 | /* expand the array once all 15 + n * 16 slots are full */ | 1964 | /* expand the array once all 15 + n * 16 slots are full */ |
1964 | struct ext4_xattr_ino_array *new_array = NULL; | 1965 | struct ext4_xattr_inode_array *new_array = NULL; |
1965 | int count = (*lea_ino_array)->xia_count; | 1966 | int count = (*ea_inode_array)->count; |
1966 | 1967 | ||
1967 | /* if new_array is NULL, this is essentially offsetof() */ | 1968 | /* if new_array is NULL, this is essentially offsetof() */ |
1968 | new_array = kmalloc( | 1969 | new_array = kmalloc( |
1969 | offsetof(struct ext4_xattr_ino_array, | 1970 | offsetof(struct ext4_xattr_inode_array, |
1970 | xia_inodes[count + EIA_INCR]), | 1971 | inodes[count + EIA_INCR]), |
1971 | GFP_NOFS); | 1972 | GFP_NOFS); |
1972 | if (new_array == NULL) | 1973 | if (new_array == NULL) |
1973 | return -ENOMEM; | 1974 | return -ENOMEM; |
1974 | memcpy(new_array, *lea_ino_array, | 1975 | memcpy(new_array, *ea_inode_array, |
1975 | offsetof(struct ext4_xattr_ino_array, | 1976 | offsetof(struct ext4_xattr_inode_array, inodes[count])); |
1976 | xia_inodes[count])); | 1977 | kfree(*ea_inode_array); |
1977 | kfree(*lea_ino_array); | 1978 | *ea_inode_array = new_array; |
1978 | *lea_ino_array = new_array; | ||
1979 | } | 1979 | } |
1980 | (*lea_ino_array)->xia_inodes[(*lea_ino_array)->xia_count++] = ino; | 1980 | (*ea_inode_array)->inodes[(*ea_inode_array)->count++] = inode; |
1981 | return 0; | 1981 | return 0; |
1982 | } | 1982 | } |
1983 | 1983 | ||
@@ -1985,16 +1985,16 @@ ext4_expand_ino_array(struct ext4_xattr_ino_array **lea_ino_array, __u32 ino) | |||
1985 | * Add xattr inode to orphan list | 1985 | * Add xattr inode to orphan list |
1986 | */ | 1986 | */ |
1987 | static int | 1987 | static int |
1988 | ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode, | 1988 | ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode, int credits, |
1989 | int credits, struct ext4_xattr_ino_array *lea_ino_array) | 1989 | struct ext4_xattr_inode_array *ea_inode_array) |
1990 | { | 1990 | { |
1991 | struct inode *ea_inode; | ||
1992 | int idx = 0, error = 0; | 1991 | int idx = 0, error = 0; |
1992 | struct inode *ea_inode; | ||
1993 | 1993 | ||
1994 | if (lea_ino_array == NULL) | 1994 | if (ea_inode_array == NULL) |
1995 | return 0; | 1995 | return 0; |
1996 | 1996 | ||
1997 | for (; idx < lea_ino_array->xia_count; ++idx) { | 1997 | for (; idx < ea_inode_array->count; ++idx) { |
1998 | if (!ext4_handle_has_enough_credits(handle, credits)) { | 1998 | if (!ext4_handle_has_enough_credits(handle, credits)) { |
1999 | error = ext4_journal_extend(handle, credits); | 1999 | error = ext4_journal_extend(handle, credits); |
2000 | if (error > 0) | 2000 | if (error > 0) |
@@ -2007,10 +2007,7 @@ ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode, | |||
2007 | return error; | 2007 | return error; |
2008 | } | 2008 | } |
2009 | } | 2009 | } |
2010 | error = ext4_xattr_inode_iget(inode, | 2010 | ea_inode = ea_inode_array->inodes[idx]; |
2011 | lea_ino_array->xia_inodes[idx], &ea_inode); | ||
2012 | if (error) | ||
2013 | continue; | ||
2014 | inode_lock(ea_inode); | 2011 | inode_lock(ea_inode); |
2015 | ext4_orphan_add(handle, ea_inode); | 2012 | ext4_orphan_add(handle, ea_inode); |
2016 | inode_unlock(ea_inode); | 2013 | inode_unlock(ea_inode); |
@@ -2032,13 +2029,14 @@ ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode, | |||
2032 | */ | 2029 | */ |
2033 | int | 2030 | int |
2034 | ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, | 2031 | ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, |
2035 | struct ext4_xattr_ino_array **lea_ino_array) | 2032 | struct ext4_xattr_inode_array **ea_inode_array) |
2036 | { | 2033 | { |
2037 | struct buffer_head *bh = NULL; | 2034 | struct buffer_head *bh = NULL; |
2038 | struct ext4_xattr_ibody_header *header; | 2035 | struct ext4_xattr_ibody_header *header; |
2039 | struct ext4_inode *raw_inode; | 2036 | struct ext4_inode *raw_inode; |
2040 | struct ext4_iloc iloc; | 2037 | struct ext4_iloc iloc; |
2041 | struct ext4_xattr_entry *entry; | 2038 | struct ext4_xattr_entry *entry; |
2039 | struct inode *ea_inode; | ||
2042 | unsigned int ea_ino; | 2040 | unsigned int ea_ino; |
2043 | int credits = 3, error = 0; | 2041 | int credits = 3, error = 0; |
2044 | 2042 | ||
@@ -2055,8 +2053,12 @@ ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, | |||
2055 | if (!entry->e_value_inum) | 2053 | if (!entry->e_value_inum) |
2056 | continue; | 2054 | continue; |
2057 | ea_ino = le32_to_cpu(entry->e_value_inum); | 2055 | ea_ino = le32_to_cpu(entry->e_value_inum); |
2058 | error = ext4_expand_ino_array(lea_ino_array, ea_ino); | 2056 | error = ext4_xattr_inode_iget(inode, ea_ino, &ea_inode); |
2057 | if (error) | ||
2058 | continue; | ||
2059 | error = ext4_expand_inode_array(ea_inode_array, ea_inode); | ||
2059 | if (error) { | 2060 | if (error) { |
2061 | iput(ea_inode); | ||
2060 | brelse(iloc.bh); | 2062 | brelse(iloc.bh); |
2061 | goto cleanup; | 2063 | goto cleanup; |
2062 | } | 2064 | } |
@@ -2068,7 +2070,7 @@ delete_external_ea: | |||
2068 | if (!EXT4_I(inode)->i_file_acl) { | 2070 | if (!EXT4_I(inode)->i_file_acl) { |
2069 | /* add xattr inode to orphan list */ | 2071 | /* add xattr inode to orphan list */ |
2070 | error = ext4_xattr_inode_orphan_add(handle, inode, credits, | 2072 | error = ext4_xattr_inode_orphan_add(handle, inode, credits, |
2071 | *lea_ino_array); | 2073 | *ea_inode_array); |
2072 | goto cleanup; | 2074 | goto cleanup; |
2073 | } | 2075 | } |
2074 | bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl); | 2076 | bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl); |
@@ -2091,7 +2093,10 @@ delete_external_ea: | |||
2091 | if (!entry->e_value_inum) | 2093 | if (!entry->e_value_inum) |
2092 | continue; | 2094 | continue; |
2093 | ea_ino = le32_to_cpu(entry->e_value_inum); | 2095 | ea_ino = le32_to_cpu(entry->e_value_inum); |
2094 | error = ext4_expand_ino_array(lea_ino_array, ea_ino); | 2096 | error = ext4_xattr_inode_iget(inode, ea_ino, &ea_inode); |
2097 | if (error) | ||
2098 | continue; | ||
2099 | error = ext4_expand_inode_array(ea_inode_array, ea_inode); | ||
2095 | if (error) | 2100 | if (error) |
2096 | goto cleanup; | 2101 | goto cleanup; |
2097 | entry->e_value_inum = 0; | 2102 | entry->e_value_inum = 0; |
@@ -2099,7 +2104,7 @@ delete_external_ea: | |||
2099 | 2104 | ||
2100 | /* add xattr inode to orphan list */ | 2105 | /* add xattr inode to orphan list */ |
2101 | error = ext4_xattr_inode_orphan_add(handle, inode, credits, | 2106 | error = ext4_xattr_inode_orphan_add(handle, inode, credits, |
2102 | *lea_ino_array); | 2107 | *ea_inode_array); |
2103 | if (error) | 2108 | if (error) |
2104 | goto cleanup; | 2109 | goto cleanup; |
2105 | 2110 | ||
@@ -2126,28 +2131,20 @@ cleanup: | |||
2126 | return error; | 2131 | return error; |
2127 | } | 2132 | } |
2128 | 2133 | ||
2129 | void | 2134 | void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *ea_inode_array) |
2130 | ext4_xattr_inode_array_free(struct inode *inode, | ||
2131 | struct ext4_xattr_ino_array *lea_ino_array) | ||
2132 | { | 2135 | { |
2133 | struct inode *ea_inode; | 2136 | struct inode *ea_inode; |
2134 | int idx = 0; | 2137 | int idx = 0; |
2135 | int err; | ||
2136 | 2138 | ||
2137 | if (lea_ino_array == NULL) | 2139 | if (ea_inode_array == NULL) |
2138 | return; | 2140 | return; |
2139 | 2141 | ||
2140 | for (; idx < lea_ino_array->xia_count; ++idx) { | 2142 | for (; idx < ea_inode_array->count; ++idx) { |
2141 | err = ext4_xattr_inode_iget(inode, | 2143 | ea_inode = ea_inode_array->inodes[idx]; |
2142 | lea_ino_array->xia_inodes[idx], &ea_inode); | ||
2143 | if (err) | ||
2144 | continue; | ||
2145 | /* for inode's i_count get from ext4_xattr_delete_inode */ | ||
2146 | iput(ea_inode); | ||
2147 | clear_nlink(ea_inode); | 2144 | clear_nlink(ea_inode); |
2148 | iput(ea_inode); | 2145 | iput(ea_inode); |
2149 | } | 2146 | } |
2150 | kfree(lea_ino_array); | 2147 | kfree(ea_inode_array); |
2151 | } | 2148 | } |
2152 | 2149 | ||
2153 | /* | 2150 | /* |
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h index e82c5fe36a26..323eba54f72f 100644 --- a/fs/ext4/xattr.h +++ b/fs/ext4/xattr.h | |||
@@ -164,9 +164,8 @@ extern int ext4_xattr_set_credits(struct inode *inode, size_t value_len); | |||
164 | 164 | ||
165 | extern int ext4_xattr_inode_unlink(struct inode *inode, unsigned long ea_ino); | 165 | extern int ext4_xattr_inode_unlink(struct inode *inode, unsigned long ea_ino); |
166 | extern int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, | 166 | extern int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, |
167 | struct ext4_xattr_ino_array **array); | 167 | struct ext4_xattr_inode_array **array); |
168 | extern void ext4_xattr_inode_array_free(struct inode *inode, | 168 | extern void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *array); |
169 | struct ext4_xattr_ino_array *array); | ||
170 | 169 | ||
171 | extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, | 170 | extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, |
172 | struct ext4_inode *raw_inode, handle_t *handle); | 171 | struct ext4_inode *raw_inode, handle_t *handle); |