diff --git a/kmod/src/dlmglue.c b/kmod/src/dlmglue.c index 63aae298..ea819588 100644 --- a/kmod/src/dlmglue.c +++ b/kmod/src/dlmglue.c @@ -909,6 +909,23 @@ static void lockres_clear_flags(struct ocfs2_lock_res *lockres, lockres_set_flags(lockres, lockres->l_flags & ~clear); } +/* + * Make sure that a lock gets a strictly increasing number only once + * each time it needs to be refreshed. The gen needs to be larger than + * any previous gen the locked resources has seen so we maintain the gen + * in the super. The caller has serialized on the lock but lots of + * locks can all be racing on the super. + * + * This is used by callers to have a single read-only indicator that + * they need to refresh their resource while they have it locked. + */ +static void lockres_inc_refresh_gen(struct ocfs2_lock_res *lockres) +{ + struct ocfs2_super *osb = ocfs2_get_lockres_osb(lockres); + + lockres->l_refresh_gen = atomic64_inc_return(&osb->refresh_gen); +} + static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res *lockres) { BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY)); @@ -935,8 +952,10 @@ static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lo * *anything* however should mark ourselves as needing an * update */ if (lockres->l_level == DLM_LOCK_NL && - lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH) + lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH) { lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH); + lockres_inc_refresh_gen(lockres); + } lockres->l_level = lockres->l_requested; @@ -962,8 +981,10 @@ static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *loc if (lockres->l_requested > DLM_LOCK_NL && !(lockres->l_flags & OCFS2_LOCK_LOCAL) && - lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH) + lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH) { lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH); + lockres_inc_refresh_gen(lockres); + } lockres->l_level = lockres->l_requested; lockres_or_flags(lockres, OCFS2_LOCK_ATTACHED); @@ -2294,6 +2315,11 @@ static inline void ocfs2_complete_lock_res_refresh(struct ocfs2_lock_res *lockre wake_up(&lockres->l_event); } +u64 ocfs2_lock_refresh_gen(struct ocfs2_lock_res *lockres) +{ + return lockres->l_refresh_gen; +} + #if 0 /* may or may not return a bh if it went to disk. */ static int ocfs2_inode_lock_update(struct inode *inode, @@ -4291,6 +4317,7 @@ int ocfs2_init_super(struct ocfs2_super *osb, int flags) init_waitqueue_head(&osb->dc_event); INIT_LIST_HEAD(&osb->blocked_lock_list); osb->s_mount_opt = flags; + atomic64_set(&osb->refresh_gen, 0); return 0; } diff --git a/kmod/src/dlmglue.h b/kmod/src/dlmglue.h index 90e31298..61b4af76 100644 --- a/kmod/src/dlmglue.h +++ b/kmod/src/dlmglue.h @@ -103,6 +103,7 @@ struct ocfs2_lock_res { struct list_head l_mask_waiters; struct list_head l_holders; + u64 l_refresh_gen; unsigned long l_flags; char l_name[OCFS2_LOCK_ID_MAX_LEN]; unsigned int l_ro_holders; @@ -167,6 +168,9 @@ struct ocfs2_super struct list_head blocked_lock_list; unsigned long blocked_lock_count; + /* refresh_gen needs to strictly increase as locks come and go */ + atomic64_t refresh_gen; + unsigned long s_mount_opt; }; /* For s_mount_opt */ @@ -317,6 +321,8 @@ void ocfs2_lock_res_init_common(struct ocfs2_super *osb, void *priv); void ocfs2_lock_res_free(struct ocfs2_lock_res *res); +u64 ocfs2_lock_refresh_gen(struct ocfs2_lock_res *lockres); + void ocfs2_mark_lockres_freeing(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres); void ocfs2_simple_drop_lockres(struct ocfs2_super *osb,