diff options
-rw-r--r-- | fs/ext4/ext4.h | 7 | ||||
-rw-r--r-- | fs/ext4/namei.c | 72 |
2 files changed, 53 insertions, 26 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index a971b65bf5ca..6cfe546282dc 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -2129,6 +2129,13 @@ extern int search_dir(struct buffer_head *bh, | |||
2129 | const struct qstr *d_name, | 2129 | const struct qstr *d_name, |
2130 | unsigned int offset, | 2130 | unsigned int offset, |
2131 | struct ext4_dir_entry_2 **res_dir); | 2131 | struct ext4_dir_entry_2 **res_dir); |
2132 | extern int ext4_generic_delete_entry(handle_t *handle, | ||
2133 | struct inode *dir, | ||
2134 | struct ext4_dir_entry_2 *de_del, | ||
2135 | struct buffer_head *bh, | ||
2136 | void *entry_buf, | ||
2137 | int buf_size, | ||
2138 | int csum_size); | ||
2132 | 2139 | ||
2133 | /* resize.c */ | 2140 | /* resize.c */ |
2134 | extern int ext4_group_add(struct super_block *sb, | 2141 | extern int ext4_group_add(struct super_block *sb, |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index b498cafed12b..c10fc2631ff5 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -2109,37 +2109,29 @@ cleanup: | |||
2109 | } | 2109 | } |
2110 | 2110 | ||
2111 | /* | 2111 | /* |
2112 | * ext4_delete_entry deletes a directory entry by merging it with the | 2112 | * ext4_generic_delete_entry deletes a directory entry by merging it |
2113 | * previous entry | 2113 | * with the previous entry |
2114 | */ | 2114 | */ |
2115 | static int ext4_delete_entry(handle_t *handle, | 2115 | int ext4_generic_delete_entry(handle_t *handle, |
2116 | struct inode *dir, | 2116 | struct inode *dir, |
2117 | struct ext4_dir_entry_2 *de_del, | 2117 | struct ext4_dir_entry_2 *de_del, |
2118 | struct buffer_head *bh) | 2118 | struct buffer_head *bh, |
2119 | void *entry_buf, | ||
2120 | int buf_size, | ||
2121 | int csum_size) | ||
2119 | { | 2122 | { |
2120 | struct ext4_dir_entry_2 *de, *pde; | 2123 | struct ext4_dir_entry_2 *de, *pde; |
2121 | unsigned int blocksize = dir->i_sb->s_blocksize; | 2124 | unsigned int blocksize = dir->i_sb->s_blocksize; |
2122 | int csum_size = 0; | 2125 | int i; |
2123 | int i, err; | ||
2124 | |||
2125 | if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, | ||
2126 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
2127 | csum_size = sizeof(struct ext4_dir_entry_tail); | ||
2128 | 2126 | ||
2129 | i = 0; | 2127 | i = 0; |
2130 | pde = NULL; | 2128 | pde = NULL; |
2131 | de = (struct ext4_dir_entry_2 *) bh->b_data; | 2129 | de = (struct ext4_dir_entry_2 *)entry_buf; |
2132 | while (i < bh->b_size - csum_size) { | 2130 | while (i < buf_size - csum_size) { |
2133 | if (ext4_check_dir_entry(dir, NULL, de, bh, | 2131 | if (ext4_check_dir_entry(dir, NULL, de, bh, |
2134 | bh->b_data, bh->b_size, i)) | 2132 | bh->b_data, bh->b_size, i)) |
2135 | return -EIO; | 2133 | return -EIO; |
2136 | if (de == de_del) { | 2134 | if (de == de_del) { |
2137 | BUFFER_TRACE(bh, "get_write_access"); | ||
2138 | err = ext4_journal_get_write_access(handle, bh); | ||
2139 | if (unlikely(err)) { | ||
2140 | ext4_std_error(dir->i_sb, err); | ||
2141 | return err; | ||
2142 | } | ||
2143 | if (pde) | 2135 | if (pde) |
2144 | pde->rec_len = ext4_rec_len_to_disk( | 2136 | pde->rec_len = ext4_rec_len_to_disk( |
2145 | ext4_rec_len_from_disk(pde->rec_len, | 2137 | ext4_rec_len_from_disk(pde->rec_len, |
@@ -2150,12 +2142,6 @@ static int ext4_delete_entry(handle_t *handle, | |||
2150 | else | 2142 | else |
2151 | de->inode = 0; | 2143 | de->inode = 0; |
2152 | dir->i_version++; | 2144 | dir->i_version++; |
2153 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); | ||
2154 | err = ext4_handle_dirty_dirent_node(handle, dir, bh); | ||
2155 | if (unlikely(err)) { | ||
2156 | ext4_std_error(dir->i_sb, err); | ||
2157 | return err; | ||
2158 | } | ||
2159 | return 0; | 2145 | return 0; |
2160 | } | 2146 | } |
2161 | i += ext4_rec_len_from_disk(de->rec_len, blocksize); | 2147 | i += ext4_rec_len_from_disk(de->rec_len, blocksize); |
@@ -2165,6 +2151,40 @@ static int ext4_delete_entry(handle_t *handle, | |||
2165 | return -ENOENT; | 2151 | return -ENOENT; |
2166 | } | 2152 | } |
2167 | 2153 | ||
2154 | static int ext4_delete_entry(handle_t *handle, | ||
2155 | struct inode *dir, | ||
2156 | struct ext4_dir_entry_2 *de_del, | ||
2157 | struct buffer_head *bh) | ||
2158 | { | ||
2159 | int err, csum_size = 0; | ||
2160 | |||
2161 | if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, | ||
2162 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
2163 | csum_size = sizeof(struct ext4_dir_entry_tail); | ||
2164 | |||
2165 | BUFFER_TRACE(bh, "get_write_access"); | ||
2166 | err = ext4_journal_get_write_access(handle, bh); | ||
2167 | if (unlikely(err)) | ||
2168 | goto out; | ||
2169 | |||
2170 | err = ext4_generic_delete_entry(handle, dir, de_del, | ||
2171 | bh, bh->b_data, | ||
2172 | dir->i_sb->s_blocksize, csum_size); | ||
2173 | if (err) | ||
2174 | goto out; | ||
2175 | |||
2176 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); | ||
2177 | err = ext4_handle_dirty_dirent_node(handle, dir, bh); | ||
2178 | if (unlikely(err)) | ||
2179 | goto out; | ||
2180 | |||
2181 | return 0; | ||
2182 | out: | ||
2183 | if (err != -ENOENT) | ||
2184 | ext4_std_error(dir->i_sb, err); | ||
2185 | return err; | ||
2186 | } | ||
2187 | |||
2168 | /* | 2188 | /* |
2169 | * DIR_NLINK feature is set if 1) nlinks > EXT4_LINK_MAX or 2) nlinks == 2, | 2189 | * DIR_NLINK feature is set if 1) nlinks > EXT4_LINK_MAX or 2) nlinks == 2, |
2170 | * since this indicates that nlinks count was previously 1. | 2190 | * since this indicates that nlinks count was previously 1. |