blob: f461f9678f9fe2305812bc1d9faf13b44e3f359b [file] [log] [blame]
Jan Kara9e33d692008-08-25 19:56:50 +02001/*
2 * Implementation of operations over global quota file
3 */
Mark Fasheh171bf932008-10-20 15:36:47 +02004#include <linux/spinlock.h>
Jan Kara9e33d692008-08-25 19:56:50 +02005#include <linux/fs.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +09006#include <linux/slab.h>
Jan Kara9e33d692008-08-25 19:56:50 +02007#include <linux/quota.h>
8#include <linux/quotaops.h>
9#include <linux/dqblk_qtree.h>
Mark Fasheh171bf932008-10-20 15:36:47 +020010#include <linux/jiffies.h>
11#include <linux/writeback.h>
12#include <linux/workqueue.h>
Jan Kara9e33d692008-08-25 19:56:50 +020013
14#define MLOG_MASK_PREFIX ML_QUOTA
15#include <cluster/masklog.h>
16
17#include "ocfs2_fs.h"
18#include "ocfs2.h"
19#include "alloc.h"
Joel Beckerd6b32bb2008-10-17 14:55:01 -070020#include "blockcheck.h"
Jan Kara9e33d692008-08-25 19:56:50 +020021#include "inode.h"
22#include "journal.h"
23#include "file.h"
24#include "sysfile.h"
25#include "dlmglue.h"
26#include "uptodate.h"
Jan Karaada50822009-08-03 18:24:21 +020027#include "super.h"
Jan Karaf64dd442010-04-28 00:22:30 +020028#include "buffer_head_io.h"
Jan Kara9e33d692008-08-25 19:56:50 +020029#include "quota.h"
30
Mark Fasheh171bf932008-10-20 15:36:47 +020031static struct workqueue_struct *ocfs2_quota_wq = NULL;
32
33static void qsync_work_fn(struct work_struct *work);
34
Jan Kara9e33d692008-08-25 19:56:50 +020035static void ocfs2_global_disk2memdqb(struct dquot *dquot, void *dp)
36{
37 struct ocfs2_global_disk_dqblk *d = dp;
38 struct mem_dqblk *m = &dquot->dq_dqb;
39
40 /* Update from disk only entries not set by the admin */
41 if (!test_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags)) {
42 m->dqb_ihardlimit = le64_to_cpu(d->dqb_ihardlimit);
43 m->dqb_isoftlimit = le64_to_cpu(d->dqb_isoftlimit);
44 }
45 if (!test_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags))
46 m->dqb_curinodes = le64_to_cpu(d->dqb_curinodes);
47 if (!test_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags)) {
48 m->dqb_bhardlimit = le64_to_cpu(d->dqb_bhardlimit);
49 m->dqb_bsoftlimit = le64_to_cpu(d->dqb_bsoftlimit);
50 }
51 if (!test_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags))
52 m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
53 if (!test_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags))
54 m->dqb_btime = le64_to_cpu(d->dqb_btime);
55 if (!test_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags))
56 m->dqb_itime = le64_to_cpu(d->dqb_itime);
57 OCFS2_DQUOT(dquot)->dq_use_count = le32_to_cpu(d->dqb_use_count);
58}
59
60static void ocfs2_global_mem2diskdqb(void *dp, struct dquot *dquot)
61{
62 struct ocfs2_global_disk_dqblk *d = dp;
63 struct mem_dqblk *m = &dquot->dq_dqb;
64
65 d->dqb_id = cpu_to_le32(dquot->dq_id);
66 d->dqb_use_count = cpu_to_le32(OCFS2_DQUOT(dquot)->dq_use_count);
67 d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
68 d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
69 d->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
70 d->dqb_bhardlimit = cpu_to_le64(m->dqb_bhardlimit);
71 d->dqb_bsoftlimit = cpu_to_le64(m->dqb_bsoftlimit);
72 d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
73 d->dqb_btime = cpu_to_le64(m->dqb_btime);
74 d->dqb_itime = cpu_to_le64(m->dqb_itime);
Jan Kara7669f542009-07-22 13:17:18 +020075 d->dqb_pad1 = d->dqb_pad2 = 0;
Jan Kara9e33d692008-08-25 19:56:50 +020076}
77
78static int ocfs2_global_is_id(void *dp, struct dquot *dquot)
79{
80 struct ocfs2_global_disk_dqblk *d = dp;
81 struct ocfs2_mem_dqinfo *oinfo =
82 sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
83
84 if (qtree_entry_unused(&oinfo->dqi_gi, dp))
85 return 0;
86 return le32_to_cpu(d->dqb_id) == dquot->dq_id;
87}
88
89struct qtree_fmt_operations ocfs2_global_ops = {
90 .mem2disk_dqblk = ocfs2_global_mem2diskdqb,
91 .disk2mem_dqblk = ocfs2_global_disk2memdqb,
92 .is_id = ocfs2_global_is_id,
93};
94
Joel Becker684ef272008-12-02 17:44:05 -080095static int ocfs2_validate_quota_block(struct super_block *sb,
96 struct buffer_head *bh)
97{
Joel Beckerd6b32bb2008-10-17 14:55:01 -070098 struct ocfs2_disk_dqtrailer *dqt =
99 ocfs2_block_dqtrailer(sb->s_blocksize, bh->b_data);
Joel Becker684ef272008-12-02 17:44:05 -0800100
101 mlog(0, "Validating quota block %llu\n",
102 (unsigned long long)bh->b_blocknr);
103
Joel Beckerd6b32bb2008-10-17 14:55:01 -0700104 BUG_ON(!buffer_uptodate(bh));
105
106 /*
107 * If the ecc fails, we return the error but otherwise
108 * leave the filesystem running. We know any error is
109 * local to this block.
110 */
111 return ocfs2_validate_meta_ecc(sb, bh->b_data, &dqt->dq_check);
Joel Becker684ef272008-12-02 17:44:05 -0800112}
113
Joel Becker85eb8b72008-11-25 15:31:27 +0100114int ocfs2_read_quota_block(struct inode *inode, u64 v_block,
115 struct buffer_head **bh)
Jan Kara9e33d692008-08-25 19:56:50 +0200116{
Joel Becker85eb8b72008-11-25 15:31:27 +0100117 int rc = 0;
118 struct buffer_head *tmp = *bh;
Jan Kara9e33d692008-08-25 19:56:50 +0200119
Jan Karaada50822009-08-03 18:24:21 +0200120 if (i_size_read(inode) >> inode->i_sb->s_blocksize_bits <= v_block) {
121 ocfs2_error(inode->i_sb,
122 "Quota file %llu is probably corrupted! Requested "
123 "to read block %Lu but file has size only %Lu\n",
124 (unsigned long long)OCFS2_I(inode)->ip_blkno,
125 (unsigned long long)v_block,
126 (unsigned long long)i_size_read(inode));
127 return -EIO;
128 }
Joel Becker684ef272008-12-02 17:44:05 -0800129 rc = ocfs2_read_virt_blocks(inode, v_block, 1, &tmp, 0,
130 ocfs2_validate_quota_block);
Joel Becker85eb8b72008-11-25 15:31:27 +0100131 if (rc)
132 mlog_errno(rc);
Jan Kara9e33d692008-08-25 19:56:50 +0200133
Joel Becker85eb8b72008-11-25 15:31:27 +0100134 /* If ocfs2_read_virt_blocks() got us a new bh, pass it up. */
135 if (!rc && !*bh)
136 *bh = tmp;
137
138 return rc;
Jan Kara9e33d692008-08-25 19:56:50 +0200139}
140
Jan Karaf64dd442010-04-28 00:22:30 +0200141int ocfs2_read_quota_phys_block(struct inode *inode, u64 p_block,
142 struct buffer_head **bhp)
143{
144 int rc;
145
146 *bhp = NULL;
147 rc = ocfs2_read_blocks(INODE_CACHE(inode), p_block, 1, bhp, 0,
148 ocfs2_validate_quota_block);
149 if (rc)
150 mlog_errno(rc);
151 return rc;
152}
153
Jan Kara53a36042008-11-25 15:31:29 +0100154static int ocfs2_get_quota_block(struct inode *inode, int block,
155 struct buffer_head **bh)
Jan Kara9e33d692008-08-25 19:56:50 +0200156{
157 u64 pblock, pcount;
Jan Kara53a36042008-11-25 15:31:29 +0100158 int err;
Jan Kara9e33d692008-08-25 19:56:50 +0200159
160 down_read(&OCFS2_I(inode)->ip_alloc_sem);
Jan Kara53a36042008-11-25 15:31:29 +0100161 err = ocfs2_extent_map_get_blocks(inode, block, &pblock, &pcount, NULL);
Jan Kara9e33d692008-08-25 19:56:50 +0200162 up_read(&OCFS2_I(inode)->ip_alloc_sem);
Jan Kara53a36042008-11-25 15:31:29 +0100163 if (err) {
164 mlog_errno(err);
165 return err;
Jan Kara9e33d692008-08-25 19:56:50 +0200166 }
Jan Kara53a36042008-11-25 15:31:29 +0100167 *bh = sb_getblk(inode->i_sb, pblock);
168 if (!*bh) {
169 err = -EIO;
170 mlog_errno(err);
Jan Kara9e33d692008-08-25 19:56:50 +0200171 }
Joe Perchesa419aef2009-08-18 11:18:35 -0700172 return err;
Jan Kara9e33d692008-08-25 19:56:50 +0200173}
174
175/* Read data from global quotafile - avoid pagecache and such because we cannot
176 * afford acquiring the locks... We use quota cluster lock to serialize
177 * operations. Caller is responsible for acquiring it. */
178ssize_t ocfs2_quota_read(struct super_block *sb, int type, char *data,
179 size_t len, loff_t off)
180{
181 struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
182 struct inode *gqinode = oinfo->dqi_gqinode;
183 loff_t i_size = i_size_read(gqinode);
184 int offset = off & (sb->s_blocksize - 1);
185 sector_t blk = off >> sb->s_blocksize_bits;
186 int err = 0;
187 struct buffer_head *bh;
188 size_t toread, tocopy;
189
190 if (off > i_size)
191 return 0;
192 if (off + len > i_size)
193 len = i_size - off;
194 toread = len;
195 while (toread > 0) {
Mark Fashehdad7d972008-12-24 16:33:08 -0800196 tocopy = min_t(size_t, (sb->s_blocksize - offset), toread);
Joel Becker85eb8b72008-11-25 15:31:27 +0100197 bh = NULL;
198 err = ocfs2_read_quota_block(gqinode, blk, &bh);
199 if (err) {
Jan Kara9e33d692008-08-25 19:56:50 +0200200 mlog_errno(err);
201 return err;
202 }
203 memcpy(data, bh->b_data + offset, tocopy);
204 brelse(bh);
205 offset = 0;
206 toread -= tocopy;
207 data += tocopy;
208 blk++;
209 }
210 return len;
211}
212
213/* Write to quotafile (we know the transaction is already started and has
214 * enough credits) */
215ssize_t ocfs2_quota_write(struct super_block *sb, int type,
216 const char *data, size_t len, loff_t off)
217{
218 struct mem_dqinfo *info = sb_dqinfo(sb, type);
219 struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
220 struct inode *gqinode = oinfo->dqi_gqinode;
221 int offset = off & (sb->s_blocksize - 1);
222 sector_t blk = off >> sb->s_blocksize_bits;
Jan Karaaf09e512008-11-25 15:31:28 +0100223 int err = 0, new = 0, ja_type;
Joel Becker85eb8b72008-11-25 15:31:27 +0100224 struct buffer_head *bh = NULL;
Jan Kara9e33d692008-08-25 19:56:50 +0200225 handle_t *handle = journal_current_handle();
226
227 if (!handle) {
228 mlog(ML_ERROR, "Quota write (off=%llu, len=%llu) cancelled "
229 "because transaction was not started.\n",
230 (unsigned long long)off, (unsigned long long)len);
231 return -EIO;
232 }
233 if (len > sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE - offset) {
234 WARN_ON(1);
235 len = sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE - offset;
236 }
237
238 mutex_lock_nested(&gqinode->i_mutex, I_MUTEX_QUOTA);
239 if (gqinode->i_size < off + len) {
Jan Karab57ac2c2009-07-22 13:17:15 +0200240 loff_t rounded_end =
241 ocfs2_align_bytes_to_blocks(sb, off + len);
242
Jan Karab409d7a2009-08-06 23:29:34 +0200243 /* Space is already allocated in ocfs2_global_read_dquot() */
Jan Kara9e33d692008-08-25 19:56:50 +0200244 err = ocfs2_simple_size_update(gqinode,
245 oinfo->dqi_gqi_bh,
Jan Karab57ac2c2009-07-22 13:17:15 +0200246 rounded_end);
Jan Kara9e33d692008-08-25 19:56:50 +0200247 if (err < 0)
248 goto out;
249 new = 1;
250 }
251 /* Not rewriting whole block? */
252 if ((offset || len < sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE) &&
253 !new) {
Joel Becker85eb8b72008-11-25 15:31:27 +0100254 err = ocfs2_read_quota_block(gqinode, blk, &bh);
Jan Karaaf09e512008-11-25 15:31:28 +0100255 ja_type = OCFS2_JOURNAL_ACCESS_WRITE;
Jan Kara9e33d692008-08-25 19:56:50 +0200256 } else {
Jan Kara53a36042008-11-25 15:31:29 +0100257 err = ocfs2_get_quota_block(gqinode, blk, &bh);
Jan Karaaf09e512008-11-25 15:31:28 +0100258 ja_type = OCFS2_JOURNAL_ACCESS_CREATE;
Jan Kara9e33d692008-08-25 19:56:50 +0200259 }
Jan Karaaf09e512008-11-25 15:31:28 +0100260 if (err) {
261 mlog_errno(err);
Tao Mae9956fa2009-07-30 16:07:10 +0800262 goto out;
Jan Kara9e33d692008-08-25 19:56:50 +0200263 }
264 lock_buffer(bh);
265 if (new)
266 memset(bh->b_data, 0, sb->s_blocksize);
267 memcpy(bh->b_data + offset, data, len);
268 flush_dcache_page(bh->b_page);
Jan Karaaf09e512008-11-25 15:31:28 +0100269 set_buffer_uptodate(bh);
Jan Kara9e33d692008-08-25 19:56:50 +0200270 unlock_buffer(bh);
Joel Becker8cb471e2009-02-10 20:00:41 -0800271 ocfs2_set_buffer_uptodate(INODE_CACHE(gqinode), bh);
Joel Becker0cf2f762009-02-12 16:41:25 -0800272 err = ocfs2_journal_access_dq(handle, INODE_CACHE(gqinode), bh,
273 ja_type);
Jan Karaaf09e512008-11-25 15:31:28 +0100274 if (err < 0) {
275 brelse(bh);
276 goto out;
277 }
Joel Beckerec20cec2010-03-19 14:13:52 -0700278 ocfs2_journal_dirty(handle, bh);
Jan Kara9e33d692008-08-25 19:56:50 +0200279 brelse(bh);
Jan Kara9e33d692008-08-25 19:56:50 +0200280out:
281 if (err) {
282 mutex_unlock(&gqinode->i_mutex);
283 mlog_errno(err);
284 return err;
285 }
286 gqinode->i_version++;
287 ocfs2_mark_inode_dirty(handle, gqinode, oinfo->dqi_gqi_bh);
288 mutex_unlock(&gqinode->i_mutex);
289 return len;
290}
291
292int ocfs2_lock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex)
293{
294 int status;
295 struct buffer_head *bh = NULL;
296
297 status = ocfs2_inode_lock(oinfo->dqi_gqinode, &bh, ex);
298 if (status < 0)
299 return status;
300 spin_lock(&dq_data_lock);
301 if (!oinfo->dqi_gqi_count++)
302 oinfo->dqi_gqi_bh = bh;
303 else
304 WARN_ON(bh != oinfo->dqi_gqi_bh);
305 spin_unlock(&dq_data_lock);
306 return 0;
307}
308
309void ocfs2_unlock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex)
310{
311 ocfs2_inode_unlock(oinfo->dqi_gqinode, ex);
312 brelse(oinfo->dqi_gqi_bh);
313 spin_lock(&dq_data_lock);
314 if (!--oinfo->dqi_gqi_count)
315 oinfo->dqi_gqi_bh = NULL;
316 spin_unlock(&dq_data_lock);
317}
318
319/* Read information header from global quota file */
320int ocfs2_global_read_info(struct super_block *sb, int type)
321{
322 struct inode *gqinode = NULL;
323 unsigned int ino[MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE,
324 GROUP_QUOTA_SYSTEM_INODE };
325 struct ocfs2_global_disk_dqinfo dinfo;
326 struct mem_dqinfo *info = sb_dqinfo(sb, type);
327 struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
328 int status;
329
330 mlog_entry_void();
331
332 /* Read global header */
333 gqinode = ocfs2_get_system_file_inode(OCFS2_SB(sb), ino[type],
334 OCFS2_INVALID_SLOT);
335 if (!gqinode) {
336 mlog(ML_ERROR, "failed to get global quota inode (type=%d)\n",
337 type);
338 status = -EINVAL;
339 goto out_err;
340 }
341 oinfo->dqi_gi.dqi_sb = sb;
342 oinfo->dqi_gi.dqi_type = type;
343 ocfs2_qinfo_lock_res_init(&oinfo->dqi_gqlock, oinfo);
344 oinfo->dqi_gi.dqi_entry_size = sizeof(struct ocfs2_global_disk_dqblk);
345 oinfo->dqi_gi.dqi_ops = &ocfs2_global_ops;
346 oinfo->dqi_gqi_bh = NULL;
347 oinfo->dqi_gqi_count = 0;
348 oinfo->dqi_gqinode = gqinode;
349 status = ocfs2_lock_global_qf(oinfo, 0);
350 if (status < 0) {
351 mlog_errno(status);
352 goto out_err;
353 }
354 status = sb->s_op->quota_read(sb, type, (char *)&dinfo,
355 sizeof(struct ocfs2_global_disk_dqinfo),
356 OCFS2_GLOBAL_INFO_OFF);
357 ocfs2_unlock_global_qf(oinfo, 0);
358 if (status != sizeof(struct ocfs2_global_disk_dqinfo)) {
359 mlog(ML_ERROR, "Cannot read global quota info (%d).\n",
360 status);
361 if (status >= 0)
362 status = -EIO;
363 mlog_errno(status);
364 goto out_err;
365 }
366 info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
367 info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
368 oinfo->dqi_syncms = le32_to_cpu(dinfo.dqi_syncms);
369 oinfo->dqi_gi.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
370 oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
371 oinfo->dqi_gi.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
372 oinfo->dqi_gi.dqi_blocksize_bits = sb->s_blocksize_bits;
373 oinfo->dqi_gi.dqi_usable_bs = sb->s_blocksize -
374 OCFS2_QBLK_RESERVED_SPACE;
375 oinfo->dqi_gi.dqi_qtree_depth = qtree_depth(&oinfo->dqi_gi);
Mark Fasheh171bf932008-10-20 15:36:47 +0200376 INIT_DELAYED_WORK(&oinfo->dqi_sync_work, qsync_work_fn);
377 queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
Jan Kara4539f1d2009-07-22 13:17:20 +0200378 msecs_to_jiffies(oinfo->dqi_syncms));
Mark Fasheh171bf932008-10-20 15:36:47 +0200379
Jan Kara9e33d692008-08-25 19:56:50 +0200380out_err:
381 mlog_exit(status);
382 return status;
383}
384
385/* Write information to global quota file. Expects exlusive lock on quota
386 * file inode and quota info */
387static int __ocfs2_global_write_info(struct super_block *sb, int type)
388{
389 struct mem_dqinfo *info = sb_dqinfo(sb, type);
390 struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
391 struct ocfs2_global_disk_dqinfo dinfo;
392 ssize_t size;
393
394 spin_lock(&dq_data_lock);
395 info->dqi_flags &= ~DQF_INFO_DIRTY;
396 dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
397 dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
398 spin_unlock(&dq_data_lock);
399 dinfo.dqi_syncms = cpu_to_le32(oinfo->dqi_syncms);
400 dinfo.dqi_blocks = cpu_to_le32(oinfo->dqi_gi.dqi_blocks);
401 dinfo.dqi_free_blk = cpu_to_le32(oinfo->dqi_gi.dqi_free_blk);
402 dinfo.dqi_free_entry = cpu_to_le32(oinfo->dqi_gi.dqi_free_entry);
403 size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
404 sizeof(struct ocfs2_global_disk_dqinfo),
405 OCFS2_GLOBAL_INFO_OFF);
406 if (size != sizeof(struct ocfs2_global_disk_dqinfo)) {
407 mlog(ML_ERROR, "Cannot write global quota info structure\n");
408 if (size >= 0)
409 size = -EIO;
410 return size;
411 }
412 return 0;
413}
414
415int ocfs2_global_write_info(struct super_block *sb, int type)
416{
417 int err;
418 struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv;
419
420 err = ocfs2_qinfo_lock(info, 1);
421 if (err < 0)
422 return err;
423 err = __ocfs2_global_write_info(sb, type);
424 ocfs2_qinfo_unlock(info, 1);
425 return err;
426}
427
Jan Karab409d7a2009-08-06 23:29:34 +0200428static int ocfs2_global_qinit_alloc(struct super_block *sb, int type)
429{
430 struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
431
432 /*
433 * We may need to allocate tree blocks and a leaf block but not the
434 * root block
435 */
436 return oinfo->dqi_gi.dqi_qtree_depth;
437}
438
439static int ocfs2_calc_global_qinit_credits(struct super_block *sb, int type)
440{
441 /* We modify all the allocated blocks, tree root, and info block */
442 return (ocfs2_global_qinit_alloc(sb, type) + 2) *
443 OCFS2_QUOTA_BLOCK_UPDATE_CREDITS;
444}
445
Jan Kara9e33d692008-08-25 19:56:50 +0200446/* Read in information from global quota file and acquire a reference to it.
447 * dquot_acquire() has already started the transaction and locked quota file */
448int ocfs2_global_read_dquot(struct dquot *dquot)
449{
450 int err, err2, ex = 0;
Jan Karab409d7a2009-08-06 23:29:34 +0200451 struct super_block *sb = dquot->dq_sb;
452 int type = dquot->dq_type;
453 struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv;
454 struct ocfs2_super *osb = OCFS2_SB(sb);
455 struct inode *gqinode = info->dqi_gqinode;
456 int need_alloc = ocfs2_global_qinit_alloc(sb, type);
457 handle_t *handle = NULL;
Jan Kara9e33d692008-08-25 19:56:50 +0200458
459 err = ocfs2_qinfo_lock(info, 0);
460 if (err < 0)
461 goto out;
462 err = qtree_read_dquot(&info->dqi_gi, dquot);
463 if (err < 0)
464 goto out_qlock;
465 OCFS2_DQUOT(dquot)->dq_use_count++;
466 OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
467 OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
Jan Karab409d7a2009-08-06 23:29:34 +0200468 ocfs2_qinfo_unlock(info, 0);
469
Jan Kara9e33d692008-08-25 19:56:50 +0200470 if (!dquot->dq_off) { /* No real quota entry? */
Jan Kara9e33d692008-08-25 19:56:50 +0200471 ex = 1;
Jan Karab409d7a2009-08-06 23:29:34 +0200472 /*
473 * Add blocks to quota file before we start a transaction since
474 * locking allocators ranks above a transaction start
475 */
476 WARN_ON(journal_current_handle());
477 down_write(&OCFS2_I(gqinode)->ip_alloc_sem);
478 err = ocfs2_extend_no_holes(gqinode,
479 gqinode->i_size + (need_alloc << sb->s_blocksize_bits),
480 gqinode->i_size);
481 up_write(&OCFS2_I(gqinode)->ip_alloc_sem);
482 if (err < 0)
483 goto out;
Jan Kara9e33d692008-08-25 19:56:50 +0200484 }
Jan Karab409d7a2009-08-06 23:29:34 +0200485
486 handle = ocfs2_start_trans(osb,
487 ocfs2_calc_global_qinit_credits(sb, type));
488 if (IS_ERR(handle)) {
489 err = PTR_ERR(handle);
490 goto out;
491 }
492 err = ocfs2_qinfo_lock(info, ex);
493 if (err < 0)
494 goto out_trans;
Jan Kara9e33d692008-08-25 19:56:50 +0200495 err = qtree_write_dquot(&info->dqi_gi, dquot);
496 if (ex && info_dirty(sb_dqinfo(dquot->dq_sb, dquot->dq_type))) {
497 err2 = __ocfs2_global_write_info(dquot->dq_sb, dquot->dq_type);
498 if (!err)
499 err = err2;
500 }
501out_qlock:
502 if (ex)
503 ocfs2_qinfo_unlock(info, 1);
Jan Kara4e8a3012009-06-02 14:23:59 +0200504 else
505 ocfs2_qinfo_unlock(info, 0);
Jan Karab409d7a2009-08-06 23:29:34 +0200506out_trans:
507 if (handle)
508 ocfs2_commit_trans(osb, handle);
Jan Kara9e33d692008-08-25 19:56:50 +0200509out:
510 if (err < 0)
511 mlog_errno(err);
512 return err;
513}
514
515/* Sync local information about quota modifications with global quota file.
516 * Caller must have started the transaction and obtained exclusive lock for
517 * global quota file inode */
518int __ocfs2_sync_dquot(struct dquot *dquot, int freeing)
519{
520 int err, err2;
521 struct super_block *sb = dquot->dq_sb;
522 int type = dquot->dq_type;
523 struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv;
524 struct ocfs2_global_disk_dqblk dqblk;
525 s64 spacechange, inodechange;
526 time_t olditime, oldbtime;
527
528 err = sb->s_op->quota_read(sb, type, (char *)&dqblk,
529 sizeof(struct ocfs2_global_disk_dqblk),
530 dquot->dq_off);
531 if (err != sizeof(struct ocfs2_global_disk_dqblk)) {
532 if (err >= 0) {
533 mlog(ML_ERROR, "Short read from global quota file "
534 "(%u read)\n", err);
535 err = -EIO;
536 }
537 goto out;
538 }
539
540 /* Update space and inode usage. Get also other information from
541 * global quota file so that we don't overwrite any changes there.
542 * We are */
543 spin_lock(&dq_data_lock);
544 spacechange = dquot->dq_dqb.dqb_curspace -
545 OCFS2_DQUOT(dquot)->dq_origspace;
546 inodechange = dquot->dq_dqb.dqb_curinodes -
547 OCFS2_DQUOT(dquot)->dq_originodes;
548 olditime = dquot->dq_dqb.dqb_itime;
549 oldbtime = dquot->dq_dqb.dqb_btime;
550 ocfs2_global_disk2memdqb(dquot, &dqblk);
Jan Kara9a2f3862008-11-25 15:31:30 +0100551 mlog(0, "Syncing global dquot %u space %lld+%lld, inodes %lld+%lld\n",
552 dquot->dq_id, dquot->dq_dqb.dqb_curspace, (long long)spacechange,
553 dquot->dq_dqb.dqb_curinodes, (long long)inodechange);
Jan Kara9e33d692008-08-25 19:56:50 +0200554 if (!test_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags))
555 dquot->dq_dqb.dqb_curspace += spacechange;
556 if (!test_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags))
557 dquot->dq_dqb.dqb_curinodes += inodechange;
558 /* Set properly space grace time... */
559 if (dquot->dq_dqb.dqb_bsoftlimit &&
560 dquot->dq_dqb.dqb_curspace > dquot->dq_dqb.dqb_bsoftlimit) {
561 if (!test_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags) &&
562 oldbtime > 0) {
563 if (dquot->dq_dqb.dqb_btime > 0)
564 dquot->dq_dqb.dqb_btime =
565 min(dquot->dq_dqb.dqb_btime, oldbtime);
566 else
567 dquot->dq_dqb.dqb_btime = oldbtime;
568 }
569 } else {
570 dquot->dq_dqb.dqb_btime = 0;
571 clear_bit(DQ_BLKS_B, &dquot->dq_flags);
572 }
573 /* Set properly inode grace time... */
574 if (dquot->dq_dqb.dqb_isoftlimit &&
575 dquot->dq_dqb.dqb_curinodes > dquot->dq_dqb.dqb_isoftlimit) {
576 if (!test_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags) &&
577 olditime > 0) {
578 if (dquot->dq_dqb.dqb_itime > 0)
579 dquot->dq_dqb.dqb_itime =
580 min(dquot->dq_dqb.dqb_itime, olditime);
581 else
582 dquot->dq_dqb.dqb_itime = olditime;
583 }
584 } else {
585 dquot->dq_dqb.dqb_itime = 0;
586 clear_bit(DQ_INODES_B, &dquot->dq_flags);
587 }
588 /* All information is properly updated, clear the flags */
589 __clear_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
590 __clear_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
591 __clear_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
592 __clear_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
593 __clear_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
594 __clear_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
595 OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
596 OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
597 spin_unlock(&dq_data_lock);
598 err = ocfs2_qinfo_lock(info, freeing);
599 if (err < 0) {
600 mlog(ML_ERROR, "Failed to lock quota info, loosing quota write"
601 " (type=%d, id=%u)\n", dquot->dq_type,
602 (unsigned)dquot->dq_id);
603 goto out;
604 }
605 if (freeing)
606 OCFS2_DQUOT(dquot)->dq_use_count--;
607 err = qtree_write_dquot(&info->dqi_gi, dquot);
608 if (err < 0)
609 goto out_qlock;
610 if (freeing && !OCFS2_DQUOT(dquot)->dq_use_count) {
611 err = qtree_release_dquot(&info->dqi_gi, dquot);
612 if (info_dirty(sb_dqinfo(sb, type))) {
613 err2 = __ocfs2_global_write_info(sb, type);
614 if (!err)
615 err = err2;
616 }
617 }
618out_qlock:
619 ocfs2_qinfo_unlock(info, freeing);
620out:
621 if (err < 0)
622 mlog_errno(err);
623 return err;
624}
625
626/*
Mark Fasheh171bf932008-10-20 15:36:47 +0200627 * Functions for periodic syncing of dquots with global file
628 */
629static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type)
630{
631 handle_t *handle;
632 struct super_block *sb = dquot->dq_sb;
633 struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
634 struct ocfs2_super *osb = OCFS2_SB(sb);
635 int status = 0;
636
637 mlog_entry("id=%u qtype=%u type=%lu device=%s\n", dquot->dq_id,
638 dquot->dq_type, type, sb->s_id);
639 if (type != dquot->dq_type)
640 goto out;
641 status = ocfs2_lock_global_qf(oinfo, 1);
642 if (status < 0)
643 goto out;
644
645 handle = ocfs2_start_trans(osb, OCFS2_QSYNC_CREDITS);
646 if (IS_ERR(handle)) {
647 status = PTR_ERR(handle);
648 mlog_errno(status);
649 goto out_ilock;
650 }
651 mutex_lock(&sb_dqopt(sb)->dqio_mutex);
652 status = ocfs2_sync_dquot(dquot);
653 mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
654 if (status < 0)
655 mlog_errno(status);
656 /* We have to write local structure as well... */
657 dquot_mark_dquot_dirty(dquot);
658 status = dquot_commit(dquot);
659 if (status < 0)
660 mlog_errno(status);
661 ocfs2_commit_trans(osb, handle);
662out_ilock:
663 ocfs2_unlock_global_qf(oinfo, 1);
664out:
665 mlog_exit(status);
666 return status;
667}
668
669static void qsync_work_fn(struct work_struct *work)
670{
671 struct ocfs2_mem_dqinfo *oinfo = container_of(work,
672 struct ocfs2_mem_dqinfo,
673 dqi_sync_work.work);
674 struct super_block *sb = oinfo->dqi_gqinode->i_sb;
675
676 dquot_scan_active(sb, ocfs2_sync_dquot_helper, oinfo->dqi_type);
677 queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
Jan Kara4539f1d2009-07-22 13:17:20 +0200678 msecs_to_jiffies(oinfo->dqi_syncms));
Mark Fasheh171bf932008-10-20 15:36:47 +0200679}
680
681/*
Jan Kara9e33d692008-08-25 19:56:50 +0200682 * Wrappers for generic quota functions
683 */
684
685static int ocfs2_write_dquot(struct dquot *dquot)
686{
687 handle_t *handle;
688 struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
689 int status = 0;
690
691 mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
692
693 handle = ocfs2_start_trans(osb, OCFS2_QWRITE_CREDITS);
694 if (IS_ERR(handle)) {
695 status = PTR_ERR(handle);
696 mlog_errno(status);
697 goto out;
698 }
699 status = dquot_commit(dquot);
700 ocfs2_commit_trans(osb, handle);
701out:
702 mlog_exit(status);
703 return status;
704}
705
Jan Karab409d7a2009-08-06 23:29:34 +0200706static int ocfs2_calc_qdel_credits(struct super_block *sb, int type)
Jan Kara9e33d692008-08-25 19:56:50 +0200707{
Jan Karab409d7a2009-08-06 23:29:34 +0200708 struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
Jan Kara05849742009-07-22 13:17:21 +0200709 /*
710 * We modify tree, leaf block, global info, local chunk header,
711 * global and local inode; OCFS2_QINFO_WRITE_CREDITS already
712 * accounts for inode update
713 */
Jan Karab409d7a2009-08-06 23:29:34 +0200714 return (oinfo->dqi_gi.dqi_qtree_depth + 2) *
715 OCFS2_QUOTA_BLOCK_UPDATE_CREDITS +
Jan Kara05849742009-07-22 13:17:21 +0200716 OCFS2_QINFO_WRITE_CREDITS +
Jan Kara05849742009-07-22 13:17:21 +0200717 OCFS2_INODE_UPDATE_CREDITS;
Jan Kara9e33d692008-08-25 19:56:50 +0200718}
719
720static int ocfs2_release_dquot(struct dquot *dquot)
721{
722 handle_t *handle;
723 struct ocfs2_mem_dqinfo *oinfo =
724 sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
725 struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
726 int status = 0;
727
728 mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
729
730 status = ocfs2_lock_global_qf(oinfo, 1);
731 if (status < 0)
732 goto out;
733 handle = ocfs2_start_trans(osb,
734 ocfs2_calc_qdel_credits(dquot->dq_sb, dquot->dq_type));
735 if (IS_ERR(handle)) {
736 status = PTR_ERR(handle);
737 mlog_errno(status);
738 goto out_ilock;
739 }
740 status = dquot_release(dquot);
741 ocfs2_commit_trans(osb, handle);
742out_ilock:
743 ocfs2_unlock_global_qf(oinfo, 1);
744out:
745 mlog_exit(status);
746 return status;
747}
748
Jan Kara9e33d692008-08-25 19:56:50 +0200749static int ocfs2_acquire_dquot(struct dquot *dquot)
750{
Jan Kara9e33d692008-08-25 19:56:50 +0200751 struct ocfs2_mem_dqinfo *oinfo =
752 sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
Jan Kara9e33d692008-08-25 19:56:50 +0200753 int status = 0;
754
755 mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
756 /* We need an exclusive lock, because we're going to update use count
757 * and instantiate possibly new dquot structure */
758 status = ocfs2_lock_global_qf(oinfo, 1);
759 if (status < 0)
760 goto out;
Jan Kara9e33d692008-08-25 19:56:50 +0200761 status = dquot_acquire(dquot);
Jan Kara9e33d692008-08-25 19:56:50 +0200762 ocfs2_unlock_global_qf(oinfo, 1);
763out:
764 mlog_exit(status);
765 return status;
766}
767
768static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
769{
770 unsigned long mask = (1 << (DQ_LASTSET_B + QIF_ILIMITS_B)) |
771 (1 << (DQ_LASTSET_B + QIF_BLIMITS_B)) |
772 (1 << (DQ_LASTSET_B + QIF_INODES_B)) |
773 (1 << (DQ_LASTSET_B + QIF_SPACE_B)) |
774 (1 << (DQ_LASTSET_B + QIF_BTIME_B)) |
775 (1 << (DQ_LASTSET_B + QIF_ITIME_B));
776 int sync = 0;
777 int status;
778 struct super_block *sb = dquot->dq_sb;
779 int type = dquot->dq_type;
780 struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
781 handle_t *handle;
782 struct ocfs2_super *osb = OCFS2_SB(sb);
783
784 mlog_entry("id=%u, type=%d", dquot->dq_id, type);
785 dquot_mark_dquot_dirty(dquot);
786
787 /* In case user set some limits, sync dquot immediately to global
788 * quota file so that information propagates quicker */
789 spin_lock(&dq_data_lock);
790 if (dquot->dq_flags & mask)
791 sync = 1;
792 spin_unlock(&dq_data_lock);
Jan Karaf8afead2009-01-12 23:20:32 +0100793 /* This is a slight hack but we can't afford getting global quota
794 * lock if we already have a transaction started. */
795 if (!sync || journal_current_handle()) {
Jan Kara9e33d692008-08-25 19:56:50 +0200796 status = ocfs2_write_dquot(dquot);
797 goto out;
798 }
799 status = ocfs2_lock_global_qf(oinfo, 1);
800 if (status < 0)
801 goto out;
802 handle = ocfs2_start_trans(osb, OCFS2_QSYNC_CREDITS);
803 if (IS_ERR(handle)) {
804 status = PTR_ERR(handle);
805 mlog_errno(status);
806 goto out_ilock;
807 }
808 status = ocfs2_sync_dquot(dquot);
809 if (status < 0) {
810 mlog_errno(status);
811 goto out_trans;
812 }
813 /* Now write updated local dquot structure */
814 status = dquot_commit(dquot);
815out_trans:
816 ocfs2_commit_trans(osb, handle);
817out_ilock:
818 ocfs2_unlock_global_qf(oinfo, 1);
819out:
820 mlog_exit(status);
821 return status;
822}
823
824/* This should happen only after set_dqinfo(). */
825static int ocfs2_write_info(struct super_block *sb, int type)
826{
827 handle_t *handle;
828 int status = 0;
829 struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
830
831 mlog_entry_void();
832
833 status = ocfs2_lock_global_qf(oinfo, 1);
834 if (status < 0)
835 goto out;
836 handle = ocfs2_start_trans(OCFS2_SB(sb), OCFS2_QINFO_WRITE_CREDITS);
837 if (IS_ERR(handle)) {
838 status = PTR_ERR(handle);
839 mlog_errno(status);
840 goto out_ilock;
841 }
842 status = dquot_commit_info(sb, type);
843 ocfs2_commit_trans(OCFS2_SB(sb), handle);
844out_ilock:
845 ocfs2_unlock_global_qf(oinfo, 1);
846out:
847 mlog_exit(status);
848 return status;
849}
850
Jan Kara9e33d692008-08-25 19:56:50 +0200851static struct dquot *ocfs2_alloc_dquot(struct super_block *sb, int type)
852{
853 struct ocfs2_dquot *dquot =
854 kmem_cache_zalloc(ocfs2_dquot_cachep, GFP_NOFS);
855
856 if (!dquot)
857 return NULL;
858 return &dquot->dq_dquot;
859}
860
861static void ocfs2_destroy_dquot(struct dquot *dquot)
862{
863 kmem_cache_free(ocfs2_dquot_cachep, dquot);
864}
865
Alexey Dobriyan61e225d2009-09-21 17:01:08 -0700866const struct dquot_operations ocfs2_quota_operations = {
Jan Kara9e33d692008-08-25 19:56:50 +0200867 .write_dquot = ocfs2_write_dquot,
868 .acquire_dquot = ocfs2_acquire_dquot,
869 .release_dquot = ocfs2_release_dquot,
870 .mark_dirty = ocfs2_mark_dquot_dirty,
871 .write_info = ocfs2_write_info,
872 .alloc_dquot = ocfs2_alloc_dquot,
873 .destroy_dquot = ocfs2_destroy_dquot,
874};
Mark Fasheh171bf932008-10-20 15:36:47 +0200875
876int ocfs2_quota_setup(void)
877{
878 ocfs2_quota_wq = create_workqueue("o2quot");
879 if (!ocfs2_quota_wq)
880 return -ENOMEM;
881 return 0;
882}
883
884void ocfs2_quota_shutdown(void)
885{
886 if (ocfs2_quota_wq) {
887 flush_workqueue(ocfs2_quota_wq);
888 destroy_workqueue(ocfs2_quota_wq);
889 ocfs2_quota_wq = NULL;
890 }
891}