From 49b271b3eb6c1d5b2ba65798239ff60c27afec70 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Wed, 13 Sep 2006 21:21:52 -0700 Subject: [PATCH] --- yaml --- r: 35502 b: refs/heads/master c: 5ef0d4ea087740908f4fb57606f6c09e3b90c477 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/fs/ocfs2/dlmglue.c | 31 +++++++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/[refs] b/[refs] index 523a18a841ba..049ffb86d9e4 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 16d5b9567ad5241b5c6e0cc4778c1af6c04bb801 +refs/heads/master: 5ef0d4ea087740908f4fb57606f6c09e3b90c477 diff --git a/trunk/fs/ocfs2/dlmglue.c b/trunk/fs/ocfs2/dlmglue.c index 9e8ed607173b..faa6f57db703 100644 --- a/trunk/fs/ocfs2/dlmglue.c +++ b/trunk/fs/ocfs2/dlmglue.c @@ -130,6 +130,17 @@ struct ocfs2_lock_res_ops { */ int (*check_downconvert)(struct ocfs2_lock_res *, int); + /* + * Allows a lock type to populate the lock value block. This + * is called on downconvert, and when we drop a lock. + * + * Locks that want to use this should set LOCK_TYPE_USES_LVB + * in the flags field. + * + * Called with the lockres spinlock held. + */ + void (*set_lvb)(struct ocfs2_lock_res *); + /* * LOCK_TYPE_* flags which describe the specific requirements * of a lock type. Descriptions of each individual flag follow. @@ -148,7 +159,8 @@ struct ocfs2_lock_res_ops { #define LOCK_TYPE_REQUIRES_REFRESH 0x1 /* - * Indicate that a lock type makes use of the lock value block. + * Indicate that a lock type makes use of the lock value block. The + * ->set_lvb lock type callback must be defined. */ #define LOCK_TYPE_USES_LVB 0x2 @@ -2629,6 +2641,7 @@ static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, int blocking; int new_level; int ret = 0; + int set_lvb = 0; mlog_entry_void(); @@ -2703,9 +2716,23 @@ static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, downconvert: ctl->requeue = 0; + if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB) { + if (lockres->l_level == LKM_EXMODE) + set_lvb = 1; + + /* + * We only set the lvb if the lock has been fully + * refreshed - otherwise we risk setting stale + * data. Otherwise, there's no need to actually clear + * out the lvb here as it's value is still valid. + */ + if (set_lvb && !(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) + lockres->l_ops->set_lvb(lockres); + } + ocfs2_prepare_downconvert(lockres, new_level); spin_unlock_irqrestore(&lockres->l_lock, flags); - ret = ocfs2_downconvert_lock(osb, lockres, new_level, 0); + ret = ocfs2_downconvert_lock(osb, lockres, new_level, set_lvb); leave: mlog_exit(ret); return ret;