aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/dlmglue.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2008-08-25 13:56:50 -0400
committerMark Fasheh <mfasheh@suse.com>2009-01-05 11:40:23 -0500
commit9e33d69f553aaf11377307e8d6f82deb3385e351 (patch)
treeded5f48f6cf82db976f30d5f0f4d44b941f60f44 /fs/ocfs2/dlmglue.c
parentbbbd0eb34bf801dee01e345785959a75258f6567 (diff)
ocfs2: Implementation of local and global quota file handling
For each quota type each node has local quota file. In this file it stores changes users have made to disk usage via this node. Once in a while this information is synced to global file (and thus with other nodes) so that limits enforcement at least aproximately works. Global quota files contain all the information about usage and limits. It's mostly handled by the generic VFS code (which implements a trie of structures inside a quota file). We only have to provide functions to convert structures from on-disk format to in-memory one. We also have to provide wrappers for various quota functions starting transactions and acquiring necessary cluster locks before the actual IO is really started. Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/dlmglue.c')
-rw-r--r--fs/ocfs2/dlmglue.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 9f2a7f75d1b3..058aa86490ae 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -32,6 +32,7 @@
32#include <linux/debugfs.h> 32#include <linux/debugfs.h>
33#include <linux/seq_file.h> 33#include <linux/seq_file.h>
34#include <linux/time.h> 34#include <linux/time.h>
35#include <linux/quotaops.h>
35 36
36#define MLOG_MASK_PREFIX ML_DLM_GLUE 37#define MLOG_MASK_PREFIX ML_DLM_GLUE
37#include <cluster/masklog.h> 38#include <cluster/masklog.h>
@@ -51,6 +52,7 @@
51#include "slot_map.h" 52#include "slot_map.h"
52#include "super.h" 53#include "super.h"
53#include "uptodate.h" 54#include "uptodate.h"
55#include "quota.h"
54 56
55#include "buffer_head_io.h" 57#include "buffer_head_io.h"
56 58
@@ -68,6 +70,7 @@ struct ocfs2_mask_waiter {
68static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres); 70static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres);
69static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres); 71static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres);
70static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres); 72static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres);
73static struct ocfs2_super *ocfs2_get_qinfo_osb(struct ocfs2_lock_res *lockres);
71 74
72/* 75/*
73 * Return value from ->downconvert_worker functions. 76 * Return value from ->downconvert_worker functions.
@@ -102,6 +105,7 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
102static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, 105static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb,
103 struct ocfs2_lock_res *lockres); 106 struct ocfs2_lock_res *lockres);
104 107
108static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres);
105 109
106#define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres) 110#define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres)
107 111
@@ -258,6 +262,12 @@ static struct ocfs2_lock_res_ops ocfs2_flock_lops = {
258 .flags = 0, 262 .flags = 0,
259}; 263};
260 264
265static struct ocfs2_lock_res_ops ocfs2_qinfo_lops = {
266 .set_lvb = ocfs2_set_qinfo_lvb,
267 .get_osb = ocfs2_get_qinfo_osb,
268 .flags = LOCK_TYPE_REQUIRES_REFRESH | LOCK_TYPE_USES_LVB,
269};
270
261static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) 271static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres)
262{ 272{
263 return lockres->l_type == OCFS2_LOCK_TYPE_META || 273 return lockres->l_type == OCFS2_LOCK_TYPE_META ||
@@ -279,6 +289,13 @@ static inline struct ocfs2_dentry_lock *ocfs2_lock_res_dl(struct ocfs2_lock_res
279 return (struct ocfs2_dentry_lock *)lockres->l_priv; 289 return (struct ocfs2_dentry_lock *)lockres->l_priv;
280} 290}
281 291
292static inline struct ocfs2_mem_dqinfo *ocfs2_lock_res_qinfo(struct ocfs2_lock_res *lockres)
293{
294 BUG_ON(lockres->l_type != OCFS2_LOCK_TYPE_QINFO);
295
296 return (struct ocfs2_mem_dqinfo *)lockres->l_priv;
297}
298
282static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres) 299static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres)
283{ 300{
284 if (lockres->l_ops->get_osb) 301 if (lockres->l_ops->get_osb)
@@ -507,6 +524,13 @@ static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres)
507 return OCFS2_SB(inode->i_sb); 524 return OCFS2_SB(inode->i_sb);
508} 525}
509 526
527static struct ocfs2_super *ocfs2_get_qinfo_osb(struct ocfs2_lock_res *lockres)
528{
529 struct ocfs2_mem_dqinfo *info = lockres->l_priv;
530
531 return OCFS2_SB(info->dqi_gi.dqi_sb);
532}
533
510static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres) 534static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres)
511{ 535{
512 struct ocfs2_file_private *fp = lockres->l_priv; 536 struct ocfs2_file_private *fp = lockres->l_priv;
@@ -609,6 +633,17 @@ void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres,
609 lockres->l_flags |= OCFS2_LOCK_NOCACHE; 633 lockres->l_flags |= OCFS2_LOCK_NOCACHE;
610} 634}
611 635
636void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
637 struct ocfs2_mem_dqinfo *info)
638{
639 ocfs2_lock_res_init_once(lockres);
640 ocfs2_build_lock_name(OCFS2_LOCK_TYPE_QINFO, info->dqi_gi.dqi_type,
641 0, lockres->l_name);
642 ocfs2_lock_res_init_common(OCFS2_SB(info->dqi_gi.dqi_sb), lockres,
643 OCFS2_LOCK_TYPE_QINFO, &ocfs2_qinfo_lops,
644 info);
645}
646
612void ocfs2_lock_res_free(struct ocfs2_lock_res *res) 647void ocfs2_lock_res_free(struct ocfs2_lock_res *res)
613{ 648{
614 mlog_entry_void(); 649 mlog_entry_void();
@@ -3445,6 +3480,117 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
3445 return UNBLOCK_CONTINUE_POST; 3480 return UNBLOCK_CONTINUE_POST;
3446} 3481}
3447 3482
3483static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres)
3484{
3485 struct ocfs2_qinfo_lvb *lvb;
3486 struct ocfs2_mem_dqinfo *oinfo = ocfs2_lock_res_qinfo(lockres);
3487 struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb,
3488 oinfo->dqi_gi.dqi_type);
3489
3490 mlog_entry_void();
3491
3492 lvb = (struct ocfs2_qinfo_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
3493 lvb->lvb_version = OCFS2_QINFO_LVB_VERSION;
3494 lvb->lvb_bgrace = cpu_to_be32(info->dqi_bgrace);
3495 lvb->lvb_igrace = cpu_to_be32(info->dqi_igrace);
3496 lvb->lvb_syncms = cpu_to_be32(oinfo->dqi_syncms);
3497 lvb->lvb_blocks = cpu_to_be32(oinfo->dqi_gi.dqi_blocks);
3498 lvb->lvb_free_blk = cpu_to_be32(oinfo->dqi_gi.dqi_free_blk);
3499 lvb->lvb_free_entry = cpu_to_be32(oinfo->dqi_gi.dqi_free_entry);
3500
3501 mlog_exit_void();
3502}
3503
3504void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex)
3505{
3506 struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
3507 struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb);
3508 int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
3509
3510 mlog_entry_void();
3511 if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb))
3512 ocfs2_cluster_unlock(osb, lockres, level);
3513 mlog_exit_void();
3514}
3515
3516static int ocfs2_refresh_qinfo(struct ocfs2_mem_dqinfo *oinfo)
3517{
3518 struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb,
3519 oinfo->dqi_gi.dqi_type);
3520 struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
3521 struct ocfs2_qinfo_lvb *lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
3522 struct buffer_head *bh;
3523 struct ocfs2_global_disk_dqinfo *gdinfo;
3524 int status = 0;
3525
3526 if (lvb->lvb_version == OCFS2_QINFO_LVB_VERSION) {
3527 info->dqi_bgrace = be32_to_cpu(lvb->lvb_bgrace);
3528 info->dqi_igrace = be32_to_cpu(lvb->lvb_igrace);
3529 oinfo->dqi_syncms = be32_to_cpu(lvb->lvb_syncms);
3530 oinfo->dqi_gi.dqi_blocks = be32_to_cpu(lvb->lvb_blocks);
3531 oinfo->dqi_gi.dqi_free_blk = be32_to_cpu(lvb->lvb_free_blk);
3532 oinfo->dqi_gi.dqi_free_entry =
3533 be32_to_cpu(lvb->lvb_free_entry);
3534 } else {
3535 bh = ocfs2_read_quota_block(oinfo->dqi_gqinode, 0, &status);
3536 if (!bh) {
3537 mlog_errno(status);
3538 goto bail;
3539 }
3540 gdinfo = (struct ocfs2_global_disk_dqinfo *)
3541 (bh->b_data + OCFS2_GLOBAL_INFO_OFF);
3542 info->dqi_bgrace = le32_to_cpu(gdinfo->dqi_bgrace);
3543 info->dqi_igrace = le32_to_cpu(gdinfo->dqi_igrace);
3544 oinfo->dqi_syncms = le32_to_cpu(gdinfo->dqi_syncms);
3545 oinfo->dqi_gi.dqi_blocks = le32_to_cpu(gdinfo->dqi_blocks);
3546 oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(gdinfo->dqi_free_blk);
3547 oinfo->dqi_gi.dqi_free_entry =
3548 le32_to_cpu(gdinfo->dqi_free_entry);
3549 brelse(bh);
3550 ocfs2_track_lock_refresh(lockres);
3551 }
3552
3553bail:
3554 return status;
3555}
3556
3557/* Lock quota info, this function expects at least shared lock on the quota file
3558 * so that we can safely refresh quota info from disk. */
3559int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex)
3560{
3561 struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
3562 struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb);
3563 int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
3564 int status = 0;
3565
3566 mlog_entry_void();
3567
3568 /* On RO devices, locking really isn't needed... */
3569 if (ocfs2_is_hard_readonly(osb)) {
3570 if (ex)
3571 status = -EROFS;
3572 goto bail;
3573 }
3574 if (ocfs2_mount_local(osb))
3575 goto bail;
3576
3577 status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
3578 if (status < 0) {
3579 mlog_errno(status);
3580 goto bail;
3581 }
3582 if (!ocfs2_should_refresh_lock_res(lockres))
3583 goto bail;
3584 /* OK, we have the lock but we need to refresh the quota info */
3585 status = ocfs2_refresh_qinfo(oinfo);
3586 if (status)
3587 ocfs2_qinfo_unlock(oinfo, ex);
3588 ocfs2_complete_lock_res_refresh(lockres, status);
3589bail:
3590 mlog_exit(status);
3591 return status;
3592}
3593
3448/* 3594/*
3449 * This is the filesystem locking protocol. It provides the lock handling 3595 * This is the filesystem locking protocol. It provides the lock handling
3450 * hooks for the underlying DLM. It has a maximum version number. 3596 * hooks for the underlying DLM. It has a maximum version number.