diff options
-rw-r--r-- | fs/ocfs2/dlmglue.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 9e8ed607173b..faa6f57db703 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -131,6 +131,17 @@ struct ocfs2_lock_res_ops { | |||
131 | int (*check_downconvert)(struct ocfs2_lock_res *, int); | 131 | int (*check_downconvert)(struct ocfs2_lock_res *, int); |
132 | 132 | ||
133 | /* | 133 | /* |
134 | * Allows a lock type to populate the lock value block. This | ||
135 | * is called on downconvert, and when we drop a lock. | ||
136 | * | ||
137 | * Locks that want to use this should set LOCK_TYPE_USES_LVB | ||
138 | * in the flags field. | ||
139 | * | ||
140 | * Called with the lockres spinlock held. | ||
141 | */ | ||
142 | void (*set_lvb)(struct ocfs2_lock_res *); | ||
143 | |||
144 | /* | ||
134 | * LOCK_TYPE_* flags which describe the specific requirements | 145 | * LOCK_TYPE_* flags which describe the specific requirements |
135 | * of a lock type. Descriptions of each individual flag follow. | 146 | * of a lock type. Descriptions of each individual flag follow. |
136 | */ | 147 | */ |
@@ -148,7 +159,8 @@ struct ocfs2_lock_res_ops { | |||
148 | #define LOCK_TYPE_REQUIRES_REFRESH 0x1 | 159 | #define LOCK_TYPE_REQUIRES_REFRESH 0x1 |
149 | 160 | ||
150 | /* | 161 | /* |
151 | * Indicate that a lock type makes use of the lock value block. | 162 | * Indicate that a lock type makes use of the lock value block. The |
163 | * ->set_lvb lock type callback must be defined. | ||
152 | */ | 164 | */ |
153 | #define LOCK_TYPE_USES_LVB 0x2 | 165 | #define LOCK_TYPE_USES_LVB 0x2 |
154 | 166 | ||
@@ -2629,6 +2641,7 @@ static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, | |||
2629 | int blocking; | 2641 | int blocking; |
2630 | int new_level; | 2642 | int new_level; |
2631 | int ret = 0; | 2643 | int ret = 0; |
2644 | int set_lvb = 0; | ||
2632 | 2645 | ||
2633 | mlog_entry_void(); | 2646 | mlog_entry_void(); |
2634 | 2647 | ||
@@ -2703,9 +2716,23 @@ recheck: | |||
2703 | downconvert: | 2716 | downconvert: |
2704 | ctl->requeue = 0; | 2717 | ctl->requeue = 0; |
2705 | 2718 | ||
2719 | if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB) { | ||
2720 | if (lockres->l_level == LKM_EXMODE) | ||
2721 | set_lvb = 1; | ||
2722 | |||
2723 | /* | ||
2724 | * We only set the lvb if the lock has been fully | ||
2725 | * refreshed - otherwise we risk setting stale | ||
2726 | * data. Otherwise, there's no need to actually clear | ||
2727 | * out the lvb here as it's value is still valid. | ||
2728 | */ | ||
2729 | if (set_lvb && !(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) | ||
2730 | lockres->l_ops->set_lvb(lockres); | ||
2731 | } | ||
2732 | |||
2706 | ocfs2_prepare_downconvert(lockres, new_level); | 2733 | ocfs2_prepare_downconvert(lockres, new_level); |
2707 | spin_unlock_irqrestore(&lockres->l_lock, flags); | 2734 | spin_unlock_irqrestore(&lockres->l_lock, flags); |
2708 | ret = ocfs2_downconvert_lock(osb, lockres, new_level, 0); | 2735 | ret = ocfs2_downconvert_lock(osb, lockres, new_level, set_lvb); |
2709 | leave: | 2736 | leave: |
2710 | mlog_exit(ret); | 2737 | mlog_exit(ret); |
2711 | return ret; | 2738 | return ret; |