]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.19.31/ext4-update-quota-information-while-swapping-boot-loader-inode.patch
Linux 4.14.108
[thirdparty/kernel/stable-queue.git] / releases / 4.19.31 / ext4-update-quota-information-while-swapping-boot-loader-inode.patch
1 From aa507b5faf38784defe49f5e64605ac3c4425e26 Mon Sep 17 00:00:00 2001
2 From: yangerkun <yangerkun@huawei.com>
3 Date: Mon, 11 Feb 2019 00:14:02 -0500
4 Subject: ext4: update quota information while swapping boot loader inode
5
6 From: yangerkun <yangerkun@huawei.com>
7
8 commit aa507b5faf38784defe49f5e64605ac3c4425e26 upstream.
9
10 While do swap between two inode, they swap i_data without update
11 quota information. Also, swap_inode_boot_loader can do "revert"
12 somtimes, so update the quota while all operations has been finished.
13
14 Signed-off-by: yangerkun <yangerkun@huawei.com>
15 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
16 Cc: stable@kernel.org
17 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
18
19 ---
20 fs/ext4/ioctl.c | 56 +++++++++++++++++++++++++++++++++++++++++++-------------
21 1 file changed, 43 insertions(+), 13 deletions(-)
22
23 --- a/fs/ext4/ioctl.c
24 +++ b/fs/ext4/ioctl.c
25 @@ -68,8 +68,6 @@ static void swap_inode_data(struct inode
26 ei2 = EXT4_I(inode2);
27
28 swap(inode1->i_version, inode2->i_version);
29 - swap(inode1->i_blocks, inode2->i_blocks);
30 - swap(inode1->i_bytes, inode2->i_bytes);
31 swap(inode1->i_atime, inode2->i_atime);
32 swap(inode1->i_mtime, inode2->i_mtime);
33
34 @@ -115,6 +113,9 @@ static long swap_inode_boot_loader(struc
35 int err;
36 struct inode *inode_bl;
37 struct ext4_inode_info *ei_bl;
38 + qsize_t size, size_bl, diff;
39 + blkcnt_t blocks;
40 + unsigned short bytes;
41
42 inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO, EXT4_IGET_SPECIAL);
43 if (IS_ERR(inode_bl))
44 @@ -180,6 +181,13 @@ static long swap_inode_boot_loader(struc
45 memset(ei_bl->i_data, 0, sizeof(ei_bl->i_data));
46 }
47
48 + err = dquot_initialize(inode);
49 + if (err)
50 + goto err_out1;
51 +
52 + size = (qsize_t)(inode->i_blocks) * (1 << 9) + inode->i_bytes;
53 + size_bl = (qsize_t)(inode_bl->i_blocks) * (1 << 9) + inode_bl->i_bytes;
54 + diff = size - size_bl;
55 swap_inode_data(inode, inode_bl);
56
57 inode->i_ctime = inode_bl->i_ctime = current_time(inode);
58 @@ -193,24 +201,46 @@ static long swap_inode_boot_loader(struc
59
60 err = ext4_mark_inode_dirty(handle, inode);
61 if (err < 0) {
62 + /* No need to update quota information. */
63 ext4_warning(inode->i_sb,
64 "couldn't mark inode #%lu dirty (err %d)",
65 inode->i_ino, err);
66 /* Revert all changes: */
67 swap_inode_data(inode, inode_bl);
68 ext4_mark_inode_dirty(handle, inode);
69 - } else {
70 - err = ext4_mark_inode_dirty(handle, inode_bl);
71 - if (err < 0) {
72 - ext4_warning(inode_bl->i_sb,
73 - "couldn't mark inode #%lu dirty (err %d)",
74 - inode_bl->i_ino, err);
75 - /* Revert all changes: */
76 - swap_inode_data(inode, inode_bl);
77 - ext4_mark_inode_dirty(handle, inode);
78 - ext4_mark_inode_dirty(handle, inode_bl);
79 - }
80 + goto err_out1;
81 + }
82 +
83 + blocks = inode_bl->i_blocks;
84 + bytes = inode_bl->i_bytes;
85 + inode_bl->i_blocks = inode->i_blocks;
86 + inode_bl->i_bytes = inode->i_bytes;
87 + err = ext4_mark_inode_dirty(handle, inode_bl);
88 + if (err < 0) {
89 + /* No need to update quota information. */
90 + ext4_warning(inode_bl->i_sb,
91 + "couldn't mark inode #%lu dirty (err %d)",
92 + inode_bl->i_ino, err);
93 + goto revert;
94 + }
95 +
96 + /* Bootloader inode should not be counted into quota information. */
97 + if (diff > 0)
98 + dquot_free_space(inode, diff);
99 + else
100 + err = dquot_alloc_space(inode, -1 * diff);
101 +
102 + if (err < 0) {
103 +revert:
104 + /* Revert all changes: */
105 + inode_bl->i_blocks = blocks;
106 + inode_bl->i_bytes = bytes;
107 + swap_inode_data(inode, inode_bl);
108 + ext4_mark_inode_dirty(handle, inode);
109 + ext4_mark_inode_dirty(handle, inode_bl);
110 }
111 +
112 +err_out1:
113 ext4_journal_stop(handle);
114 ext4_double_up_write_data_sem(inode, inode_bl);
115