aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTahsin Erdogan <tahsin@google.com>2017-06-22 10:26:31 -0400
committerTheodore Ts'o <tytso@mit.edu>2017-06-22 10:26:31 -0400
commit0421a189bc8cdefa18a34aee962ac0558679b944 (patch)
tree3e701dfeeca3c987d1c815e8fa1461ea979bf8b8
parentc1a5d5f6ab21eb7e6ff8cb99489d9001cf2a2850 (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.h6
-rw-r--r--fs/ext4/inode.c8
-rw-r--r--fs/ext4/xattr.c93
-rw-r--r--fs/ext4/xattr.h5
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
2246struct ext4_xattr_ino_array { 2246struct 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 */
2251extern unsigned int ext4_count_free(char *bitmap, unsigned numchars); 2251extern 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;
352no_delete: 350no_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 */
1947static int 1947static int
1948ext4_expand_ino_array(struct ext4_xattr_ino_array **lea_ino_array, __u32 ino) 1948ext4_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 */
1987static int 1987static int
1988ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode, 1988ext4_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 */
2033int 2030int
2034ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, 2031ext4_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
2129void 2134void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *ea_inode_array)
2130ext4_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
165extern int ext4_xattr_inode_unlink(struct inode *inode, unsigned long ea_ino); 165extern int ext4_xattr_inode_unlink(struct inode *inode, unsigned long ea_ino);
166extern int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, 166extern 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);
168extern void ext4_xattr_inode_array_free(struct inode *inode, 168extern void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *array);
169 struct ext4_xattr_ino_array *array);
170 169
171extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, 170extern 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);