]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: Jan Kara <jack@suse.cz> |
2 | References: fate#302681 | |
3 | Subject: [PATCH 10/28] quota: Introduce DQUOT_QUOTA_SYS_FILE flag | |
4 | Patch-mainline: 2.6.29? | |
5 | ||
6 | If filesystem can handle quota files as system files hidden from users, we can | |
7 | skip a lot of cache invalidation, syncing, inode flags setting etc. when | |
8 | turning quotas on, off and quota_sync. Allow filesystem to indicate that it is | |
9 | hiding quota files from users by DQUOT_QUOTA_SYS_FILE flag. | |
10 | ||
11 | Signed-off-by: Jan Kara <jack@suse.cz> | |
12 | --- | |
13 | fs/dquot.c | 45 ++++++++++++++++++++++++++++++--------------- | |
14 | fs/quota.c | 3 +++ | |
15 | include/linux/quota.h | 7 +++++++ | |
16 | 3 files changed, 40 insertions(+), 15 deletions(-) | |
17 | ||
18 | diff --git a/fs/dquot.c b/fs/dquot.c | |
19 | index bdfae7d..904bd67 100644 | |
20 | --- a/fs/dquot.c | |
21 | +++ b/fs/dquot.c | |
22 | @@ -1629,6 +1629,11 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags) | |
23 | dqopt->ops[cnt] = NULL; | |
24 | } | |
25 | mutex_unlock(&dqopt->dqonoff_mutex); | |
26 | + | |
27 | + /* Skip syncing and setting flags if quota files are hidden */ | |
28 | + if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) | |
29 | + goto put_inodes; | |
30 | + | |
31 | /* Sync the superblock so that buffers with quota data are written to | |
32 | * disk (and so userspace sees correct data afterwards). */ | |
33 | if (sb->s_op->sync_fs) | |
34 | @@ -1653,6 +1658,12 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags) | |
35 | mark_inode_dirty(toputinode[cnt]); | |
36 | } | |
37 | mutex_unlock(&dqopt->dqonoff_mutex); | |
38 | + } | |
39 | + if (sb->s_bdev) | |
40 | + invalidate_bdev(sb->s_bdev); | |
41 | +put_inodes: | |
42 | + for (cnt = 0; cnt < MAXQUOTAS; cnt++) | |
43 | + if (toputinode[cnt]) { | |
44 | /* On remount RO, we keep the inode pointer so that we | |
45 | * can reenable quota on the subsequent remount RW. We | |
46 | * have to check 'flags' variable and not use sb_has_ | |
47 | @@ -1665,8 +1676,6 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags) | |
48 | else if (!toputinode[cnt]->i_nlink) | |
49 | ret = -EBUSY; | |
50 | } | |
51 | - if (sb->s_bdev) | |
52 | - invalidate_bdev(sb->s_bdev); | |
53 | return ret; | |
54 | } | |
55 | ||
56 | @@ -1713,25 +1722,31 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |
57 | goto out_fmt; | |
58 | } | |
59 | ||
60 | - /* As we bypass the pagecache we must now flush the inode so that | |
61 | - * we see all the changes from userspace... */ | |
62 | - write_inode_now(inode, 1); | |
63 | - /* And now flush the block cache so that kernel sees the changes */ | |
64 | - invalidate_bdev(sb->s_bdev); | |
65 | + if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { | |
66 | + /* As we bypass the pagecache we must now flush the inode so | |
67 | + * that we see all the changes from userspace... */ | |
68 | + write_inode_now(inode, 1); | |
69 | + /* And now flush the block cache so that kernel sees the | |
70 | + * changes */ | |
71 | + invalidate_bdev(sb->s_bdev); | |
72 | + } | |
73 | mutex_lock(&inode->i_mutex); | |
74 | mutex_lock(&dqopt->dqonoff_mutex); | |
75 | if (sb_has_quota_loaded(sb, type)) { | |
76 | error = -EBUSY; | |
77 | goto out_lock; | |
78 | } | |
79 | - /* We don't want quota and atime on quota files (deadlocks possible) | |
80 | - * Also nobody should write to the file - we use special IO operations | |
81 | - * which ignore the immutable bit. */ | |
82 | - down_write(&dqopt->dqptr_sem); | |
83 | - oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | S_NOQUOTA); | |
84 | - inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; | |
85 | - up_write(&dqopt->dqptr_sem); | |
86 | - sb->dq_op->drop(inode); | |
87 | + | |
88 | + if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { | |
89 | + /* We don't want quota and atime on quota files (deadlocks | |
90 | + * possible) Also nobody should write to the file - we use | |
91 | + * special IO operations which ignore the immutable bit. */ | |
92 | + down_write(&dqopt->dqptr_sem); | |
93 | + oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | S_NOQUOTA); | |
94 | + inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; | |
95 | + up_write(&dqopt->dqptr_sem); | |
96 | + sb->dq_op->drop(inode); | |
97 | + } | |
98 | ||
99 | error = -EIO; | |
100 | dqopt->files[type] = igrab(inode); | |
101 | diff --git a/fs/quota.c b/fs/quota.c | |
102 | index a8026f1..2c6ea78 100644 | |
103 | --- a/fs/quota.c | |
104 | +++ b/fs/quota.c | |
105 | @@ -160,6 +160,9 @@ static void quota_sync_sb(struct super_block *sb, int type) | |
106 | int cnt; | |
107 | ||
108 | sb->s_qcop->quota_sync(sb, type); | |
109 | + | |
110 | + if (sb_dqopt(sb)->flags & DQUOT_QUOTA_SYS_FILE) | |
111 | + return; | |
112 | /* This is not very clever (and fast) but currently I don't know about | |
113 | * any other simple way of getting quota data to disk and we must get | |
114 | * them there for userspace to be visible... */ | |
115 | diff --git a/include/linux/quota.h b/include/linux/quota.h | |
116 | index 0e4b550..8dd5333 100644 | |
117 | --- a/include/linux/quota.h | |
118 | +++ b/include/linux/quota.h | |
119 | @@ -334,6 +334,13 @@ enum { | |
120 | #define DQUOT_SUSPENDED (1 << _DQUOT_SUSPENDED) | |
121 | #define DQUOT_STATE_FLAGS (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED | \ | |
122 | DQUOT_SUSPENDED) | |
123 | +/* Other quota flags */ | |
124 | +#define DQUOT_QUOTA_SYS_FILE (1 << 6) /* Quota file is a special | |
125 | + * system file and user cannot | |
126 | + * touch it. Filesystem is | |
127 | + * responsible for setting | |
128 | + * S_NOQUOTA, S_NOATIME flags | |
129 | + */ | |
130 | ||
131 | static inline unsigned int dquot_state_flag(unsigned int flags, int type) | |
132 | { | |
133 | -- | |
134 | 1.5.2.4 | |
135 |