udf: Fix file counting in LVID
authorJan Kara <jack@suse.cz>
Wed, 25 Jan 2023 18:31:38 +0000 (19:31 +0100)
committerJan Kara <jack@suse.cz>
Thu, 26 Jan 2023 15:46:37 +0000 (16:46 +0100)
numFiles entry in LVID should actually contain number for non-dir file
entries, not the number of non-dir inodes. Move the counting from inode
allocation / deallocation into directory entry handling functions.

Signed-off-by: Jan Kara <jack@suse.cz>
fs/udf/ialloc.c
fs/udf/namei.c

index b5d611cee749ca422b63dbf1db6fd15c629df3c8..ffd9ccbce0d0649ec6ecacdfad3b9ee871c5684e 100644 (file)
 
 void udf_free_inode(struct inode *inode)
 {
-       struct super_block *sb = inode->i_sb;
-       struct udf_sb_info *sbi = UDF_SB(sb);
-       struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb);
-
-       if (lvidiu) {
-               mutex_lock(&sbi->s_alloc_mutex);
-               if (S_ISDIR(inode->i_mode))
-                       le32_add_cpu(&lvidiu->numDirs, -1);
-               else
-                       le32_add_cpu(&lvidiu->numFiles, -1);
-               udf_updated_lvid(sb);
-               mutex_unlock(&sbi->s_alloc_mutex);
-       }
-
-       udf_free_blocks(sb, NULL, &UDF_I(inode)->i_location, 0, 1);
+       udf_free_blocks(inode->i_sb, NULL, &UDF_I(inode)->i_location, 0, 1);
 }
 
 struct inode *udf_new_inode(struct inode *dir, umode_t mode)
@@ -54,7 +40,6 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode)
        uint32_t start = UDF_I(dir)->i_location.logicalBlockNum;
        struct udf_inode_info *iinfo;
        struct udf_inode_info *dinfo = UDF_I(dir);
-       struct logicalVolIntegrityDescImpUse *lvidiu;
        int err;
 
        inode = new_inode(sb);
@@ -92,18 +77,8 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode)
                return ERR_PTR(err);
        }
 
-       lvidiu = udf_sb_lvidiu(sb);
-       if (lvidiu) {
-               iinfo->i_unique = lvid_get_unique_id(sb);
-               inode->i_generation = iinfo->i_unique;
-               mutex_lock(&sbi->s_alloc_mutex);
-               if (S_ISDIR(mode))
-                       le32_add_cpu(&lvidiu->numDirs, 1);
-               else
-                       le32_add_cpu(&lvidiu->numFiles, 1);
-               udf_updated_lvid(sb);
-               mutex_unlock(&sbi->s_alloc_mutex);
-       }
+       iinfo->i_unique = lvid_get_unique_id(sb);
+       inode->i_generation = iinfo->i_unique;
 
        inode_init_owner(&init_user_ns, inode, dir, mode);
        if (UDF_QUERY_FLAG(sb, UDF_FLAG_UID_SET))
index d68a0c2b58b7e25eb2e7518ba0283262a82dcd1c..55b0d78a581fcd306b8244cb2395f5cfb788a313 100644 (file)
@@ -336,6 +336,21 @@ static void udf_fiiter_delete_entry(struct udf_fileident_iter *iter)
        udf_fiiter_write_fi(iter, NULL);
 }
 
+static void udf_add_fid_counter(struct super_block *sb, bool dir, int val)
+{
+       struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb);
+
+       if (!lvidiu)
+               return;
+       mutex_lock(&UDF_SB(sb)->s_alloc_mutex);
+       if (dir)
+               le32_add_cpu(&lvidiu->numDirs, val);
+       else
+               le32_add_cpu(&lvidiu->numFiles, val);
+       udf_updated_lvid(sb);
+       mutex_unlock(&UDF_SB(sb)->s_alloc_mutex);
+}
+
 static int udf_add_nondir(struct dentry *dentry, struct inode *inode)
 {
        struct udf_inode_info *iinfo = UDF_I(inode);
@@ -357,6 +372,7 @@ static int udf_add_nondir(struct dentry *dentry, struct inode *inode)
        dir->i_ctime = dir->i_mtime = current_time(dir);
        mark_inode_dirty(dir);
        udf_fiiter_release(&iter);
+       udf_add_fid_counter(dir->i_sb, false, 1);
        d_instantiate_new(dentry, inode);
 
        return 0;
@@ -457,6 +473,7 @@ static int udf_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
        iter.fi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
        udf_fiiter_write_fi(&iter, NULL);
        udf_fiiter_release(&iter);
+       udf_add_fid_counter(dir->i_sb, true, 1);
        inc_nlink(dir);
        dir->i_ctime = dir->i_mtime = current_time(dir);
        mark_inode_dirty(dir);
@@ -509,6 +526,7 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry)
        clear_nlink(inode);
        inode->i_size = 0;
        inode_dec_link_count(dir);
+       udf_add_fid_counter(dir->i_sb, true, -1);
        inode->i_ctime = dir->i_ctime = dir->i_mtime =
                                                current_time(inode);
        mark_inode_dirty(dir);
@@ -544,6 +562,7 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry)
        dir->i_ctime = dir->i_mtime = current_time(dir);
        mark_inode_dirty(dir);
        inode_dec_link_count(inode);
+       udf_add_fid_counter(dir->i_sb, false, -1);
        inode->i_ctime = dir->i_ctime;
        ret = 0;
 end_unlink:
@@ -730,6 +749,7 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir,
        udf_fiiter_release(&iter);
 
        inc_nlink(inode);
+       udf_add_fid_counter(dir->i_sb, false, 1);
        inode->i_ctime = current_time(inode);
        mark_inode_dirty(inode);
        dir->i_ctime = dir->i_mtime = current_time(dir);
@@ -854,6 +874,8 @@ static int udf_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
        if (new_inode) {
                new_inode->i_ctime = current_time(new_inode);
                inode_dec_link_count(new_inode);
+               udf_add_fid_counter(old_dir->i_sb, S_ISDIR(new_inode->i_mode),
+                                   -1);
        }
        old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
        new_dir->i_ctime = new_dir->i_mtime = current_time(new_dir);