Merge tag 'ubifs-for-linus-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-block.git] / fs / ubifs / dir.c
index 1e92c1730c16540cf804fa74299a7b1228eda45e..1505539f6fe974ae73990e57773a8c96628136f4 100644 (file)
@@ -1151,7 +1151,6 @@ static int ubifs_symlink(struct mnt_idmap *idmap, struct inode *dir,
        int err, sz_change, len = strlen(symname);
        struct fscrypt_str disk_link;
        struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
-                                       .new_ino_d = ALIGN(len, 8),
                                        .dirtied_ino = 1 };
        struct fscrypt_name nm;
 
@@ -1167,6 +1166,7 @@ static int ubifs_symlink(struct mnt_idmap *idmap, struct inode *dir,
         * Budget request settings: new inode, new direntry and changing parent
         * directory inode.
         */
+       req.new_ino_d = ALIGN(disk_link.len - 1, 8);
        err = ubifs_budget_space(c, &req);
        if (err)
                return err;
@@ -1324,6 +1324,8 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
        if (unlink) {
                ubifs_assert(c, inode_is_locked(new_inode));
 
+               /* Budget for old inode's data when its nlink > 1. */
+               req.dirtied_ino_d = ALIGN(ubifs_inode(new_inode)->data_len, 8);
                err = ubifs_purge_xattrs(new_inode);
                if (err)
                        return err;
@@ -1566,6 +1568,15 @@ static int ubifs_xrename(struct inode *old_dir, struct dentry *old_dentry,
 
        ubifs_assert(c, fst_inode && snd_inode);
 
+       /*
+        * Budget request settings: changing two direntries, changing the two
+        * parent directory inodes.
+        */
+
+       dbg_gen("dent '%pd' ino %lu in dir ino %lu exchange dent '%pd' ino %lu in dir ino %lu",
+               old_dentry, fst_inode->i_ino, old_dir->i_ino,
+               new_dentry, snd_inode->i_ino, new_dir->i_ino);
+
        err = fscrypt_setup_filename(old_dir, &old_dentry->d_name, 0, &fst_nm);
        if (err)
                return err;
@@ -1576,6 +1587,10 @@ static int ubifs_xrename(struct inode *old_dir, struct dentry *old_dentry,
                return err;
        }
 
+       err = ubifs_budget_space(c, &req);
+       if (err)
+               goto out;
+
        lock_4_inodes(old_dir, new_dir, NULL, NULL);
 
        time = current_time(old_dir);
@@ -1601,6 +1616,7 @@ static int ubifs_xrename(struct inode *old_dir, struct dentry *old_dentry,
        unlock_4_inodes(old_dir, new_dir, NULL, NULL);
        ubifs_release_budget(c, &req);
 
+out:
        fscrypt_free_filename(&fst_nm);
        fscrypt_free_filename(&snd_nm);
        return err;