diff options
Diffstat (limited to 'fs/ocfs2/dlmglue.c')
-rw-r--r-- | fs/ocfs2/dlmglue.c | 146 |
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 { | |||
68 | static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres); | 70 | static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres); |
69 | static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres); | 71 | static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres); |
70 | static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres); | 72 | static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres); |
73 | static 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, | |||
102 | static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, | 105 | static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, |
103 | struct ocfs2_lock_res *lockres); | 106 | struct ocfs2_lock_res *lockres); |
104 | 107 | ||
108 | static 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 | ||
265 | static 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 | |||
261 | static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) | 271 | static 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 | ||
292 | static 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 | |||
282 | static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres) | 299 | static 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 | ||
527 | static 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 | |||
510 | static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres) | 534 | static 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 | ||
636 | void 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 | |||
612 | void ocfs2_lock_res_free(struct ocfs2_lock_res *res) | 647 | void 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 | ||
3483 | static 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 | |||
3504 | void 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 | |||
3516 | static 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 | |||
3553 | bail: | ||
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. */ | ||
3559 | int 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); | ||
3589 | bail: | ||
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. |