1 From: Jan Kara <jack@suse.cz>
2 References: fate#302681
3 Subject: [PATCH 16/28] quota: Add helpers to allow ocfs2 specific quota initialization, freeing and recovery
4 Patch-mainline: 2.6.29?
6 OCFS2 needs to peek whether quota structure is already in memory so
7 that it can avoid expensive cluster locking in that case. Similarly
8 when freeing dquots, it checks whether it is the last quota structure
9 user or not. Finally, it needs to get reference to dquot structure for
10 specified id and quota type when recovering quota file after crash.
12 Signed-off-by: Jan Kara <jack@suse.cz>
14 fs/dquot.c | 38 ++++++++++++++++++++++++++++++++------
15 include/linux/quotaops.h | 4 ++++
16 2 files changed, 36 insertions(+), 6 deletions(-)
18 diff --git a/fs/dquot.c b/fs/dquot.c
19 index 3fde18b..9fb1d71 100644
22 @@ -213,8 +213,6 @@ static struct hlist_head *dquot_hash;
24 struct dqstats dqstats;
26 -static void dqput(struct dquot *dquot);
28 static inline unsigned int
29 hashfn(const struct super_block *sb, unsigned int id, int type)
31 @@ -568,7 +566,7 @@ static struct shrinker dqcache_shrinker = {
32 * NOTE: If you change this function please check whether dqput_blocks() works right...
33 * MUST be called with either dqptr_sem or dqonoff_mutex held
35 -static void dqput(struct dquot *dquot)
36 +void dqput(struct dquot *dquot)
40 @@ -660,10 +658,28 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
44 + * Check whether dquot is in memory.
45 + * MUST be called with either dqptr_sem or dqonoff_mutex held
47 +int dquot_is_cached(struct super_block *sb, unsigned int id, int type)
49 + unsigned int hashent = hashfn(sb, id, type);
52 + if (!sb_has_quota_active(sb, type))
54 + spin_lock(&dq_list_lock);
55 + if (find_dquot(hashent, sb, id, type) != NODQUOT)
57 + spin_unlock(&dq_list_lock);
62 * Get reference to dquot
63 * MUST be called with either dqptr_sem or dqonoff_mutex held
65 -static struct dquot *dqget(struct super_block *sb, unsigned int id, int type)
66 +struct dquot *dqget(struct super_block *sb, unsigned int id, int type)
68 unsigned int hashent = hashfn(sb, id, type);
69 struct dquot *dquot, *empty = NODQUOT;
70 @@ -1184,17 +1200,23 @@ out_err:
71 * Release all quotas referenced by inode
72 * Transaction must be started at an entry
74 -int dquot_drop(struct inode *inode)
75 +int dquot_drop_locked(struct inode *inode)
79 - down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
80 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
81 if (inode->i_dquot[cnt] != NODQUOT) {
82 dqput(inode->i_dquot[cnt]);
83 inode->i_dquot[cnt] = NODQUOT;
89 +int dquot_drop(struct inode *inode)
91 + down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
92 + dquot_drop_locked(inode);
93 up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
96 @@ -2306,7 +2328,11 @@ EXPORT_SYMBOL(dquot_release);
97 EXPORT_SYMBOL(dquot_mark_dquot_dirty);
98 EXPORT_SYMBOL(dquot_initialize);
99 EXPORT_SYMBOL(dquot_drop);
100 +EXPORT_SYMBOL(dquot_drop_locked);
101 EXPORT_SYMBOL(vfs_dq_drop);
102 +EXPORT_SYMBOL(dqget);
103 +EXPORT_SYMBOL(dqput);
104 +EXPORT_SYMBOL(dquot_is_cached);
105 EXPORT_SYMBOL(dquot_alloc_space);
106 EXPORT_SYMBOL(dquot_alloc_inode);
107 EXPORT_SYMBOL(dquot_free_space);
108 diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
109 index 94f00ec..1f990f2 100644
110 --- a/include/linux/quotaops.h
111 +++ b/include/linux/quotaops.h
112 @@ -27,6 +27,10 @@ void sync_dquots(struct super_block *sb, int type);
114 int dquot_initialize(struct inode *inode, int type);
115 int dquot_drop(struct inode *inode);
116 +int dquot_drop_locked(struct inode *inode);
117 +struct dquot *dqget(struct super_block *sb, unsigned int id, int type);
118 +void dqput(struct dquot *dquot);
119 +int dquot_is_cached(struct super_block *sb, unsigned int id, int type);
121 int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
122 int dquot_alloc_inode(const struct inode *inode, qsize_t number);