diff options
author | Tao Ma <tao.ma@oracle.com> | 2009-08-17 23:19:58 -0400 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2009-09-22 23:09:28 -0400 |
commit | 8dec98edfe9684ce00b580a09dde3dcd21ee785b (patch) | |
tree | 3002e990974163a09ea6d427d7cf775aaca7acca /fs/ocfs2/dlmglue.c | |
parent | a433848132d8cdfb8173745b922ddb919de11527 (diff) |
ocfs2: Add new refcount tree lock resource in dlmglue.
refcount tree lock resource is used to protect refcount
tree read/write among multiple nodes.
Signed-off-by: Tao Ma <tao.ma@oracle.com>
Diffstat (limited to 'fs/ocfs2/dlmglue.c')
-rw-r--r-- | fs/ocfs2/dlmglue.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 79db0557df88..bb2fc6993e2a 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(); |
@@ -3648,6 +3677,26 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres, | |||
3648 | return UNBLOCK_CONTINUE_POST; | 3677 | return UNBLOCK_CONTINUE_POST; |
3649 | } | 3678 | } |
3650 | 3679 | ||
3680 | static int ocfs2_check_refcount_downconvert(struct ocfs2_lock_res *lockres, | ||
3681 | int new_level) | ||
3682 | { | ||
3683 | struct ocfs2_refcount_tree *tree = | ||
3684 | ocfs2_lock_res_refcount_tree(lockres); | ||
3685 | |||
3686 | return ocfs2_ci_checkpointed(&tree->rf_ci, lockres, new_level); | ||
3687 | } | ||
3688 | |||
3689 | static int ocfs2_refcount_convert_worker(struct ocfs2_lock_res *lockres, | ||
3690 | int blocking) | ||
3691 | { | ||
3692 | struct ocfs2_refcount_tree *tree = | ||
3693 | ocfs2_lock_res_refcount_tree(lockres); | ||
3694 | |||
3695 | ocfs2_metadata_cache_purge(&tree->rf_ci); | ||
3696 | |||
3697 | return UNBLOCK_CONTINUE; | ||
3698 | } | ||
3699 | |||
3651 | static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres) | 3700 | static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres) |
3652 | { | 3701 | { |
3653 | struct ocfs2_qinfo_lvb *lvb; | 3702 | struct ocfs2_qinfo_lvb *lvb; |
@@ -3760,6 +3809,37 @@ bail: | |||
3760 | return status; | 3809 | return status; |
3761 | } | 3810 | } |
3762 | 3811 | ||
3812 | int ocfs2_refcount_lock(struct ocfs2_refcount_tree *ref_tree, int ex) | ||
3813 | { | ||
3814 | int status; | ||
3815 | int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; | ||
3816 | struct ocfs2_lock_res *lockres = &ref_tree->rf_lockres; | ||
3817 | struct ocfs2_super *osb = lockres->l_priv; | ||
3818 | |||
3819 | |||
3820 | if (ocfs2_is_hard_readonly(osb)) | ||
3821 | return -EROFS; | ||
3822 | |||
3823 | if (ocfs2_mount_local(osb)) | ||
3824 | return 0; | ||
3825 | |||
3826 | status = ocfs2_cluster_lock(osb, lockres, level, 0, 0); | ||
3827 | if (status < 0) | ||
3828 | mlog_errno(status); | ||
3829 | |||
3830 | return status; | ||
3831 | } | ||
3832 | |||
3833 | void ocfs2_refcount_unlock(struct ocfs2_refcount_tree *ref_tree, int ex) | ||
3834 | { | ||
3835 | int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; | ||
3836 | struct ocfs2_lock_res *lockres = &ref_tree->rf_lockres; | ||
3837 | struct ocfs2_super *osb = lockres->l_priv; | ||
3838 | |||
3839 | if (!ocfs2_mount_local(osb)) | ||
3840 | ocfs2_cluster_unlock(osb, lockres, level); | ||
3841 | } | ||
3842 | |||
3763 | /* | 3843 | /* |
3764 | * This is the filesystem locking protocol. It provides the lock handling | 3844 | * This is the filesystem locking protocol. It provides the lock handling |
3765 | * hooks for the underlying DLM. It has a maximum version number. | 3845 | * hooks for the underlying DLM. It has a maximum version number. |