]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.19.31/ext4-update-quota-information-while-swapping-boot-loader-inode.patch
Linux 4.19.31
[thirdparty/kernel/stable-queue.git] / releases / 4.19.31 / ext4-update-quota-information-while-swapping-boot-loader-inode.patch
CommitLineData
ec71c73b
GKH
1From aa507b5faf38784defe49f5e64605ac3c4425e26 Mon Sep 17 00:00:00 2001
2From: yangerkun <yangerkun@huawei.com>
3Date: Mon, 11 Feb 2019 00:14:02 -0500
4Subject: ext4: update quota information while swapping boot loader inode
5
6From: yangerkun <yangerkun@huawei.com>
7
8commit aa507b5faf38784defe49f5e64605ac3c4425e26 upstream.
9
10While do swap between two inode, they swap i_data without update
11quota information. Also, swap_inode_boot_loader can do "revert"
12somtimes, so update the quota while all operations has been finished.
13
14Signed-off-by: yangerkun <yangerkun@huawei.com>
15Signed-off-by: Theodore Ts'o <tytso@mit.edu>
16Cc: stable@kernel.org
17Signed-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