diff options
| -rw-r--r-- | fs/ocfs2/dlmglue.c | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 399d6e24b8db..d92756dcd477 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
| @@ -71,7 +71,7 @@ static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres); | |||
| 71 | 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); |
| 72 | 72 | ||
| 73 | /* | 73 | /* |
| 74 | * Return value from ocfs2_convert_worker_t functions. | 74 | * Return value from ->downconvert_worker functions. |
| 75 | * | 75 | * |
| 76 | * These control the precise actions of ocfs2_generic_unblock_lock() | 76 | * These control the precise actions of ocfs2_generic_unblock_lock() |
| 77 | * and ocfs2_process_blocked_lock() | 77 | * and ocfs2_process_blocked_lock() |
| @@ -98,16 +98,23 @@ static void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres); | |||
| 98 | 98 | ||
| 99 | static int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, | 99 | static int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, |
| 100 | struct ocfs2_unblock_ctl *ctl); | 100 | struct ocfs2_unblock_ctl *ctl); |
| 101 | static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, | ||
| 102 | int blocking); | ||
| 103 | |||
| 101 | static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, | 104 | static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, |
| 102 | struct ocfs2_unblock_ctl *ctl); | 105 | struct ocfs2_unblock_ctl *ctl); |
| 106 | |||
| 103 | static int ocfs2_unblock_dentry_lock(struct ocfs2_lock_res *lockres, | 107 | static int ocfs2_unblock_dentry_lock(struct ocfs2_lock_res *lockres, |
| 104 | struct ocfs2_unblock_ctl *ctl); | 108 | struct ocfs2_unblock_ctl *ctl); |
| 105 | static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, | 109 | static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres, |
| 106 | struct ocfs2_unblock_ctl *ctl); | 110 | int blocking); |
| 107 | 111 | ||
| 108 | static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, | 112 | static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, |
| 109 | struct ocfs2_lock_res *lockres); | 113 | struct ocfs2_lock_res *lockres); |
| 110 | 114 | ||
| 115 | static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, | ||
| 116 | struct ocfs2_unblock_ctl *ctl); | ||
| 117 | |||
| 111 | /* | 118 | /* |
| 112 | * OCFS2 Lock Resource Operations | 119 | * OCFS2 Lock Resource Operations |
| 113 | * | 120 | * |
| @@ -146,6 +153,17 @@ struct ocfs2_lock_res_ops { | |||
| 146 | void (*set_lvb)(struct ocfs2_lock_res *); | 153 | void (*set_lvb)(struct ocfs2_lock_res *); |
| 147 | 154 | ||
| 148 | /* | 155 | /* |
| 156 | * Called from the downconvert thread when it is determined | ||
| 157 | * that a lock will be downconverted. This is called without | ||
| 158 | * any locks held so the function can do work that might | ||
| 159 | * schedule (syncing out data, etc). | ||
| 160 | * | ||
| 161 | * This should return any one of the ocfs2_unblock_action | ||
| 162 | * values, depending on what it wants the thread to do. | ||
| 163 | */ | ||
| 164 | int (*downconvert_worker)(struct ocfs2_lock_res *, int); | ||
| 165 | |||
| 166 | /* | ||
| 149 | * LOCK_TYPE_* flags which describe the specific requirements | 167 | * LOCK_TYPE_* flags which describe the specific requirements |
| 150 | * of a lock type. Descriptions of each individual flag follow. | 168 | * of a lock type. Descriptions of each individual flag follow. |
| 151 | */ | 169 | */ |
| @@ -168,11 +186,9 @@ struct ocfs2_lock_res_ops { | |||
| 168 | */ | 186 | */ |
| 169 | #define LOCK_TYPE_USES_LVB 0x2 | 187 | #define LOCK_TYPE_USES_LVB 0x2 |
| 170 | 188 | ||
| 171 | typedef int (ocfs2_convert_worker_t)(struct ocfs2_lock_res *, int); | ||
| 172 | static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, | 189 | static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, |
| 173 | struct ocfs2_lock_res *lockres, | 190 | struct ocfs2_lock_res *lockres, |
| 174 | struct ocfs2_unblock_ctl *ctl, | 191 | struct ocfs2_unblock_ctl *ctl); |
| 175 | ocfs2_convert_worker_t *worker); | ||
| 176 | 192 | ||
| 177 | static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { | 193 | static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { |
| 178 | .get_osb = ocfs2_get_inode_osb, | 194 | .get_osb = ocfs2_get_inode_osb, |
| @@ -191,6 +207,7 @@ static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { | |||
| 191 | static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { | 207 | static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { |
| 192 | .get_osb = ocfs2_get_inode_osb, | 208 | .get_osb = ocfs2_get_inode_osb, |
| 193 | .unblock = ocfs2_unblock_data, | 209 | .unblock = ocfs2_unblock_data, |
| 210 | .downconvert_worker = ocfs2_data_convert_worker, | ||
| 194 | .flags = 0, | 211 | .flags = 0, |
| 195 | }; | 212 | }; |
| 196 | 213 | ||
| @@ -208,6 +225,7 @@ static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { | |||
| 208 | .get_osb = ocfs2_get_dentry_osb, | 225 | .get_osb = ocfs2_get_dentry_osb, |
| 209 | .unblock = ocfs2_unblock_dentry_lock, | 226 | .unblock = ocfs2_unblock_dentry_lock, |
| 210 | .post_unlock = ocfs2_dentry_post_unlock, | 227 | .post_unlock = ocfs2_dentry_post_unlock, |
| 228 | .downconvert_worker = ocfs2_dentry_convert_worker, | ||
| 211 | .flags = 0, | 229 | .flags = 0, |
| 212 | }; | 230 | }; |
| 213 | 231 | ||
| @@ -2537,8 +2555,7 @@ static int ocfs2_cancel_convert(struct ocfs2_super *osb, | |||
| 2537 | 2555 | ||
| 2538 | static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, | 2556 | static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, |
| 2539 | struct ocfs2_lock_res *lockres, | 2557 | struct ocfs2_lock_res *lockres, |
| 2540 | struct ocfs2_unblock_ctl *ctl, | 2558 | struct ocfs2_unblock_ctl *ctl) |
| 2541 | ocfs2_convert_worker_t *worker) | ||
| 2542 | { | 2559 | { |
| 2543 | unsigned long flags; | 2560 | unsigned long flags; |
| 2544 | int blocking; | 2561 | int blocking; |
| @@ -2594,7 +2611,7 @@ recheck: | |||
| 2594 | /* If we get here, then we know that there are no more | 2611 | /* If we get here, then we know that there are no more |
| 2595 | * incompatible holders (and anyone asking for an incompatible | 2612 | * incompatible holders (and anyone asking for an incompatible |
| 2596 | * lock is blocked). We can now downconvert the lock */ | 2613 | * lock is blocked). We can now downconvert the lock */ |
| 2597 | if (!worker) | 2614 | if (!lockres->l_ops->downconvert_worker) |
| 2598 | goto downconvert; | 2615 | goto downconvert; |
| 2599 | 2616 | ||
| 2600 | /* Some lockres types want to do a bit of work before | 2617 | /* Some lockres types want to do a bit of work before |
| @@ -2604,7 +2621,7 @@ recheck: | |||
| 2604 | blocking = lockres->l_blocking; | 2621 | blocking = lockres->l_blocking; |
| 2605 | spin_unlock_irqrestore(&lockres->l_lock, flags); | 2622 | spin_unlock_irqrestore(&lockres->l_lock, flags); |
| 2606 | 2623 | ||
| 2607 | ctl->unblock_action = worker(lockres, blocking); | 2624 | ctl->unblock_action = lockres->l_ops->downconvert_worker(lockres, blocking); |
| 2608 | 2625 | ||
| 2609 | if (ctl->unblock_action == UNBLOCK_STOP_POST) | 2626 | if (ctl->unblock_action == UNBLOCK_STOP_POST) |
| 2610 | goto leave; | 2627 | goto leave; |
| @@ -2692,8 +2709,7 @@ int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, | |||
| 2692 | mlog(0, "unblock inode %llu\n", | 2709 | mlog(0, "unblock inode %llu\n", |
| 2693 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | 2710 | (unsigned long long)OCFS2_I(inode)->ip_blkno); |
| 2694 | 2711 | ||
| 2695 | status = ocfs2_generic_unblock_lock(osb, lockres, ctl, | 2712 | status = ocfs2_generic_unblock_lock(osb, lockres, ctl); |
| 2696 | ocfs2_data_convert_worker); | ||
| 2697 | if (status < 0) | 2713 | if (status < 0) |
| 2698 | mlog_errno(status); | 2714 | mlog_errno(status); |
| 2699 | 2715 | ||
| @@ -2717,7 +2733,7 @@ static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, | |||
| 2717 | inode = ocfs2_lock_res_inode(lockres); | 2733 | inode = ocfs2_lock_res_inode(lockres); |
| 2718 | 2734 | ||
| 2719 | status = ocfs2_generic_unblock_lock(OCFS2_SB(inode->i_sb), | 2735 | status = ocfs2_generic_unblock_lock(OCFS2_SB(inode->i_sb), |
| 2720 | lockres, ctl, NULL); | 2736 | lockres, ctl); |
| 2721 | if (status < 0) | 2737 | if (status < 0) |
| 2722 | mlog_errno(status); | 2738 | mlog_errno(status); |
| 2723 | 2739 | ||
| @@ -2762,7 +2778,7 @@ static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, | |||
| 2762 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | 2778 | (unsigned long long)OCFS2_I(inode)->ip_blkno); |
| 2763 | 2779 | ||
| 2764 | status = ocfs2_generic_unblock_lock(OCFS2_SB(inode->i_sb), | 2780 | status = ocfs2_generic_unblock_lock(OCFS2_SB(inode->i_sb), |
| 2765 | lockres, ctl, NULL); | 2781 | lockres, ctl); |
| 2766 | if (status < 0) | 2782 | if (status < 0) |
| 2767 | mlog_errno(status); | 2783 | mlog_errno(status); |
| 2768 | 2784 | ||
| @@ -2907,8 +2923,7 @@ static int ocfs2_unblock_dentry_lock(struct ocfs2_lock_res *lockres, | |||
| 2907 | 2923 | ||
| 2908 | ret = ocfs2_generic_unblock_lock(osb, | 2924 | ret = ocfs2_generic_unblock_lock(osb, |
| 2909 | lockres, | 2925 | lockres, |
| 2910 | ctl, | 2926 | ctl); |
| 2911 | ocfs2_dentry_convert_worker); | ||
| 2912 | if (ret < 0) | 2927 | if (ret < 0) |
| 2913 | mlog_errno(ret); | 2928 | mlog_errno(ret); |
| 2914 | 2929 | ||
| @@ -2933,8 +2948,7 @@ static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, | |||
| 2933 | 2948 | ||
| 2934 | status = ocfs2_generic_unblock_lock(osb, | 2949 | status = ocfs2_generic_unblock_lock(osb, |
| 2935 | lockres, | 2950 | lockres, |
| 2936 | ctl, | 2951 | ctl); |
| 2937 | NULL); | ||
| 2938 | if (status < 0) | 2952 | if (status < 0) |
| 2939 | mlog_errno(status); | 2953 | mlog_errno(status); |
| 2940 | 2954 | ||
