|
@@ -2109,37 +2109,29 @@ cleanup:
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * ext4_delete_entry deletes a directory entry by merging it with the
|
|
|
- * previous entry
|
|
|
+ * ext4_generic_delete_entry deletes a directory entry by merging it
|
|
|
+ * with the previous entry
|
|
|
*/
|
|
|
-static int ext4_delete_entry(handle_t *handle,
|
|
|
- struct inode *dir,
|
|
|
- struct ext4_dir_entry_2 *de_del,
|
|
|
- struct buffer_head *bh)
|
|
|
+int ext4_generic_delete_entry(handle_t *handle,
|
|
|
+ struct inode *dir,
|
|
|
+ struct ext4_dir_entry_2 *de_del,
|
|
|
+ struct buffer_head *bh,
|
|
|
+ void *entry_buf,
|
|
|
+ int buf_size,
|
|
|
+ int csum_size)
|
|
|
{
|
|
|
struct ext4_dir_entry_2 *de, *pde;
|
|
|
unsigned int blocksize = dir->i_sb->s_blocksize;
|
|
|
- int csum_size = 0;
|
|
|
- int i, err;
|
|
|
-
|
|
|
- if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
|
|
|
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
|
|
|
- csum_size = sizeof(struct ext4_dir_entry_tail);
|
|
|
+ int i;
|
|
|
|
|
|
i = 0;
|
|
|
pde = NULL;
|
|
|
- de = (struct ext4_dir_entry_2 *) bh->b_data;
|
|
|
- while (i < bh->b_size - csum_size) {
|
|
|
+ de = (struct ext4_dir_entry_2 *)entry_buf;
|
|
|
+ while (i < buf_size - csum_size) {
|
|
|
if (ext4_check_dir_entry(dir, NULL, de, bh,
|
|
|
bh->b_data, bh->b_size, i))
|
|
|
return -EIO;
|
|
|
if (de == de_del) {
|
|
|
- BUFFER_TRACE(bh, "get_write_access");
|
|
|
- err = ext4_journal_get_write_access(handle, bh);
|
|
|
- if (unlikely(err)) {
|
|
|
- ext4_std_error(dir->i_sb, err);
|
|
|
- return err;
|
|
|
- }
|
|
|
if (pde)
|
|
|
pde->rec_len = ext4_rec_len_to_disk(
|
|
|
ext4_rec_len_from_disk(pde->rec_len,
|
|
@@ -2150,12 +2142,6 @@ static int ext4_delete_entry(handle_t *handle,
|
|
|
else
|
|
|
de->inode = 0;
|
|
|
dir->i_version++;
|
|
|
- BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
|
|
|
- err = ext4_handle_dirty_dirent_node(handle, dir, bh);
|
|
|
- if (unlikely(err)) {
|
|
|
- ext4_std_error(dir->i_sb, err);
|
|
|
- return err;
|
|
|
- }
|
|
|
return 0;
|
|
|
}
|
|
|
i += ext4_rec_len_from_disk(de->rec_len, blocksize);
|
|
@@ -2165,6 +2151,40 @@ static int ext4_delete_entry(handle_t *handle,
|
|
|
return -ENOENT;
|
|
|
}
|
|
|
|
|
|
+static int ext4_delete_entry(handle_t *handle,
|
|
|
+ struct inode *dir,
|
|
|
+ struct ext4_dir_entry_2 *de_del,
|
|
|
+ struct buffer_head *bh)
|
|
|
+{
|
|
|
+ int err, csum_size = 0;
|
|
|
+
|
|
|
+ if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
|
|
|
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
|
|
|
+ csum_size = sizeof(struct ext4_dir_entry_tail);
|
|
|
+
|
|
|
+ BUFFER_TRACE(bh, "get_write_access");
|
|
|
+ err = ext4_journal_get_write_access(handle, bh);
|
|
|
+ if (unlikely(err))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ err = ext4_generic_delete_entry(handle, dir, de_del,
|
|
|
+ bh, bh->b_data,
|
|
|
+ dir->i_sb->s_blocksize, csum_size);
|
|
|
+ if (err)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
|
|
|
+ err = ext4_handle_dirty_dirent_node(handle, dir, bh);
|
|
|
+ if (unlikely(err))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+out:
|
|
|
+ if (err != -ENOENT)
|
|
|
+ ext4_std_error(dir->i_sb, err);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* DIR_NLINK feature is set if 1) nlinks > EXT4_LINK_MAX or 2) nlinks == 2,
|
|
|
* since this indicates that nlinks count was previously 1.
|