diff options
Diffstat (limited to 'fs/ocfs2/dlmglue.c')
-rw-r--r-- | fs/ocfs2/dlmglue.c | 105 |
1 files changed, 98 insertions, 7 deletions
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 110bb57c46ab..0d38d67194cb 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include "super.h" | 53 | #include "super.h" |
54 | #include "uptodate.h" | 54 | #include "uptodate.h" |
55 | #include "quota.h" | 55 | #include "quota.h" |
56 | #include "refcounttree.h" | ||
56 | 57 | ||
57 | #include "buffer_head_io.h" | 58 | #include "buffer_head_io.h" |
58 | 59 | ||
@@ -110,6 +111,11 @@ static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, | |||
110 | 111 | ||
111 | static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres); | 112 | static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres); |
112 | 113 | ||
114 | static int ocfs2_check_refcount_downconvert(struct ocfs2_lock_res *lockres, | ||
115 | int new_level); | ||
116 | static int ocfs2_refcount_convert_worker(struct ocfs2_lock_res *lockres, | ||
117 | int blocking); | ||
118 | |||
113 | #define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres) | 119 | #define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres) |
114 | 120 | ||
115 | /* This aids in debugging situations where a bad LVB might be involved. */ | 121 | /* This aids in debugging situations where a bad LVB might be involved. */ |
@@ -278,6 +284,12 @@ static struct ocfs2_lock_res_ops ocfs2_qinfo_lops = { | |||
278 | .flags = LOCK_TYPE_REQUIRES_REFRESH | LOCK_TYPE_USES_LVB, | 284 | .flags = LOCK_TYPE_REQUIRES_REFRESH | LOCK_TYPE_USES_LVB, |
279 | }; | 285 | }; |
280 | 286 | ||
287 | static struct ocfs2_lock_res_ops ocfs2_refcount_block_lops = { | ||
288 | .check_downconvert = ocfs2_check_refcount_downconvert, | ||
289 | .downconvert_worker = ocfs2_refcount_convert_worker, | ||
290 | .flags = 0, | ||
291 | }; | ||
292 | |||
281 | static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) | 293 | static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) |
282 | { | 294 | { |
283 | return lockres->l_type == OCFS2_LOCK_TYPE_META || | 295 | return lockres->l_type == OCFS2_LOCK_TYPE_META || |
@@ -306,6 +318,12 @@ static inline struct ocfs2_mem_dqinfo *ocfs2_lock_res_qinfo(struct ocfs2_lock_re | |||
306 | return (struct ocfs2_mem_dqinfo *)lockres->l_priv; | 318 | return (struct ocfs2_mem_dqinfo *)lockres->l_priv; |
307 | } | 319 | } |
308 | 320 | ||
321 | static inline struct ocfs2_refcount_tree * | ||
322 | ocfs2_lock_res_refcount_tree(struct ocfs2_lock_res *res) | ||
323 | { | ||
324 | return container_of(res, struct ocfs2_refcount_tree, rf_lockres); | ||
325 | } | ||
326 | |||
309 | static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres) | 327 | static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres) |
310 | { | 328 | { |
311 | if (lockres->l_ops->get_osb) | 329 | if (lockres->l_ops->get_osb) |
@@ -693,6 +711,17 @@ void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres, | |||
693 | info); | 711 | info); |
694 | } | 712 | } |
695 | 713 | ||
714 | void ocfs2_refcount_lock_res_init(struct ocfs2_lock_res *lockres, | ||
715 | struct ocfs2_super *osb, u64 ref_blkno, | ||
716 | unsigned int generation) | ||
717 | { | ||
718 | ocfs2_lock_res_init_once(lockres); | ||
719 | ocfs2_build_lock_name(OCFS2_LOCK_TYPE_REFCOUNT, ref_blkno, | ||
720 | generation, lockres->l_name); | ||
721 | ocfs2_lock_res_init_common(osb, lockres, OCFS2_LOCK_TYPE_REFCOUNT, | ||
722 | &ocfs2_refcount_block_lops, osb); | ||
723 | } | ||
724 | |||
696 | void ocfs2_lock_res_free(struct ocfs2_lock_res *res) | 725 | void ocfs2_lock_res_free(struct ocfs2_lock_res *res) |
697 | { | 726 | { |
698 | mlog_entry_void(); | 727 | mlog_entry_void(); |
@@ -1548,8 +1577,10 @@ int ocfs2_rw_lock(struct inode *inode, int write) | |||
1548 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | 1577 | (unsigned long long)OCFS2_I(inode)->ip_blkno, |
1549 | write ? "EXMODE" : "PRMODE"); | 1578 | write ? "EXMODE" : "PRMODE"); |
1550 | 1579 | ||
1551 | if (ocfs2_mount_local(osb)) | 1580 | if (ocfs2_mount_local(osb)) { |
1581 | mlog_exit(0); | ||
1552 | return 0; | 1582 | return 0; |
1583 | } | ||
1553 | 1584 | ||
1554 | lockres = &OCFS2_I(inode)->ip_rw_lockres; | 1585 | lockres = &OCFS2_I(inode)->ip_rw_lockres; |
1555 | 1586 | ||
@@ -2127,7 +2158,7 @@ static int ocfs2_inode_lock_update(struct inode *inode, | |||
2127 | 2158 | ||
2128 | /* This will discard any caching information we might have had | 2159 | /* This will discard any caching information we might have had |
2129 | * for the inode metadata. */ | 2160 | * for the inode metadata. */ |
2130 | ocfs2_metadata_cache_purge(inode); | 2161 | ocfs2_metadata_cache_purge(INODE_CACHE(inode)); |
2131 | 2162 | ||
2132 | ocfs2_extent_map_trunc(inode, 0); | 2163 | ocfs2_extent_map_trunc(inode, 0); |
2133 | 2164 | ||
@@ -3009,6 +3040,7 @@ static void ocfs2_unlock_ast(void *opaque, int error) | |||
3009 | "unlock_action %d\n", error, lockres->l_name, | 3040 | "unlock_action %d\n", error, lockres->l_name, |
3010 | lockres->l_unlock_action); | 3041 | lockres->l_unlock_action); |
3011 | spin_unlock_irqrestore(&lockres->l_lock, flags); | 3042 | spin_unlock_irqrestore(&lockres->l_lock, flags); |
3043 | mlog_exit_void(); | ||
3012 | return; | 3044 | return; |
3013 | } | 3045 | } |
3014 | 3046 | ||
@@ -3495,11 +3527,11 @@ out: | |||
3495 | return UNBLOCK_CONTINUE; | 3527 | return UNBLOCK_CONTINUE; |
3496 | } | 3528 | } |
3497 | 3529 | ||
3498 | static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres, | 3530 | static int ocfs2_ci_checkpointed(struct ocfs2_caching_info *ci, |
3499 | int new_level) | 3531 | struct ocfs2_lock_res *lockres, |
3532 | int new_level) | ||
3500 | { | 3533 | { |
3501 | struct inode *inode = ocfs2_lock_res_inode(lockres); | 3534 | int checkpointed = ocfs2_ci_fully_checkpointed(ci); |
3502 | int checkpointed = ocfs2_inode_fully_checkpointed(inode); | ||
3503 | 3535 | ||
3504 | BUG_ON(new_level != DLM_LOCK_NL && new_level != DLM_LOCK_PR); | 3536 | BUG_ON(new_level != DLM_LOCK_NL && new_level != DLM_LOCK_PR); |
3505 | BUG_ON(lockres->l_level != DLM_LOCK_EX && !checkpointed); | 3537 | BUG_ON(lockres->l_level != DLM_LOCK_EX && !checkpointed); |
@@ -3507,10 +3539,18 @@ static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres, | |||
3507 | if (checkpointed) | 3539 | if (checkpointed) |
3508 | return 1; | 3540 | return 1; |
3509 | 3541 | ||
3510 | ocfs2_start_checkpoint(OCFS2_SB(inode->i_sb)); | 3542 | ocfs2_start_checkpoint(OCFS2_SB(ocfs2_metadata_cache_get_super(ci))); |
3511 | return 0; | 3543 | return 0; |
3512 | } | 3544 | } |
3513 | 3545 | ||
3546 | static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres, | ||
3547 | int new_level) | ||
3548 | { | ||
3549 | struct inode *inode = ocfs2_lock_res_inode(lockres); | ||
3550 | |||
3551 | return ocfs2_ci_checkpointed(INODE_CACHE(inode), lockres, new_level); | ||
3552 | } | ||
3553 | |||
3514 | static void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres) | 3554 | static void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres) |
3515 | { | 3555 | { |
3516 | struct inode *inode = ocfs2_lock_res_inode(lockres); | 3556 | struct inode *inode = ocfs2_lock_res_inode(lockres); |
@@ -3640,6 +3680,26 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres, | |||
3640 | return UNBLOCK_CONTINUE_POST; | 3680 | return UNBLOCK_CONTINUE_POST; |
3641 | } | 3681 | } |
3642 | 3682 | ||
3683 | static int ocfs2_check_refcount_downconvert(struct ocfs2_lock_res *lockres, | ||
3684 | int new_level) | ||
3685 | { | ||
3686 | struct ocfs2_refcount_tree *tree = | ||
3687 | ocfs2_lock_res_refcount_tree(lockres); | ||
3688 | |||
3689 | return ocfs2_ci_checkpointed(&tree->rf_ci, lockres, new_level); | ||
3690 | } | ||
3691 | |||
3692 | static int ocfs2_refcount_convert_worker(struct ocfs2_lock_res *lockres, | ||
3693 | int blocking) | ||
3694 | { | ||
3695 | struct ocfs2_refcount_tree *tree = | ||
3696 | ocfs2_lock_res_refcount_tree(lockres); | ||
3697 | |||
3698 | ocfs2_metadata_cache_purge(&tree->rf_ci); | ||
3699 | |||
3700 | return UNBLOCK_CONTINUE; | ||
3701 | } | ||
3702 | |||
3643 | static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres) | 3703 | static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres) |
3644 | { | 3704 | { |
3645 | struct ocfs2_qinfo_lvb *lvb; | 3705 | struct ocfs2_qinfo_lvb *lvb; |
@@ -3752,6 +3812,37 @@ bail: | |||
3752 | return status; | 3812 | return status; |
3753 | } | 3813 | } |
3754 | 3814 | ||
3815 | int ocfs2_refcount_lock(struct ocfs2_refcount_tree *ref_tree, int ex) | ||
3816 | { | ||
3817 | int status; | ||
3818 | int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; | ||
3819 | struct ocfs2_lock_res *lockres = &ref_tree->rf_lockres; | ||
3820 | struct ocfs2_super *osb = lockres->l_priv; | ||
3821 | |||
3822 | |||
3823 | if (ocfs2_is_hard_readonly(osb)) | ||
3824 | return -EROFS; | ||
3825 | |||
3826 | if (ocfs2_mount_local(osb)) | ||
3827 | return 0; | ||
3828 | |||
3829 | status = ocfs2_cluster_lock(osb, lockres, level, 0, 0); | ||
3830 | if (status < 0) | ||
3831 | mlog_errno(status); | ||
3832 | |||
3833 | return status; | ||
3834 | } | ||
3835 | |||
3836 | void ocfs2_refcount_unlock(struct ocfs2_refcount_tree *ref_tree, int ex) | ||
3837 | { | ||
3838 | int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; | ||
3839 | struct ocfs2_lock_res *lockres = &ref_tree->rf_lockres; | ||
3840 | struct ocfs2_super *osb = lockres->l_priv; | ||
3841 | |||
3842 | if (!ocfs2_mount_local(osb)) | ||
3843 | ocfs2_cluster_unlock(osb, lockres, level); | ||
3844 | } | ||
3845 | |||
3755 | /* | 3846 | /* |
3756 | * This is the filesystem locking protocol. It provides the lock handling | 3847 | * This is the filesystem locking protocol. It provides the lock handling |
3757 | * hooks for the underlying DLM. It has a maximum version number. | 3848 | * hooks for the underlying DLM. It has a maximum version number. |