ext4: update quota information while swapping boot loader inode
commit aa507b5faf38784defe49f5e64605ac3c4425e26 upstream. While do swap between two inode, they swap i_data without update quota information. Also, swap_inode_boot_loader can do "revert" somtimes, so update the quota while all operations has been finished. Signed-off-by: yangerkun <yangerkun@huawei.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu> [bwh: Backported to 3.16: - Include <linux/quotaops.h> - dquot_initialize() does not return an erro - Adjust context] Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
This commit is contained in:
parent
35ee909ac1
commit
59d8638300
|
@ -14,6 +14,7 @@
|
|||
#include <linux/compat.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/quotaops.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "ext4_jbd2.h"
|
||||
#include "ext4.h"
|
||||
|
@ -67,9 +68,6 @@ static void swap_inode_data(struct inode *inode1, struct inode *inode2)
|
|||
|
||||
memswap(&inode1->i_version, &inode2->i_version,
|
||||
sizeof(inode1->i_version));
|
||||
memswap(&inode1->i_blocks, &inode2->i_blocks,
|
||||
sizeof(inode1->i_blocks));
|
||||
memswap(&inode1->i_bytes, &inode2->i_bytes, sizeof(inode1->i_bytes));
|
||||
memswap(&inode1->i_atime, &inode2->i_atime, sizeof(inode1->i_atime));
|
||||
memswap(&inode1->i_mtime, &inode2->i_mtime, sizeof(inode1->i_mtime));
|
||||
|
||||
|
@ -118,6 +116,9 @@ static long swap_inode_boot_loader(struct super_block *sb,
|
|||
struct inode *inode_bl;
|
||||
struct ext4_inode_info *ei_bl;
|
||||
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||
qsize_t size, size_bl, diff;
|
||||
blkcnt_t blocks;
|
||||
unsigned short bytes;
|
||||
|
||||
inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO, EXT4_IGET_SPECIAL);
|
||||
if (IS_ERR(inode_bl))
|
||||
|
@ -180,6 +181,11 @@ static long swap_inode_boot_loader(struct super_block *sb,
|
|||
memset(ei_bl->i_data, 0, sizeof(ei_bl->i_data));
|
||||
}
|
||||
|
||||
dquot_initialize(inode);
|
||||
|
||||
size = (qsize_t)(inode->i_blocks) * (1 << 9) + inode->i_bytes;
|
||||
size_bl = (qsize_t)(inode_bl->i_blocks) * (1 << 9) + inode_bl->i_bytes;
|
||||
diff = size - size_bl;
|
||||
swap_inode_data(inode, inode_bl);
|
||||
|
||||
inode->i_ctime = inode_bl->i_ctime = ext4_current_time(inode);
|
||||
|
@ -195,24 +201,46 @@ static long swap_inode_boot_loader(struct super_block *sb,
|
|||
|
||||
err = ext4_mark_inode_dirty(handle, inode);
|
||||
if (err < 0) {
|
||||
/* No need to update quota information. */
|
||||
ext4_warning(inode->i_sb,
|
||||
"couldn't mark inode #%lu dirty (err %d)",
|
||||
inode->i_ino, err);
|
||||
/* Revert all changes: */
|
||||
swap_inode_data(inode, inode_bl);
|
||||
ext4_mark_inode_dirty(handle, inode);
|
||||
} else {
|
||||
err = ext4_mark_inode_dirty(handle, inode_bl);
|
||||
if (err < 0) {
|
||||
ext4_warning(inode_bl->i_sb,
|
||||
"couldn't mark inode #%lu dirty (err %d)",
|
||||
inode_bl->i_ino, err);
|
||||
/* Revert all changes: */
|
||||
swap_inode_data(inode, inode_bl);
|
||||
ext4_mark_inode_dirty(handle, inode);
|
||||
ext4_mark_inode_dirty(handle, inode_bl);
|
||||
}
|
||||
goto err_out1;
|
||||
}
|
||||
|
||||
blocks = inode_bl->i_blocks;
|
||||
bytes = inode_bl->i_bytes;
|
||||
inode_bl->i_blocks = inode->i_blocks;
|
||||
inode_bl->i_bytes = inode->i_bytes;
|
||||
err = ext4_mark_inode_dirty(handle, inode_bl);
|
||||
if (err < 0) {
|
||||
/* No need to update quota information. */
|
||||
ext4_warning(inode_bl->i_sb,
|
||||
"couldn't mark inode #%lu dirty (err %d)",
|
||||
inode_bl->i_ino, err);
|
||||
goto revert;
|
||||
}
|
||||
|
||||
/* Bootloader inode should not be counted into quota information. */
|
||||
if (diff > 0)
|
||||
dquot_free_space(inode, diff);
|
||||
else
|
||||
err = dquot_alloc_space(inode, -1 * diff);
|
||||
|
||||
if (err < 0) {
|
||||
revert:
|
||||
/* Revert all changes: */
|
||||
inode_bl->i_blocks = blocks;
|
||||
inode_bl->i_bytes = bytes;
|
||||
swap_inode_data(inode, inode_bl);
|
||||
ext4_mark_inode_dirty(handle, inode);
|
||||
ext4_mark_inode_dirty(handle, inode_bl);
|
||||
}
|
||||
|
||||
err_out1:
|
||||
ext4_journal_stop(handle);
|
||||
ext4_double_up_write_data_sem(inode, inode_bl);
|
||||
|
||||
|
|
Loading…
Reference in New Issue