]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.suse/ocfs2-Implement-quota-syncing-thread.patch
Imported linux-2.6.27.39 suse/xen patches.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.suse / ocfs2-Implement-quota-syncing-thread.patch
CommitLineData
2cb7cef9
BS
1From: Jan Kara <jack@suse.cz>
2References: fate#302681
3Subject: [PATCH 27/28] ocfs2: Implement quota syncing thread
4Patch-mainline: 2.6.29?
5
6This patch implements functions and timer setup which handles periodic
7syncing of locally cached quota information to global quota file.
8
9Signed-off-by: Jan Kara <jack@suse.cz>
10---
11 fs/ocfs2/quota.h | 3 ++
12 fs/ocfs2/quota_global.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++
13 fs/ocfs2/quota_local.c | 4 ++
14 mm/pdflush.c | 1
15 4 files changed, 79 insertions(+)
16
17--- a/fs/ocfs2/quota.h
18+++ b/fs/ocfs2/quota.h
19@@ -14,6 +14,7 @@
20 #include <linux/quota.h>
21 #include <linux/list.h>
22 #include <linux/dqblk_qtree.h>
23+#include <linux/timer.h>
24
25 #include "ocfs2.h"
26
27@@ -43,6 +44,7 @@ struct ocfs2_mem_dqinfo {
28 unsigned int dqi_chunks; /* Number of chunks in local quota file */
29 unsigned int dqi_blocks; /* Number of blocks allocated for local quota file */
30 unsigned int dqi_syncms; /* How often should we sync with other nodes */
31+ unsigned int dqi_syncjiff; /* Precomputed dqi_syncms in jiffies */
32 struct list_head dqi_chunk; /* List of chunks */
33 struct inode *dqi_gqinode; /* Global quota file inode */
34 struct ocfs2_lock_res dqi_gqlock; /* Lock protecting quota information structure */
35@@ -51,6 +53,7 @@ struct ocfs2_mem_dqinfo {
36 struct buffer_head *dqi_lqi_bh; /* Buffer head with local quota file inode */
37 struct buffer_head *dqi_ibh; /* Buffer with information header */
38 struct qtree_mem_dqinfo dqi_gi; /* Info about global file */
39+ struct timer_list dqi_sync_timer; /* Timer for syncing dquots */
40 };
41
42 static inline struct ocfs2_dquot *OCFS2_DQUOT(struct dquot *dquot)
43--- a/fs/ocfs2/quota_global.c
44+++ b/fs/ocfs2/quota_global.c
45@@ -1,10 +1,14 @@
46 /*
47 * Implementation of operations over global quota file
48 */
49+#include <linux/spinlock.h>
50 #include <linux/fs.h>
51 #include <linux/quota.h>
52 #include <linux/quotaops.h>
53 #include <linux/dqblk_qtree.h>
54+#include <linux/jiffies.h>
55+#include <linux/timer.h>
56+#include <linux/writeback.h>
57
58 #define MLOG_MASK_PREFIX ML_QUOTA
59 #include <cluster/masklog.h>
60@@ -19,6 +23,8 @@
61 #include "dlmglue.h"
62 #include "quota.h"
63
64+static void qsync_timer_fn(unsigned long oinfo_ptr);
65+
66 static void ocfs2_global_disk2memdqb(struct dquot *dquot, void *dp)
67 {
68 struct ocfs2_global_disk_dqblk *d = dp;
69@@ -269,6 +275,7 @@ int ocfs2_global_read_info(struct super_
70 info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
71 info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
72 oinfo->dqi_syncms = le32_to_cpu(dinfo.dqi_syncms);
73+ oinfo->dqi_syncjiff = msecs_to_jiffies(oinfo->dqi_syncms);
74 oinfo->dqi_gi.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
75 oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
76 oinfo->dqi_gi.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
77@@ -276,6 +283,10 @@ int ocfs2_global_read_info(struct super_
78 oinfo->dqi_gi.dqi_usable_bs = sb->s_blocksize -
79 OCFS2_QBLK_RESERVED_SPACE;
80 oinfo->dqi_gi.dqi_qtree_depth = qtree_depth(&oinfo->dqi_gi);
81+ setup_timer(&oinfo->dqi_sync_timer, qsync_timer_fn,
82+ (unsigned long)oinfo);
83+ mod_timer(&oinfo->dqi_sync_timer,
84+ round_jiffies(jiffies + oinfo->dqi_syncjiff));
85 out_err:
86 mlog_exit(status);
87 return status;
88@@ -463,6 +474,66 @@ out:
89 }
90
91 /*
92+ * Functions for periodic syncing of dquots with global file
93+ */
94+static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type)
95+{
96+ handle_t *handle;
97+ struct super_block *sb = dquot->dq_sb;
98+ struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
99+ struct ocfs2_super *osb = OCFS2_SB(sb);
100+ int status = 0;
101+
102+ mlog_entry("id=%u qtype=%u type=%lu device=%s\n", dquot->dq_id,
103+ dquot->dq_type, type, sb->s_id);
104+ if (type != dquot->dq_type)
105+ goto out;
106+ status = ocfs2_lock_global_qf(oinfo, 1);
107+ if (status < 0)
108+ goto out;
109+
110+ handle = ocfs2_start_trans(osb, OCFS2_QSYNC_CREDITS);
111+ if (IS_ERR(handle)) {
112+ status = PTR_ERR(handle);
113+ mlog_errno(status);
114+ goto out_ilock;
115+ }
116+ mutex_lock(&sb_dqopt(sb)->dqio_mutex);
117+ status = ocfs2_sync_dquot(dquot);
118+ mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
119+ if (status < 0)
120+ mlog_errno(status);
121+ /* We have to write local structure as well... */
122+ dquot_mark_dquot_dirty(dquot);
123+ status = dquot_commit(dquot);
124+ if (status < 0)
125+ mlog_errno(status);
126+ ocfs2_commit_trans(osb, handle);
127+out_ilock:
128+ ocfs2_unlock_global_qf(oinfo, 1);
129+out:
130+ mlog_exit(status);
131+ return status;
132+}
133+
134+static void ocfs2_do_qsync(unsigned long oinfo_ptr)
135+{
136+ struct ocfs2_mem_dqinfo *oinfo = (struct ocfs2_mem_dqinfo *)oinfo_ptr;
137+ struct super_block *sb = oinfo->dqi_gqinode->i_sb;
138+
139+ dquot_scan_active(sb, ocfs2_sync_dquot_helper, oinfo->dqi_type);
140+}
141+
142+static void qsync_timer_fn(unsigned long oinfo_ptr)
143+{
144+ struct ocfs2_mem_dqinfo *oinfo = (struct ocfs2_mem_dqinfo *)oinfo_ptr;
145+
146+ pdflush_operation(ocfs2_do_qsync, oinfo_ptr);
147+ mod_timer(&oinfo->dqi_sync_timer,
148+ round_jiffies(jiffies + oinfo->dqi_syncjiff));
149+}
150+
151+/*
152 * Wrappers for generic quota functions
153 */
154
155--- a/fs/ocfs2/quota_local.c
156+++ b/fs/ocfs2/quota_local.c
157@@ -368,6 +368,10 @@ static int ocfs2_local_free_info(struct
158 int mark_clean = 1, len;
159 int status;
160
161+ /* At this point we know there are no more dquots and thus
162+ * even if there's some sync in the pdflush queue, it won't
163+ * find any dquots and return without doing anything */
164+ del_timer_sync(&oinfo->dqi_sync_timer);
165 iput(oinfo->dqi_gqinode);
166 ocfs2_simple_drop_lockres(OCFS2_SB(sb), &oinfo->dqi_gqlock);
167 ocfs2_lock_res_free(&oinfo->dqi_gqlock);
168--- a/mm/pdflush.c
169+++ b/mm/pdflush.c
170@@ -225,6 +225,7 @@ int pdflush_operation(void (*fn)(unsigne
171
172 return ret;
173 }
174+EXPORT_SYMBOL(pdflush_operation);
175
176 static void start_one_pdflush_thread(void)
177 {