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. |
