162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * dlmglue.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Code which implements an OCFS2 specific interface to our DLM.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (C) 2003, 2004 Oracle.  All rights reserved.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/types.h>
1162306a36Sopenharmony_ci#include <linux/slab.h>
1262306a36Sopenharmony_ci#include <linux/highmem.h>
1362306a36Sopenharmony_ci#include <linux/mm.h>
1462306a36Sopenharmony_ci#include <linux/kthread.h>
1562306a36Sopenharmony_ci#include <linux/pagemap.h>
1662306a36Sopenharmony_ci#include <linux/debugfs.h>
1762306a36Sopenharmony_ci#include <linux/seq_file.h>
1862306a36Sopenharmony_ci#include <linux/time.h>
1962306a36Sopenharmony_ci#include <linux/delay.h>
2062306a36Sopenharmony_ci#include <linux/quotaops.h>
2162306a36Sopenharmony_ci#include <linux/sched/signal.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define MLOG_MASK_PREFIX ML_DLM_GLUE
2462306a36Sopenharmony_ci#include <cluster/masklog.h>
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#include "ocfs2.h"
2762306a36Sopenharmony_ci#include "ocfs2_lockingver.h"
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#include "alloc.h"
3062306a36Sopenharmony_ci#include "dcache.h"
3162306a36Sopenharmony_ci#include "dlmglue.h"
3262306a36Sopenharmony_ci#include "extent_map.h"
3362306a36Sopenharmony_ci#include "file.h"
3462306a36Sopenharmony_ci#include "heartbeat.h"
3562306a36Sopenharmony_ci#include "inode.h"
3662306a36Sopenharmony_ci#include "journal.h"
3762306a36Sopenharmony_ci#include "stackglue.h"
3862306a36Sopenharmony_ci#include "slot_map.h"
3962306a36Sopenharmony_ci#include "super.h"
4062306a36Sopenharmony_ci#include "uptodate.h"
4162306a36Sopenharmony_ci#include "quota.h"
4262306a36Sopenharmony_ci#include "refcounttree.h"
4362306a36Sopenharmony_ci#include "acl.h"
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#include "buffer_head_io.h"
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistruct ocfs2_mask_waiter {
4862306a36Sopenharmony_ci	struct list_head	mw_item;
4962306a36Sopenharmony_ci	int			mw_status;
5062306a36Sopenharmony_ci	struct completion	mw_complete;
5162306a36Sopenharmony_ci	unsigned long		mw_mask;
5262306a36Sopenharmony_ci	unsigned long		mw_goal;
5362306a36Sopenharmony_ci#ifdef CONFIG_OCFS2_FS_STATS
5462306a36Sopenharmony_ci	ktime_t			mw_lock_start;
5562306a36Sopenharmony_ci#endif
5662306a36Sopenharmony_ci};
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres);
5962306a36Sopenharmony_cistatic struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres);
6062306a36Sopenharmony_cistatic struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres);
6162306a36Sopenharmony_cistatic struct ocfs2_super *ocfs2_get_qinfo_osb(struct ocfs2_lock_res *lockres);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/*
6462306a36Sopenharmony_ci * Return value from ->downconvert_worker functions.
6562306a36Sopenharmony_ci *
6662306a36Sopenharmony_ci * These control the precise actions of ocfs2_unblock_lock()
6762306a36Sopenharmony_ci * and ocfs2_process_blocked_lock()
6862306a36Sopenharmony_ci *
6962306a36Sopenharmony_ci */
7062306a36Sopenharmony_cienum ocfs2_unblock_action {
7162306a36Sopenharmony_ci	UNBLOCK_CONTINUE	= 0, /* Continue downconvert */
7262306a36Sopenharmony_ci	UNBLOCK_CONTINUE_POST	= 1, /* Continue downconvert, fire
7362306a36Sopenharmony_ci				      * ->post_unlock callback */
7462306a36Sopenharmony_ci	UNBLOCK_STOP_POST	= 2, /* Do not downconvert, fire
7562306a36Sopenharmony_ci				      * ->post_unlock() callback. */
7662306a36Sopenharmony_ci};
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cistruct ocfs2_unblock_ctl {
7962306a36Sopenharmony_ci	int requeue;
8062306a36Sopenharmony_ci	enum ocfs2_unblock_action unblock_action;
8162306a36Sopenharmony_ci};
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/* Lockdep class keys */
8462306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_LOCK_ALLOC
8562306a36Sopenharmony_cistatic struct lock_class_key lockdep_keys[OCFS2_NUM_LOCK_TYPES];
8662306a36Sopenharmony_ci#endif
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres,
8962306a36Sopenharmony_ci					int new_level);
9062306a36Sopenharmony_cistatic void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres);
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistatic int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres,
9362306a36Sopenharmony_ci				     int blocking);
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
9662306a36Sopenharmony_ci				       int blocking);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic void ocfs2_dentry_post_unlock(struct ocfs2_super *osb,
9962306a36Sopenharmony_ci				     struct ocfs2_lock_res *lockres);
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres);
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic int ocfs2_check_refcount_downconvert(struct ocfs2_lock_res *lockres,
10462306a36Sopenharmony_ci					    int new_level);
10562306a36Sopenharmony_cistatic int ocfs2_refcount_convert_worker(struct ocfs2_lock_res *lockres,
10662306a36Sopenharmony_ci					 int blocking);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci#define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres)
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci/* This aids in debugging situations where a bad LVB might be involved. */
11162306a36Sopenharmony_cistatic void ocfs2_dump_meta_lvb_info(u64 level,
11262306a36Sopenharmony_ci				     const char *function,
11362306a36Sopenharmony_ci				     unsigned int line,
11462306a36Sopenharmony_ci				     struct ocfs2_lock_res *lockres)
11562306a36Sopenharmony_ci{
11662306a36Sopenharmony_ci	struct ocfs2_meta_lvb *lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	mlog(level, "LVB information for %s (called from %s:%u):\n",
11962306a36Sopenharmony_ci	     lockres->l_name, function, line);
12062306a36Sopenharmony_ci	mlog(level, "version: %u, clusters: %u, generation: 0x%x\n",
12162306a36Sopenharmony_ci	     lvb->lvb_version, be32_to_cpu(lvb->lvb_iclusters),
12262306a36Sopenharmony_ci	     be32_to_cpu(lvb->lvb_igeneration));
12362306a36Sopenharmony_ci	mlog(level, "size: %llu, uid %u, gid %u, mode 0x%x\n",
12462306a36Sopenharmony_ci	     (unsigned long long)be64_to_cpu(lvb->lvb_isize),
12562306a36Sopenharmony_ci	     be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid),
12662306a36Sopenharmony_ci	     be16_to_cpu(lvb->lvb_imode));
12762306a36Sopenharmony_ci	mlog(level, "nlink %u, atime_packed 0x%llx, ctime_packed 0x%llx, "
12862306a36Sopenharmony_ci	     "mtime_packed 0x%llx iattr 0x%x\n", be16_to_cpu(lvb->lvb_inlink),
12962306a36Sopenharmony_ci	     (long long)be64_to_cpu(lvb->lvb_iatime_packed),
13062306a36Sopenharmony_ci	     (long long)be64_to_cpu(lvb->lvb_ictime_packed),
13162306a36Sopenharmony_ci	     (long long)be64_to_cpu(lvb->lvb_imtime_packed),
13262306a36Sopenharmony_ci	     be32_to_cpu(lvb->lvb_iattr));
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci/*
13762306a36Sopenharmony_ci * OCFS2 Lock Resource Operations
13862306a36Sopenharmony_ci *
13962306a36Sopenharmony_ci * These fine tune the behavior of the generic dlmglue locking infrastructure.
14062306a36Sopenharmony_ci *
14162306a36Sopenharmony_ci * The most basic of lock types can point ->l_priv to their respective
14262306a36Sopenharmony_ci * struct ocfs2_super and allow the default actions to manage things.
14362306a36Sopenharmony_ci *
14462306a36Sopenharmony_ci * Right now, each lock type also needs to implement an init function,
14562306a36Sopenharmony_ci * and trivial lock/unlock wrappers. ocfs2_simple_drop_lockres()
14662306a36Sopenharmony_ci * should be called when the lock is no longer needed (i.e., object
14762306a36Sopenharmony_ci * destruction time).
14862306a36Sopenharmony_ci */
14962306a36Sopenharmony_cistruct ocfs2_lock_res_ops {
15062306a36Sopenharmony_ci	/*
15162306a36Sopenharmony_ci	 * Translate an ocfs2_lock_res * into an ocfs2_super *. Define
15262306a36Sopenharmony_ci	 * this callback if ->l_priv is not an ocfs2_super pointer
15362306a36Sopenharmony_ci	 */
15462306a36Sopenharmony_ci	struct ocfs2_super * (*get_osb)(struct ocfs2_lock_res *);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	/*
15762306a36Sopenharmony_ci	 * Optionally called in the downconvert thread after a
15862306a36Sopenharmony_ci	 * successful downconvert. The lockres will not be referenced
15962306a36Sopenharmony_ci	 * after this callback is called, so it is safe to free
16062306a36Sopenharmony_ci	 * memory, etc.
16162306a36Sopenharmony_ci	 *
16262306a36Sopenharmony_ci	 * The exact semantics of when this is called are controlled
16362306a36Sopenharmony_ci	 * by ->downconvert_worker()
16462306a36Sopenharmony_ci	 */
16562306a36Sopenharmony_ci	void (*post_unlock)(struct ocfs2_super *, struct ocfs2_lock_res *);
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	/*
16862306a36Sopenharmony_ci	 * Allow a lock type to add checks to determine whether it is
16962306a36Sopenharmony_ci	 * safe to downconvert a lock. Return 0 to re-queue the
17062306a36Sopenharmony_ci	 * downconvert at a later time, nonzero to continue.
17162306a36Sopenharmony_ci	 *
17262306a36Sopenharmony_ci	 * For most locks, the default checks that there are no
17362306a36Sopenharmony_ci	 * incompatible holders are sufficient.
17462306a36Sopenharmony_ci	 *
17562306a36Sopenharmony_ci	 * Called with the lockres spinlock held.
17662306a36Sopenharmony_ci	 */
17762306a36Sopenharmony_ci	int (*check_downconvert)(struct ocfs2_lock_res *, int);
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	/*
18062306a36Sopenharmony_ci	 * Allows a lock type to populate the lock value block. This
18162306a36Sopenharmony_ci	 * is called on downconvert, and when we drop a lock.
18262306a36Sopenharmony_ci	 *
18362306a36Sopenharmony_ci	 * Locks that want to use this should set LOCK_TYPE_USES_LVB
18462306a36Sopenharmony_ci	 * in the flags field.
18562306a36Sopenharmony_ci	 *
18662306a36Sopenharmony_ci	 * Called with the lockres spinlock held.
18762306a36Sopenharmony_ci	 */
18862306a36Sopenharmony_ci	void (*set_lvb)(struct ocfs2_lock_res *);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	/*
19162306a36Sopenharmony_ci	 * Called from the downconvert thread when it is determined
19262306a36Sopenharmony_ci	 * that a lock will be downconverted. This is called without
19362306a36Sopenharmony_ci	 * any locks held so the function can do work that might
19462306a36Sopenharmony_ci	 * schedule (syncing out data, etc).
19562306a36Sopenharmony_ci	 *
19662306a36Sopenharmony_ci	 * This should return any one of the ocfs2_unblock_action
19762306a36Sopenharmony_ci	 * values, depending on what it wants the thread to do.
19862306a36Sopenharmony_ci	 */
19962306a36Sopenharmony_ci	int (*downconvert_worker)(struct ocfs2_lock_res *, int);
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	/*
20262306a36Sopenharmony_ci	 * LOCK_TYPE_* flags which describe the specific requirements
20362306a36Sopenharmony_ci	 * of a lock type. Descriptions of each individual flag follow.
20462306a36Sopenharmony_ci	 */
20562306a36Sopenharmony_ci	int flags;
20662306a36Sopenharmony_ci};
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci/*
20962306a36Sopenharmony_ci * Some locks want to "refresh" potentially stale data when a
21062306a36Sopenharmony_ci * meaningful (PRMODE or EXMODE) lock level is first obtained. If this
21162306a36Sopenharmony_ci * flag is set, the OCFS2_LOCK_NEEDS_REFRESH flag will be set on the
21262306a36Sopenharmony_ci * individual lockres l_flags member from the ast function. It is
21362306a36Sopenharmony_ci * expected that the locking wrapper will clear the
21462306a36Sopenharmony_ci * OCFS2_LOCK_NEEDS_REFRESH flag when done.
21562306a36Sopenharmony_ci */
21662306a36Sopenharmony_ci#define LOCK_TYPE_REQUIRES_REFRESH 0x1
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci/*
21962306a36Sopenharmony_ci * Indicate that a lock type makes use of the lock value block. The
22062306a36Sopenharmony_ci * ->set_lvb lock type callback must be defined.
22162306a36Sopenharmony_ci */
22262306a36Sopenharmony_ci#define LOCK_TYPE_USES_LVB		0x2
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistatic struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = {
22562306a36Sopenharmony_ci	.get_osb	= ocfs2_get_inode_osb,
22662306a36Sopenharmony_ci	.flags		= 0,
22762306a36Sopenharmony_ci};
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_cistatic struct ocfs2_lock_res_ops ocfs2_inode_inode_lops = {
23062306a36Sopenharmony_ci	.get_osb	= ocfs2_get_inode_osb,
23162306a36Sopenharmony_ci	.check_downconvert = ocfs2_check_meta_downconvert,
23262306a36Sopenharmony_ci	.set_lvb	= ocfs2_set_meta_lvb,
23362306a36Sopenharmony_ci	.downconvert_worker = ocfs2_data_convert_worker,
23462306a36Sopenharmony_ci	.flags		= LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
23562306a36Sopenharmony_ci};
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_cistatic struct ocfs2_lock_res_ops ocfs2_super_lops = {
23862306a36Sopenharmony_ci	.flags		= LOCK_TYPE_REQUIRES_REFRESH,
23962306a36Sopenharmony_ci};
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_cistatic struct ocfs2_lock_res_ops ocfs2_rename_lops = {
24262306a36Sopenharmony_ci	.flags		= 0,
24362306a36Sopenharmony_ci};
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_cistatic struct ocfs2_lock_res_ops ocfs2_nfs_sync_lops = {
24662306a36Sopenharmony_ci	.flags		= 0,
24762306a36Sopenharmony_ci};
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_cistatic struct ocfs2_lock_res_ops ocfs2_trim_fs_lops = {
25062306a36Sopenharmony_ci	.flags		= LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
25162306a36Sopenharmony_ci};
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_cistatic struct ocfs2_lock_res_ops ocfs2_orphan_scan_lops = {
25462306a36Sopenharmony_ci	.flags		= LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
25562306a36Sopenharmony_ci};
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_cistatic struct ocfs2_lock_res_ops ocfs2_dentry_lops = {
25862306a36Sopenharmony_ci	.get_osb	= ocfs2_get_dentry_osb,
25962306a36Sopenharmony_ci	.post_unlock	= ocfs2_dentry_post_unlock,
26062306a36Sopenharmony_ci	.downconvert_worker = ocfs2_dentry_convert_worker,
26162306a36Sopenharmony_ci	.flags		= 0,
26262306a36Sopenharmony_ci};
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistatic struct ocfs2_lock_res_ops ocfs2_inode_open_lops = {
26562306a36Sopenharmony_ci	.get_osb	= ocfs2_get_inode_osb,
26662306a36Sopenharmony_ci	.flags		= 0,
26762306a36Sopenharmony_ci};
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_cistatic struct ocfs2_lock_res_ops ocfs2_flock_lops = {
27062306a36Sopenharmony_ci	.get_osb	= ocfs2_get_file_osb,
27162306a36Sopenharmony_ci	.flags		= 0,
27262306a36Sopenharmony_ci};
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_cistatic struct ocfs2_lock_res_ops ocfs2_qinfo_lops = {
27562306a36Sopenharmony_ci	.set_lvb	= ocfs2_set_qinfo_lvb,
27662306a36Sopenharmony_ci	.get_osb	= ocfs2_get_qinfo_osb,
27762306a36Sopenharmony_ci	.flags		= LOCK_TYPE_REQUIRES_REFRESH | LOCK_TYPE_USES_LVB,
27862306a36Sopenharmony_ci};
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic struct ocfs2_lock_res_ops ocfs2_refcount_block_lops = {
28162306a36Sopenharmony_ci	.check_downconvert = ocfs2_check_refcount_downconvert,
28262306a36Sopenharmony_ci	.downconvert_worker = ocfs2_refcount_convert_worker,
28362306a36Sopenharmony_ci	.flags		= 0,
28462306a36Sopenharmony_ci};
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_cistatic inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres)
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	return lockres->l_type == OCFS2_LOCK_TYPE_META ||
28962306a36Sopenharmony_ci		lockres->l_type == OCFS2_LOCK_TYPE_RW ||
29062306a36Sopenharmony_ci		lockres->l_type == OCFS2_LOCK_TYPE_OPEN;
29162306a36Sopenharmony_ci}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_cistatic inline struct ocfs2_lock_res *ocfs2_lksb_to_lock_res(struct ocfs2_dlm_lksb *lksb)
29462306a36Sopenharmony_ci{
29562306a36Sopenharmony_ci	return container_of(lksb, struct ocfs2_lock_res, l_lksb);
29662306a36Sopenharmony_ci}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_cistatic inline struct inode *ocfs2_lock_res_inode(struct ocfs2_lock_res *lockres)
29962306a36Sopenharmony_ci{
30062306a36Sopenharmony_ci	BUG_ON(!ocfs2_is_inode_lock(lockres));
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	return (struct inode *) lockres->l_priv;
30362306a36Sopenharmony_ci}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_cistatic inline struct ocfs2_dentry_lock *ocfs2_lock_res_dl(struct ocfs2_lock_res *lockres)
30662306a36Sopenharmony_ci{
30762306a36Sopenharmony_ci	BUG_ON(lockres->l_type != OCFS2_LOCK_TYPE_DENTRY);
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	return (struct ocfs2_dentry_lock *)lockres->l_priv;
31062306a36Sopenharmony_ci}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_cistatic inline struct ocfs2_mem_dqinfo *ocfs2_lock_res_qinfo(struct ocfs2_lock_res *lockres)
31362306a36Sopenharmony_ci{
31462306a36Sopenharmony_ci	BUG_ON(lockres->l_type != OCFS2_LOCK_TYPE_QINFO);
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	return (struct ocfs2_mem_dqinfo *)lockres->l_priv;
31762306a36Sopenharmony_ci}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_cistatic inline struct ocfs2_refcount_tree *
32062306a36Sopenharmony_ciocfs2_lock_res_refcount_tree(struct ocfs2_lock_res *res)
32162306a36Sopenharmony_ci{
32262306a36Sopenharmony_ci	return container_of(res, struct ocfs2_refcount_tree, rf_lockres);
32362306a36Sopenharmony_ci}
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_cistatic inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres)
32662306a36Sopenharmony_ci{
32762306a36Sopenharmony_ci	if (lockres->l_ops->get_osb)
32862306a36Sopenharmony_ci		return lockres->l_ops->get_osb(lockres);
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	return (struct ocfs2_super *)lockres->l_priv;
33162306a36Sopenharmony_ci}
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_cistatic int ocfs2_lock_create(struct ocfs2_super *osb,
33462306a36Sopenharmony_ci			     struct ocfs2_lock_res *lockres,
33562306a36Sopenharmony_ci			     int level,
33662306a36Sopenharmony_ci			     u32 dlm_flags);
33762306a36Sopenharmony_cistatic inline int ocfs2_may_continue_on_blocked_lock(struct ocfs2_lock_res *lockres,
33862306a36Sopenharmony_ci						     int wanted);
33962306a36Sopenharmony_cistatic void __ocfs2_cluster_unlock(struct ocfs2_super *osb,
34062306a36Sopenharmony_ci				   struct ocfs2_lock_res *lockres,
34162306a36Sopenharmony_ci				   int level, unsigned long caller_ip);
34262306a36Sopenharmony_cistatic inline void ocfs2_cluster_unlock(struct ocfs2_super *osb,
34362306a36Sopenharmony_ci					struct ocfs2_lock_res *lockres,
34462306a36Sopenharmony_ci					int level)
34562306a36Sopenharmony_ci{
34662306a36Sopenharmony_ci	__ocfs2_cluster_unlock(osb, lockres, level, _RET_IP_);
34762306a36Sopenharmony_ci}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_cistatic inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res *lockres);
35062306a36Sopenharmony_cistatic inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres);
35162306a36Sopenharmony_cistatic inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres);
35262306a36Sopenharmony_cistatic int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres, int level);
35362306a36Sopenharmony_cistatic void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb,
35462306a36Sopenharmony_ci					struct ocfs2_lock_res *lockres);
35562306a36Sopenharmony_cistatic inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,
35662306a36Sopenharmony_ci						int convert);
35762306a36Sopenharmony_ci#define ocfs2_log_dlm_error(_func, _err, _lockres) do {					\
35862306a36Sopenharmony_ci	if ((_lockres)->l_type != OCFS2_LOCK_TYPE_DENTRY)				\
35962306a36Sopenharmony_ci		mlog(ML_ERROR, "DLM error %d while calling %s on resource %s\n",	\
36062306a36Sopenharmony_ci		     _err, _func, _lockres->l_name);					\
36162306a36Sopenharmony_ci	else										\
36262306a36Sopenharmony_ci		mlog(ML_ERROR, "DLM error %d while calling %s on resource %.*s%08x\n",	\
36362306a36Sopenharmony_ci		     _err, _func, OCFS2_DENTRY_LOCK_INO_START - 1, (_lockres)->l_name,	\
36462306a36Sopenharmony_ci		     (unsigned int)ocfs2_get_dentry_lock_ino(_lockres));		\
36562306a36Sopenharmony_ci} while (0)
36662306a36Sopenharmony_cistatic int ocfs2_downconvert_thread(void *arg);
36762306a36Sopenharmony_cistatic void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb,
36862306a36Sopenharmony_ci					struct ocfs2_lock_res *lockres);
36962306a36Sopenharmony_cistatic int ocfs2_inode_lock_update(struct inode *inode,
37062306a36Sopenharmony_ci				  struct buffer_head **bh);
37162306a36Sopenharmony_cistatic void ocfs2_drop_osb_locks(struct ocfs2_super *osb);
37262306a36Sopenharmony_cistatic inline int ocfs2_highest_compat_lock_level(int level);
37362306a36Sopenharmony_cistatic unsigned int ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres,
37462306a36Sopenharmony_ci					      int new_level);
37562306a36Sopenharmony_cistatic int ocfs2_downconvert_lock(struct ocfs2_super *osb,
37662306a36Sopenharmony_ci				  struct ocfs2_lock_res *lockres,
37762306a36Sopenharmony_ci				  int new_level,
37862306a36Sopenharmony_ci				  int lvb,
37962306a36Sopenharmony_ci				  unsigned int generation);
38062306a36Sopenharmony_cistatic int ocfs2_prepare_cancel_convert(struct ocfs2_super *osb,
38162306a36Sopenharmony_ci				        struct ocfs2_lock_res *lockres);
38262306a36Sopenharmony_cistatic int ocfs2_cancel_convert(struct ocfs2_super *osb,
38362306a36Sopenharmony_ci				struct ocfs2_lock_res *lockres);
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_cistatic void ocfs2_build_lock_name(enum ocfs2_lock_type type,
38762306a36Sopenharmony_ci				  u64 blkno,
38862306a36Sopenharmony_ci				  u32 generation,
38962306a36Sopenharmony_ci				  char *name)
39062306a36Sopenharmony_ci{
39162306a36Sopenharmony_ci	int len;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	BUG_ON(type >= OCFS2_NUM_LOCK_TYPES);
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	len = snprintf(name, OCFS2_LOCK_ID_MAX_LEN, "%c%s%016llx%08x",
39662306a36Sopenharmony_ci		       ocfs2_lock_type_char(type), OCFS2_LOCK_ID_PAD,
39762306a36Sopenharmony_ci		       (long long)blkno, generation);
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	BUG_ON(len != (OCFS2_LOCK_ID_MAX_LEN - 1));
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	mlog(0, "built lock resource with name: %s\n", name);
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_cistatic DEFINE_SPINLOCK(ocfs2_dlm_tracking_lock);
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_cistatic void ocfs2_add_lockres_tracking(struct ocfs2_lock_res *res,
40762306a36Sopenharmony_ci				       struct ocfs2_dlm_debug *dlm_debug)
40862306a36Sopenharmony_ci{
40962306a36Sopenharmony_ci	mlog(0, "Add tracking for lockres %s\n", res->l_name);
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	spin_lock(&ocfs2_dlm_tracking_lock);
41262306a36Sopenharmony_ci	list_add(&res->l_debug_list, &dlm_debug->d_lockres_tracking);
41362306a36Sopenharmony_ci	spin_unlock(&ocfs2_dlm_tracking_lock);
41462306a36Sopenharmony_ci}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_cistatic void ocfs2_remove_lockres_tracking(struct ocfs2_lock_res *res)
41762306a36Sopenharmony_ci{
41862306a36Sopenharmony_ci	spin_lock(&ocfs2_dlm_tracking_lock);
41962306a36Sopenharmony_ci	if (!list_empty(&res->l_debug_list))
42062306a36Sopenharmony_ci		list_del_init(&res->l_debug_list);
42162306a36Sopenharmony_ci	spin_unlock(&ocfs2_dlm_tracking_lock);
42262306a36Sopenharmony_ci}
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci#ifdef CONFIG_OCFS2_FS_STATS
42562306a36Sopenharmony_cistatic void ocfs2_init_lock_stats(struct ocfs2_lock_res *res)
42662306a36Sopenharmony_ci{
42762306a36Sopenharmony_ci	res->l_lock_refresh = 0;
42862306a36Sopenharmony_ci	res->l_lock_wait = 0;
42962306a36Sopenharmony_ci	memset(&res->l_lock_prmode, 0, sizeof(struct ocfs2_lock_stats));
43062306a36Sopenharmony_ci	memset(&res->l_lock_exmode, 0, sizeof(struct ocfs2_lock_stats));
43162306a36Sopenharmony_ci}
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_cistatic void ocfs2_update_lock_stats(struct ocfs2_lock_res *res, int level,
43462306a36Sopenharmony_ci				    struct ocfs2_mask_waiter *mw, int ret)
43562306a36Sopenharmony_ci{
43662306a36Sopenharmony_ci	u32 usec;
43762306a36Sopenharmony_ci	ktime_t kt;
43862306a36Sopenharmony_ci	struct ocfs2_lock_stats *stats;
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	if (level == LKM_PRMODE)
44162306a36Sopenharmony_ci		stats = &res->l_lock_prmode;
44262306a36Sopenharmony_ci	else if (level == LKM_EXMODE)
44362306a36Sopenharmony_ci		stats = &res->l_lock_exmode;
44462306a36Sopenharmony_ci	else
44562306a36Sopenharmony_ci		return;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	kt = ktime_sub(ktime_get(), mw->mw_lock_start);
44862306a36Sopenharmony_ci	usec = ktime_to_us(kt);
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	stats->ls_gets++;
45162306a36Sopenharmony_ci	stats->ls_total += ktime_to_ns(kt);
45262306a36Sopenharmony_ci	/* overflow */
45362306a36Sopenharmony_ci	if (unlikely(stats->ls_gets == 0)) {
45462306a36Sopenharmony_ci		stats->ls_gets++;
45562306a36Sopenharmony_ci		stats->ls_total = ktime_to_ns(kt);
45662306a36Sopenharmony_ci	}
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	if (stats->ls_max < usec)
45962306a36Sopenharmony_ci		stats->ls_max = usec;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	if (ret)
46262306a36Sopenharmony_ci		stats->ls_fail++;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	stats->ls_last = ktime_to_us(ktime_get_real());
46562306a36Sopenharmony_ci}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_cistatic inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres)
46862306a36Sopenharmony_ci{
46962306a36Sopenharmony_ci	lockres->l_lock_refresh++;
47062306a36Sopenharmony_ci}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_cistatic inline void ocfs2_track_lock_wait(struct ocfs2_lock_res *lockres)
47362306a36Sopenharmony_ci{
47462306a36Sopenharmony_ci	struct ocfs2_mask_waiter *mw;
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	if (list_empty(&lockres->l_mask_waiters)) {
47762306a36Sopenharmony_ci		lockres->l_lock_wait = 0;
47862306a36Sopenharmony_ci		return;
47962306a36Sopenharmony_ci	}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	mw = list_first_entry(&lockres->l_mask_waiters,
48262306a36Sopenharmony_ci				struct ocfs2_mask_waiter, mw_item);
48362306a36Sopenharmony_ci	lockres->l_lock_wait =
48462306a36Sopenharmony_ci			ktime_to_us(ktime_mono_to_real(mw->mw_lock_start));
48562306a36Sopenharmony_ci}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_cistatic inline void ocfs2_init_start_time(struct ocfs2_mask_waiter *mw)
48862306a36Sopenharmony_ci{
48962306a36Sopenharmony_ci	mw->mw_lock_start = ktime_get();
49062306a36Sopenharmony_ci}
49162306a36Sopenharmony_ci#else
49262306a36Sopenharmony_cistatic inline void ocfs2_init_lock_stats(struct ocfs2_lock_res *res)
49362306a36Sopenharmony_ci{
49462306a36Sopenharmony_ci}
49562306a36Sopenharmony_cistatic inline void ocfs2_update_lock_stats(struct ocfs2_lock_res *res,
49662306a36Sopenharmony_ci			   int level, struct ocfs2_mask_waiter *mw, int ret)
49762306a36Sopenharmony_ci{
49862306a36Sopenharmony_ci}
49962306a36Sopenharmony_cistatic inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres)
50062306a36Sopenharmony_ci{
50162306a36Sopenharmony_ci}
50262306a36Sopenharmony_cistatic inline void ocfs2_track_lock_wait(struct ocfs2_lock_res *lockres)
50362306a36Sopenharmony_ci{
50462306a36Sopenharmony_ci}
50562306a36Sopenharmony_cistatic inline void ocfs2_init_start_time(struct ocfs2_mask_waiter *mw)
50662306a36Sopenharmony_ci{
50762306a36Sopenharmony_ci}
50862306a36Sopenharmony_ci#endif
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_cistatic void ocfs2_lock_res_init_common(struct ocfs2_super *osb,
51162306a36Sopenharmony_ci				       struct ocfs2_lock_res *res,
51262306a36Sopenharmony_ci				       enum ocfs2_lock_type type,
51362306a36Sopenharmony_ci				       struct ocfs2_lock_res_ops *ops,
51462306a36Sopenharmony_ci				       void *priv)
51562306a36Sopenharmony_ci{
51662306a36Sopenharmony_ci	res->l_type          = type;
51762306a36Sopenharmony_ci	res->l_ops           = ops;
51862306a36Sopenharmony_ci	res->l_priv          = priv;
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	res->l_level         = DLM_LOCK_IV;
52162306a36Sopenharmony_ci	res->l_requested     = DLM_LOCK_IV;
52262306a36Sopenharmony_ci	res->l_blocking      = DLM_LOCK_IV;
52362306a36Sopenharmony_ci	res->l_action        = OCFS2_AST_INVALID;
52462306a36Sopenharmony_ci	res->l_unlock_action = OCFS2_UNLOCK_INVALID;
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci	res->l_flags         = OCFS2_LOCK_INITIALIZED;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	ocfs2_add_lockres_tracking(res, osb->osb_dlm_debug);
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	ocfs2_init_lock_stats(res);
53162306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_LOCK_ALLOC
53262306a36Sopenharmony_ci	if (type != OCFS2_LOCK_TYPE_OPEN)
53362306a36Sopenharmony_ci		lockdep_init_map(&res->l_lockdep_map, ocfs2_lock_type_strings[type],
53462306a36Sopenharmony_ci				 &lockdep_keys[type], 0);
53562306a36Sopenharmony_ci	else
53662306a36Sopenharmony_ci		res->l_lockdep_map.key = NULL;
53762306a36Sopenharmony_ci#endif
53862306a36Sopenharmony_ci}
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_civoid ocfs2_lock_res_init_once(struct ocfs2_lock_res *res)
54162306a36Sopenharmony_ci{
54262306a36Sopenharmony_ci	/* This also clears out the lock status block */
54362306a36Sopenharmony_ci	memset(res, 0, sizeof(struct ocfs2_lock_res));
54462306a36Sopenharmony_ci	spin_lock_init(&res->l_lock);
54562306a36Sopenharmony_ci	init_waitqueue_head(&res->l_event);
54662306a36Sopenharmony_ci	INIT_LIST_HEAD(&res->l_blocked_list);
54762306a36Sopenharmony_ci	INIT_LIST_HEAD(&res->l_mask_waiters);
54862306a36Sopenharmony_ci	INIT_LIST_HEAD(&res->l_holders);
54962306a36Sopenharmony_ci}
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_civoid ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res,
55262306a36Sopenharmony_ci			       enum ocfs2_lock_type type,
55362306a36Sopenharmony_ci			       unsigned int generation,
55462306a36Sopenharmony_ci			       struct inode *inode)
55562306a36Sopenharmony_ci{
55662306a36Sopenharmony_ci	struct ocfs2_lock_res_ops *ops;
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	switch(type) {
55962306a36Sopenharmony_ci		case OCFS2_LOCK_TYPE_RW:
56062306a36Sopenharmony_ci			ops = &ocfs2_inode_rw_lops;
56162306a36Sopenharmony_ci			break;
56262306a36Sopenharmony_ci		case OCFS2_LOCK_TYPE_META:
56362306a36Sopenharmony_ci			ops = &ocfs2_inode_inode_lops;
56462306a36Sopenharmony_ci			break;
56562306a36Sopenharmony_ci		case OCFS2_LOCK_TYPE_OPEN:
56662306a36Sopenharmony_ci			ops = &ocfs2_inode_open_lops;
56762306a36Sopenharmony_ci			break;
56862306a36Sopenharmony_ci		default:
56962306a36Sopenharmony_ci			mlog_bug_on_msg(1, "type: %d\n", type);
57062306a36Sopenharmony_ci			ops = NULL; /* thanks, gcc */
57162306a36Sopenharmony_ci			break;
57262306a36Sopenharmony_ci	}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	ocfs2_build_lock_name(type, OCFS2_I(inode)->ip_blkno,
57562306a36Sopenharmony_ci			      generation, res->l_name);
57662306a36Sopenharmony_ci	ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), res, type, ops, inode);
57762306a36Sopenharmony_ci}
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_cistatic struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres)
58062306a36Sopenharmony_ci{
58162306a36Sopenharmony_ci	struct inode *inode = ocfs2_lock_res_inode(lockres);
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci	return OCFS2_SB(inode->i_sb);
58462306a36Sopenharmony_ci}
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_cistatic struct ocfs2_super *ocfs2_get_qinfo_osb(struct ocfs2_lock_res *lockres)
58762306a36Sopenharmony_ci{
58862306a36Sopenharmony_ci	struct ocfs2_mem_dqinfo *info = lockres->l_priv;
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	return OCFS2_SB(info->dqi_gi.dqi_sb);
59162306a36Sopenharmony_ci}
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_cistatic struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres)
59462306a36Sopenharmony_ci{
59562306a36Sopenharmony_ci	struct ocfs2_file_private *fp = lockres->l_priv;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	return OCFS2_SB(fp->fp_file->f_mapping->host->i_sb);
59862306a36Sopenharmony_ci}
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_cistatic __u64 ocfs2_get_dentry_lock_ino(struct ocfs2_lock_res *lockres)
60162306a36Sopenharmony_ci{
60262306a36Sopenharmony_ci	__be64 inode_blkno_be;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	memcpy(&inode_blkno_be, &lockres->l_name[OCFS2_DENTRY_LOCK_INO_START],
60562306a36Sopenharmony_ci	       sizeof(__be64));
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	return be64_to_cpu(inode_blkno_be);
60862306a36Sopenharmony_ci}
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_cistatic struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres)
61162306a36Sopenharmony_ci{
61262306a36Sopenharmony_ci	struct ocfs2_dentry_lock *dl = lockres->l_priv;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	return OCFS2_SB(dl->dl_inode->i_sb);
61562306a36Sopenharmony_ci}
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_civoid ocfs2_dentry_lock_res_init(struct ocfs2_dentry_lock *dl,
61862306a36Sopenharmony_ci				u64 parent, struct inode *inode)
61962306a36Sopenharmony_ci{
62062306a36Sopenharmony_ci	int len;
62162306a36Sopenharmony_ci	u64 inode_blkno = OCFS2_I(inode)->ip_blkno;
62262306a36Sopenharmony_ci	__be64 inode_blkno_be = cpu_to_be64(inode_blkno);
62362306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &dl->dl_lockres;
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	ocfs2_lock_res_init_once(lockres);
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	/*
62862306a36Sopenharmony_ci	 * Unfortunately, the standard lock naming scheme won't work
62962306a36Sopenharmony_ci	 * here because we have two 16 byte values to use. Instead,
63062306a36Sopenharmony_ci	 * we'll stuff the inode number as a binary value. We still
63162306a36Sopenharmony_ci	 * want error prints to show something without garbling the
63262306a36Sopenharmony_ci	 * display, so drop a null byte in there before the inode
63362306a36Sopenharmony_ci	 * number. A future version of OCFS2 will likely use all
63462306a36Sopenharmony_ci	 * binary lock names. The stringified names have been a
63562306a36Sopenharmony_ci	 * tremendous aid in debugging, but now that the debugfs
63662306a36Sopenharmony_ci	 * interface exists, we can mangle things there if need be.
63762306a36Sopenharmony_ci	 *
63862306a36Sopenharmony_ci	 * NOTE: We also drop the standard "pad" value (the total lock
63962306a36Sopenharmony_ci	 * name size stays the same though - the last part is all
64062306a36Sopenharmony_ci	 * zeros due to the memset in ocfs2_lock_res_init_once()
64162306a36Sopenharmony_ci	 */
64262306a36Sopenharmony_ci	len = snprintf(lockres->l_name, OCFS2_DENTRY_LOCK_INO_START,
64362306a36Sopenharmony_ci		       "%c%016llx",
64462306a36Sopenharmony_ci		       ocfs2_lock_type_char(OCFS2_LOCK_TYPE_DENTRY),
64562306a36Sopenharmony_ci		       (long long)parent);
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	BUG_ON(len != (OCFS2_DENTRY_LOCK_INO_START - 1));
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci	memcpy(&lockres->l_name[OCFS2_DENTRY_LOCK_INO_START], &inode_blkno_be,
65062306a36Sopenharmony_ci	       sizeof(__be64));
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), lockres,
65362306a36Sopenharmony_ci				   OCFS2_LOCK_TYPE_DENTRY, &ocfs2_dentry_lops,
65462306a36Sopenharmony_ci				   dl);
65562306a36Sopenharmony_ci}
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_cistatic void ocfs2_super_lock_res_init(struct ocfs2_lock_res *res,
65862306a36Sopenharmony_ci				      struct ocfs2_super *osb)
65962306a36Sopenharmony_ci{
66062306a36Sopenharmony_ci	/* Superblock lockres doesn't come from a slab so we call init
66162306a36Sopenharmony_ci	 * once on it manually.  */
66262306a36Sopenharmony_ci	ocfs2_lock_res_init_once(res);
66362306a36Sopenharmony_ci	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_SUPER, OCFS2_SUPER_BLOCK_BLKNO,
66462306a36Sopenharmony_ci			      0, res->l_name);
66562306a36Sopenharmony_ci	ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_SUPER,
66662306a36Sopenharmony_ci				   &ocfs2_super_lops, osb);
66762306a36Sopenharmony_ci}
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_cistatic void ocfs2_rename_lock_res_init(struct ocfs2_lock_res *res,
67062306a36Sopenharmony_ci				       struct ocfs2_super *osb)
67162306a36Sopenharmony_ci{
67262306a36Sopenharmony_ci	/* Rename lockres doesn't come from a slab so we call init
67362306a36Sopenharmony_ci	 * once on it manually.  */
67462306a36Sopenharmony_ci	ocfs2_lock_res_init_once(res);
67562306a36Sopenharmony_ci	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_RENAME, 0, 0, res->l_name);
67662306a36Sopenharmony_ci	ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_RENAME,
67762306a36Sopenharmony_ci				   &ocfs2_rename_lops, osb);
67862306a36Sopenharmony_ci}
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_cistatic void ocfs2_nfs_sync_lock_res_init(struct ocfs2_lock_res *res,
68162306a36Sopenharmony_ci					 struct ocfs2_super *osb)
68262306a36Sopenharmony_ci{
68362306a36Sopenharmony_ci	/* nfs_sync lockres doesn't come from a slab so we call init
68462306a36Sopenharmony_ci	 * once on it manually.  */
68562306a36Sopenharmony_ci	ocfs2_lock_res_init_once(res);
68662306a36Sopenharmony_ci	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_NFS_SYNC, 0, 0, res->l_name);
68762306a36Sopenharmony_ci	ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_NFS_SYNC,
68862306a36Sopenharmony_ci				   &ocfs2_nfs_sync_lops, osb);
68962306a36Sopenharmony_ci}
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_cistatic void ocfs2_nfs_sync_lock_init(struct ocfs2_super *osb)
69262306a36Sopenharmony_ci{
69362306a36Sopenharmony_ci	ocfs2_nfs_sync_lock_res_init(&osb->osb_nfs_sync_lockres, osb);
69462306a36Sopenharmony_ci	init_rwsem(&osb->nfs_sync_rwlock);
69562306a36Sopenharmony_ci}
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_civoid ocfs2_trim_fs_lock_res_init(struct ocfs2_super *osb)
69862306a36Sopenharmony_ci{
69962306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	/* Only one trimfs thread are allowed to work at the same time. */
70262306a36Sopenharmony_ci	mutex_lock(&osb->obs_trim_fs_mutex);
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	ocfs2_lock_res_init_once(lockres);
70562306a36Sopenharmony_ci	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_TRIM_FS, 0, 0, lockres->l_name);
70662306a36Sopenharmony_ci	ocfs2_lock_res_init_common(osb, lockres, OCFS2_LOCK_TYPE_TRIM_FS,
70762306a36Sopenharmony_ci				   &ocfs2_trim_fs_lops, osb);
70862306a36Sopenharmony_ci}
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_civoid ocfs2_trim_fs_lock_res_uninit(struct ocfs2_super *osb)
71162306a36Sopenharmony_ci{
71262306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci	ocfs2_simple_drop_lockres(osb, lockres);
71562306a36Sopenharmony_ci	ocfs2_lock_res_free(lockres);
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci	mutex_unlock(&osb->obs_trim_fs_mutex);
71862306a36Sopenharmony_ci}
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_cistatic void ocfs2_orphan_scan_lock_res_init(struct ocfs2_lock_res *res,
72162306a36Sopenharmony_ci					    struct ocfs2_super *osb)
72262306a36Sopenharmony_ci{
72362306a36Sopenharmony_ci	ocfs2_lock_res_init_once(res);
72462306a36Sopenharmony_ci	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_ORPHAN_SCAN, 0, 0, res->l_name);
72562306a36Sopenharmony_ci	ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_ORPHAN_SCAN,
72662306a36Sopenharmony_ci				   &ocfs2_orphan_scan_lops, osb);
72762306a36Sopenharmony_ci}
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_civoid ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres,
73062306a36Sopenharmony_ci			      struct ocfs2_file_private *fp)
73162306a36Sopenharmony_ci{
73262306a36Sopenharmony_ci	struct inode *inode = fp->fp_file->f_mapping->host;
73362306a36Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(inode);
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	ocfs2_lock_res_init_once(lockres);
73662306a36Sopenharmony_ci	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_FLOCK, oi->ip_blkno,
73762306a36Sopenharmony_ci			      inode->i_generation, lockres->l_name);
73862306a36Sopenharmony_ci	ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), lockres,
73962306a36Sopenharmony_ci				   OCFS2_LOCK_TYPE_FLOCK, &ocfs2_flock_lops,
74062306a36Sopenharmony_ci				   fp);
74162306a36Sopenharmony_ci	lockres->l_flags |= OCFS2_LOCK_NOCACHE;
74262306a36Sopenharmony_ci}
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_civoid ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
74562306a36Sopenharmony_ci			       struct ocfs2_mem_dqinfo *info)
74662306a36Sopenharmony_ci{
74762306a36Sopenharmony_ci	ocfs2_lock_res_init_once(lockres);
74862306a36Sopenharmony_ci	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_QINFO, info->dqi_gi.dqi_type,
74962306a36Sopenharmony_ci			      0, lockres->l_name);
75062306a36Sopenharmony_ci	ocfs2_lock_res_init_common(OCFS2_SB(info->dqi_gi.dqi_sb), lockres,
75162306a36Sopenharmony_ci				   OCFS2_LOCK_TYPE_QINFO, &ocfs2_qinfo_lops,
75262306a36Sopenharmony_ci				   info);
75362306a36Sopenharmony_ci}
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_civoid ocfs2_refcount_lock_res_init(struct ocfs2_lock_res *lockres,
75662306a36Sopenharmony_ci				  struct ocfs2_super *osb, u64 ref_blkno,
75762306a36Sopenharmony_ci				  unsigned int generation)
75862306a36Sopenharmony_ci{
75962306a36Sopenharmony_ci	ocfs2_lock_res_init_once(lockres);
76062306a36Sopenharmony_ci	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_REFCOUNT, ref_blkno,
76162306a36Sopenharmony_ci			      generation, lockres->l_name);
76262306a36Sopenharmony_ci	ocfs2_lock_res_init_common(osb, lockres, OCFS2_LOCK_TYPE_REFCOUNT,
76362306a36Sopenharmony_ci				   &ocfs2_refcount_block_lops, osb);
76462306a36Sopenharmony_ci}
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_civoid ocfs2_lock_res_free(struct ocfs2_lock_res *res)
76762306a36Sopenharmony_ci{
76862306a36Sopenharmony_ci	if (!(res->l_flags & OCFS2_LOCK_INITIALIZED))
76962306a36Sopenharmony_ci		return;
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	ocfs2_remove_lockres_tracking(res);
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	mlog_bug_on_msg(!list_empty(&res->l_blocked_list),
77462306a36Sopenharmony_ci			"Lockres %s is on the blocked list\n",
77562306a36Sopenharmony_ci			res->l_name);
77662306a36Sopenharmony_ci	mlog_bug_on_msg(!list_empty(&res->l_mask_waiters),
77762306a36Sopenharmony_ci			"Lockres %s has mask waiters pending\n",
77862306a36Sopenharmony_ci			res->l_name);
77962306a36Sopenharmony_ci	mlog_bug_on_msg(spin_is_locked(&res->l_lock),
78062306a36Sopenharmony_ci			"Lockres %s is locked\n",
78162306a36Sopenharmony_ci			res->l_name);
78262306a36Sopenharmony_ci	mlog_bug_on_msg(res->l_ro_holders,
78362306a36Sopenharmony_ci			"Lockres %s has %u ro holders\n",
78462306a36Sopenharmony_ci			res->l_name, res->l_ro_holders);
78562306a36Sopenharmony_ci	mlog_bug_on_msg(res->l_ex_holders,
78662306a36Sopenharmony_ci			"Lockres %s has %u ex holders\n",
78762306a36Sopenharmony_ci			res->l_name, res->l_ex_holders);
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	/* Need to clear out the lock status block for the dlm */
79062306a36Sopenharmony_ci	memset(&res->l_lksb, 0, sizeof(res->l_lksb));
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	res->l_flags = 0UL;
79362306a36Sopenharmony_ci}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci/*
79662306a36Sopenharmony_ci * Keep a list of processes who have interest in a lockres.
79762306a36Sopenharmony_ci * Note: this is now only uesed for check recursive cluster locking.
79862306a36Sopenharmony_ci */
79962306a36Sopenharmony_cistatic inline void ocfs2_add_holder(struct ocfs2_lock_res *lockres,
80062306a36Sopenharmony_ci				   struct ocfs2_lock_holder *oh)
80162306a36Sopenharmony_ci{
80262306a36Sopenharmony_ci	INIT_LIST_HEAD(&oh->oh_list);
80362306a36Sopenharmony_ci	oh->oh_owner_pid = get_pid(task_pid(current));
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	spin_lock(&lockres->l_lock);
80662306a36Sopenharmony_ci	list_add_tail(&oh->oh_list, &lockres->l_holders);
80762306a36Sopenharmony_ci	spin_unlock(&lockres->l_lock);
80862306a36Sopenharmony_ci}
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_cistatic struct ocfs2_lock_holder *
81162306a36Sopenharmony_ciocfs2_pid_holder(struct ocfs2_lock_res *lockres,
81262306a36Sopenharmony_ci		struct pid *pid)
81362306a36Sopenharmony_ci{
81462306a36Sopenharmony_ci	struct ocfs2_lock_holder *oh;
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	spin_lock(&lockres->l_lock);
81762306a36Sopenharmony_ci	list_for_each_entry(oh, &lockres->l_holders, oh_list) {
81862306a36Sopenharmony_ci		if (oh->oh_owner_pid == pid) {
81962306a36Sopenharmony_ci			spin_unlock(&lockres->l_lock);
82062306a36Sopenharmony_ci			return oh;
82162306a36Sopenharmony_ci		}
82262306a36Sopenharmony_ci	}
82362306a36Sopenharmony_ci	spin_unlock(&lockres->l_lock);
82462306a36Sopenharmony_ci	return NULL;
82562306a36Sopenharmony_ci}
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_cistatic inline void ocfs2_remove_holder(struct ocfs2_lock_res *lockres,
82862306a36Sopenharmony_ci				       struct ocfs2_lock_holder *oh)
82962306a36Sopenharmony_ci{
83062306a36Sopenharmony_ci	spin_lock(&lockres->l_lock);
83162306a36Sopenharmony_ci	list_del(&oh->oh_list);
83262306a36Sopenharmony_ci	spin_unlock(&lockres->l_lock);
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	put_pid(oh->oh_owner_pid);
83562306a36Sopenharmony_ci}
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_cistatic inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres,
83962306a36Sopenharmony_ci				     int level)
84062306a36Sopenharmony_ci{
84162306a36Sopenharmony_ci	BUG_ON(!lockres);
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	switch(level) {
84462306a36Sopenharmony_ci	case DLM_LOCK_EX:
84562306a36Sopenharmony_ci		lockres->l_ex_holders++;
84662306a36Sopenharmony_ci		break;
84762306a36Sopenharmony_ci	case DLM_LOCK_PR:
84862306a36Sopenharmony_ci		lockres->l_ro_holders++;
84962306a36Sopenharmony_ci		break;
85062306a36Sopenharmony_ci	default:
85162306a36Sopenharmony_ci		BUG();
85262306a36Sopenharmony_ci	}
85362306a36Sopenharmony_ci}
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_cistatic inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres,
85662306a36Sopenharmony_ci				     int level)
85762306a36Sopenharmony_ci{
85862306a36Sopenharmony_ci	BUG_ON(!lockres);
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci	switch(level) {
86162306a36Sopenharmony_ci	case DLM_LOCK_EX:
86262306a36Sopenharmony_ci		BUG_ON(!lockres->l_ex_holders);
86362306a36Sopenharmony_ci		lockres->l_ex_holders--;
86462306a36Sopenharmony_ci		break;
86562306a36Sopenharmony_ci	case DLM_LOCK_PR:
86662306a36Sopenharmony_ci		BUG_ON(!lockres->l_ro_holders);
86762306a36Sopenharmony_ci		lockres->l_ro_holders--;
86862306a36Sopenharmony_ci		break;
86962306a36Sopenharmony_ci	default:
87062306a36Sopenharmony_ci		BUG();
87162306a36Sopenharmony_ci	}
87262306a36Sopenharmony_ci}
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci/* WARNING: This function lives in a world where the only three lock
87562306a36Sopenharmony_ci * levels are EX, PR, and NL. It *will* have to be adjusted when more
87662306a36Sopenharmony_ci * lock types are added. */
87762306a36Sopenharmony_cistatic inline int ocfs2_highest_compat_lock_level(int level)
87862306a36Sopenharmony_ci{
87962306a36Sopenharmony_ci	int new_level = DLM_LOCK_EX;
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_ci	if (level == DLM_LOCK_EX)
88262306a36Sopenharmony_ci		new_level = DLM_LOCK_NL;
88362306a36Sopenharmony_ci	else if (level == DLM_LOCK_PR)
88462306a36Sopenharmony_ci		new_level = DLM_LOCK_PR;
88562306a36Sopenharmony_ci	return new_level;
88662306a36Sopenharmony_ci}
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_cistatic void lockres_set_flags(struct ocfs2_lock_res *lockres,
88962306a36Sopenharmony_ci			      unsigned long newflags)
89062306a36Sopenharmony_ci{
89162306a36Sopenharmony_ci	struct ocfs2_mask_waiter *mw, *tmp;
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci 	assert_spin_locked(&lockres->l_lock);
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	lockres->l_flags = newflags;
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	list_for_each_entry_safe(mw, tmp, &lockres->l_mask_waiters, mw_item) {
89862306a36Sopenharmony_ci		if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal)
89962306a36Sopenharmony_ci			continue;
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci		list_del_init(&mw->mw_item);
90262306a36Sopenharmony_ci		mw->mw_status = 0;
90362306a36Sopenharmony_ci		complete(&mw->mw_complete);
90462306a36Sopenharmony_ci		ocfs2_track_lock_wait(lockres);
90562306a36Sopenharmony_ci	}
90662306a36Sopenharmony_ci}
90762306a36Sopenharmony_cistatic void lockres_or_flags(struct ocfs2_lock_res *lockres, unsigned long or)
90862306a36Sopenharmony_ci{
90962306a36Sopenharmony_ci	lockres_set_flags(lockres, lockres->l_flags | or);
91062306a36Sopenharmony_ci}
91162306a36Sopenharmony_cistatic void lockres_clear_flags(struct ocfs2_lock_res *lockres,
91262306a36Sopenharmony_ci				unsigned long clear)
91362306a36Sopenharmony_ci{
91462306a36Sopenharmony_ci	lockres_set_flags(lockres, lockres->l_flags & ~clear);
91562306a36Sopenharmony_ci}
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_cistatic inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res *lockres)
91862306a36Sopenharmony_ci{
91962306a36Sopenharmony_ci	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY));
92062306a36Sopenharmony_ci	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED));
92162306a36Sopenharmony_ci	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED));
92262306a36Sopenharmony_ci	BUG_ON(lockres->l_blocking <= DLM_LOCK_NL);
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	lockres->l_level = lockres->l_requested;
92562306a36Sopenharmony_ci	if (lockres->l_level <=
92662306a36Sopenharmony_ci	    ocfs2_highest_compat_lock_level(lockres->l_blocking)) {
92762306a36Sopenharmony_ci		lockres->l_blocking = DLM_LOCK_NL;
92862306a36Sopenharmony_ci		lockres_clear_flags(lockres, OCFS2_LOCK_BLOCKED);
92962306a36Sopenharmony_ci	}
93062306a36Sopenharmony_ci	lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
93162306a36Sopenharmony_ci}
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_cistatic inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres)
93462306a36Sopenharmony_ci{
93562306a36Sopenharmony_ci	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY));
93662306a36Sopenharmony_ci	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED));
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	/* Convert from RO to EX doesn't really need anything as our
93962306a36Sopenharmony_ci	 * information is already up to data. Convert from NL to
94062306a36Sopenharmony_ci	 * *anything* however should mark ourselves as needing an
94162306a36Sopenharmony_ci	 * update */
94262306a36Sopenharmony_ci	if (lockres->l_level == DLM_LOCK_NL &&
94362306a36Sopenharmony_ci	    lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH)
94462306a36Sopenharmony_ci		lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	lockres->l_level = lockres->l_requested;
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	/*
94962306a36Sopenharmony_ci	 * We set the OCFS2_LOCK_UPCONVERT_FINISHING flag before clearing
95062306a36Sopenharmony_ci	 * the OCFS2_LOCK_BUSY flag to prevent the dc thread from
95162306a36Sopenharmony_ci	 * downconverting the lock before the upconvert has fully completed.
95262306a36Sopenharmony_ci	 * Do not prevent the dc thread from downconverting if NONBLOCK lock
95362306a36Sopenharmony_ci	 * had already returned.
95462306a36Sopenharmony_ci	 */
95562306a36Sopenharmony_ci	if (!(lockres->l_flags & OCFS2_LOCK_NONBLOCK_FINISHED))
95662306a36Sopenharmony_ci		lockres_or_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
95762306a36Sopenharmony_ci	else
95862306a36Sopenharmony_ci		lockres_clear_flags(lockres, OCFS2_LOCK_NONBLOCK_FINISHED);
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
96162306a36Sopenharmony_ci}
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_cistatic inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres)
96462306a36Sopenharmony_ci{
96562306a36Sopenharmony_ci	BUG_ON((!(lockres->l_flags & OCFS2_LOCK_BUSY)));
96662306a36Sopenharmony_ci	BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED);
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	if (lockres->l_requested > DLM_LOCK_NL &&
96962306a36Sopenharmony_ci	    !(lockres->l_flags & OCFS2_LOCK_LOCAL) &&
97062306a36Sopenharmony_ci	    lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH)
97162306a36Sopenharmony_ci		lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	lockres->l_level = lockres->l_requested;
97462306a36Sopenharmony_ci	lockres_or_flags(lockres, OCFS2_LOCK_ATTACHED);
97562306a36Sopenharmony_ci	lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
97662306a36Sopenharmony_ci}
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_cistatic int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres,
97962306a36Sopenharmony_ci				     int level)
98062306a36Sopenharmony_ci{
98162306a36Sopenharmony_ci	int needs_downconvert = 0;
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_ci	assert_spin_locked(&lockres->l_lock);
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci	if (level > lockres->l_blocking) {
98662306a36Sopenharmony_ci		/* only schedule a downconvert if we haven't already scheduled
98762306a36Sopenharmony_ci		 * one that goes low enough to satisfy the level we're
98862306a36Sopenharmony_ci		 * blocking.  this also catches the case where we get
98962306a36Sopenharmony_ci		 * duplicate BASTs */
99062306a36Sopenharmony_ci		if (ocfs2_highest_compat_lock_level(level) <
99162306a36Sopenharmony_ci		    ocfs2_highest_compat_lock_level(lockres->l_blocking))
99262306a36Sopenharmony_ci			needs_downconvert = 1;
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci		lockres->l_blocking = level;
99562306a36Sopenharmony_ci	}
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	mlog(ML_BASTS, "lockres %s, block %d, level %d, l_block %d, dwn %d\n",
99862306a36Sopenharmony_ci	     lockres->l_name, level, lockres->l_level, lockres->l_blocking,
99962306a36Sopenharmony_ci	     needs_downconvert);
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci	if (needs_downconvert)
100262306a36Sopenharmony_ci		lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED);
100362306a36Sopenharmony_ci	mlog(0, "needs_downconvert = %d\n", needs_downconvert);
100462306a36Sopenharmony_ci	return needs_downconvert;
100562306a36Sopenharmony_ci}
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci/*
100862306a36Sopenharmony_ci * OCFS2_LOCK_PENDING and l_pending_gen.
100962306a36Sopenharmony_ci *
101062306a36Sopenharmony_ci * Why does OCFS2_LOCK_PENDING exist?  To close a race between setting
101162306a36Sopenharmony_ci * OCFS2_LOCK_BUSY and calling ocfs2_dlm_lock().  See ocfs2_unblock_lock()
101262306a36Sopenharmony_ci * for more details on the race.
101362306a36Sopenharmony_ci *
101462306a36Sopenharmony_ci * OCFS2_LOCK_PENDING closes the race quite nicely.  However, it introduces
101562306a36Sopenharmony_ci * a race on itself.  In o2dlm, we can get the ast before ocfs2_dlm_lock()
101662306a36Sopenharmony_ci * returns.  The ast clears OCFS2_LOCK_BUSY, and must therefore clear
101762306a36Sopenharmony_ci * OCFS2_LOCK_PENDING at the same time.  When ocfs2_dlm_lock() returns,
101862306a36Sopenharmony_ci * the caller is going to try to clear PENDING again.  If nothing else is
101962306a36Sopenharmony_ci * happening, __lockres_clear_pending() sees PENDING is unset and does
102062306a36Sopenharmony_ci * nothing.
102162306a36Sopenharmony_ci *
102262306a36Sopenharmony_ci * But what if another path (eg downconvert thread) has just started a
102362306a36Sopenharmony_ci * new locking action?  The other path has re-set PENDING.  Our path
102462306a36Sopenharmony_ci * cannot clear PENDING, because that will re-open the original race
102562306a36Sopenharmony_ci * window.
102662306a36Sopenharmony_ci *
102762306a36Sopenharmony_ci * [Example]
102862306a36Sopenharmony_ci *
102962306a36Sopenharmony_ci * ocfs2_meta_lock()
103062306a36Sopenharmony_ci *  ocfs2_cluster_lock()
103162306a36Sopenharmony_ci *   set BUSY
103262306a36Sopenharmony_ci *   set PENDING
103362306a36Sopenharmony_ci *   drop l_lock
103462306a36Sopenharmony_ci *   ocfs2_dlm_lock()
103562306a36Sopenharmony_ci *    ocfs2_locking_ast()		ocfs2_downconvert_thread()
103662306a36Sopenharmony_ci *     clear PENDING			 ocfs2_unblock_lock()
103762306a36Sopenharmony_ci *					  take_l_lock
103862306a36Sopenharmony_ci *					  !BUSY
103962306a36Sopenharmony_ci *					  ocfs2_prepare_downconvert()
104062306a36Sopenharmony_ci *					   set BUSY
104162306a36Sopenharmony_ci *					   set PENDING
104262306a36Sopenharmony_ci *					  drop l_lock
104362306a36Sopenharmony_ci *   take l_lock
104462306a36Sopenharmony_ci *   clear PENDING
104562306a36Sopenharmony_ci *   drop l_lock
104662306a36Sopenharmony_ci *			<window>
104762306a36Sopenharmony_ci *					  ocfs2_dlm_lock()
104862306a36Sopenharmony_ci *
104962306a36Sopenharmony_ci * So as you can see, we now have a window where l_lock is not held,
105062306a36Sopenharmony_ci * PENDING is not set, and ocfs2_dlm_lock() has not been called.
105162306a36Sopenharmony_ci *
105262306a36Sopenharmony_ci * The core problem is that ocfs2_cluster_lock() has cleared the PENDING
105362306a36Sopenharmony_ci * set by ocfs2_prepare_downconvert().  That wasn't nice.
105462306a36Sopenharmony_ci *
105562306a36Sopenharmony_ci * To solve this we introduce l_pending_gen.  A call to
105662306a36Sopenharmony_ci * lockres_clear_pending() will only do so when it is passed a generation
105762306a36Sopenharmony_ci * number that matches the lockres.  lockres_set_pending() will return the
105862306a36Sopenharmony_ci * current generation number.  When ocfs2_cluster_lock() goes to clear
105962306a36Sopenharmony_ci * PENDING, it passes the generation it got from set_pending().  In our
106062306a36Sopenharmony_ci * example above, the generation numbers will *not* match.  Thus,
106162306a36Sopenharmony_ci * ocfs2_cluster_lock() will not clear the PENDING set by
106262306a36Sopenharmony_ci * ocfs2_prepare_downconvert().
106362306a36Sopenharmony_ci */
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci/* Unlocked version for ocfs2_locking_ast() */
106662306a36Sopenharmony_cistatic void __lockres_clear_pending(struct ocfs2_lock_res *lockres,
106762306a36Sopenharmony_ci				    unsigned int generation,
106862306a36Sopenharmony_ci				    struct ocfs2_super *osb)
106962306a36Sopenharmony_ci{
107062306a36Sopenharmony_ci	assert_spin_locked(&lockres->l_lock);
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci	/*
107362306a36Sopenharmony_ci	 * The ast and locking functions can race us here.  The winner
107462306a36Sopenharmony_ci	 * will clear pending, the loser will not.
107562306a36Sopenharmony_ci	 */
107662306a36Sopenharmony_ci	if (!(lockres->l_flags & OCFS2_LOCK_PENDING) ||
107762306a36Sopenharmony_ci	    (lockres->l_pending_gen != generation))
107862306a36Sopenharmony_ci		return;
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	lockres_clear_flags(lockres, OCFS2_LOCK_PENDING);
108162306a36Sopenharmony_ci	lockres->l_pending_gen++;
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	/*
108462306a36Sopenharmony_ci	 * The downconvert thread may have skipped us because we
108562306a36Sopenharmony_ci	 * were PENDING.  Wake it up.
108662306a36Sopenharmony_ci	 */
108762306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_BLOCKED)
108862306a36Sopenharmony_ci		ocfs2_wake_downconvert_thread(osb);
108962306a36Sopenharmony_ci}
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci/* Locked version for callers of ocfs2_dlm_lock() */
109262306a36Sopenharmony_cistatic void lockres_clear_pending(struct ocfs2_lock_res *lockres,
109362306a36Sopenharmony_ci				  unsigned int generation,
109462306a36Sopenharmony_ci				  struct ocfs2_super *osb)
109562306a36Sopenharmony_ci{
109662306a36Sopenharmony_ci	unsigned long flags;
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
109962306a36Sopenharmony_ci	__lockres_clear_pending(lockres, generation, osb);
110062306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
110162306a36Sopenharmony_ci}
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_cistatic unsigned int lockres_set_pending(struct ocfs2_lock_res *lockres)
110462306a36Sopenharmony_ci{
110562306a36Sopenharmony_ci	assert_spin_locked(&lockres->l_lock);
110662306a36Sopenharmony_ci	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY));
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_ci	lockres_or_flags(lockres, OCFS2_LOCK_PENDING);
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	return lockres->l_pending_gen;
111162306a36Sopenharmony_ci}
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_cistatic void ocfs2_blocking_ast(struct ocfs2_dlm_lksb *lksb, int level)
111462306a36Sopenharmony_ci{
111562306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = ocfs2_lksb_to_lock_res(lksb);
111662306a36Sopenharmony_ci	struct ocfs2_super *osb = ocfs2_get_lockres_osb(lockres);
111762306a36Sopenharmony_ci	int needs_downconvert;
111862306a36Sopenharmony_ci	unsigned long flags;
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci	BUG_ON(level <= DLM_LOCK_NL);
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	mlog(ML_BASTS, "BAST fired for lockres %s, blocking %d, level %d, "
112362306a36Sopenharmony_ci	     "type %s\n", lockres->l_name, level, lockres->l_level,
112462306a36Sopenharmony_ci	     ocfs2_lock_type_string(lockres->l_type));
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci	/*
112762306a36Sopenharmony_ci	 * We can skip the bast for locks which don't enable caching -
112862306a36Sopenharmony_ci	 * they'll be dropped at the earliest possible time anyway.
112962306a36Sopenharmony_ci	 */
113062306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_NOCACHE)
113162306a36Sopenharmony_ci		return;
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
113462306a36Sopenharmony_ci	needs_downconvert = ocfs2_generic_handle_bast(lockres, level);
113562306a36Sopenharmony_ci	if (needs_downconvert)
113662306a36Sopenharmony_ci		ocfs2_schedule_blocked_lock(osb, lockres);
113762306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ci	wake_up(&lockres->l_event);
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	ocfs2_wake_downconvert_thread(osb);
114262306a36Sopenharmony_ci}
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_cistatic void ocfs2_locking_ast(struct ocfs2_dlm_lksb *lksb)
114562306a36Sopenharmony_ci{
114662306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = ocfs2_lksb_to_lock_res(lksb);
114762306a36Sopenharmony_ci	struct ocfs2_super *osb = ocfs2_get_lockres_osb(lockres);
114862306a36Sopenharmony_ci	unsigned long flags;
114962306a36Sopenharmony_ci	int status;
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	status = ocfs2_dlm_lock_status(&lockres->l_lksb);
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	if (status == -EAGAIN) {
115662306a36Sopenharmony_ci		lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
115762306a36Sopenharmony_ci		goto out;
115862306a36Sopenharmony_ci	}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci	if (status) {
116162306a36Sopenharmony_ci		mlog(ML_ERROR, "lockres %s: lksb status value of %d!\n",
116262306a36Sopenharmony_ci		     lockres->l_name, status);
116362306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
116462306a36Sopenharmony_ci		return;
116562306a36Sopenharmony_ci	}
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	mlog(ML_BASTS, "AST fired for lockres %s, action %d, unlock %d, "
116862306a36Sopenharmony_ci	     "level %d => %d\n", lockres->l_name, lockres->l_action,
116962306a36Sopenharmony_ci	     lockres->l_unlock_action, lockres->l_level, lockres->l_requested);
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci	switch(lockres->l_action) {
117262306a36Sopenharmony_ci	case OCFS2_AST_ATTACH:
117362306a36Sopenharmony_ci		ocfs2_generic_handle_attach_action(lockres);
117462306a36Sopenharmony_ci		lockres_clear_flags(lockres, OCFS2_LOCK_LOCAL);
117562306a36Sopenharmony_ci		break;
117662306a36Sopenharmony_ci	case OCFS2_AST_CONVERT:
117762306a36Sopenharmony_ci		ocfs2_generic_handle_convert_action(lockres);
117862306a36Sopenharmony_ci		break;
117962306a36Sopenharmony_ci	case OCFS2_AST_DOWNCONVERT:
118062306a36Sopenharmony_ci		ocfs2_generic_handle_downconvert_action(lockres);
118162306a36Sopenharmony_ci		break;
118262306a36Sopenharmony_ci	default:
118362306a36Sopenharmony_ci		mlog(ML_ERROR, "lockres %s: AST fired with invalid action: %u, "
118462306a36Sopenharmony_ci		     "flags 0x%lx, unlock: %u\n",
118562306a36Sopenharmony_ci		     lockres->l_name, lockres->l_action, lockres->l_flags,
118662306a36Sopenharmony_ci		     lockres->l_unlock_action);
118762306a36Sopenharmony_ci		BUG();
118862306a36Sopenharmony_ci	}
118962306a36Sopenharmony_ciout:
119062306a36Sopenharmony_ci	/* set it to something invalid so if we get called again we
119162306a36Sopenharmony_ci	 * can catch it. */
119262306a36Sopenharmony_ci	lockres->l_action = OCFS2_AST_INVALID;
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci	/* Did we try to cancel this lock?  Clear that state */
119562306a36Sopenharmony_ci	if (lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT)
119662306a36Sopenharmony_ci		lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci	/*
119962306a36Sopenharmony_ci	 * We may have beaten the locking functions here.  We certainly
120062306a36Sopenharmony_ci	 * know that dlm_lock() has been called :-)
120162306a36Sopenharmony_ci	 * Because we can't have two lock calls in flight at once, we
120262306a36Sopenharmony_ci	 * can use lockres->l_pending_gen.
120362306a36Sopenharmony_ci	 */
120462306a36Sopenharmony_ci	__lockres_clear_pending(lockres, lockres->l_pending_gen,  osb);
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci	wake_up(&lockres->l_event);
120762306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
120862306a36Sopenharmony_ci}
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_cistatic void ocfs2_unlock_ast(struct ocfs2_dlm_lksb *lksb, int error)
121162306a36Sopenharmony_ci{
121262306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = ocfs2_lksb_to_lock_res(lksb);
121362306a36Sopenharmony_ci	unsigned long flags;
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	mlog(ML_BASTS, "UNLOCK AST fired for lockres %s, action = %d\n",
121662306a36Sopenharmony_ci	     lockres->l_name, lockres->l_unlock_action);
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
121962306a36Sopenharmony_ci	if (error) {
122062306a36Sopenharmony_ci		mlog(ML_ERROR, "Dlm passes error %d for lock %s, "
122162306a36Sopenharmony_ci		     "unlock_action %d\n", error, lockres->l_name,
122262306a36Sopenharmony_ci		     lockres->l_unlock_action);
122362306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
122462306a36Sopenharmony_ci		return;
122562306a36Sopenharmony_ci	}
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	switch(lockres->l_unlock_action) {
122862306a36Sopenharmony_ci	case OCFS2_UNLOCK_CANCEL_CONVERT:
122962306a36Sopenharmony_ci		mlog(0, "Cancel convert success for %s\n", lockres->l_name);
123062306a36Sopenharmony_ci		lockres->l_action = OCFS2_AST_INVALID;
123162306a36Sopenharmony_ci		/* Downconvert thread may have requeued this lock, we
123262306a36Sopenharmony_ci		 * need to wake it. */
123362306a36Sopenharmony_ci		if (lockres->l_flags & OCFS2_LOCK_BLOCKED)
123462306a36Sopenharmony_ci			ocfs2_wake_downconvert_thread(ocfs2_get_lockres_osb(lockres));
123562306a36Sopenharmony_ci		break;
123662306a36Sopenharmony_ci	case OCFS2_UNLOCK_DROP_LOCK:
123762306a36Sopenharmony_ci		lockres->l_level = DLM_LOCK_IV;
123862306a36Sopenharmony_ci		break;
123962306a36Sopenharmony_ci	default:
124062306a36Sopenharmony_ci		BUG();
124162306a36Sopenharmony_ci	}
124262306a36Sopenharmony_ci
124362306a36Sopenharmony_ci	lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
124462306a36Sopenharmony_ci	lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
124562306a36Sopenharmony_ci	wake_up(&lockres->l_event);
124662306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
124762306a36Sopenharmony_ci}
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci/*
125062306a36Sopenharmony_ci * This is the filesystem locking protocol.  It provides the lock handling
125162306a36Sopenharmony_ci * hooks for the underlying DLM.  It has a maximum version number.
125262306a36Sopenharmony_ci * The version number allows interoperability with systems running at
125362306a36Sopenharmony_ci * the same major number and an equal or smaller minor number.
125462306a36Sopenharmony_ci *
125562306a36Sopenharmony_ci * Whenever the filesystem does new things with locks (adds or removes a
125662306a36Sopenharmony_ci * lock, orders them differently, does different things underneath a lock),
125762306a36Sopenharmony_ci * the version must be changed.  The protocol is negotiated when joining
125862306a36Sopenharmony_ci * the dlm domain.  A node may join the domain if its major version is
125962306a36Sopenharmony_ci * identical to all other nodes and its minor version is greater than
126062306a36Sopenharmony_ci * or equal to all other nodes.  When its minor version is greater than
126162306a36Sopenharmony_ci * the other nodes, it will run at the minor version specified by the
126262306a36Sopenharmony_ci * other nodes.
126362306a36Sopenharmony_ci *
126462306a36Sopenharmony_ci * If a locking change is made that will not be compatible with older
126562306a36Sopenharmony_ci * versions, the major number must be increased and the minor version set
126662306a36Sopenharmony_ci * to zero.  If a change merely adds a behavior that can be disabled when
126762306a36Sopenharmony_ci * speaking to older versions, the minor version must be increased.  If a
126862306a36Sopenharmony_ci * change adds a fully backwards compatible change (eg, LVB changes that
126962306a36Sopenharmony_ci * are just ignored by older versions), the version does not need to be
127062306a36Sopenharmony_ci * updated.
127162306a36Sopenharmony_ci */
127262306a36Sopenharmony_cistatic struct ocfs2_locking_protocol lproto = {
127362306a36Sopenharmony_ci	.lp_max_version = {
127462306a36Sopenharmony_ci		.pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR,
127562306a36Sopenharmony_ci		.pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR,
127662306a36Sopenharmony_ci	},
127762306a36Sopenharmony_ci	.lp_lock_ast		= ocfs2_locking_ast,
127862306a36Sopenharmony_ci	.lp_blocking_ast	= ocfs2_blocking_ast,
127962306a36Sopenharmony_ci	.lp_unlock_ast		= ocfs2_unlock_ast,
128062306a36Sopenharmony_ci};
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_civoid ocfs2_set_locking_protocol(void)
128362306a36Sopenharmony_ci{
128462306a36Sopenharmony_ci	ocfs2_stack_glue_set_max_proto_version(&lproto.lp_max_version);
128562306a36Sopenharmony_ci}
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_cistatic inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,
128862306a36Sopenharmony_ci						int convert)
128962306a36Sopenharmony_ci{
129062306a36Sopenharmony_ci	unsigned long flags;
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
129362306a36Sopenharmony_ci	lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
129462306a36Sopenharmony_ci	lockres_clear_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
129562306a36Sopenharmony_ci	if (convert)
129662306a36Sopenharmony_ci		lockres->l_action = OCFS2_AST_INVALID;
129762306a36Sopenharmony_ci	else
129862306a36Sopenharmony_ci		lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
129962306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_ci	wake_up(&lockres->l_event);
130262306a36Sopenharmony_ci}
130362306a36Sopenharmony_ci
130462306a36Sopenharmony_ci/* Note: If we detect another process working on the lock (i.e.,
130562306a36Sopenharmony_ci * OCFS2_LOCK_BUSY), we'll bail out returning 0. It's up to the caller
130662306a36Sopenharmony_ci * to do the right thing in that case.
130762306a36Sopenharmony_ci */
130862306a36Sopenharmony_cistatic int ocfs2_lock_create(struct ocfs2_super *osb,
130962306a36Sopenharmony_ci			     struct ocfs2_lock_res *lockres,
131062306a36Sopenharmony_ci			     int level,
131162306a36Sopenharmony_ci			     u32 dlm_flags)
131262306a36Sopenharmony_ci{
131362306a36Sopenharmony_ci	int ret = 0;
131462306a36Sopenharmony_ci	unsigned long flags;
131562306a36Sopenharmony_ci	unsigned int gen;
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci	mlog(0, "lock %s, level = %d, flags = %u\n", lockres->l_name, level,
131862306a36Sopenharmony_ci	     dlm_flags);
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
132162306a36Sopenharmony_ci	if ((lockres->l_flags & OCFS2_LOCK_ATTACHED) ||
132262306a36Sopenharmony_ci	    (lockres->l_flags & OCFS2_LOCK_BUSY)) {
132362306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
132462306a36Sopenharmony_ci		goto bail;
132562306a36Sopenharmony_ci	}
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci	lockres->l_action = OCFS2_AST_ATTACH;
132862306a36Sopenharmony_ci	lockres->l_requested = level;
132962306a36Sopenharmony_ci	lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
133062306a36Sopenharmony_ci	gen = lockres_set_pending(lockres);
133162306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci	ret = ocfs2_dlm_lock(osb->cconn,
133462306a36Sopenharmony_ci			     level,
133562306a36Sopenharmony_ci			     &lockres->l_lksb,
133662306a36Sopenharmony_ci			     dlm_flags,
133762306a36Sopenharmony_ci			     lockres->l_name,
133862306a36Sopenharmony_ci			     OCFS2_LOCK_ID_MAX_LEN - 1);
133962306a36Sopenharmony_ci	lockres_clear_pending(lockres, gen, osb);
134062306a36Sopenharmony_ci	if (ret) {
134162306a36Sopenharmony_ci		ocfs2_log_dlm_error("ocfs2_dlm_lock", ret, lockres);
134262306a36Sopenharmony_ci		ocfs2_recover_from_dlm_error(lockres, 1);
134362306a36Sopenharmony_ci	}
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci	mlog(0, "lock %s, return from ocfs2_dlm_lock\n", lockres->l_name);
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_cibail:
134862306a36Sopenharmony_ci	return ret;
134962306a36Sopenharmony_ci}
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_cistatic inline int ocfs2_check_wait_flag(struct ocfs2_lock_res *lockres,
135262306a36Sopenharmony_ci					int flag)
135362306a36Sopenharmony_ci{
135462306a36Sopenharmony_ci	unsigned long flags;
135562306a36Sopenharmony_ci	int ret;
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
135862306a36Sopenharmony_ci	ret = lockres->l_flags & flag;
135962306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	return ret;
136262306a36Sopenharmony_ci}
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_cistatic inline void ocfs2_wait_on_busy_lock(struct ocfs2_lock_res *lockres)
136562306a36Sopenharmony_ci
136662306a36Sopenharmony_ci{
136762306a36Sopenharmony_ci	wait_event(lockres->l_event,
136862306a36Sopenharmony_ci		   !ocfs2_check_wait_flag(lockres, OCFS2_LOCK_BUSY));
136962306a36Sopenharmony_ci}
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_cistatic inline void ocfs2_wait_on_refreshing_lock(struct ocfs2_lock_res *lockres)
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ci{
137462306a36Sopenharmony_ci	wait_event(lockres->l_event,
137562306a36Sopenharmony_ci		   !ocfs2_check_wait_flag(lockres, OCFS2_LOCK_REFRESHING));
137662306a36Sopenharmony_ci}
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci/* predict what lock level we'll be dropping down to on behalf
137962306a36Sopenharmony_ci * of another node, and return true if the currently wanted
138062306a36Sopenharmony_ci * level will be compatible with it. */
138162306a36Sopenharmony_cistatic inline int ocfs2_may_continue_on_blocked_lock(struct ocfs2_lock_res *lockres,
138262306a36Sopenharmony_ci						     int wanted)
138362306a36Sopenharmony_ci{
138462306a36Sopenharmony_ci	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED));
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci	return wanted <= ocfs2_highest_compat_lock_level(lockres->l_blocking);
138762306a36Sopenharmony_ci}
138862306a36Sopenharmony_ci
138962306a36Sopenharmony_cistatic void ocfs2_init_mask_waiter(struct ocfs2_mask_waiter *mw)
139062306a36Sopenharmony_ci{
139162306a36Sopenharmony_ci	INIT_LIST_HEAD(&mw->mw_item);
139262306a36Sopenharmony_ci	init_completion(&mw->mw_complete);
139362306a36Sopenharmony_ci	ocfs2_init_start_time(mw);
139462306a36Sopenharmony_ci}
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_cistatic int ocfs2_wait_for_mask(struct ocfs2_mask_waiter *mw)
139762306a36Sopenharmony_ci{
139862306a36Sopenharmony_ci	wait_for_completion(&mw->mw_complete);
139962306a36Sopenharmony_ci	/* Re-arm the completion in case we want to wait on it again */
140062306a36Sopenharmony_ci	reinit_completion(&mw->mw_complete);
140162306a36Sopenharmony_ci	return mw->mw_status;
140262306a36Sopenharmony_ci}
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_cistatic void lockres_add_mask_waiter(struct ocfs2_lock_res *lockres,
140562306a36Sopenharmony_ci				    struct ocfs2_mask_waiter *mw,
140662306a36Sopenharmony_ci				    unsigned long mask,
140762306a36Sopenharmony_ci				    unsigned long goal)
140862306a36Sopenharmony_ci{
140962306a36Sopenharmony_ci	BUG_ON(!list_empty(&mw->mw_item));
141062306a36Sopenharmony_ci
141162306a36Sopenharmony_ci	assert_spin_locked(&lockres->l_lock);
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci	list_add_tail(&mw->mw_item, &lockres->l_mask_waiters);
141462306a36Sopenharmony_ci	mw->mw_mask = mask;
141562306a36Sopenharmony_ci	mw->mw_goal = goal;
141662306a36Sopenharmony_ci	ocfs2_track_lock_wait(lockres);
141762306a36Sopenharmony_ci}
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ci/* returns 0 if the mw that was removed was already satisfied, -EBUSY
142062306a36Sopenharmony_ci * if the mask still hadn't reached its goal */
142162306a36Sopenharmony_cistatic int __lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres,
142262306a36Sopenharmony_ci				      struct ocfs2_mask_waiter *mw)
142362306a36Sopenharmony_ci{
142462306a36Sopenharmony_ci	int ret = 0;
142562306a36Sopenharmony_ci
142662306a36Sopenharmony_ci	assert_spin_locked(&lockres->l_lock);
142762306a36Sopenharmony_ci	if (!list_empty(&mw->mw_item)) {
142862306a36Sopenharmony_ci		if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal)
142962306a36Sopenharmony_ci			ret = -EBUSY;
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_ci		list_del_init(&mw->mw_item);
143262306a36Sopenharmony_ci		init_completion(&mw->mw_complete);
143362306a36Sopenharmony_ci		ocfs2_track_lock_wait(lockres);
143462306a36Sopenharmony_ci	}
143562306a36Sopenharmony_ci
143662306a36Sopenharmony_ci	return ret;
143762306a36Sopenharmony_ci}
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_cistatic int lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres,
144062306a36Sopenharmony_ci				      struct ocfs2_mask_waiter *mw)
144162306a36Sopenharmony_ci{
144262306a36Sopenharmony_ci	unsigned long flags;
144362306a36Sopenharmony_ci	int ret = 0;
144462306a36Sopenharmony_ci
144562306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
144662306a36Sopenharmony_ci	ret = __lockres_remove_mask_waiter(lockres, mw);
144762306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci	return ret;
145062306a36Sopenharmony_ci
145162306a36Sopenharmony_ci}
145262306a36Sopenharmony_ci
145362306a36Sopenharmony_cistatic int ocfs2_wait_for_mask_interruptible(struct ocfs2_mask_waiter *mw,
145462306a36Sopenharmony_ci					     struct ocfs2_lock_res *lockres)
145562306a36Sopenharmony_ci{
145662306a36Sopenharmony_ci	int ret;
145762306a36Sopenharmony_ci
145862306a36Sopenharmony_ci	ret = wait_for_completion_interruptible(&mw->mw_complete);
145962306a36Sopenharmony_ci	if (ret)
146062306a36Sopenharmony_ci		lockres_remove_mask_waiter(lockres, mw);
146162306a36Sopenharmony_ci	else
146262306a36Sopenharmony_ci		ret = mw->mw_status;
146362306a36Sopenharmony_ci	/* Re-arm the completion in case we want to wait on it again */
146462306a36Sopenharmony_ci	reinit_completion(&mw->mw_complete);
146562306a36Sopenharmony_ci	return ret;
146662306a36Sopenharmony_ci}
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_cistatic int __ocfs2_cluster_lock(struct ocfs2_super *osb,
146962306a36Sopenharmony_ci				struct ocfs2_lock_res *lockres,
147062306a36Sopenharmony_ci				int level,
147162306a36Sopenharmony_ci				u32 lkm_flags,
147262306a36Sopenharmony_ci				int arg_flags,
147362306a36Sopenharmony_ci				int l_subclass,
147462306a36Sopenharmony_ci				unsigned long caller_ip)
147562306a36Sopenharmony_ci{
147662306a36Sopenharmony_ci	struct ocfs2_mask_waiter mw;
147762306a36Sopenharmony_ci	int wait, catch_signals = !(osb->s_mount_opt & OCFS2_MOUNT_NOINTR);
147862306a36Sopenharmony_ci	int ret = 0; /* gcc doesn't realize wait = 1 guarantees ret is set */
147962306a36Sopenharmony_ci	unsigned long flags;
148062306a36Sopenharmony_ci	unsigned int gen;
148162306a36Sopenharmony_ci	int noqueue_attempted = 0;
148262306a36Sopenharmony_ci	int dlm_locked = 0;
148362306a36Sopenharmony_ci	int kick_dc = 0;
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci	if (!(lockres->l_flags & OCFS2_LOCK_INITIALIZED)) {
148662306a36Sopenharmony_ci		mlog_errno(-EINVAL);
148762306a36Sopenharmony_ci		return -EINVAL;
148862306a36Sopenharmony_ci	}
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ci	ocfs2_init_mask_waiter(&mw);
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci	if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB)
149362306a36Sopenharmony_ci		lkm_flags |= DLM_LKF_VALBLK;
149462306a36Sopenharmony_ci
149562306a36Sopenharmony_ciagain:
149662306a36Sopenharmony_ci	wait = 0;
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_ci	if (catch_signals && signal_pending(current)) {
150162306a36Sopenharmony_ci		ret = -ERESTARTSYS;
150262306a36Sopenharmony_ci		goto unlock;
150362306a36Sopenharmony_ci	}
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	mlog_bug_on_msg(lockres->l_flags & OCFS2_LOCK_FREEING,
150662306a36Sopenharmony_ci			"Cluster lock called on freeing lockres %s! flags "
150762306a36Sopenharmony_ci			"0x%lx\n", lockres->l_name, lockres->l_flags);
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_ci	/* We only compare against the currently granted level
151062306a36Sopenharmony_ci	 * here. If the lock is blocked waiting on a downconvert,
151162306a36Sopenharmony_ci	 * we'll get caught below. */
151262306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_BUSY &&
151362306a36Sopenharmony_ci	    level > lockres->l_level) {
151462306a36Sopenharmony_ci		/* is someone sitting in dlm_lock? If so, wait on
151562306a36Sopenharmony_ci		 * them. */
151662306a36Sopenharmony_ci		lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0);
151762306a36Sopenharmony_ci		wait = 1;
151862306a36Sopenharmony_ci		goto unlock;
151962306a36Sopenharmony_ci	}
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_UPCONVERT_FINISHING) {
152262306a36Sopenharmony_ci		/*
152362306a36Sopenharmony_ci		 * We've upconverted. If the lock now has a level we can
152462306a36Sopenharmony_ci		 * work with, we take it. If, however, the lock is not at the
152562306a36Sopenharmony_ci		 * required level, we go thru the full cycle. One way this could
152662306a36Sopenharmony_ci		 * happen is if a process requesting an upconvert to PR is
152762306a36Sopenharmony_ci		 * closely followed by another requesting upconvert to an EX.
152862306a36Sopenharmony_ci		 * If the process requesting EX lands here, we want it to
152962306a36Sopenharmony_ci		 * continue attempting to upconvert and let the process
153062306a36Sopenharmony_ci		 * requesting PR take the lock.
153162306a36Sopenharmony_ci		 * If multiple processes request upconvert to PR, the first one
153262306a36Sopenharmony_ci		 * here will take the lock. The others will have to go thru the
153362306a36Sopenharmony_ci		 * OCFS2_LOCK_BLOCKED check to ensure that there is no pending
153462306a36Sopenharmony_ci		 * downconvert request.
153562306a36Sopenharmony_ci		 */
153662306a36Sopenharmony_ci		if (level <= lockres->l_level)
153762306a36Sopenharmony_ci			goto update_holders;
153862306a36Sopenharmony_ci	}
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_BLOCKED &&
154162306a36Sopenharmony_ci	    !ocfs2_may_continue_on_blocked_lock(lockres, level)) {
154262306a36Sopenharmony_ci		/* is the lock is currently blocked on behalf of
154362306a36Sopenharmony_ci		 * another node */
154462306a36Sopenharmony_ci		lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BLOCKED, 0);
154562306a36Sopenharmony_ci		wait = 1;
154662306a36Sopenharmony_ci		goto unlock;
154762306a36Sopenharmony_ci	}
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci	if (level > lockres->l_level) {
155062306a36Sopenharmony_ci		if (noqueue_attempted > 0) {
155162306a36Sopenharmony_ci			ret = -EAGAIN;
155262306a36Sopenharmony_ci			goto unlock;
155362306a36Sopenharmony_ci		}
155462306a36Sopenharmony_ci		if (lkm_flags & DLM_LKF_NOQUEUE)
155562306a36Sopenharmony_ci			noqueue_attempted = 1;
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci		if (lockres->l_action != OCFS2_AST_INVALID)
155862306a36Sopenharmony_ci			mlog(ML_ERROR, "lockres %s has action %u pending\n",
155962306a36Sopenharmony_ci			     lockres->l_name, lockres->l_action);
156062306a36Sopenharmony_ci
156162306a36Sopenharmony_ci		if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) {
156262306a36Sopenharmony_ci			lockres->l_action = OCFS2_AST_ATTACH;
156362306a36Sopenharmony_ci			lkm_flags &= ~DLM_LKF_CONVERT;
156462306a36Sopenharmony_ci		} else {
156562306a36Sopenharmony_ci			lockres->l_action = OCFS2_AST_CONVERT;
156662306a36Sopenharmony_ci			lkm_flags |= DLM_LKF_CONVERT;
156762306a36Sopenharmony_ci		}
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_ci		lockres->l_requested = level;
157062306a36Sopenharmony_ci		lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
157162306a36Sopenharmony_ci		gen = lockres_set_pending(lockres);
157262306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
157362306a36Sopenharmony_ci
157462306a36Sopenharmony_ci		BUG_ON(level == DLM_LOCK_IV);
157562306a36Sopenharmony_ci		BUG_ON(level == DLM_LOCK_NL);
157662306a36Sopenharmony_ci
157762306a36Sopenharmony_ci		mlog(ML_BASTS, "lockres %s, convert from %d to %d\n",
157862306a36Sopenharmony_ci		     lockres->l_name, lockres->l_level, level);
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci		/* call dlm_lock to upgrade lock now */
158162306a36Sopenharmony_ci		ret = ocfs2_dlm_lock(osb->cconn,
158262306a36Sopenharmony_ci				     level,
158362306a36Sopenharmony_ci				     &lockres->l_lksb,
158462306a36Sopenharmony_ci				     lkm_flags,
158562306a36Sopenharmony_ci				     lockres->l_name,
158662306a36Sopenharmony_ci				     OCFS2_LOCK_ID_MAX_LEN - 1);
158762306a36Sopenharmony_ci		lockres_clear_pending(lockres, gen, osb);
158862306a36Sopenharmony_ci		if (ret) {
158962306a36Sopenharmony_ci			if (!(lkm_flags & DLM_LKF_NOQUEUE) ||
159062306a36Sopenharmony_ci			    (ret != -EAGAIN)) {
159162306a36Sopenharmony_ci				ocfs2_log_dlm_error("ocfs2_dlm_lock",
159262306a36Sopenharmony_ci						    ret, lockres);
159362306a36Sopenharmony_ci			}
159462306a36Sopenharmony_ci			ocfs2_recover_from_dlm_error(lockres, 1);
159562306a36Sopenharmony_ci			goto out;
159662306a36Sopenharmony_ci		}
159762306a36Sopenharmony_ci		dlm_locked = 1;
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_ci		mlog(0, "lock %s, successful return from ocfs2_dlm_lock\n",
160062306a36Sopenharmony_ci		     lockres->l_name);
160162306a36Sopenharmony_ci
160262306a36Sopenharmony_ci		/* At this point we've gone inside the dlm and need to
160362306a36Sopenharmony_ci		 * complete our work regardless. */
160462306a36Sopenharmony_ci		catch_signals = 0;
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci		/* wait for busy to clear and carry on */
160762306a36Sopenharmony_ci		goto again;
160862306a36Sopenharmony_ci	}
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ciupdate_holders:
161162306a36Sopenharmony_ci	/* Ok, if we get here then we're good to go. */
161262306a36Sopenharmony_ci	ocfs2_inc_holders(lockres, level);
161362306a36Sopenharmony_ci
161462306a36Sopenharmony_ci	ret = 0;
161562306a36Sopenharmony_ciunlock:
161662306a36Sopenharmony_ci	lockres_clear_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci	/* ocfs2_unblock_lock reques on seeing OCFS2_LOCK_UPCONVERT_FINISHING */
161962306a36Sopenharmony_ci	kick_dc = (lockres->l_flags & OCFS2_LOCK_BLOCKED);
162062306a36Sopenharmony_ci
162162306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
162262306a36Sopenharmony_ci	if (kick_dc)
162362306a36Sopenharmony_ci		ocfs2_wake_downconvert_thread(osb);
162462306a36Sopenharmony_ciout:
162562306a36Sopenharmony_ci	/*
162662306a36Sopenharmony_ci	 * This is helping work around a lock inversion between the page lock
162762306a36Sopenharmony_ci	 * and dlm locks.  One path holds the page lock while calling aops
162862306a36Sopenharmony_ci	 * which block acquiring dlm locks.  The voting thread holds dlm
162962306a36Sopenharmony_ci	 * locks while acquiring page locks while down converting data locks.
163062306a36Sopenharmony_ci	 * This block is helping an aop path notice the inversion and back
163162306a36Sopenharmony_ci	 * off to unlock its page lock before trying the dlm lock again.
163262306a36Sopenharmony_ci	 */
163362306a36Sopenharmony_ci	if (wait && arg_flags & OCFS2_LOCK_NONBLOCK &&
163462306a36Sopenharmony_ci	    mw.mw_mask & (OCFS2_LOCK_BUSY|OCFS2_LOCK_BLOCKED)) {
163562306a36Sopenharmony_ci		wait = 0;
163662306a36Sopenharmony_ci		spin_lock_irqsave(&lockres->l_lock, flags);
163762306a36Sopenharmony_ci		if (__lockres_remove_mask_waiter(lockres, &mw)) {
163862306a36Sopenharmony_ci			if (dlm_locked)
163962306a36Sopenharmony_ci				lockres_or_flags(lockres,
164062306a36Sopenharmony_ci					OCFS2_LOCK_NONBLOCK_FINISHED);
164162306a36Sopenharmony_ci			spin_unlock_irqrestore(&lockres->l_lock, flags);
164262306a36Sopenharmony_ci			ret = -EAGAIN;
164362306a36Sopenharmony_ci		} else {
164462306a36Sopenharmony_ci			spin_unlock_irqrestore(&lockres->l_lock, flags);
164562306a36Sopenharmony_ci			goto again;
164662306a36Sopenharmony_ci		}
164762306a36Sopenharmony_ci	}
164862306a36Sopenharmony_ci	if (wait) {
164962306a36Sopenharmony_ci		ret = ocfs2_wait_for_mask(&mw);
165062306a36Sopenharmony_ci		if (ret == 0)
165162306a36Sopenharmony_ci			goto again;
165262306a36Sopenharmony_ci		mlog_errno(ret);
165362306a36Sopenharmony_ci	}
165462306a36Sopenharmony_ci	ocfs2_update_lock_stats(lockres, level, &mw, ret);
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_LOCK_ALLOC
165762306a36Sopenharmony_ci	if (!ret && lockres->l_lockdep_map.key != NULL) {
165862306a36Sopenharmony_ci		if (level == DLM_LOCK_PR)
165962306a36Sopenharmony_ci			rwsem_acquire_read(&lockres->l_lockdep_map, l_subclass,
166062306a36Sopenharmony_ci				!!(arg_flags & OCFS2_META_LOCK_NOQUEUE),
166162306a36Sopenharmony_ci				caller_ip);
166262306a36Sopenharmony_ci		else
166362306a36Sopenharmony_ci			rwsem_acquire(&lockres->l_lockdep_map, l_subclass,
166462306a36Sopenharmony_ci				!!(arg_flags & OCFS2_META_LOCK_NOQUEUE),
166562306a36Sopenharmony_ci				caller_ip);
166662306a36Sopenharmony_ci	}
166762306a36Sopenharmony_ci#endif
166862306a36Sopenharmony_ci	return ret;
166962306a36Sopenharmony_ci}
167062306a36Sopenharmony_ci
167162306a36Sopenharmony_cistatic inline int ocfs2_cluster_lock(struct ocfs2_super *osb,
167262306a36Sopenharmony_ci				     struct ocfs2_lock_res *lockres,
167362306a36Sopenharmony_ci				     int level,
167462306a36Sopenharmony_ci				     u32 lkm_flags,
167562306a36Sopenharmony_ci				     int arg_flags)
167662306a36Sopenharmony_ci{
167762306a36Sopenharmony_ci	return __ocfs2_cluster_lock(osb, lockres, level, lkm_flags, arg_flags,
167862306a36Sopenharmony_ci				    0, _RET_IP_);
167962306a36Sopenharmony_ci}
168062306a36Sopenharmony_ci
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_cistatic void __ocfs2_cluster_unlock(struct ocfs2_super *osb,
168362306a36Sopenharmony_ci				   struct ocfs2_lock_res *lockres,
168462306a36Sopenharmony_ci				   int level,
168562306a36Sopenharmony_ci				   unsigned long caller_ip)
168662306a36Sopenharmony_ci{
168762306a36Sopenharmony_ci	unsigned long flags;
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
169062306a36Sopenharmony_ci	ocfs2_dec_holders(lockres, level);
169162306a36Sopenharmony_ci	ocfs2_downconvert_on_unlock(osb, lockres);
169262306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
169362306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_LOCK_ALLOC
169462306a36Sopenharmony_ci	if (lockres->l_lockdep_map.key != NULL)
169562306a36Sopenharmony_ci		rwsem_release(&lockres->l_lockdep_map, caller_ip);
169662306a36Sopenharmony_ci#endif
169762306a36Sopenharmony_ci}
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_cistatic int ocfs2_create_new_lock(struct ocfs2_super *osb,
170062306a36Sopenharmony_ci				 struct ocfs2_lock_res *lockres,
170162306a36Sopenharmony_ci				 int ex,
170262306a36Sopenharmony_ci				 int local)
170362306a36Sopenharmony_ci{
170462306a36Sopenharmony_ci	int level =  ex ? DLM_LOCK_EX : DLM_LOCK_PR;
170562306a36Sopenharmony_ci	unsigned long flags;
170662306a36Sopenharmony_ci	u32 lkm_flags = local ? DLM_LKF_LOCAL : 0;
170762306a36Sopenharmony_ci
170862306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
170962306a36Sopenharmony_ci	BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED);
171062306a36Sopenharmony_ci	lockres_or_flags(lockres, OCFS2_LOCK_LOCAL);
171162306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci	return ocfs2_lock_create(osb, lockres, level, lkm_flags);
171462306a36Sopenharmony_ci}
171562306a36Sopenharmony_ci
171662306a36Sopenharmony_ci/* Grants us an EX lock on the data and metadata resources, skipping
171762306a36Sopenharmony_ci * the normal cluster directory lookup. Use this ONLY on newly created
171862306a36Sopenharmony_ci * inodes which other nodes can't possibly see, and which haven't been
171962306a36Sopenharmony_ci * hashed in the inode hash yet. This can give us a good performance
172062306a36Sopenharmony_ci * increase as it'll skip the network broadcast normally associated
172162306a36Sopenharmony_ci * with creating a new lock resource. */
172262306a36Sopenharmony_ciint ocfs2_create_new_inode_locks(struct inode *inode)
172362306a36Sopenharmony_ci{
172462306a36Sopenharmony_ci	int ret;
172562306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci	BUG_ON(!ocfs2_inode_is_new(inode));
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci	mlog(0, "Inode %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno);
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci	/* NOTE: That we don't increment any of the holder counts, nor
173262306a36Sopenharmony_ci	 * do we add anything to a journal handle. Since this is
173362306a36Sopenharmony_ci	 * supposed to be a new inode which the cluster doesn't know
173462306a36Sopenharmony_ci	 * about yet, there is no need to.  As far as the LVB handling
173562306a36Sopenharmony_ci	 * is concerned, this is basically like acquiring an EX lock
173662306a36Sopenharmony_ci	 * on a resource which has an invalid one -- we'll set it
173762306a36Sopenharmony_ci	 * valid when we release the EX. */
173862306a36Sopenharmony_ci
173962306a36Sopenharmony_ci	ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_rw_lockres, 1, 1);
174062306a36Sopenharmony_ci	if (ret) {
174162306a36Sopenharmony_ci		mlog_errno(ret);
174262306a36Sopenharmony_ci		goto bail;
174362306a36Sopenharmony_ci	}
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci	/*
174662306a36Sopenharmony_ci	 * We don't want to use DLM_LKF_LOCAL on a meta data lock as they
174762306a36Sopenharmony_ci	 * don't use a generation in their lock names.
174862306a36Sopenharmony_ci	 */
174962306a36Sopenharmony_ci	ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_inode_lockres, 1, 0);
175062306a36Sopenharmony_ci	if (ret) {
175162306a36Sopenharmony_ci		mlog_errno(ret);
175262306a36Sopenharmony_ci		goto bail;
175362306a36Sopenharmony_ci	}
175462306a36Sopenharmony_ci
175562306a36Sopenharmony_ci	ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_open_lockres, 0, 0);
175662306a36Sopenharmony_ci	if (ret)
175762306a36Sopenharmony_ci		mlog_errno(ret);
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_cibail:
176062306a36Sopenharmony_ci	return ret;
176162306a36Sopenharmony_ci}
176262306a36Sopenharmony_ci
176362306a36Sopenharmony_ciint ocfs2_rw_lock(struct inode *inode, int write)
176462306a36Sopenharmony_ci{
176562306a36Sopenharmony_ci	int status, level;
176662306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres;
176762306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_ci	mlog(0, "inode %llu take %s RW lock\n",
177062306a36Sopenharmony_ci	     (unsigned long long)OCFS2_I(inode)->ip_blkno,
177162306a36Sopenharmony_ci	     write ? "EXMODE" : "PRMODE");
177262306a36Sopenharmony_ci
177362306a36Sopenharmony_ci	if (ocfs2_mount_local(osb))
177462306a36Sopenharmony_ci		return 0;
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_ci	lockres = &OCFS2_I(inode)->ip_rw_lockres;
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci	level = write ? DLM_LOCK_EX : DLM_LOCK_PR;
177962306a36Sopenharmony_ci
178062306a36Sopenharmony_ci	status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
178162306a36Sopenharmony_ci	if (status < 0)
178262306a36Sopenharmony_ci		mlog_errno(status);
178362306a36Sopenharmony_ci
178462306a36Sopenharmony_ci	return status;
178562306a36Sopenharmony_ci}
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ciint ocfs2_try_rw_lock(struct inode *inode, int write)
178862306a36Sopenharmony_ci{
178962306a36Sopenharmony_ci	int status, level;
179062306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres;
179162306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
179262306a36Sopenharmony_ci
179362306a36Sopenharmony_ci	mlog(0, "inode %llu try to take %s RW lock\n",
179462306a36Sopenharmony_ci	     (unsigned long long)OCFS2_I(inode)->ip_blkno,
179562306a36Sopenharmony_ci	     write ? "EXMODE" : "PRMODE");
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_ci	if (ocfs2_mount_local(osb))
179862306a36Sopenharmony_ci		return 0;
179962306a36Sopenharmony_ci
180062306a36Sopenharmony_ci	lockres = &OCFS2_I(inode)->ip_rw_lockres;
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci	level = write ? DLM_LOCK_EX : DLM_LOCK_PR;
180362306a36Sopenharmony_ci
180462306a36Sopenharmony_ci	status = ocfs2_cluster_lock(osb, lockres, level, DLM_LKF_NOQUEUE, 0);
180562306a36Sopenharmony_ci	return status;
180662306a36Sopenharmony_ci}
180762306a36Sopenharmony_ci
180862306a36Sopenharmony_civoid ocfs2_rw_unlock(struct inode *inode, int write)
180962306a36Sopenharmony_ci{
181062306a36Sopenharmony_ci	int level = write ? DLM_LOCK_EX : DLM_LOCK_PR;
181162306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_rw_lockres;
181262306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_ci	mlog(0, "inode %llu drop %s RW lock\n",
181562306a36Sopenharmony_ci	     (unsigned long long)OCFS2_I(inode)->ip_blkno,
181662306a36Sopenharmony_ci	     write ? "EXMODE" : "PRMODE");
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_ci	if (!ocfs2_mount_local(osb))
181962306a36Sopenharmony_ci		ocfs2_cluster_unlock(osb, lockres, level);
182062306a36Sopenharmony_ci}
182162306a36Sopenharmony_ci
182262306a36Sopenharmony_ci/*
182362306a36Sopenharmony_ci * ocfs2_open_lock always get PR mode lock.
182462306a36Sopenharmony_ci */
182562306a36Sopenharmony_ciint ocfs2_open_lock(struct inode *inode)
182662306a36Sopenharmony_ci{
182762306a36Sopenharmony_ci	int status = 0;
182862306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres;
182962306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
183062306a36Sopenharmony_ci
183162306a36Sopenharmony_ci	mlog(0, "inode %llu take PRMODE open lock\n",
183262306a36Sopenharmony_ci	     (unsigned long long)OCFS2_I(inode)->ip_blkno);
183362306a36Sopenharmony_ci
183462306a36Sopenharmony_ci	if (ocfs2_is_hard_readonly(osb) || ocfs2_mount_local(osb))
183562306a36Sopenharmony_ci		goto out;
183662306a36Sopenharmony_ci
183762306a36Sopenharmony_ci	lockres = &OCFS2_I(inode)->ip_open_lockres;
183862306a36Sopenharmony_ci
183962306a36Sopenharmony_ci	status = ocfs2_cluster_lock(osb, lockres, DLM_LOCK_PR, 0, 0);
184062306a36Sopenharmony_ci	if (status < 0)
184162306a36Sopenharmony_ci		mlog_errno(status);
184262306a36Sopenharmony_ci
184362306a36Sopenharmony_ciout:
184462306a36Sopenharmony_ci	return status;
184562306a36Sopenharmony_ci}
184662306a36Sopenharmony_ci
184762306a36Sopenharmony_ciint ocfs2_try_open_lock(struct inode *inode, int write)
184862306a36Sopenharmony_ci{
184962306a36Sopenharmony_ci	int status = 0, level;
185062306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres;
185162306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
185262306a36Sopenharmony_ci
185362306a36Sopenharmony_ci	mlog(0, "inode %llu try to take %s open lock\n",
185462306a36Sopenharmony_ci	     (unsigned long long)OCFS2_I(inode)->ip_blkno,
185562306a36Sopenharmony_ci	     write ? "EXMODE" : "PRMODE");
185662306a36Sopenharmony_ci
185762306a36Sopenharmony_ci	if (ocfs2_is_hard_readonly(osb)) {
185862306a36Sopenharmony_ci		if (write)
185962306a36Sopenharmony_ci			status = -EROFS;
186062306a36Sopenharmony_ci		goto out;
186162306a36Sopenharmony_ci	}
186262306a36Sopenharmony_ci
186362306a36Sopenharmony_ci	if (ocfs2_mount_local(osb))
186462306a36Sopenharmony_ci		goto out;
186562306a36Sopenharmony_ci
186662306a36Sopenharmony_ci	lockres = &OCFS2_I(inode)->ip_open_lockres;
186762306a36Sopenharmony_ci
186862306a36Sopenharmony_ci	level = write ? DLM_LOCK_EX : DLM_LOCK_PR;
186962306a36Sopenharmony_ci
187062306a36Sopenharmony_ci	/*
187162306a36Sopenharmony_ci	 * The file system may already holding a PRMODE/EXMODE open lock.
187262306a36Sopenharmony_ci	 * Since we pass DLM_LKF_NOQUEUE, the request won't block waiting on
187362306a36Sopenharmony_ci	 * other nodes and the -EAGAIN will indicate to the caller that
187462306a36Sopenharmony_ci	 * this inode is still in use.
187562306a36Sopenharmony_ci	 */
187662306a36Sopenharmony_ci	status = ocfs2_cluster_lock(osb, lockres, level, DLM_LKF_NOQUEUE, 0);
187762306a36Sopenharmony_ci
187862306a36Sopenharmony_ciout:
187962306a36Sopenharmony_ci	return status;
188062306a36Sopenharmony_ci}
188162306a36Sopenharmony_ci
188262306a36Sopenharmony_ci/*
188362306a36Sopenharmony_ci * ocfs2_open_unlock unlock PR and EX mode open locks.
188462306a36Sopenharmony_ci */
188562306a36Sopenharmony_civoid ocfs2_open_unlock(struct inode *inode)
188662306a36Sopenharmony_ci{
188762306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_open_lockres;
188862306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci	mlog(0, "inode %llu drop open lock\n",
189162306a36Sopenharmony_ci	     (unsigned long long)OCFS2_I(inode)->ip_blkno);
189262306a36Sopenharmony_ci
189362306a36Sopenharmony_ci	if (ocfs2_mount_local(osb))
189462306a36Sopenharmony_ci		goto out;
189562306a36Sopenharmony_ci
189662306a36Sopenharmony_ci	if(lockres->l_ro_holders)
189762306a36Sopenharmony_ci		ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_PR);
189862306a36Sopenharmony_ci	if(lockres->l_ex_holders)
189962306a36Sopenharmony_ci		ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_EX);
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ciout:
190262306a36Sopenharmony_ci	return;
190362306a36Sopenharmony_ci}
190462306a36Sopenharmony_ci
190562306a36Sopenharmony_cistatic int ocfs2_flock_handle_signal(struct ocfs2_lock_res *lockres,
190662306a36Sopenharmony_ci				     int level)
190762306a36Sopenharmony_ci{
190862306a36Sopenharmony_ci	int ret;
190962306a36Sopenharmony_ci	struct ocfs2_super *osb = ocfs2_get_lockres_osb(lockres);
191062306a36Sopenharmony_ci	unsigned long flags;
191162306a36Sopenharmony_ci	struct ocfs2_mask_waiter mw;
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_ci	ocfs2_init_mask_waiter(&mw);
191462306a36Sopenharmony_ci
191562306a36Sopenharmony_ciretry_cancel:
191662306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
191762306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_BUSY) {
191862306a36Sopenharmony_ci		ret = ocfs2_prepare_cancel_convert(osb, lockres);
191962306a36Sopenharmony_ci		if (ret) {
192062306a36Sopenharmony_ci			spin_unlock_irqrestore(&lockres->l_lock, flags);
192162306a36Sopenharmony_ci			ret = ocfs2_cancel_convert(osb, lockres);
192262306a36Sopenharmony_ci			if (ret < 0) {
192362306a36Sopenharmony_ci				mlog_errno(ret);
192462306a36Sopenharmony_ci				goto out;
192562306a36Sopenharmony_ci			}
192662306a36Sopenharmony_ci			goto retry_cancel;
192762306a36Sopenharmony_ci		}
192862306a36Sopenharmony_ci		lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0);
192962306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
193062306a36Sopenharmony_ci
193162306a36Sopenharmony_ci		ocfs2_wait_for_mask(&mw);
193262306a36Sopenharmony_ci		goto retry_cancel;
193362306a36Sopenharmony_ci	}
193462306a36Sopenharmony_ci
193562306a36Sopenharmony_ci	ret = -ERESTARTSYS;
193662306a36Sopenharmony_ci	/*
193762306a36Sopenharmony_ci	 * We may still have gotten the lock, in which case there's no
193862306a36Sopenharmony_ci	 * point to restarting the syscall.
193962306a36Sopenharmony_ci	 */
194062306a36Sopenharmony_ci	if (lockres->l_level == level)
194162306a36Sopenharmony_ci		ret = 0;
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_ci	mlog(0, "Cancel returning %d. flags: 0x%lx, level: %d, act: %d\n", ret,
194462306a36Sopenharmony_ci	     lockres->l_flags, lockres->l_level, lockres->l_action);
194562306a36Sopenharmony_ci
194662306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
194762306a36Sopenharmony_ci
194862306a36Sopenharmony_ciout:
194962306a36Sopenharmony_ci	return ret;
195062306a36Sopenharmony_ci}
195162306a36Sopenharmony_ci
195262306a36Sopenharmony_ci/*
195362306a36Sopenharmony_ci * ocfs2_file_lock() and ocfs2_file_unlock() map to a single pair of
195462306a36Sopenharmony_ci * flock() calls. The locking approach this requires is sufficiently
195562306a36Sopenharmony_ci * different from all other cluster lock types that we implement a
195662306a36Sopenharmony_ci * separate path to the "low-level" dlm calls. In particular:
195762306a36Sopenharmony_ci *
195862306a36Sopenharmony_ci * - No optimization of lock levels is done - we take at exactly
195962306a36Sopenharmony_ci *   what's been requested.
196062306a36Sopenharmony_ci *
196162306a36Sopenharmony_ci * - No lock caching is employed. We immediately downconvert to
196262306a36Sopenharmony_ci *   no-lock at unlock time. This also means flock locks never go on
196362306a36Sopenharmony_ci *   the blocking list).
196462306a36Sopenharmony_ci *
196562306a36Sopenharmony_ci * - Since userspace can trivially deadlock itself with flock, we make
196662306a36Sopenharmony_ci *   sure to allow cancellation of a misbehaving applications flock()
196762306a36Sopenharmony_ci *   request.
196862306a36Sopenharmony_ci *
196962306a36Sopenharmony_ci * - Access to any flock lockres doesn't require concurrency, so we
197062306a36Sopenharmony_ci *   can simplify the code by requiring the caller to guarantee
197162306a36Sopenharmony_ci *   serialization of dlmglue flock calls.
197262306a36Sopenharmony_ci */
197362306a36Sopenharmony_ciint ocfs2_file_lock(struct file *file, int ex, int trylock)
197462306a36Sopenharmony_ci{
197562306a36Sopenharmony_ci	int ret, level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
197662306a36Sopenharmony_ci	unsigned int lkm_flags = trylock ? DLM_LKF_NOQUEUE : 0;
197762306a36Sopenharmony_ci	unsigned long flags;
197862306a36Sopenharmony_ci	struct ocfs2_file_private *fp = file->private_data;
197962306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &fp->fp_flock;
198062306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(file->f_mapping->host->i_sb);
198162306a36Sopenharmony_ci	struct ocfs2_mask_waiter mw;
198262306a36Sopenharmony_ci
198362306a36Sopenharmony_ci	ocfs2_init_mask_waiter(&mw);
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci	if ((lockres->l_flags & OCFS2_LOCK_BUSY) ||
198662306a36Sopenharmony_ci	    (lockres->l_level > DLM_LOCK_NL)) {
198762306a36Sopenharmony_ci		mlog(ML_ERROR,
198862306a36Sopenharmony_ci		     "File lock \"%s\" has busy or locked state: flags: 0x%lx, "
198962306a36Sopenharmony_ci		     "level: %u\n", lockres->l_name, lockres->l_flags,
199062306a36Sopenharmony_ci		     lockres->l_level);
199162306a36Sopenharmony_ci		return -EINVAL;
199262306a36Sopenharmony_ci	}
199362306a36Sopenharmony_ci
199462306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
199562306a36Sopenharmony_ci	if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) {
199662306a36Sopenharmony_ci		lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0);
199762306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_ci		/*
200062306a36Sopenharmony_ci		 * Get the lock at NLMODE to start - that way we
200162306a36Sopenharmony_ci		 * can cancel the upconvert request if need be.
200262306a36Sopenharmony_ci		 */
200362306a36Sopenharmony_ci		ret = ocfs2_lock_create(osb, lockres, DLM_LOCK_NL, 0);
200462306a36Sopenharmony_ci		if (ret < 0) {
200562306a36Sopenharmony_ci			mlog_errno(ret);
200662306a36Sopenharmony_ci			goto out;
200762306a36Sopenharmony_ci		}
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_ci		ret = ocfs2_wait_for_mask(&mw);
201062306a36Sopenharmony_ci		if (ret) {
201162306a36Sopenharmony_ci			mlog_errno(ret);
201262306a36Sopenharmony_ci			goto out;
201362306a36Sopenharmony_ci		}
201462306a36Sopenharmony_ci		spin_lock_irqsave(&lockres->l_lock, flags);
201562306a36Sopenharmony_ci	}
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_ci	lockres->l_action = OCFS2_AST_CONVERT;
201862306a36Sopenharmony_ci	lkm_flags |= DLM_LKF_CONVERT;
201962306a36Sopenharmony_ci	lockres->l_requested = level;
202062306a36Sopenharmony_ci	lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_ci	lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0);
202362306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
202462306a36Sopenharmony_ci
202562306a36Sopenharmony_ci	ret = ocfs2_dlm_lock(osb->cconn, level, &lockres->l_lksb, lkm_flags,
202662306a36Sopenharmony_ci			     lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1);
202762306a36Sopenharmony_ci	if (ret) {
202862306a36Sopenharmony_ci		if (!trylock || (ret != -EAGAIN)) {
202962306a36Sopenharmony_ci			ocfs2_log_dlm_error("ocfs2_dlm_lock", ret, lockres);
203062306a36Sopenharmony_ci			ret = -EINVAL;
203162306a36Sopenharmony_ci		}
203262306a36Sopenharmony_ci
203362306a36Sopenharmony_ci		ocfs2_recover_from_dlm_error(lockres, 1);
203462306a36Sopenharmony_ci		lockres_remove_mask_waiter(lockres, &mw);
203562306a36Sopenharmony_ci		goto out;
203662306a36Sopenharmony_ci	}
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_ci	ret = ocfs2_wait_for_mask_interruptible(&mw, lockres);
203962306a36Sopenharmony_ci	if (ret == -ERESTARTSYS) {
204062306a36Sopenharmony_ci		/*
204162306a36Sopenharmony_ci		 * Userspace can cause deadlock itself with
204262306a36Sopenharmony_ci		 * flock(). Current behavior locally is to allow the
204362306a36Sopenharmony_ci		 * deadlock, but abort the system call if a signal is
204462306a36Sopenharmony_ci		 * received. We follow this example, otherwise a
204562306a36Sopenharmony_ci		 * poorly written program could sit in kernel until
204662306a36Sopenharmony_ci		 * reboot.
204762306a36Sopenharmony_ci		 *
204862306a36Sopenharmony_ci		 * Handling this is a bit more complicated for Ocfs2
204962306a36Sopenharmony_ci		 * though. We can't exit this function with an
205062306a36Sopenharmony_ci		 * outstanding lock request, so a cancel convert is
205162306a36Sopenharmony_ci		 * required. We intentionally overwrite 'ret' - if the
205262306a36Sopenharmony_ci		 * cancel fails and the lock was granted, it's easier
205362306a36Sopenharmony_ci		 * to just bubble success back up to the user.
205462306a36Sopenharmony_ci		 */
205562306a36Sopenharmony_ci		ret = ocfs2_flock_handle_signal(lockres, level);
205662306a36Sopenharmony_ci	} else if (!ret && (level > lockres->l_level)) {
205762306a36Sopenharmony_ci		/* Trylock failed asynchronously */
205862306a36Sopenharmony_ci		BUG_ON(!trylock);
205962306a36Sopenharmony_ci		ret = -EAGAIN;
206062306a36Sopenharmony_ci	}
206162306a36Sopenharmony_ci
206262306a36Sopenharmony_ciout:
206362306a36Sopenharmony_ci
206462306a36Sopenharmony_ci	mlog(0, "Lock: \"%s\" ex: %d, trylock: %d, returns: %d\n",
206562306a36Sopenharmony_ci	     lockres->l_name, ex, trylock, ret);
206662306a36Sopenharmony_ci	return ret;
206762306a36Sopenharmony_ci}
206862306a36Sopenharmony_ci
206962306a36Sopenharmony_civoid ocfs2_file_unlock(struct file *file)
207062306a36Sopenharmony_ci{
207162306a36Sopenharmony_ci	int ret;
207262306a36Sopenharmony_ci	unsigned int gen;
207362306a36Sopenharmony_ci	unsigned long flags;
207462306a36Sopenharmony_ci	struct ocfs2_file_private *fp = file->private_data;
207562306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &fp->fp_flock;
207662306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(file->f_mapping->host->i_sb);
207762306a36Sopenharmony_ci	struct ocfs2_mask_waiter mw;
207862306a36Sopenharmony_ci
207962306a36Sopenharmony_ci	ocfs2_init_mask_waiter(&mw);
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ci	if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED))
208262306a36Sopenharmony_ci		return;
208362306a36Sopenharmony_ci
208462306a36Sopenharmony_ci	if (lockres->l_level == DLM_LOCK_NL)
208562306a36Sopenharmony_ci		return;
208662306a36Sopenharmony_ci
208762306a36Sopenharmony_ci	mlog(0, "Unlock: \"%s\" flags: 0x%lx, level: %d, act: %d\n",
208862306a36Sopenharmony_ci	     lockres->l_name, lockres->l_flags, lockres->l_level,
208962306a36Sopenharmony_ci	     lockres->l_action);
209062306a36Sopenharmony_ci
209162306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
209262306a36Sopenharmony_ci	/*
209362306a36Sopenharmony_ci	 * Fake a blocking ast for the downconvert code.
209462306a36Sopenharmony_ci	 */
209562306a36Sopenharmony_ci	lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED);
209662306a36Sopenharmony_ci	lockres->l_blocking = DLM_LOCK_EX;
209762306a36Sopenharmony_ci
209862306a36Sopenharmony_ci	gen = ocfs2_prepare_downconvert(lockres, DLM_LOCK_NL);
209962306a36Sopenharmony_ci	lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0);
210062306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
210162306a36Sopenharmony_ci
210262306a36Sopenharmony_ci	ret = ocfs2_downconvert_lock(osb, lockres, DLM_LOCK_NL, 0, gen);
210362306a36Sopenharmony_ci	if (ret) {
210462306a36Sopenharmony_ci		mlog_errno(ret);
210562306a36Sopenharmony_ci		return;
210662306a36Sopenharmony_ci	}
210762306a36Sopenharmony_ci
210862306a36Sopenharmony_ci	ret = ocfs2_wait_for_mask(&mw);
210962306a36Sopenharmony_ci	if (ret)
211062306a36Sopenharmony_ci		mlog_errno(ret);
211162306a36Sopenharmony_ci}
211262306a36Sopenharmony_ci
211362306a36Sopenharmony_cistatic void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb,
211462306a36Sopenharmony_ci					struct ocfs2_lock_res *lockres)
211562306a36Sopenharmony_ci{
211662306a36Sopenharmony_ci	int kick = 0;
211762306a36Sopenharmony_ci
211862306a36Sopenharmony_ci	/* If we know that another node is waiting on our lock, kick
211962306a36Sopenharmony_ci	 * the downconvert thread * pre-emptively when we reach a release
212062306a36Sopenharmony_ci	 * condition. */
212162306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_BLOCKED) {
212262306a36Sopenharmony_ci		switch(lockres->l_blocking) {
212362306a36Sopenharmony_ci		case DLM_LOCK_EX:
212462306a36Sopenharmony_ci			if (!lockres->l_ex_holders && !lockres->l_ro_holders)
212562306a36Sopenharmony_ci				kick = 1;
212662306a36Sopenharmony_ci			break;
212762306a36Sopenharmony_ci		case DLM_LOCK_PR:
212862306a36Sopenharmony_ci			if (!lockres->l_ex_holders)
212962306a36Sopenharmony_ci				kick = 1;
213062306a36Sopenharmony_ci			break;
213162306a36Sopenharmony_ci		default:
213262306a36Sopenharmony_ci			BUG();
213362306a36Sopenharmony_ci		}
213462306a36Sopenharmony_ci	}
213562306a36Sopenharmony_ci
213662306a36Sopenharmony_ci	if (kick)
213762306a36Sopenharmony_ci		ocfs2_wake_downconvert_thread(osb);
213862306a36Sopenharmony_ci}
213962306a36Sopenharmony_ci
214062306a36Sopenharmony_ci#define OCFS2_SEC_BITS   34
214162306a36Sopenharmony_ci#define OCFS2_SEC_SHIFT  (64 - OCFS2_SEC_BITS)
214262306a36Sopenharmony_ci#define OCFS2_NSEC_MASK  ((1ULL << OCFS2_SEC_SHIFT) - 1)
214362306a36Sopenharmony_ci
214462306a36Sopenharmony_ci/* LVB only has room for 64 bits of time here so we pack it for
214562306a36Sopenharmony_ci * now. */
214662306a36Sopenharmony_cistatic u64 ocfs2_pack_timespec(struct timespec64 *spec)
214762306a36Sopenharmony_ci{
214862306a36Sopenharmony_ci	u64 res;
214962306a36Sopenharmony_ci	u64 sec = clamp_t(time64_t, spec->tv_sec, 0, 0x3ffffffffull);
215062306a36Sopenharmony_ci	u32 nsec = spec->tv_nsec;
215162306a36Sopenharmony_ci
215262306a36Sopenharmony_ci	res = (sec << OCFS2_SEC_SHIFT) | (nsec & OCFS2_NSEC_MASK);
215362306a36Sopenharmony_ci
215462306a36Sopenharmony_ci	return res;
215562306a36Sopenharmony_ci}
215662306a36Sopenharmony_ci
215762306a36Sopenharmony_ci/* Call this with the lockres locked. I am reasonably sure we don't
215862306a36Sopenharmony_ci * need ip_lock in this function as anyone who would be changing those
215962306a36Sopenharmony_ci * values is supposed to be blocked in ocfs2_inode_lock right now. */
216062306a36Sopenharmony_cistatic void __ocfs2_stuff_meta_lvb(struct inode *inode)
216162306a36Sopenharmony_ci{
216262306a36Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(inode);
216362306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres;
216462306a36Sopenharmony_ci	struct ocfs2_meta_lvb *lvb;
216562306a36Sopenharmony_ci	struct timespec64 ctime = inode_get_ctime(inode);
216662306a36Sopenharmony_ci
216762306a36Sopenharmony_ci	lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
216862306a36Sopenharmony_ci
216962306a36Sopenharmony_ci	/*
217062306a36Sopenharmony_ci	 * Invalidate the LVB of a deleted inode - this way other
217162306a36Sopenharmony_ci	 * nodes are forced to go to disk and discover the new inode
217262306a36Sopenharmony_ci	 * status.
217362306a36Sopenharmony_ci	 */
217462306a36Sopenharmony_ci	if (oi->ip_flags & OCFS2_INODE_DELETED) {
217562306a36Sopenharmony_ci		lvb->lvb_version = 0;
217662306a36Sopenharmony_ci		goto out;
217762306a36Sopenharmony_ci	}
217862306a36Sopenharmony_ci
217962306a36Sopenharmony_ci	lvb->lvb_version   = OCFS2_LVB_VERSION;
218062306a36Sopenharmony_ci	lvb->lvb_isize	   = cpu_to_be64(i_size_read(inode));
218162306a36Sopenharmony_ci	lvb->lvb_iclusters = cpu_to_be32(oi->ip_clusters);
218262306a36Sopenharmony_ci	lvb->lvb_iuid      = cpu_to_be32(i_uid_read(inode));
218362306a36Sopenharmony_ci	lvb->lvb_igid      = cpu_to_be32(i_gid_read(inode));
218462306a36Sopenharmony_ci	lvb->lvb_imode     = cpu_to_be16(inode->i_mode);
218562306a36Sopenharmony_ci	lvb->lvb_inlink    = cpu_to_be16(inode->i_nlink);
218662306a36Sopenharmony_ci	lvb->lvb_iatime_packed  =
218762306a36Sopenharmony_ci		cpu_to_be64(ocfs2_pack_timespec(&inode->i_atime));
218862306a36Sopenharmony_ci	lvb->lvb_ictime_packed =
218962306a36Sopenharmony_ci		cpu_to_be64(ocfs2_pack_timespec(&ctime));
219062306a36Sopenharmony_ci	lvb->lvb_imtime_packed =
219162306a36Sopenharmony_ci		cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime));
219262306a36Sopenharmony_ci	lvb->lvb_iattr    = cpu_to_be32(oi->ip_attr);
219362306a36Sopenharmony_ci	lvb->lvb_idynfeatures = cpu_to_be16(oi->ip_dyn_features);
219462306a36Sopenharmony_ci	lvb->lvb_igeneration = cpu_to_be32(inode->i_generation);
219562306a36Sopenharmony_ci
219662306a36Sopenharmony_ciout:
219762306a36Sopenharmony_ci	mlog_meta_lvb(0, lockres);
219862306a36Sopenharmony_ci}
219962306a36Sopenharmony_ci
220062306a36Sopenharmony_cistatic void ocfs2_unpack_timespec(struct timespec64 *spec,
220162306a36Sopenharmony_ci				  u64 packed_time)
220262306a36Sopenharmony_ci{
220362306a36Sopenharmony_ci	spec->tv_sec = packed_time >> OCFS2_SEC_SHIFT;
220462306a36Sopenharmony_ci	spec->tv_nsec = packed_time & OCFS2_NSEC_MASK;
220562306a36Sopenharmony_ci}
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_cistatic int ocfs2_refresh_inode_from_lvb(struct inode *inode)
220862306a36Sopenharmony_ci{
220962306a36Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(inode);
221062306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres;
221162306a36Sopenharmony_ci	struct ocfs2_meta_lvb *lvb;
221262306a36Sopenharmony_ci	struct timespec64 ctime;
221362306a36Sopenharmony_ci
221462306a36Sopenharmony_ci	mlog_meta_lvb(0, lockres);
221562306a36Sopenharmony_ci
221662306a36Sopenharmony_ci	lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
221762306a36Sopenharmony_ci	if (inode_wrong_type(inode, be16_to_cpu(lvb->lvb_imode)))
221862306a36Sopenharmony_ci		return -ESTALE;
221962306a36Sopenharmony_ci
222062306a36Sopenharmony_ci	/* We're safe here without the lockres lock... */
222162306a36Sopenharmony_ci	spin_lock(&oi->ip_lock);
222262306a36Sopenharmony_ci	oi->ip_clusters = be32_to_cpu(lvb->lvb_iclusters);
222362306a36Sopenharmony_ci	i_size_write(inode, be64_to_cpu(lvb->lvb_isize));
222462306a36Sopenharmony_ci
222562306a36Sopenharmony_ci	oi->ip_attr = be32_to_cpu(lvb->lvb_iattr);
222662306a36Sopenharmony_ci	oi->ip_dyn_features = be16_to_cpu(lvb->lvb_idynfeatures);
222762306a36Sopenharmony_ci	ocfs2_set_inode_flags(inode);
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_ci	/* fast-symlinks are a special case */
223062306a36Sopenharmony_ci	if (S_ISLNK(inode->i_mode) && !oi->ip_clusters)
223162306a36Sopenharmony_ci		inode->i_blocks = 0;
223262306a36Sopenharmony_ci	else
223362306a36Sopenharmony_ci		inode->i_blocks = ocfs2_inode_sector_count(inode);
223462306a36Sopenharmony_ci
223562306a36Sopenharmony_ci	i_uid_write(inode, be32_to_cpu(lvb->lvb_iuid));
223662306a36Sopenharmony_ci	i_gid_write(inode, be32_to_cpu(lvb->lvb_igid));
223762306a36Sopenharmony_ci	inode->i_mode    = be16_to_cpu(lvb->lvb_imode);
223862306a36Sopenharmony_ci	set_nlink(inode, be16_to_cpu(lvb->lvb_inlink));
223962306a36Sopenharmony_ci	ocfs2_unpack_timespec(&inode->i_atime,
224062306a36Sopenharmony_ci			      be64_to_cpu(lvb->lvb_iatime_packed));
224162306a36Sopenharmony_ci	ocfs2_unpack_timespec(&inode->i_mtime,
224262306a36Sopenharmony_ci			      be64_to_cpu(lvb->lvb_imtime_packed));
224362306a36Sopenharmony_ci	ocfs2_unpack_timespec(&ctime,
224462306a36Sopenharmony_ci			      be64_to_cpu(lvb->lvb_ictime_packed));
224562306a36Sopenharmony_ci	inode_set_ctime_to_ts(inode, ctime);
224662306a36Sopenharmony_ci	spin_unlock(&oi->ip_lock);
224762306a36Sopenharmony_ci	return 0;
224862306a36Sopenharmony_ci}
224962306a36Sopenharmony_ci
225062306a36Sopenharmony_cistatic inline int ocfs2_meta_lvb_is_trustable(struct inode *inode,
225162306a36Sopenharmony_ci					      struct ocfs2_lock_res *lockres)
225262306a36Sopenharmony_ci{
225362306a36Sopenharmony_ci	struct ocfs2_meta_lvb *lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
225462306a36Sopenharmony_ci
225562306a36Sopenharmony_ci	if (ocfs2_dlm_lvb_valid(&lockres->l_lksb)
225662306a36Sopenharmony_ci	    && lvb->lvb_version == OCFS2_LVB_VERSION
225762306a36Sopenharmony_ci	    && be32_to_cpu(lvb->lvb_igeneration) == inode->i_generation)
225862306a36Sopenharmony_ci		return 1;
225962306a36Sopenharmony_ci	return 0;
226062306a36Sopenharmony_ci}
226162306a36Sopenharmony_ci
226262306a36Sopenharmony_ci/* Determine whether a lock resource needs to be refreshed, and
226362306a36Sopenharmony_ci * arbitrate who gets to refresh it.
226462306a36Sopenharmony_ci *
226562306a36Sopenharmony_ci *   0 means no refresh needed.
226662306a36Sopenharmony_ci *
226762306a36Sopenharmony_ci *   > 0 means you need to refresh this and you MUST call
226862306a36Sopenharmony_ci *   ocfs2_complete_lock_res_refresh afterwards. */
226962306a36Sopenharmony_cistatic int ocfs2_should_refresh_lock_res(struct ocfs2_lock_res *lockres)
227062306a36Sopenharmony_ci{
227162306a36Sopenharmony_ci	unsigned long flags;
227262306a36Sopenharmony_ci	int status = 0;
227362306a36Sopenharmony_ci
227462306a36Sopenharmony_cirefresh_check:
227562306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
227662306a36Sopenharmony_ci	if (!(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) {
227762306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
227862306a36Sopenharmony_ci		goto bail;
227962306a36Sopenharmony_ci	}
228062306a36Sopenharmony_ci
228162306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_REFRESHING) {
228262306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
228362306a36Sopenharmony_ci
228462306a36Sopenharmony_ci		ocfs2_wait_on_refreshing_lock(lockres);
228562306a36Sopenharmony_ci		goto refresh_check;
228662306a36Sopenharmony_ci	}
228762306a36Sopenharmony_ci
228862306a36Sopenharmony_ci	/* Ok, I'll be the one to refresh this lock. */
228962306a36Sopenharmony_ci	lockres_or_flags(lockres, OCFS2_LOCK_REFRESHING);
229062306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
229162306a36Sopenharmony_ci
229262306a36Sopenharmony_ci	status = 1;
229362306a36Sopenharmony_cibail:
229462306a36Sopenharmony_ci	mlog(0, "status %d\n", status);
229562306a36Sopenharmony_ci	return status;
229662306a36Sopenharmony_ci}
229762306a36Sopenharmony_ci
229862306a36Sopenharmony_ci/* If status is non zero, I'll mark it as not being in refresh
229962306a36Sopenharmony_ci * anymroe, but i won't clear the needs refresh flag. */
230062306a36Sopenharmony_cistatic inline void ocfs2_complete_lock_res_refresh(struct ocfs2_lock_res *lockres,
230162306a36Sopenharmony_ci						   int status)
230262306a36Sopenharmony_ci{
230362306a36Sopenharmony_ci	unsigned long flags;
230462306a36Sopenharmony_ci
230562306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
230662306a36Sopenharmony_ci	lockres_clear_flags(lockres, OCFS2_LOCK_REFRESHING);
230762306a36Sopenharmony_ci	if (!status)
230862306a36Sopenharmony_ci		lockres_clear_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);
230962306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
231062306a36Sopenharmony_ci
231162306a36Sopenharmony_ci	wake_up(&lockres->l_event);
231262306a36Sopenharmony_ci}
231362306a36Sopenharmony_ci
231462306a36Sopenharmony_ci/* may or may not return a bh if it went to disk. */
231562306a36Sopenharmony_cistatic int ocfs2_inode_lock_update(struct inode *inode,
231662306a36Sopenharmony_ci				  struct buffer_head **bh)
231762306a36Sopenharmony_ci{
231862306a36Sopenharmony_ci	int status = 0;
231962306a36Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(inode);
232062306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres;
232162306a36Sopenharmony_ci	struct ocfs2_dinode *fe;
232262306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
232362306a36Sopenharmony_ci
232462306a36Sopenharmony_ci	if (ocfs2_mount_local(osb))
232562306a36Sopenharmony_ci		goto bail;
232662306a36Sopenharmony_ci
232762306a36Sopenharmony_ci	spin_lock(&oi->ip_lock);
232862306a36Sopenharmony_ci	if (oi->ip_flags & OCFS2_INODE_DELETED) {
232962306a36Sopenharmony_ci		mlog(0, "Orphaned inode %llu was deleted while we "
233062306a36Sopenharmony_ci		     "were waiting on a lock. ip_flags = 0x%x\n",
233162306a36Sopenharmony_ci		     (unsigned long long)oi->ip_blkno, oi->ip_flags);
233262306a36Sopenharmony_ci		spin_unlock(&oi->ip_lock);
233362306a36Sopenharmony_ci		status = -ENOENT;
233462306a36Sopenharmony_ci		goto bail;
233562306a36Sopenharmony_ci	}
233662306a36Sopenharmony_ci	spin_unlock(&oi->ip_lock);
233762306a36Sopenharmony_ci
233862306a36Sopenharmony_ci	if (!ocfs2_should_refresh_lock_res(lockres))
233962306a36Sopenharmony_ci		goto bail;
234062306a36Sopenharmony_ci
234162306a36Sopenharmony_ci	/* This will discard any caching information we might have had
234262306a36Sopenharmony_ci	 * for the inode metadata. */
234362306a36Sopenharmony_ci	ocfs2_metadata_cache_purge(INODE_CACHE(inode));
234462306a36Sopenharmony_ci
234562306a36Sopenharmony_ci	ocfs2_extent_map_trunc(inode, 0);
234662306a36Sopenharmony_ci
234762306a36Sopenharmony_ci	if (ocfs2_meta_lvb_is_trustable(inode, lockres)) {
234862306a36Sopenharmony_ci		mlog(0, "Trusting LVB on inode %llu\n",
234962306a36Sopenharmony_ci		     (unsigned long long)oi->ip_blkno);
235062306a36Sopenharmony_ci		status = ocfs2_refresh_inode_from_lvb(inode);
235162306a36Sopenharmony_ci		goto bail_refresh;
235262306a36Sopenharmony_ci	} else {
235362306a36Sopenharmony_ci		/* Boo, we have to go to disk. */
235462306a36Sopenharmony_ci		/* read bh, cast, ocfs2_refresh_inode */
235562306a36Sopenharmony_ci		status = ocfs2_read_inode_block(inode, bh);
235662306a36Sopenharmony_ci		if (status < 0) {
235762306a36Sopenharmony_ci			mlog_errno(status);
235862306a36Sopenharmony_ci			goto bail_refresh;
235962306a36Sopenharmony_ci		}
236062306a36Sopenharmony_ci		fe = (struct ocfs2_dinode *) (*bh)->b_data;
236162306a36Sopenharmony_ci		if (inode_wrong_type(inode, le16_to_cpu(fe->i_mode))) {
236262306a36Sopenharmony_ci			status = -ESTALE;
236362306a36Sopenharmony_ci			goto bail_refresh;
236462306a36Sopenharmony_ci		}
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci		/* This is a good chance to make sure we're not
236762306a36Sopenharmony_ci		 * locking an invalid object.  ocfs2_read_inode_block()
236862306a36Sopenharmony_ci		 * already checked that the inode block is sane.
236962306a36Sopenharmony_ci		 *
237062306a36Sopenharmony_ci		 * We bug on a stale inode here because we checked
237162306a36Sopenharmony_ci		 * above whether it was wiped from disk. The wiping
237262306a36Sopenharmony_ci		 * node provides a guarantee that we receive that
237362306a36Sopenharmony_ci		 * message and can mark the inode before dropping any
237462306a36Sopenharmony_ci		 * locks associated with it. */
237562306a36Sopenharmony_ci		mlog_bug_on_msg(inode->i_generation !=
237662306a36Sopenharmony_ci				le32_to_cpu(fe->i_generation),
237762306a36Sopenharmony_ci				"Invalid dinode %llu disk generation: %u "
237862306a36Sopenharmony_ci				"inode->i_generation: %u\n",
237962306a36Sopenharmony_ci				(unsigned long long)oi->ip_blkno,
238062306a36Sopenharmony_ci				le32_to_cpu(fe->i_generation),
238162306a36Sopenharmony_ci				inode->i_generation);
238262306a36Sopenharmony_ci		mlog_bug_on_msg(le64_to_cpu(fe->i_dtime) ||
238362306a36Sopenharmony_ci				!(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL)),
238462306a36Sopenharmony_ci				"Stale dinode %llu dtime: %llu flags: 0x%x\n",
238562306a36Sopenharmony_ci				(unsigned long long)oi->ip_blkno,
238662306a36Sopenharmony_ci				(unsigned long long)le64_to_cpu(fe->i_dtime),
238762306a36Sopenharmony_ci				le32_to_cpu(fe->i_flags));
238862306a36Sopenharmony_ci
238962306a36Sopenharmony_ci		ocfs2_refresh_inode(inode, fe);
239062306a36Sopenharmony_ci		ocfs2_track_lock_refresh(lockres);
239162306a36Sopenharmony_ci	}
239262306a36Sopenharmony_ci
239362306a36Sopenharmony_ci	status = 0;
239462306a36Sopenharmony_cibail_refresh:
239562306a36Sopenharmony_ci	ocfs2_complete_lock_res_refresh(lockres, status);
239662306a36Sopenharmony_cibail:
239762306a36Sopenharmony_ci	return status;
239862306a36Sopenharmony_ci}
239962306a36Sopenharmony_ci
240062306a36Sopenharmony_cistatic int ocfs2_assign_bh(struct inode *inode,
240162306a36Sopenharmony_ci			   struct buffer_head **ret_bh,
240262306a36Sopenharmony_ci			   struct buffer_head *passed_bh)
240362306a36Sopenharmony_ci{
240462306a36Sopenharmony_ci	int status;
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci	if (passed_bh) {
240762306a36Sopenharmony_ci		/* Ok, the update went to disk for us, use the
240862306a36Sopenharmony_ci		 * returned bh. */
240962306a36Sopenharmony_ci		*ret_bh = passed_bh;
241062306a36Sopenharmony_ci		get_bh(*ret_bh);
241162306a36Sopenharmony_ci
241262306a36Sopenharmony_ci		return 0;
241362306a36Sopenharmony_ci	}
241462306a36Sopenharmony_ci
241562306a36Sopenharmony_ci	status = ocfs2_read_inode_block(inode, ret_bh);
241662306a36Sopenharmony_ci	if (status < 0)
241762306a36Sopenharmony_ci		mlog_errno(status);
241862306a36Sopenharmony_ci
241962306a36Sopenharmony_ci	return status;
242062306a36Sopenharmony_ci}
242162306a36Sopenharmony_ci
242262306a36Sopenharmony_ci/*
242362306a36Sopenharmony_ci * returns < 0 error if the callback will never be called, otherwise
242462306a36Sopenharmony_ci * the result of the lock will be communicated via the callback.
242562306a36Sopenharmony_ci */
242662306a36Sopenharmony_ciint ocfs2_inode_lock_full_nested(struct inode *inode,
242762306a36Sopenharmony_ci				 struct buffer_head **ret_bh,
242862306a36Sopenharmony_ci				 int ex,
242962306a36Sopenharmony_ci				 int arg_flags,
243062306a36Sopenharmony_ci				 int subclass)
243162306a36Sopenharmony_ci{
243262306a36Sopenharmony_ci	int status, level, acquired;
243362306a36Sopenharmony_ci	u32 dlm_flags;
243462306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = NULL;
243562306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
243662306a36Sopenharmony_ci	struct buffer_head *local_bh = NULL;
243762306a36Sopenharmony_ci
243862306a36Sopenharmony_ci	mlog(0, "inode %llu, take %s META lock\n",
243962306a36Sopenharmony_ci	     (unsigned long long)OCFS2_I(inode)->ip_blkno,
244062306a36Sopenharmony_ci	     ex ? "EXMODE" : "PRMODE");
244162306a36Sopenharmony_ci
244262306a36Sopenharmony_ci	status = 0;
244362306a36Sopenharmony_ci	acquired = 0;
244462306a36Sopenharmony_ci	/* We'll allow faking a readonly metadata lock for
244562306a36Sopenharmony_ci	 * rodevices. */
244662306a36Sopenharmony_ci	if (ocfs2_is_hard_readonly(osb)) {
244762306a36Sopenharmony_ci		if (ex)
244862306a36Sopenharmony_ci			status = -EROFS;
244962306a36Sopenharmony_ci		goto getbh;
245062306a36Sopenharmony_ci	}
245162306a36Sopenharmony_ci
245262306a36Sopenharmony_ci	if ((arg_flags & OCFS2_META_LOCK_GETBH) ||
245362306a36Sopenharmony_ci	    ocfs2_mount_local(osb))
245462306a36Sopenharmony_ci		goto update;
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_ci	if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
245762306a36Sopenharmony_ci		ocfs2_wait_for_recovery(osb);
245862306a36Sopenharmony_ci
245962306a36Sopenharmony_ci	lockres = &OCFS2_I(inode)->ip_inode_lockres;
246062306a36Sopenharmony_ci	level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
246162306a36Sopenharmony_ci	dlm_flags = 0;
246262306a36Sopenharmony_ci	if (arg_flags & OCFS2_META_LOCK_NOQUEUE)
246362306a36Sopenharmony_ci		dlm_flags |= DLM_LKF_NOQUEUE;
246462306a36Sopenharmony_ci
246562306a36Sopenharmony_ci	status = __ocfs2_cluster_lock(osb, lockres, level, dlm_flags,
246662306a36Sopenharmony_ci				      arg_flags, subclass, _RET_IP_);
246762306a36Sopenharmony_ci	if (status < 0) {
246862306a36Sopenharmony_ci		if (status != -EAGAIN)
246962306a36Sopenharmony_ci			mlog_errno(status);
247062306a36Sopenharmony_ci		goto bail;
247162306a36Sopenharmony_ci	}
247262306a36Sopenharmony_ci
247362306a36Sopenharmony_ci	/* Notify the error cleanup path to drop the cluster lock. */
247462306a36Sopenharmony_ci	acquired = 1;
247562306a36Sopenharmony_ci
247662306a36Sopenharmony_ci	/* We wait twice because a node may have died while we were in
247762306a36Sopenharmony_ci	 * the lower dlm layers. The second time though, we've
247862306a36Sopenharmony_ci	 * committed to owning this lock so we don't allow signals to
247962306a36Sopenharmony_ci	 * abort the operation. */
248062306a36Sopenharmony_ci	if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
248162306a36Sopenharmony_ci		ocfs2_wait_for_recovery(osb);
248262306a36Sopenharmony_ci
248362306a36Sopenharmony_ciupdate:
248462306a36Sopenharmony_ci	/*
248562306a36Sopenharmony_ci	 * We only see this flag if we're being called from
248662306a36Sopenharmony_ci	 * ocfs2_read_locked_inode(). It means we're locking an inode
248762306a36Sopenharmony_ci	 * which hasn't been populated yet, so clear the refresh flag
248862306a36Sopenharmony_ci	 * and let the caller handle it.
248962306a36Sopenharmony_ci	 */
249062306a36Sopenharmony_ci	if (inode->i_state & I_NEW) {
249162306a36Sopenharmony_ci		status = 0;
249262306a36Sopenharmony_ci		if (lockres)
249362306a36Sopenharmony_ci			ocfs2_complete_lock_res_refresh(lockres, 0);
249462306a36Sopenharmony_ci		goto bail;
249562306a36Sopenharmony_ci	}
249662306a36Sopenharmony_ci
249762306a36Sopenharmony_ci	/* This is fun. The caller may want a bh back, or it may
249862306a36Sopenharmony_ci	 * not. ocfs2_inode_lock_update definitely wants one in, but
249962306a36Sopenharmony_ci	 * may or may not read one, depending on what's in the
250062306a36Sopenharmony_ci	 * LVB. The result of all of this is that we've *only* gone to
250162306a36Sopenharmony_ci	 * disk if we have to, so the complexity is worthwhile. */
250262306a36Sopenharmony_ci	status = ocfs2_inode_lock_update(inode, &local_bh);
250362306a36Sopenharmony_ci	if (status < 0) {
250462306a36Sopenharmony_ci		if (status != -ENOENT)
250562306a36Sopenharmony_ci			mlog_errno(status);
250662306a36Sopenharmony_ci		goto bail;
250762306a36Sopenharmony_ci	}
250862306a36Sopenharmony_cigetbh:
250962306a36Sopenharmony_ci	if (ret_bh) {
251062306a36Sopenharmony_ci		status = ocfs2_assign_bh(inode, ret_bh, local_bh);
251162306a36Sopenharmony_ci		if (status < 0) {
251262306a36Sopenharmony_ci			mlog_errno(status);
251362306a36Sopenharmony_ci			goto bail;
251462306a36Sopenharmony_ci		}
251562306a36Sopenharmony_ci	}
251662306a36Sopenharmony_ci
251762306a36Sopenharmony_cibail:
251862306a36Sopenharmony_ci	if (status < 0) {
251962306a36Sopenharmony_ci		if (ret_bh && (*ret_bh)) {
252062306a36Sopenharmony_ci			brelse(*ret_bh);
252162306a36Sopenharmony_ci			*ret_bh = NULL;
252262306a36Sopenharmony_ci		}
252362306a36Sopenharmony_ci		if (acquired)
252462306a36Sopenharmony_ci			ocfs2_inode_unlock(inode, ex);
252562306a36Sopenharmony_ci	}
252662306a36Sopenharmony_ci
252762306a36Sopenharmony_ci	brelse(local_bh);
252862306a36Sopenharmony_ci	return status;
252962306a36Sopenharmony_ci}
253062306a36Sopenharmony_ci
253162306a36Sopenharmony_ci/*
253262306a36Sopenharmony_ci * This is working around a lock inversion between tasks acquiring DLM
253362306a36Sopenharmony_ci * locks while holding a page lock and the downconvert thread which
253462306a36Sopenharmony_ci * blocks dlm lock acquiry while acquiring page locks.
253562306a36Sopenharmony_ci *
253662306a36Sopenharmony_ci * ** These _with_page variantes are only intended to be called from aop
253762306a36Sopenharmony_ci * methods that hold page locks and return a very specific *positive* error
253862306a36Sopenharmony_ci * code that aop methods pass up to the VFS -- test for errors with != 0. **
253962306a36Sopenharmony_ci *
254062306a36Sopenharmony_ci * The DLM is called such that it returns -EAGAIN if it would have
254162306a36Sopenharmony_ci * blocked waiting for the downconvert thread.  In that case we unlock
254262306a36Sopenharmony_ci * our page so the downconvert thread can make progress.  Once we've
254362306a36Sopenharmony_ci * done this we have to return AOP_TRUNCATED_PAGE so the aop method
254462306a36Sopenharmony_ci * that called us can bubble that back up into the VFS who will then
254562306a36Sopenharmony_ci * immediately retry the aop call.
254662306a36Sopenharmony_ci */
254762306a36Sopenharmony_ciint ocfs2_inode_lock_with_page(struct inode *inode,
254862306a36Sopenharmony_ci			      struct buffer_head **ret_bh,
254962306a36Sopenharmony_ci			      int ex,
255062306a36Sopenharmony_ci			      struct page *page)
255162306a36Sopenharmony_ci{
255262306a36Sopenharmony_ci	int ret;
255362306a36Sopenharmony_ci
255462306a36Sopenharmony_ci	ret = ocfs2_inode_lock_full(inode, ret_bh, ex, OCFS2_LOCK_NONBLOCK);
255562306a36Sopenharmony_ci	if (ret == -EAGAIN) {
255662306a36Sopenharmony_ci		unlock_page(page);
255762306a36Sopenharmony_ci		/*
255862306a36Sopenharmony_ci		 * If we can't get inode lock immediately, we should not return
255962306a36Sopenharmony_ci		 * directly here, since this will lead to a softlockup problem.
256062306a36Sopenharmony_ci		 * The method is to get a blocking lock and immediately unlock
256162306a36Sopenharmony_ci		 * before returning, this can avoid CPU resource waste due to
256262306a36Sopenharmony_ci		 * lots of retries, and benefits fairness in getting lock.
256362306a36Sopenharmony_ci		 */
256462306a36Sopenharmony_ci		if (ocfs2_inode_lock(inode, ret_bh, ex) == 0)
256562306a36Sopenharmony_ci			ocfs2_inode_unlock(inode, ex);
256662306a36Sopenharmony_ci		ret = AOP_TRUNCATED_PAGE;
256762306a36Sopenharmony_ci	}
256862306a36Sopenharmony_ci
256962306a36Sopenharmony_ci	return ret;
257062306a36Sopenharmony_ci}
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_ciint ocfs2_inode_lock_atime(struct inode *inode,
257362306a36Sopenharmony_ci			  struct vfsmount *vfsmnt,
257462306a36Sopenharmony_ci			  int *level, int wait)
257562306a36Sopenharmony_ci{
257662306a36Sopenharmony_ci	int ret;
257762306a36Sopenharmony_ci
257862306a36Sopenharmony_ci	if (wait)
257962306a36Sopenharmony_ci		ret = ocfs2_inode_lock(inode, NULL, 0);
258062306a36Sopenharmony_ci	else
258162306a36Sopenharmony_ci		ret = ocfs2_try_inode_lock(inode, NULL, 0);
258262306a36Sopenharmony_ci
258362306a36Sopenharmony_ci	if (ret < 0) {
258462306a36Sopenharmony_ci		if (ret != -EAGAIN)
258562306a36Sopenharmony_ci			mlog_errno(ret);
258662306a36Sopenharmony_ci		return ret;
258762306a36Sopenharmony_ci	}
258862306a36Sopenharmony_ci
258962306a36Sopenharmony_ci	/*
259062306a36Sopenharmony_ci	 * If we should update atime, we will get EX lock,
259162306a36Sopenharmony_ci	 * otherwise we just get PR lock.
259262306a36Sopenharmony_ci	 */
259362306a36Sopenharmony_ci	if (ocfs2_should_update_atime(inode, vfsmnt)) {
259462306a36Sopenharmony_ci		struct buffer_head *bh = NULL;
259562306a36Sopenharmony_ci
259662306a36Sopenharmony_ci		ocfs2_inode_unlock(inode, 0);
259762306a36Sopenharmony_ci		if (wait)
259862306a36Sopenharmony_ci			ret = ocfs2_inode_lock(inode, &bh, 1);
259962306a36Sopenharmony_ci		else
260062306a36Sopenharmony_ci			ret = ocfs2_try_inode_lock(inode, &bh, 1);
260162306a36Sopenharmony_ci
260262306a36Sopenharmony_ci		if (ret < 0) {
260362306a36Sopenharmony_ci			if (ret != -EAGAIN)
260462306a36Sopenharmony_ci				mlog_errno(ret);
260562306a36Sopenharmony_ci			return ret;
260662306a36Sopenharmony_ci		}
260762306a36Sopenharmony_ci		*level = 1;
260862306a36Sopenharmony_ci		if (ocfs2_should_update_atime(inode, vfsmnt))
260962306a36Sopenharmony_ci			ocfs2_update_inode_atime(inode, bh);
261062306a36Sopenharmony_ci		brelse(bh);
261162306a36Sopenharmony_ci	} else
261262306a36Sopenharmony_ci		*level = 0;
261362306a36Sopenharmony_ci
261462306a36Sopenharmony_ci	return ret;
261562306a36Sopenharmony_ci}
261662306a36Sopenharmony_ci
261762306a36Sopenharmony_civoid ocfs2_inode_unlock(struct inode *inode,
261862306a36Sopenharmony_ci		       int ex)
261962306a36Sopenharmony_ci{
262062306a36Sopenharmony_ci	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
262162306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_inode_lockres;
262262306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
262362306a36Sopenharmony_ci
262462306a36Sopenharmony_ci	mlog(0, "inode %llu drop %s META lock\n",
262562306a36Sopenharmony_ci	     (unsigned long long)OCFS2_I(inode)->ip_blkno,
262662306a36Sopenharmony_ci	     ex ? "EXMODE" : "PRMODE");
262762306a36Sopenharmony_ci
262862306a36Sopenharmony_ci	if (!ocfs2_is_hard_readonly(osb) &&
262962306a36Sopenharmony_ci	    !ocfs2_mount_local(osb))
263062306a36Sopenharmony_ci		ocfs2_cluster_unlock(osb, lockres, level);
263162306a36Sopenharmony_ci}
263262306a36Sopenharmony_ci
263362306a36Sopenharmony_ci/*
263462306a36Sopenharmony_ci * This _tracker variantes are introduced to deal with the recursive cluster
263562306a36Sopenharmony_ci * locking issue. The idea is to keep track of a lock holder on the stack of
263662306a36Sopenharmony_ci * the current process. If there's a lock holder on the stack, we know the
263762306a36Sopenharmony_ci * task context is already protected by cluster locking. Currently, they're
263862306a36Sopenharmony_ci * used in some VFS entry routines.
263962306a36Sopenharmony_ci *
264062306a36Sopenharmony_ci * return < 0 on error, return == 0 if there's no lock holder on the stack
264162306a36Sopenharmony_ci * before this call, return == 1 if this call would be a recursive locking.
264262306a36Sopenharmony_ci * return == -1 if this lock attempt will cause an upgrade which is forbidden.
264362306a36Sopenharmony_ci *
264462306a36Sopenharmony_ci * When taking lock levels into account,we face some different situations.
264562306a36Sopenharmony_ci *
264662306a36Sopenharmony_ci * 1. no lock is held
264762306a36Sopenharmony_ci *    In this case, just lock the inode as requested and return 0
264862306a36Sopenharmony_ci *
264962306a36Sopenharmony_ci * 2. We are holding a lock
265062306a36Sopenharmony_ci *    For this situation, things diverges into several cases
265162306a36Sopenharmony_ci *
265262306a36Sopenharmony_ci *    wanted     holding	     what to do
265362306a36Sopenharmony_ci *    ex		ex	    see 2.1 below
265462306a36Sopenharmony_ci *    ex		pr	    see 2.2 below
265562306a36Sopenharmony_ci *    pr		ex	    see 2.1 below
265662306a36Sopenharmony_ci *    pr		pr	    see 2.1 below
265762306a36Sopenharmony_ci *
265862306a36Sopenharmony_ci *    2.1 lock level that is been held is compatible
265962306a36Sopenharmony_ci *    with the wanted level, so no lock action will be tacken.
266062306a36Sopenharmony_ci *
266162306a36Sopenharmony_ci *    2.2 Otherwise, an upgrade is needed, but it is forbidden.
266262306a36Sopenharmony_ci *
266362306a36Sopenharmony_ci * Reason why upgrade within a process is forbidden is that
266462306a36Sopenharmony_ci * lock upgrade may cause dead lock. The following illustrates
266562306a36Sopenharmony_ci * how it happens.
266662306a36Sopenharmony_ci *
266762306a36Sopenharmony_ci *         thread on node1                             thread on node2
266862306a36Sopenharmony_ci * ocfs2_inode_lock_tracker(ex=0)
266962306a36Sopenharmony_ci *
267062306a36Sopenharmony_ci *                                <======   ocfs2_inode_lock_tracker(ex=1)
267162306a36Sopenharmony_ci *
267262306a36Sopenharmony_ci * ocfs2_inode_lock_tracker(ex=1)
267362306a36Sopenharmony_ci */
267462306a36Sopenharmony_ciint ocfs2_inode_lock_tracker(struct inode *inode,
267562306a36Sopenharmony_ci			     struct buffer_head **ret_bh,
267662306a36Sopenharmony_ci			     int ex,
267762306a36Sopenharmony_ci			     struct ocfs2_lock_holder *oh)
267862306a36Sopenharmony_ci{
267962306a36Sopenharmony_ci	int status = 0;
268062306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres;
268162306a36Sopenharmony_ci	struct ocfs2_lock_holder *tmp_oh;
268262306a36Sopenharmony_ci	struct pid *pid = task_pid(current);
268362306a36Sopenharmony_ci
268462306a36Sopenharmony_ci
268562306a36Sopenharmony_ci	lockres = &OCFS2_I(inode)->ip_inode_lockres;
268662306a36Sopenharmony_ci	tmp_oh = ocfs2_pid_holder(lockres, pid);
268762306a36Sopenharmony_ci
268862306a36Sopenharmony_ci	if (!tmp_oh) {
268962306a36Sopenharmony_ci		/*
269062306a36Sopenharmony_ci		 * This corresponds to the case 1.
269162306a36Sopenharmony_ci		 * We haven't got any lock before.
269262306a36Sopenharmony_ci		 */
269362306a36Sopenharmony_ci		status = ocfs2_inode_lock_full(inode, ret_bh, ex, 0);
269462306a36Sopenharmony_ci		if (status < 0) {
269562306a36Sopenharmony_ci			if (status != -ENOENT)
269662306a36Sopenharmony_ci				mlog_errno(status);
269762306a36Sopenharmony_ci			return status;
269862306a36Sopenharmony_ci		}
269962306a36Sopenharmony_ci
270062306a36Sopenharmony_ci		oh->oh_ex = ex;
270162306a36Sopenharmony_ci		ocfs2_add_holder(lockres, oh);
270262306a36Sopenharmony_ci		return 0;
270362306a36Sopenharmony_ci	}
270462306a36Sopenharmony_ci
270562306a36Sopenharmony_ci	if (unlikely(ex && !tmp_oh->oh_ex)) {
270662306a36Sopenharmony_ci		/*
270762306a36Sopenharmony_ci		 * case 2.2 upgrade may cause dead lock, forbid it.
270862306a36Sopenharmony_ci		 */
270962306a36Sopenharmony_ci		mlog(ML_ERROR, "Recursive locking is not permitted to "
271062306a36Sopenharmony_ci		     "upgrade to EX level from PR level.\n");
271162306a36Sopenharmony_ci		dump_stack();
271262306a36Sopenharmony_ci		return -EINVAL;
271362306a36Sopenharmony_ci	}
271462306a36Sopenharmony_ci
271562306a36Sopenharmony_ci	/*
271662306a36Sopenharmony_ci	 *  case 2.1 OCFS2_META_LOCK_GETBH flag make ocfs2_inode_lock_full.
271762306a36Sopenharmony_ci	 *  ignore the lock level and just update it.
271862306a36Sopenharmony_ci	 */
271962306a36Sopenharmony_ci	if (ret_bh) {
272062306a36Sopenharmony_ci		status = ocfs2_inode_lock_full(inode, ret_bh, ex,
272162306a36Sopenharmony_ci					       OCFS2_META_LOCK_GETBH);
272262306a36Sopenharmony_ci		if (status < 0) {
272362306a36Sopenharmony_ci			if (status != -ENOENT)
272462306a36Sopenharmony_ci				mlog_errno(status);
272562306a36Sopenharmony_ci			return status;
272662306a36Sopenharmony_ci		}
272762306a36Sopenharmony_ci	}
272862306a36Sopenharmony_ci	return 1;
272962306a36Sopenharmony_ci}
273062306a36Sopenharmony_ci
273162306a36Sopenharmony_civoid ocfs2_inode_unlock_tracker(struct inode *inode,
273262306a36Sopenharmony_ci				int ex,
273362306a36Sopenharmony_ci				struct ocfs2_lock_holder *oh,
273462306a36Sopenharmony_ci				int had_lock)
273562306a36Sopenharmony_ci{
273662306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres;
273762306a36Sopenharmony_ci
273862306a36Sopenharmony_ci	lockres = &OCFS2_I(inode)->ip_inode_lockres;
273962306a36Sopenharmony_ci	/* had_lock means that the currect process already takes the cluster
274062306a36Sopenharmony_ci	 * lock previously.
274162306a36Sopenharmony_ci	 * If had_lock is 1, we have nothing to do here.
274262306a36Sopenharmony_ci	 * If had_lock is 0, we will release the lock.
274362306a36Sopenharmony_ci	 */
274462306a36Sopenharmony_ci	if (!had_lock) {
274562306a36Sopenharmony_ci		ocfs2_inode_unlock(inode, oh->oh_ex);
274662306a36Sopenharmony_ci		ocfs2_remove_holder(lockres, oh);
274762306a36Sopenharmony_ci	}
274862306a36Sopenharmony_ci}
274962306a36Sopenharmony_ci
275062306a36Sopenharmony_ciint ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno)
275162306a36Sopenharmony_ci{
275262306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres;
275362306a36Sopenharmony_ci	struct ocfs2_orphan_scan_lvb *lvb;
275462306a36Sopenharmony_ci	int status = 0;
275562306a36Sopenharmony_ci
275662306a36Sopenharmony_ci	if (ocfs2_is_hard_readonly(osb))
275762306a36Sopenharmony_ci		return -EROFS;
275862306a36Sopenharmony_ci
275962306a36Sopenharmony_ci	if (ocfs2_mount_local(osb))
276062306a36Sopenharmony_ci		return 0;
276162306a36Sopenharmony_ci
276262306a36Sopenharmony_ci	lockres = &osb->osb_orphan_scan.os_lockres;
276362306a36Sopenharmony_ci	status = ocfs2_cluster_lock(osb, lockres, DLM_LOCK_EX, 0, 0);
276462306a36Sopenharmony_ci	if (status < 0)
276562306a36Sopenharmony_ci		return status;
276662306a36Sopenharmony_ci
276762306a36Sopenharmony_ci	lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
276862306a36Sopenharmony_ci	if (ocfs2_dlm_lvb_valid(&lockres->l_lksb) &&
276962306a36Sopenharmony_ci	    lvb->lvb_version == OCFS2_ORPHAN_LVB_VERSION)
277062306a36Sopenharmony_ci		*seqno = be32_to_cpu(lvb->lvb_os_seqno);
277162306a36Sopenharmony_ci	else
277262306a36Sopenharmony_ci		*seqno = osb->osb_orphan_scan.os_seqno + 1;
277362306a36Sopenharmony_ci
277462306a36Sopenharmony_ci	return status;
277562306a36Sopenharmony_ci}
277662306a36Sopenharmony_ci
277762306a36Sopenharmony_civoid ocfs2_orphan_scan_unlock(struct ocfs2_super *osb, u32 seqno)
277862306a36Sopenharmony_ci{
277962306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres;
278062306a36Sopenharmony_ci	struct ocfs2_orphan_scan_lvb *lvb;
278162306a36Sopenharmony_ci
278262306a36Sopenharmony_ci	if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb)) {
278362306a36Sopenharmony_ci		lockres = &osb->osb_orphan_scan.os_lockres;
278462306a36Sopenharmony_ci		lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
278562306a36Sopenharmony_ci		lvb->lvb_version = OCFS2_ORPHAN_LVB_VERSION;
278662306a36Sopenharmony_ci		lvb->lvb_os_seqno = cpu_to_be32(seqno);
278762306a36Sopenharmony_ci		ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_EX);
278862306a36Sopenharmony_ci	}
278962306a36Sopenharmony_ci}
279062306a36Sopenharmony_ci
279162306a36Sopenharmony_ciint ocfs2_super_lock(struct ocfs2_super *osb,
279262306a36Sopenharmony_ci		     int ex)
279362306a36Sopenharmony_ci{
279462306a36Sopenharmony_ci	int status = 0;
279562306a36Sopenharmony_ci	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
279662306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
279762306a36Sopenharmony_ci
279862306a36Sopenharmony_ci	if (ocfs2_is_hard_readonly(osb))
279962306a36Sopenharmony_ci		return -EROFS;
280062306a36Sopenharmony_ci
280162306a36Sopenharmony_ci	if (ocfs2_mount_local(osb))
280262306a36Sopenharmony_ci		goto bail;
280362306a36Sopenharmony_ci
280462306a36Sopenharmony_ci	status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
280562306a36Sopenharmony_ci	if (status < 0) {
280662306a36Sopenharmony_ci		mlog_errno(status);
280762306a36Sopenharmony_ci		goto bail;
280862306a36Sopenharmony_ci	}
280962306a36Sopenharmony_ci
281062306a36Sopenharmony_ci	/* The super block lock path is really in the best position to
281162306a36Sopenharmony_ci	 * know when resources covered by the lock need to be
281262306a36Sopenharmony_ci	 * refreshed, so we do it here. Of course, making sense of
281362306a36Sopenharmony_ci	 * everything is up to the caller :) */
281462306a36Sopenharmony_ci	status = ocfs2_should_refresh_lock_res(lockres);
281562306a36Sopenharmony_ci	if (status) {
281662306a36Sopenharmony_ci		status = ocfs2_refresh_slot_info(osb);
281762306a36Sopenharmony_ci
281862306a36Sopenharmony_ci		ocfs2_complete_lock_res_refresh(lockres, status);
281962306a36Sopenharmony_ci
282062306a36Sopenharmony_ci		if (status < 0) {
282162306a36Sopenharmony_ci			ocfs2_cluster_unlock(osb, lockres, level);
282262306a36Sopenharmony_ci			mlog_errno(status);
282362306a36Sopenharmony_ci		}
282462306a36Sopenharmony_ci		ocfs2_track_lock_refresh(lockres);
282562306a36Sopenharmony_ci	}
282662306a36Sopenharmony_cibail:
282762306a36Sopenharmony_ci	return status;
282862306a36Sopenharmony_ci}
282962306a36Sopenharmony_ci
283062306a36Sopenharmony_civoid ocfs2_super_unlock(struct ocfs2_super *osb,
283162306a36Sopenharmony_ci			int ex)
283262306a36Sopenharmony_ci{
283362306a36Sopenharmony_ci	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
283462306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
283562306a36Sopenharmony_ci
283662306a36Sopenharmony_ci	if (!ocfs2_mount_local(osb))
283762306a36Sopenharmony_ci		ocfs2_cluster_unlock(osb, lockres, level);
283862306a36Sopenharmony_ci}
283962306a36Sopenharmony_ci
284062306a36Sopenharmony_ciint ocfs2_rename_lock(struct ocfs2_super *osb)
284162306a36Sopenharmony_ci{
284262306a36Sopenharmony_ci	int status;
284362306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &osb->osb_rename_lockres;
284462306a36Sopenharmony_ci
284562306a36Sopenharmony_ci	if (ocfs2_is_hard_readonly(osb))
284662306a36Sopenharmony_ci		return -EROFS;
284762306a36Sopenharmony_ci
284862306a36Sopenharmony_ci	if (ocfs2_mount_local(osb))
284962306a36Sopenharmony_ci		return 0;
285062306a36Sopenharmony_ci
285162306a36Sopenharmony_ci	status = ocfs2_cluster_lock(osb, lockres, DLM_LOCK_EX, 0, 0);
285262306a36Sopenharmony_ci	if (status < 0)
285362306a36Sopenharmony_ci		mlog_errno(status);
285462306a36Sopenharmony_ci
285562306a36Sopenharmony_ci	return status;
285662306a36Sopenharmony_ci}
285762306a36Sopenharmony_ci
285862306a36Sopenharmony_civoid ocfs2_rename_unlock(struct ocfs2_super *osb)
285962306a36Sopenharmony_ci{
286062306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &osb->osb_rename_lockres;
286162306a36Sopenharmony_ci
286262306a36Sopenharmony_ci	if (!ocfs2_mount_local(osb))
286362306a36Sopenharmony_ci		ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_EX);
286462306a36Sopenharmony_ci}
286562306a36Sopenharmony_ci
286662306a36Sopenharmony_ciint ocfs2_nfs_sync_lock(struct ocfs2_super *osb, int ex)
286762306a36Sopenharmony_ci{
286862306a36Sopenharmony_ci	int status;
286962306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &osb->osb_nfs_sync_lockres;
287062306a36Sopenharmony_ci
287162306a36Sopenharmony_ci	if (ocfs2_is_hard_readonly(osb))
287262306a36Sopenharmony_ci		return -EROFS;
287362306a36Sopenharmony_ci
287462306a36Sopenharmony_ci	if (ex)
287562306a36Sopenharmony_ci		down_write(&osb->nfs_sync_rwlock);
287662306a36Sopenharmony_ci	else
287762306a36Sopenharmony_ci		down_read(&osb->nfs_sync_rwlock);
287862306a36Sopenharmony_ci
287962306a36Sopenharmony_ci	if (ocfs2_mount_local(osb))
288062306a36Sopenharmony_ci		return 0;
288162306a36Sopenharmony_ci
288262306a36Sopenharmony_ci	status = ocfs2_cluster_lock(osb, lockres, ex ? LKM_EXMODE : LKM_PRMODE,
288362306a36Sopenharmony_ci				    0, 0);
288462306a36Sopenharmony_ci	if (status < 0) {
288562306a36Sopenharmony_ci		mlog(ML_ERROR, "lock on nfs sync lock failed %d\n", status);
288662306a36Sopenharmony_ci
288762306a36Sopenharmony_ci		if (ex)
288862306a36Sopenharmony_ci			up_write(&osb->nfs_sync_rwlock);
288962306a36Sopenharmony_ci		else
289062306a36Sopenharmony_ci			up_read(&osb->nfs_sync_rwlock);
289162306a36Sopenharmony_ci	}
289262306a36Sopenharmony_ci
289362306a36Sopenharmony_ci	return status;
289462306a36Sopenharmony_ci}
289562306a36Sopenharmony_ci
289662306a36Sopenharmony_civoid ocfs2_nfs_sync_unlock(struct ocfs2_super *osb, int ex)
289762306a36Sopenharmony_ci{
289862306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &osb->osb_nfs_sync_lockres;
289962306a36Sopenharmony_ci
290062306a36Sopenharmony_ci	if (!ocfs2_mount_local(osb))
290162306a36Sopenharmony_ci		ocfs2_cluster_unlock(osb, lockres,
290262306a36Sopenharmony_ci				     ex ? LKM_EXMODE : LKM_PRMODE);
290362306a36Sopenharmony_ci	if (ex)
290462306a36Sopenharmony_ci		up_write(&osb->nfs_sync_rwlock);
290562306a36Sopenharmony_ci	else
290662306a36Sopenharmony_ci		up_read(&osb->nfs_sync_rwlock);
290762306a36Sopenharmony_ci}
290862306a36Sopenharmony_ci
290962306a36Sopenharmony_ciint ocfs2_trim_fs_lock(struct ocfs2_super *osb,
291062306a36Sopenharmony_ci		       struct ocfs2_trim_fs_info *info, int trylock)
291162306a36Sopenharmony_ci{
291262306a36Sopenharmony_ci	int status;
291362306a36Sopenharmony_ci	struct ocfs2_trim_fs_lvb *lvb;
291462306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
291562306a36Sopenharmony_ci
291662306a36Sopenharmony_ci	if (info)
291762306a36Sopenharmony_ci		info->tf_valid = 0;
291862306a36Sopenharmony_ci
291962306a36Sopenharmony_ci	if (ocfs2_is_hard_readonly(osb))
292062306a36Sopenharmony_ci		return -EROFS;
292162306a36Sopenharmony_ci
292262306a36Sopenharmony_ci	if (ocfs2_mount_local(osb))
292362306a36Sopenharmony_ci		return 0;
292462306a36Sopenharmony_ci
292562306a36Sopenharmony_ci	status = ocfs2_cluster_lock(osb, lockres, DLM_LOCK_EX,
292662306a36Sopenharmony_ci				    trylock ? DLM_LKF_NOQUEUE : 0, 0);
292762306a36Sopenharmony_ci	if (status < 0) {
292862306a36Sopenharmony_ci		if (status != -EAGAIN)
292962306a36Sopenharmony_ci			mlog_errno(status);
293062306a36Sopenharmony_ci		return status;
293162306a36Sopenharmony_ci	}
293262306a36Sopenharmony_ci
293362306a36Sopenharmony_ci	if (info) {
293462306a36Sopenharmony_ci		lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
293562306a36Sopenharmony_ci		if (ocfs2_dlm_lvb_valid(&lockres->l_lksb) &&
293662306a36Sopenharmony_ci		    lvb->lvb_version == OCFS2_TRIMFS_LVB_VERSION) {
293762306a36Sopenharmony_ci			info->tf_valid = 1;
293862306a36Sopenharmony_ci			info->tf_success = lvb->lvb_success;
293962306a36Sopenharmony_ci			info->tf_nodenum = be32_to_cpu(lvb->lvb_nodenum);
294062306a36Sopenharmony_ci			info->tf_start = be64_to_cpu(lvb->lvb_start);
294162306a36Sopenharmony_ci			info->tf_len = be64_to_cpu(lvb->lvb_len);
294262306a36Sopenharmony_ci			info->tf_minlen = be64_to_cpu(lvb->lvb_minlen);
294362306a36Sopenharmony_ci			info->tf_trimlen = be64_to_cpu(lvb->lvb_trimlen);
294462306a36Sopenharmony_ci		}
294562306a36Sopenharmony_ci	}
294662306a36Sopenharmony_ci
294762306a36Sopenharmony_ci	return status;
294862306a36Sopenharmony_ci}
294962306a36Sopenharmony_ci
295062306a36Sopenharmony_civoid ocfs2_trim_fs_unlock(struct ocfs2_super *osb,
295162306a36Sopenharmony_ci			  struct ocfs2_trim_fs_info *info)
295262306a36Sopenharmony_ci{
295362306a36Sopenharmony_ci	struct ocfs2_trim_fs_lvb *lvb;
295462306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
295562306a36Sopenharmony_ci
295662306a36Sopenharmony_ci	if (ocfs2_mount_local(osb))
295762306a36Sopenharmony_ci		return;
295862306a36Sopenharmony_ci
295962306a36Sopenharmony_ci	if (info) {
296062306a36Sopenharmony_ci		lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
296162306a36Sopenharmony_ci		lvb->lvb_version = OCFS2_TRIMFS_LVB_VERSION;
296262306a36Sopenharmony_ci		lvb->lvb_success = info->tf_success;
296362306a36Sopenharmony_ci		lvb->lvb_nodenum = cpu_to_be32(info->tf_nodenum);
296462306a36Sopenharmony_ci		lvb->lvb_start = cpu_to_be64(info->tf_start);
296562306a36Sopenharmony_ci		lvb->lvb_len = cpu_to_be64(info->tf_len);
296662306a36Sopenharmony_ci		lvb->lvb_minlen = cpu_to_be64(info->tf_minlen);
296762306a36Sopenharmony_ci		lvb->lvb_trimlen = cpu_to_be64(info->tf_trimlen);
296862306a36Sopenharmony_ci	}
296962306a36Sopenharmony_ci
297062306a36Sopenharmony_ci	ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_EX);
297162306a36Sopenharmony_ci}
297262306a36Sopenharmony_ci
297362306a36Sopenharmony_ciint ocfs2_dentry_lock(struct dentry *dentry, int ex)
297462306a36Sopenharmony_ci{
297562306a36Sopenharmony_ci	int ret;
297662306a36Sopenharmony_ci	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
297762306a36Sopenharmony_ci	struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
297862306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
297962306a36Sopenharmony_ci
298062306a36Sopenharmony_ci	BUG_ON(!dl);
298162306a36Sopenharmony_ci
298262306a36Sopenharmony_ci	if (ocfs2_is_hard_readonly(osb)) {
298362306a36Sopenharmony_ci		if (ex)
298462306a36Sopenharmony_ci			return -EROFS;
298562306a36Sopenharmony_ci		return 0;
298662306a36Sopenharmony_ci	}
298762306a36Sopenharmony_ci
298862306a36Sopenharmony_ci	if (ocfs2_mount_local(osb))
298962306a36Sopenharmony_ci		return 0;
299062306a36Sopenharmony_ci
299162306a36Sopenharmony_ci	ret = ocfs2_cluster_lock(osb, &dl->dl_lockres, level, 0, 0);
299262306a36Sopenharmony_ci	if (ret < 0)
299362306a36Sopenharmony_ci		mlog_errno(ret);
299462306a36Sopenharmony_ci
299562306a36Sopenharmony_ci	return ret;
299662306a36Sopenharmony_ci}
299762306a36Sopenharmony_ci
299862306a36Sopenharmony_civoid ocfs2_dentry_unlock(struct dentry *dentry, int ex)
299962306a36Sopenharmony_ci{
300062306a36Sopenharmony_ci	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
300162306a36Sopenharmony_ci	struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
300262306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
300362306a36Sopenharmony_ci
300462306a36Sopenharmony_ci	if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb))
300562306a36Sopenharmony_ci		ocfs2_cluster_unlock(osb, &dl->dl_lockres, level);
300662306a36Sopenharmony_ci}
300762306a36Sopenharmony_ci
300862306a36Sopenharmony_ci/* Reference counting of the dlm debug structure. We want this because
300962306a36Sopenharmony_ci * open references on the debug inodes can live on after a mount, so
301062306a36Sopenharmony_ci * we can't rely on the ocfs2_super to always exist. */
301162306a36Sopenharmony_cistatic void ocfs2_dlm_debug_free(struct kref *kref)
301262306a36Sopenharmony_ci{
301362306a36Sopenharmony_ci	struct ocfs2_dlm_debug *dlm_debug;
301462306a36Sopenharmony_ci
301562306a36Sopenharmony_ci	dlm_debug = container_of(kref, struct ocfs2_dlm_debug, d_refcnt);
301662306a36Sopenharmony_ci
301762306a36Sopenharmony_ci	kfree(dlm_debug);
301862306a36Sopenharmony_ci}
301962306a36Sopenharmony_ci
302062306a36Sopenharmony_civoid ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug)
302162306a36Sopenharmony_ci{
302262306a36Sopenharmony_ci	if (dlm_debug)
302362306a36Sopenharmony_ci		kref_put(&dlm_debug->d_refcnt, ocfs2_dlm_debug_free);
302462306a36Sopenharmony_ci}
302562306a36Sopenharmony_ci
302662306a36Sopenharmony_cistatic void ocfs2_get_dlm_debug(struct ocfs2_dlm_debug *debug)
302762306a36Sopenharmony_ci{
302862306a36Sopenharmony_ci	kref_get(&debug->d_refcnt);
302962306a36Sopenharmony_ci}
303062306a36Sopenharmony_ci
303162306a36Sopenharmony_cistruct ocfs2_dlm_debug *ocfs2_new_dlm_debug(void)
303262306a36Sopenharmony_ci{
303362306a36Sopenharmony_ci	struct ocfs2_dlm_debug *dlm_debug;
303462306a36Sopenharmony_ci
303562306a36Sopenharmony_ci	dlm_debug = kmalloc(sizeof(struct ocfs2_dlm_debug), GFP_KERNEL);
303662306a36Sopenharmony_ci	if (!dlm_debug) {
303762306a36Sopenharmony_ci		mlog_errno(-ENOMEM);
303862306a36Sopenharmony_ci		goto out;
303962306a36Sopenharmony_ci	}
304062306a36Sopenharmony_ci
304162306a36Sopenharmony_ci	kref_init(&dlm_debug->d_refcnt);
304262306a36Sopenharmony_ci	INIT_LIST_HEAD(&dlm_debug->d_lockres_tracking);
304362306a36Sopenharmony_ci	dlm_debug->d_filter_secs = 0;
304462306a36Sopenharmony_ciout:
304562306a36Sopenharmony_ci	return dlm_debug;
304662306a36Sopenharmony_ci}
304762306a36Sopenharmony_ci
304862306a36Sopenharmony_ci/* Access to this is arbitrated for us via seq_file->sem. */
304962306a36Sopenharmony_cistruct ocfs2_dlm_seq_priv {
305062306a36Sopenharmony_ci	struct ocfs2_dlm_debug *p_dlm_debug;
305162306a36Sopenharmony_ci	struct ocfs2_lock_res p_iter_res;
305262306a36Sopenharmony_ci	struct ocfs2_lock_res p_tmp_res;
305362306a36Sopenharmony_ci};
305462306a36Sopenharmony_ci
305562306a36Sopenharmony_cistatic struct ocfs2_lock_res *ocfs2_dlm_next_res(struct ocfs2_lock_res *start,
305662306a36Sopenharmony_ci						 struct ocfs2_dlm_seq_priv *priv)
305762306a36Sopenharmony_ci{
305862306a36Sopenharmony_ci	struct ocfs2_lock_res *iter, *ret = NULL;
305962306a36Sopenharmony_ci	struct ocfs2_dlm_debug *dlm_debug = priv->p_dlm_debug;
306062306a36Sopenharmony_ci
306162306a36Sopenharmony_ci	assert_spin_locked(&ocfs2_dlm_tracking_lock);
306262306a36Sopenharmony_ci
306362306a36Sopenharmony_ci	list_for_each_entry(iter, &start->l_debug_list, l_debug_list) {
306462306a36Sopenharmony_ci		/* discover the head of the list */
306562306a36Sopenharmony_ci		if (&iter->l_debug_list == &dlm_debug->d_lockres_tracking) {
306662306a36Sopenharmony_ci			mlog(0, "End of list found, %p\n", ret);
306762306a36Sopenharmony_ci			break;
306862306a36Sopenharmony_ci		}
306962306a36Sopenharmony_ci
307062306a36Sopenharmony_ci		/* We track our "dummy" iteration lockres' by a NULL
307162306a36Sopenharmony_ci		 * l_ops field. */
307262306a36Sopenharmony_ci		if (iter->l_ops != NULL) {
307362306a36Sopenharmony_ci			ret = iter;
307462306a36Sopenharmony_ci			break;
307562306a36Sopenharmony_ci		}
307662306a36Sopenharmony_ci	}
307762306a36Sopenharmony_ci
307862306a36Sopenharmony_ci	return ret;
307962306a36Sopenharmony_ci}
308062306a36Sopenharmony_ci
308162306a36Sopenharmony_cistatic void *ocfs2_dlm_seq_start(struct seq_file *m, loff_t *pos)
308262306a36Sopenharmony_ci{
308362306a36Sopenharmony_ci	struct ocfs2_dlm_seq_priv *priv = m->private;
308462306a36Sopenharmony_ci	struct ocfs2_lock_res *iter;
308562306a36Sopenharmony_ci
308662306a36Sopenharmony_ci	spin_lock(&ocfs2_dlm_tracking_lock);
308762306a36Sopenharmony_ci	iter = ocfs2_dlm_next_res(&priv->p_iter_res, priv);
308862306a36Sopenharmony_ci	if (iter) {
308962306a36Sopenharmony_ci		/* Since lockres' have the lifetime of their container
309062306a36Sopenharmony_ci		 * (which can be inodes, ocfs2_supers, etc) we want to
309162306a36Sopenharmony_ci		 * copy this out to a temporary lockres while still
309262306a36Sopenharmony_ci		 * under the spinlock. Obviously after this we can't
309362306a36Sopenharmony_ci		 * trust any pointers on the copy returned, but that's
309462306a36Sopenharmony_ci		 * ok as the information we want isn't typically held
309562306a36Sopenharmony_ci		 * in them. */
309662306a36Sopenharmony_ci		priv->p_tmp_res = *iter;
309762306a36Sopenharmony_ci		iter = &priv->p_tmp_res;
309862306a36Sopenharmony_ci	}
309962306a36Sopenharmony_ci	spin_unlock(&ocfs2_dlm_tracking_lock);
310062306a36Sopenharmony_ci
310162306a36Sopenharmony_ci	return iter;
310262306a36Sopenharmony_ci}
310362306a36Sopenharmony_ci
310462306a36Sopenharmony_cistatic void ocfs2_dlm_seq_stop(struct seq_file *m, void *v)
310562306a36Sopenharmony_ci{
310662306a36Sopenharmony_ci}
310762306a36Sopenharmony_ci
310862306a36Sopenharmony_cistatic void *ocfs2_dlm_seq_next(struct seq_file *m, void *v, loff_t *pos)
310962306a36Sopenharmony_ci{
311062306a36Sopenharmony_ci	struct ocfs2_dlm_seq_priv *priv = m->private;
311162306a36Sopenharmony_ci	struct ocfs2_lock_res *iter = v;
311262306a36Sopenharmony_ci	struct ocfs2_lock_res *dummy = &priv->p_iter_res;
311362306a36Sopenharmony_ci
311462306a36Sopenharmony_ci	spin_lock(&ocfs2_dlm_tracking_lock);
311562306a36Sopenharmony_ci	iter = ocfs2_dlm_next_res(iter, priv);
311662306a36Sopenharmony_ci	list_del_init(&dummy->l_debug_list);
311762306a36Sopenharmony_ci	if (iter) {
311862306a36Sopenharmony_ci		list_add(&dummy->l_debug_list, &iter->l_debug_list);
311962306a36Sopenharmony_ci		priv->p_tmp_res = *iter;
312062306a36Sopenharmony_ci		iter = &priv->p_tmp_res;
312162306a36Sopenharmony_ci	}
312262306a36Sopenharmony_ci	spin_unlock(&ocfs2_dlm_tracking_lock);
312362306a36Sopenharmony_ci
312462306a36Sopenharmony_ci	return iter;
312562306a36Sopenharmony_ci}
312662306a36Sopenharmony_ci
312762306a36Sopenharmony_ci/*
312862306a36Sopenharmony_ci * Version is used by debugfs.ocfs2 to determine the format being used
312962306a36Sopenharmony_ci *
313062306a36Sopenharmony_ci * New in version 2
313162306a36Sopenharmony_ci *	- Lock stats printed
313262306a36Sopenharmony_ci * New in version 3
313362306a36Sopenharmony_ci *	- Max time in lock stats is in usecs (instead of nsecs)
313462306a36Sopenharmony_ci * New in version 4
313562306a36Sopenharmony_ci *	- Add last pr/ex unlock times and first lock wait time in usecs
313662306a36Sopenharmony_ci */
313762306a36Sopenharmony_ci#define OCFS2_DLM_DEBUG_STR_VERSION 4
313862306a36Sopenharmony_cistatic int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
313962306a36Sopenharmony_ci{
314062306a36Sopenharmony_ci	int i;
314162306a36Sopenharmony_ci	char *lvb;
314262306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = v;
314362306a36Sopenharmony_ci#ifdef CONFIG_OCFS2_FS_STATS
314462306a36Sopenharmony_ci	u64 now, last;
314562306a36Sopenharmony_ci	struct ocfs2_dlm_debug *dlm_debug =
314662306a36Sopenharmony_ci			((struct ocfs2_dlm_seq_priv *)m->private)->p_dlm_debug;
314762306a36Sopenharmony_ci#endif
314862306a36Sopenharmony_ci
314962306a36Sopenharmony_ci	if (!lockres)
315062306a36Sopenharmony_ci		return -EINVAL;
315162306a36Sopenharmony_ci
315262306a36Sopenharmony_ci#ifdef CONFIG_OCFS2_FS_STATS
315362306a36Sopenharmony_ci	if (!lockres->l_lock_wait && dlm_debug->d_filter_secs) {
315462306a36Sopenharmony_ci		now = ktime_to_us(ktime_get_real());
315562306a36Sopenharmony_ci		if (lockres->l_lock_prmode.ls_last >
315662306a36Sopenharmony_ci		    lockres->l_lock_exmode.ls_last)
315762306a36Sopenharmony_ci			last = lockres->l_lock_prmode.ls_last;
315862306a36Sopenharmony_ci		else
315962306a36Sopenharmony_ci			last = lockres->l_lock_exmode.ls_last;
316062306a36Sopenharmony_ci		/*
316162306a36Sopenharmony_ci		 * Use d_filter_secs field to filter lock resources dump,
316262306a36Sopenharmony_ci		 * the default d_filter_secs(0) value filters nothing,
316362306a36Sopenharmony_ci		 * otherwise, only dump the last N seconds active lock
316462306a36Sopenharmony_ci		 * resources.
316562306a36Sopenharmony_ci		 */
316662306a36Sopenharmony_ci		if (div_u64(now - last, 1000000) > dlm_debug->d_filter_secs)
316762306a36Sopenharmony_ci			return 0;
316862306a36Sopenharmony_ci	}
316962306a36Sopenharmony_ci#endif
317062306a36Sopenharmony_ci
317162306a36Sopenharmony_ci	seq_printf(m, "0x%x\t", OCFS2_DLM_DEBUG_STR_VERSION);
317262306a36Sopenharmony_ci
317362306a36Sopenharmony_ci	if (lockres->l_type == OCFS2_LOCK_TYPE_DENTRY)
317462306a36Sopenharmony_ci		seq_printf(m, "%.*s%08x\t", OCFS2_DENTRY_LOCK_INO_START - 1,
317562306a36Sopenharmony_ci			   lockres->l_name,
317662306a36Sopenharmony_ci			   (unsigned int)ocfs2_get_dentry_lock_ino(lockres));
317762306a36Sopenharmony_ci	else
317862306a36Sopenharmony_ci		seq_printf(m, "%.*s\t", OCFS2_LOCK_ID_MAX_LEN, lockres->l_name);
317962306a36Sopenharmony_ci
318062306a36Sopenharmony_ci	seq_printf(m, "%d\t"
318162306a36Sopenharmony_ci		   "0x%lx\t"
318262306a36Sopenharmony_ci		   "0x%x\t"
318362306a36Sopenharmony_ci		   "0x%x\t"
318462306a36Sopenharmony_ci		   "%u\t"
318562306a36Sopenharmony_ci		   "%u\t"
318662306a36Sopenharmony_ci		   "%d\t"
318762306a36Sopenharmony_ci		   "%d\t",
318862306a36Sopenharmony_ci		   lockres->l_level,
318962306a36Sopenharmony_ci		   lockres->l_flags,
319062306a36Sopenharmony_ci		   lockres->l_action,
319162306a36Sopenharmony_ci		   lockres->l_unlock_action,
319262306a36Sopenharmony_ci		   lockres->l_ro_holders,
319362306a36Sopenharmony_ci		   lockres->l_ex_holders,
319462306a36Sopenharmony_ci		   lockres->l_requested,
319562306a36Sopenharmony_ci		   lockres->l_blocking);
319662306a36Sopenharmony_ci
319762306a36Sopenharmony_ci	/* Dump the raw LVB */
319862306a36Sopenharmony_ci	lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
319962306a36Sopenharmony_ci	for(i = 0; i < DLM_LVB_LEN; i++)
320062306a36Sopenharmony_ci		seq_printf(m, "0x%x\t", lvb[i]);
320162306a36Sopenharmony_ci
320262306a36Sopenharmony_ci#ifdef CONFIG_OCFS2_FS_STATS
320362306a36Sopenharmony_ci# define lock_num_prmode(_l)		((_l)->l_lock_prmode.ls_gets)
320462306a36Sopenharmony_ci# define lock_num_exmode(_l)		((_l)->l_lock_exmode.ls_gets)
320562306a36Sopenharmony_ci# define lock_num_prmode_failed(_l)	((_l)->l_lock_prmode.ls_fail)
320662306a36Sopenharmony_ci# define lock_num_exmode_failed(_l)	((_l)->l_lock_exmode.ls_fail)
320762306a36Sopenharmony_ci# define lock_total_prmode(_l)		((_l)->l_lock_prmode.ls_total)
320862306a36Sopenharmony_ci# define lock_total_exmode(_l)		((_l)->l_lock_exmode.ls_total)
320962306a36Sopenharmony_ci# define lock_max_prmode(_l)		((_l)->l_lock_prmode.ls_max)
321062306a36Sopenharmony_ci# define lock_max_exmode(_l)		((_l)->l_lock_exmode.ls_max)
321162306a36Sopenharmony_ci# define lock_refresh(_l)		((_l)->l_lock_refresh)
321262306a36Sopenharmony_ci# define lock_last_prmode(_l)		((_l)->l_lock_prmode.ls_last)
321362306a36Sopenharmony_ci# define lock_last_exmode(_l)		((_l)->l_lock_exmode.ls_last)
321462306a36Sopenharmony_ci# define lock_wait(_l)			((_l)->l_lock_wait)
321562306a36Sopenharmony_ci#else
321662306a36Sopenharmony_ci# define lock_num_prmode(_l)		(0)
321762306a36Sopenharmony_ci# define lock_num_exmode(_l)		(0)
321862306a36Sopenharmony_ci# define lock_num_prmode_failed(_l)	(0)
321962306a36Sopenharmony_ci# define lock_num_exmode_failed(_l)	(0)
322062306a36Sopenharmony_ci# define lock_total_prmode(_l)		(0ULL)
322162306a36Sopenharmony_ci# define lock_total_exmode(_l)		(0ULL)
322262306a36Sopenharmony_ci# define lock_max_prmode(_l)		(0)
322362306a36Sopenharmony_ci# define lock_max_exmode(_l)		(0)
322462306a36Sopenharmony_ci# define lock_refresh(_l)		(0)
322562306a36Sopenharmony_ci# define lock_last_prmode(_l)		(0ULL)
322662306a36Sopenharmony_ci# define lock_last_exmode(_l)		(0ULL)
322762306a36Sopenharmony_ci# define lock_wait(_l)			(0ULL)
322862306a36Sopenharmony_ci#endif
322962306a36Sopenharmony_ci	/* The following seq_print was added in version 2 of this output */
323062306a36Sopenharmony_ci	seq_printf(m, "%u\t"
323162306a36Sopenharmony_ci		   "%u\t"
323262306a36Sopenharmony_ci		   "%u\t"
323362306a36Sopenharmony_ci		   "%u\t"
323462306a36Sopenharmony_ci		   "%llu\t"
323562306a36Sopenharmony_ci		   "%llu\t"
323662306a36Sopenharmony_ci		   "%u\t"
323762306a36Sopenharmony_ci		   "%u\t"
323862306a36Sopenharmony_ci		   "%u\t"
323962306a36Sopenharmony_ci		   "%llu\t"
324062306a36Sopenharmony_ci		   "%llu\t"
324162306a36Sopenharmony_ci		   "%llu\t",
324262306a36Sopenharmony_ci		   lock_num_prmode(lockres),
324362306a36Sopenharmony_ci		   lock_num_exmode(lockres),
324462306a36Sopenharmony_ci		   lock_num_prmode_failed(lockres),
324562306a36Sopenharmony_ci		   lock_num_exmode_failed(lockres),
324662306a36Sopenharmony_ci		   lock_total_prmode(lockres),
324762306a36Sopenharmony_ci		   lock_total_exmode(lockres),
324862306a36Sopenharmony_ci		   lock_max_prmode(lockres),
324962306a36Sopenharmony_ci		   lock_max_exmode(lockres),
325062306a36Sopenharmony_ci		   lock_refresh(lockres),
325162306a36Sopenharmony_ci		   lock_last_prmode(lockres),
325262306a36Sopenharmony_ci		   lock_last_exmode(lockres),
325362306a36Sopenharmony_ci		   lock_wait(lockres));
325462306a36Sopenharmony_ci
325562306a36Sopenharmony_ci	/* End the line */
325662306a36Sopenharmony_ci	seq_printf(m, "\n");
325762306a36Sopenharmony_ci	return 0;
325862306a36Sopenharmony_ci}
325962306a36Sopenharmony_ci
326062306a36Sopenharmony_cistatic const struct seq_operations ocfs2_dlm_seq_ops = {
326162306a36Sopenharmony_ci	.start =	ocfs2_dlm_seq_start,
326262306a36Sopenharmony_ci	.stop =		ocfs2_dlm_seq_stop,
326362306a36Sopenharmony_ci	.next =		ocfs2_dlm_seq_next,
326462306a36Sopenharmony_ci	.show =		ocfs2_dlm_seq_show,
326562306a36Sopenharmony_ci};
326662306a36Sopenharmony_ci
326762306a36Sopenharmony_cistatic int ocfs2_dlm_debug_release(struct inode *inode, struct file *file)
326862306a36Sopenharmony_ci{
326962306a36Sopenharmony_ci	struct seq_file *seq = file->private_data;
327062306a36Sopenharmony_ci	struct ocfs2_dlm_seq_priv *priv = seq->private;
327162306a36Sopenharmony_ci	struct ocfs2_lock_res *res = &priv->p_iter_res;
327262306a36Sopenharmony_ci
327362306a36Sopenharmony_ci	ocfs2_remove_lockres_tracking(res);
327462306a36Sopenharmony_ci	ocfs2_put_dlm_debug(priv->p_dlm_debug);
327562306a36Sopenharmony_ci	return seq_release_private(inode, file);
327662306a36Sopenharmony_ci}
327762306a36Sopenharmony_ci
327862306a36Sopenharmony_cistatic int ocfs2_dlm_debug_open(struct inode *inode, struct file *file)
327962306a36Sopenharmony_ci{
328062306a36Sopenharmony_ci	struct ocfs2_dlm_seq_priv *priv;
328162306a36Sopenharmony_ci	struct ocfs2_super *osb;
328262306a36Sopenharmony_ci
328362306a36Sopenharmony_ci	priv = __seq_open_private(file, &ocfs2_dlm_seq_ops, sizeof(*priv));
328462306a36Sopenharmony_ci	if (!priv) {
328562306a36Sopenharmony_ci		mlog_errno(-ENOMEM);
328662306a36Sopenharmony_ci		return -ENOMEM;
328762306a36Sopenharmony_ci	}
328862306a36Sopenharmony_ci
328962306a36Sopenharmony_ci	osb = inode->i_private;
329062306a36Sopenharmony_ci	ocfs2_get_dlm_debug(osb->osb_dlm_debug);
329162306a36Sopenharmony_ci	priv->p_dlm_debug = osb->osb_dlm_debug;
329262306a36Sopenharmony_ci	INIT_LIST_HEAD(&priv->p_iter_res.l_debug_list);
329362306a36Sopenharmony_ci
329462306a36Sopenharmony_ci	ocfs2_add_lockres_tracking(&priv->p_iter_res,
329562306a36Sopenharmony_ci				   priv->p_dlm_debug);
329662306a36Sopenharmony_ci
329762306a36Sopenharmony_ci	return 0;
329862306a36Sopenharmony_ci}
329962306a36Sopenharmony_ci
330062306a36Sopenharmony_cistatic const struct file_operations ocfs2_dlm_debug_fops = {
330162306a36Sopenharmony_ci	.open =		ocfs2_dlm_debug_open,
330262306a36Sopenharmony_ci	.release =	ocfs2_dlm_debug_release,
330362306a36Sopenharmony_ci	.read =		seq_read,
330462306a36Sopenharmony_ci	.llseek =	seq_lseek,
330562306a36Sopenharmony_ci};
330662306a36Sopenharmony_ci
330762306a36Sopenharmony_cistatic void ocfs2_dlm_init_debug(struct ocfs2_super *osb)
330862306a36Sopenharmony_ci{
330962306a36Sopenharmony_ci	struct ocfs2_dlm_debug *dlm_debug = osb->osb_dlm_debug;
331062306a36Sopenharmony_ci
331162306a36Sopenharmony_ci	debugfs_create_file("locking_state", S_IFREG|S_IRUSR,
331262306a36Sopenharmony_ci			    osb->osb_debug_root, osb, &ocfs2_dlm_debug_fops);
331362306a36Sopenharmony_ci
331462306a36Sopenharmony_ci	debugfs_create_u32("locking_filter", 0600, osb->osb_debug_root,
331562306a36Sopenharmony_ci			   &dlm_debug->d_filter_secs);
331662306a36Sopenharmony_ci	ocfs2_get_dlm_debug(dlm_debug);
331762306a36Sopenharmony_ci}
331862306a36Sopenharmony_ci
331962306a36Sopenharmony_cistatic void ocfs2_dlm_shutdown_debug(struct ocfs2_super *osb)
332062306a36Sopenharmony_ci{
332162306a36Sopenharmony_ci	struct ocfs2_dlm_debug *dlm_debug = osb->osb_dlm_debug;
332262306a36Sopenharmony_ci
332362306a36Sopenharmony_ci	if (dlm_debug)
332462306a36Sopenharmony_ci		ocfs2_put_dlm_debug(dlm_debug);
332562306a36Sopenharmony_ci}
332662306a36Sopenharmony_ci
332762306a36Sopenharmony_ciint ocfs2_dlm_init(struct ocfs2_super *osb)
332862306a36Sopenharmony_ci{
332962306a36Sopenharmony_ci	int status = 0;
333062306a36Sopenharmony_ci	struct ocfs2_cluster_connection *conn = NULL;
333162306a36Sopenharmony_ci
333262306a36Sopenharmony_ci	if (ocfs2_mount_local(osb)) {
333362306a36Sopenharmony_ci		osb->node_num = 0;
333462306a36Sopenharmony_ci		goto local;
333562306a36Sopenharmony_ci	}
333662306a36Sopenharmony_ci
333762306a36Sopenharmony_ci	ocfs2_dlm_init_debug(osb);
333862306a36Sopenharmony_ci
333962306a36Sopenharmony_ci	/* launch downconvert thread */
334062306a36Sopenharmony_ci	osb->dc_task = kthread_run(ocfs2_downconvert_thread, osb, "ocfs2dc-%s",
334162306a36Sopenharmony_ci			osb->uuid_str);
334262306a36Sopenharmony_ci	if (IS_ERR(osb->dc_task)) {
334362306a36Sopenharmony_ci		status = PTR_ERR(osb->dc_task);
334462306a36Sopenharmony_ci		osb->dc_task = NULL;
334562306a36Sopenharmony_ci		mlog_errno(status);
334662306a36Sopenharmony_ci		goto bail;
334762306a36Sopenharmony_ci	}
334862306a36Sopenharmony_ci
334962306a36Sopenharmony_ci	/* for now, uuid == domain */
335062306a36Sopenharmony_ci	status = ocfs2_cluster_connect(osb->osb_cluster_stack,
335162306a36Sopenharmony_ci				       osb->osb_cluster_name,
335262306a36Sopenharmony_ci				       strlen(osb->osb_cluster_name),
335362306a36Sopenharmony_ci				       osb->uuid_str,
335462306a36Sopenharmony_ci				       strlen(osb->uuid_str),
335562306a36Sopenharmony_ci				       &lproto, ocfs2_do_node_down, osb,
335662306a36Sopenharmony_ci				       &conn);
335762306a36Sopenharmony_ci	if (status) {
335862306a36Sopenharmony_ci		mlog_errno(status);
335962306a36Sopenharmony_ci		goto bail;
336062306a36Sopenharmony_ci	}
336162306a36Sopenharmony_ci
336262306a36Sopenharmony_ci	status = ocfs2_cluster_this_node(conn, &osb->node_num);
336362306a36Sopenharmony_ci	if (status < 0) {
336462306a36Sopenharmony_ci		mlog_errno(status);
336562306a36Sopenharmony_ci		mlog(ML_ERROR,
336662306a36Sopenharmony_ci		     "could not find this host's node number\n");
336762306a36Sopenharmony_ci		ocfs2_cluster_disconnect(conn, 0);
336862306a36Sopenharmony_ci		goto bail;
336962306a36Sopenharmony_ci	}
337062306a36Sopenharmony_ci
337162306a36Sopenharmony_cilocal:
337262306a36Sopenharmony_ci	ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb);
337362306a36Sopenharmony_ci	ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb);
337462306a36Sopenharmony_ci	ocfs2_nfs_sync_lock_init(osb);
337562306a36Sopenharmony_ci	ocfs2_orphan_scan_lock_res_init(&osb->osb_orphan_scan.os_lockres, osb);
337662306a36Sopenharmony_ci
337762306a36Sopenharmony_ci	osb->cconn = conn;
337862306a36Sopenharmony_cibail:
337962306a36Sopenharmony_ci	if (status < 0) {
338062306a36Sopenharmony_ci		ocfs2_dlm_shutdown_debug(osb);
338162306a36Sopenharmony_ci		if (osb->dc_task)
338262306a36Sopenharmony_ci			kthread_stop(osb->dc_task);
338362306a36Sopenharmony_ci	}
338462306a36Sopenharmony_ci
338562306a36Sopenharmony_ci	return status;
338662306a36Sopenharmony_ci}
338762306a36Sopenharmony_ci
338862306a36Sopenharmony_civoid ocfs2_dlm_shutdown(struct ocfs2_super *osb,
338962306a36Sopenharmony_ci			int hangup_pending)
339062306a36Sopenharmony_ci{
339162306a36Sopenharmony_ci	ocfs2_drop_osb_locks(osb);
339262306a36Sopenharmony_ci
339362306a36Sopenharmony_ci	/*
339462306a36Sopenharmony_ci	 * Now that we have dropped all locks and ocfs2_dismount_volume()
339562306a36Sopenharmony_ci	 * has disabled recovery, the DLM won't be talking to us.  It's
339662306a36Sopenharmony_ci	 * safe to tear things down before disconnecting the cluster.
339762306a36Sopenharmony_ci	 */
339862306a36Sopenharmony_ci
339962306a36Sopenharmony_ci	if (osb->dc_task) {
340062306a36Sopenharmony_ci		kthread_stop(osb->dc_task);
340162306a36Sopenharmony_ci		osb->dc_task = NULL;
340262306a36Sopenharmony_ci	}
340362306a36Sopenharmony_ci
340462306a36Sopenharmony_ci	ocfs2_lock_res_free(&osb->osb_super_lockres);
340562306a36Sopenharmony_ci	ocfs2_lock_res_free(&osb->osb_rename_lockres);
340662306a36Sopenharmony_ci	ocfs2_lock_res_free(&osb->osb_nfs_sync_lockres);
340762306a36Sopenharmony_ci	ocfs2_lock_res_free(&osb->osb_orphan_scan.os_lockres);
340862306a36Sopenharmony_ci
340962306a36Sopenharmony_ci	if (osb->cconn) {
341062306a36Sopenharmony_ci		ocfs2_cluster_disconnect(osb->cconn, hangup_pending);
341162306a36Sopenharmony_ci		osb->cconn = NULL;
341262306a36Sopenharmony_ci
341362306a36Sopenharmony_ci		ocfs2_dlm_shutdown_debug(osb);
341462306a36Sopenharmony_ci	}
341562306a36Sopenharmony_ci}
341662306a36Sopenharmony_ci
341762306a36Sopenharmony_cistatic int ocfs2_drop_lock(struct ocfs2_super *osb,
341862306a36Sopenharmony_ci			   struct ocfs2_lock_res *lockres)
341962306a36Sopenharmony_ci{
342062306a36Sopenharmony_ci	int ret;
342162306a36Sopenharmony_ci	unsigned long flags;
342262306a36Sopenharmony_ci	u32 lkm_flags = 0;
342362306a36Sopenharmony_ci
342462306a36Sopenharmony_ci	/* We didn't get anywhere near actually using this lockres. */
342562306a36Sopenharmony_ci	if (!(lockres->l_flags & OCFS2_LOCK_INITIALIZED))
342662306a36Sopenharmony_ci		goto out;
342762306a36Sopenharmony_ci
342862306a36Sopenharmony_ci	if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB)
342962306a36Sopenharmony_ci		lkm_flags |= DLM_LKF_VALBLK;
343062306a36Sopenharmony_ci
343162306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
343262306a36Sopenharmony_ci
343362306a36Sopenharmony_ci	mlog_bug_on_msg(!(lockres->l_flags & OCFS2_LOCK_FREEING),
343462306a36Sopenharmony_ci			"lockres %s, flags 0x%lx\n",
343562306a36Sopenharmony_ci			lockres->l_name, lockres->l_flags);
343662306a36Sopenharmony_ci
343762306a36Sopenharmony_ci	while (lockres->l_flags & OCFS2_LOCK_BUSY) {
343862306a36Sopenharmony_ci		mlog(0, "waiting on busy lock \"%s\": flags = %lx, action = "
343962306a36Sopenharmony_ci		     "%u, unlock_action = %u\n",
344062306a36Sopenharmony_ci		     lockres->l_name, lockres->l_flags, lockres->l_action,
344162306a36Sopenharmony_ci		     lockres->l_unlock_action);
344262306a36Sopenharmony_ci
344362306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
344462306a36Sopenharmony_ci
344562306a36Sopenharmony_ci		/* XXX: Today we just wait on any busy
344662306a36Sopenharmony_ci		 * locks... Perhaps we need to cancel converts in the
344762306a36Sopenharmony_ci		 * future? */
344862306a36Sopenharmony_ci		ocfs2_wait_on_busy_lock(lockres);
344962306a36Sopenharmony_ci
345062306a36Sopenharmony_ci		spin_lock_irqsave(&lockres->l_lock, flags);
345162306a36Sopenharmony_ci	}
345262306a36Sopenharmony_ci
345362306a36Sopenharmony_ci	if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB) {
345462306a36Sopenharmony_ci		if (lockres->l_flags & OCFS2_LOCK_ATTACHED &&
345562306a36Sopenharmony_ci		    lockres->l_level == DLM_LOCK_EX &&
345662306a36Sopenharmony_ci		    !(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH))
345762306a36Sopenharmony_ci			lockres->l_ops->set_lvb(lockres);
345862306a36Sopenharmony_ci	}
345962306a36Sopenharmony_ci
346062306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_BUSY)
346162306a36Sopenharmony_ci		mlog(ML_ERROR, "destroying busy lock: \"%s\"\n",
346262306a36Sopenharmony_ci		     lockres->l_name);
346362306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_BLOCKED)
346462306a36Sopenharmony_ci		mlog(0, "destroying blocked lock: \"%s\"\n", lockres->l_name);
346562306a36Sopenharmony_ci
346662306a36Sopenharmony_ci	if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) {
346762306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
346862306a36Sopenharmony_ci		goto out;
346962306a36Sopenharmony_ci	}
347062306a36Sopenharmony_ci
347162306a36Sopenharmony_ci	lockres_clear_flags(lockres, OCFS2_LOCK_ATTACHED);
347262306a36Sopenharmony_ci
347362306a36Sopenharmony_ci	/* make sure we never get here while waiting for an ast to
347462306a36Sopenharmony_ci	 * fire. */
347562306a36Sopenharmony_ci	BUG_ON(lockres->l_action != OCFS2_AST_INVALID);
347662306a36Sopenharmony_ci
347762306a36Sopenharmony_ci	/* is this necessary? */
347862306a36Sopenharmony_ci	lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
347962306a36Sopenharmony_ci	lockres->l_unlock_action = OCFS2_UNLOCK_DROP_LOCK;
348062306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
348162306a36Sopenharmony_ci
348262306a36Sopenharmony_ci	mlog(0, "lock %s\n", lockres->l_name);
348362306a36Sopenharmony_ci
348462306a36Sopenharmony_ci	ret = ocfs2_dlm_unlock(osb->cconn, &lockres->l_lksb, lkm_flags);
348562306a36Sopenharmony_ci	if (ret) {
348662306a36Sopenharmony_ci		ocfs2_log_dlm_error("ocfs2_dlm_unlock", ret, lockres);
348762306a36Sopenharmony_ci		mlog(ML_ERROR, "lockres flags: %lu\n", lockres->l_flags);
348862306a36Sopenharmony_ci		ocfs2_dlm_dump_lksb(&lockres->l_lksb);
348962306a36Sopenharmony_ci		BUG();
349062306a36Sopenharmony_ci	}
349162306a36Sopenharmony_ci	mlog(0, "lock %s, successful return from ocfs2_dlm_unlock\n",
349262306a36Sopenharmony_ci	     lockres->l_name);
349362306a36Sopenharmony_ci
349462306a36Sopenharmony_ci	ocfs2_wait_on_busy_lock(lockres);
349562306a36Sopenharmony_ciout:
349662306a36Sopenharmony_ci	return 0;
349762306a36Sopenharmony_ci}
349862306a36Sopenharmony_ci
349962306a36Sopenharmony_cistatic void ocfs2_process_blocked_lock(struct ocfs2_super *osb,
350062306a36Sopenharmony_ci				       struct ocfs2_lock_res *lockres);
350162306a36Sopenharmony_ci
350262306a36Sopenharmony_ci/* Mark the lockres as being dropped. It will no longer be
350362306a36Sopenharmony_ci * queued if blocking, but we still may have to wait on it
350462306a36Sopenharmony_ci * being dequeued from the downconvert thread before we can consider
350562306a36Sopenharmony_ci * it safe to drop.
350662306a36Sopenharmony_ci *
350762306a36Sopenharmony_ci * You can *not* attempt to call cluster_lock on this lockres anymore. */
350862306a36Sopenharmony_civoid ocfs2_mark_lockres_freeing(struct ocfs2_super *osb,
350962306a36Sopenharmony_ci				struct ocfs2_lock_res *lockres)
351062306a36Sopenharmony_ci{
351162306a36Sopenharmony_ci	int status;
351262306a36Sopenharmony_ci	struct ocfs2_mask_waiter mw;
351362306a36Sopenharmony_ci	unsigned long flags, flags2;
351462306a36Sopenharmony_ci
351562306a36Sopenharmony_ci	ocfs2_init_mask_waiter(&mw);
351662306a36Sopenharmony_ci
351762306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
351862306a36Sopenharmony_ci	lockres->l_flags |= OCFS2_LOCK_FREEING;
351962306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_QUEUED && current == osb->dc_task) {
352062306a36Sopenharmony_ci		/*
352162306a36Sopenharmony_ci		 * We know the downconvert is queued but not in progress
352262306a36Sopenharmony_ci		 * because we are the downconvert thread and processing
352362306a36Sopenharmony_ci		 * different lock. So we can just remove the lock from the
352462306a36Sopenharmony_ci		 * queue. This is not only an optimization but also a way
352562306a36Sopenharmony_ci		 * to avoid the following deadlock:
352662306a36Sopenharmony_ci		 *   ocfs2_dentry_post_unlock()
352762306a36Sopenharmony_ci		 *     ocfs2_dentry_lock_put()
352862306a36Sopenharmony_ci		 *       ocfs2_drop_dentry_lock()
352962306a36Sopenharmony_ci		 *         iput()
353062306a36Sopenharmony_ci		 *           ocfs2_evict_inode()
353162306a36Sopenharmony_ci		 *             ocfs2_clear_inode()
353262306a36Sopenharmony_ci		 *               ocfs2_mark_lockres_freeing()
353362306a36Sopenharmony_ci		 *                 ... blocks waiting for OCFS2_LOCK_QUEUED
353462306a36Sopenharmony_ci		 *                 since we are the downconvert thread which
353562306a36Sopenharmony_ci		 *                 should clear the flag.
353662306a36Sopenharmony_ci		 */
353762306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
353862306a36Sopenharmony_ci		spin_lock_irqsave(&osb->dc_task_lock, flags2);
353962306a36Sopenharmony_ci		list_del_init(&lockres->l_blocked_list);
354062306a36Sopenharmony_ci		osb->blocked_lock_count--;
354162306a36Sopenharmony_ci		spin_unlock_irqrestore(&osb->dc_task_lock, flags2);
354262306a36Sopenharmony_ci		/*
354362306a36Sopenharmony_ci		 * Warn if we recurse into another post_unlock call.  Strictly
354462306a36Sopenharmony_ci		 * speaking it isn't a problem but we need to be careful if
354562306a36Sopenharmony_ci		 * that happens (stack overflow, deadlocks, ...) so warn if
354662306a36Sopenharmony_ci		 * ocfs2 grows a path for which this can happen.
354762306a36Sopenharmony_ci		 */
354862306a36Sopenharmony_ci		WARN_ON_ONCE(lockres->l_ops->post_unlock);
354962306a36Sopenharmony_ci		/* Since the lock is freeing we don't do much in the fn below */
355062306a36Sopenharmony_ci		ocfs2_process_blocked_lock(osb, lockres);
355162306a36Sopenharmony_ci		return;
355262306a36Sopenharmony_ci	}
355362306a36Sopenharmony_ci	while (lockres->l_flags & OCFS2_LOCK_QUEUED) {
355462306a36Sopenharmony_ci		lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_QUEUED, 0);
355562306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
355662306a36Sopenharmony_ci
355762306a36Sopenharmony_ci		mlog(0, "Waiting on lockres %s\n", lockres->l_name);
355862306a36Sopenharmony_ci
355962306a36Sopenharmony_ci		status = ocfs2_wait_for_mask(&mw);
356062306a36Sopenharmony_ci		if (status)
356162306a36Sopenharmony_ci			mlog_errno(status);
356262306a36Sopenharmony_ci
356362306a36Sopenharmony_ci		spin_lock_irqsave(&lockres->l_lock, flags);
356462306a36Sopenharmony_ci	}
356562306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
356662306a36Sopenharmony_ci}
356762306a36Sopenharmony_ci
356862306a36Sopenharmony_civoid ocfs2_simple_drop_lockres(struct ocfs2_super *osb,
356962306a36Sopenharmony_ci			       struct ocfs2_lock_res *lockres)
357062306a36Sopenharmony_ci{
357162306a36Sopenharmony_ci	int ret;
357262306a36Sopenharmony_ci
357362306a36Sopenharmony_ci	ocfs2_mark_lockres_freeing(osb, lockres);
357462306a36Sopenharmony_ci	ret = ocfs2_drop_lock(osb, lockres);
357562306a36Sopenharmony_ci	if (ret)
357662306a36Sopenharmony_ci		mlog_errno(ret);
357762306a36Sopenharmony_ci}
357862306a36Sopenharmony_ci
357962306a36Sopenharmony_cistatic void ocfs2_drop_osb_locks(struct ocfs2_super *osb)
358062306a36Sopenharmony_ci{
358162306a36Sopenharmony_ci	ocfs2_simple_drop_lockres(osb, &osb->osb_super_lockres);
358262306a36Sopenharmony_ci	ocfs2_simple_drop_lockres(osb, &osb->osb_rename_lockres);
358362306a36Sopenharmony_ci	ocfs2_simple_drop_lockres(osb, &osb->osb_nfs_sync_lockres);
358462306a36Sopenharmony_ci	ocfs2_simple_drop_lockres(osb, &osb->osb_orphan_scan.os_lockres);
358562306a36Sopenharmony_ci}
358662306a36Sopenharmony_ci
358762306a36Sopenharmony_ciint ocfs2_drop_inode_locks(struct inode *inode)
358862306a36Sopenharmony_ci{
358962306a36Sopenharmony_ci	int status, err;
359062306a36Sopenharmony_ci
359162306a36Sopenharmony_ci	/* No need to call ocfs2_mark_lockres_freeing here -
359262306a36Sopenharmony_ci	 * ocfs2_clear_inode has done it for us. */
359362306a36Sopenharmony_ci
359462306a36Sopenharmony_ci	err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb),
359562306a36Sopenharmony_ci			      &OCFS2_I(inode)->ip_open_lockres);
359662306a36Sopenharmony_ci	if (err < 0)
359762306a36Sopenharmony_ci		mlog_errno(err);
359862306a36Sopenharmony_ci
359962306a36Sopenharmony_ci	status = err;
360062306a36Sopenharmony_ci
360162306a36Sopenharmony_ci	err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb),
360262306a36Sopenharmony_ci			      &OCFS2_I(inode)->ip_inode_lockres);
360362306a36Sopenharmony_ci	if (err < 0)
360462306a36Sopenharmony_ci		mlog_errno(err);
360562306a36Sopenharmony_ci	if (err < 0 && !status)
360662306a36Sopenharmony_ci		status = err;
360762306a36Sopenharmony_ci
360862306a36Sopenharmony_ci	err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb),
360962306a36Sopenharmony_ci			      &OCFS2_I(inode)->ip_rw_lockres);
361062306a36Sopenharmony_ci	if (err < 0)
361162306a36Sopenharmony_ci		mlog_errno(err);
361262306a36Sopenharmony_ci	if (err < 0 && !status)
361362306a36Sopenharmony_ci		status = err;
361462306a36Sopenharmony_ci
361562306a36Sopenharmony_ci	return status;
361662306a36Sopenharmony_ci}
361762306a36Sopenharmony_ci
361862306a36Sopenharmony_cistatic unsigned int ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres,
361962306a36Sopenharmony_ci					      int new_level)
362062306a36Sopenharmony_ci{
362162306a36Sopenharmony_ci	assert_spin_locked(&lockres->l_lock);
362262306a36Sopenharmony_ci
362362306a36Sopenharmony_ci	BUG_ON(lockres->l_blocking <= DLM_LOCK_NL);
362462306a36Sopenharmony_ci
362562306a36Sopenharmony_ci	if (lockres->l_level <= new_level) {
362662306a36Sopenharmony_ci		mlog(ML_ERROR, "lockres %s, lvl %d <= %d, blcklst %d, mask %d, "
362762306a36Sopenharmony_ci		     "type %d, flags 0x%lx, hold %d %d, act %d %d, req %d, "
362862306a36Sopenharmony_ci		     "block %d, pgen %d\n", lockres->l_name, lockres->l_level,
362962306a36Sopenharmony_ci		     new_level, list_empty(&lockres->l_blocked_list),
363062306a36Sopenharmony_ci		     list_empty(&lockres->l_mask_waiters), lockres->l_type,
363162306a36Sopenharmony_ci		     lockres->l_flags, lockres->l_ro_holders,
363262306a36Sopenharmony_ci		     lockres->l_ex_holders, lockres->l_action,
363362306a36Sopenharmony_ci		     lockres->l_unlock_action, lockres->l_requested,
363462306a36Sopenharmony_ci		     lockres->l_blocking, lockres->l_pending_gen);
363562306a36Sopenharmony_ci		BUG();
363662306a36Sopenharmony_ci	}
363762306a36Sopenharmony_ci
363862306a36Sopenharmony_ci	mlog(ML_BASTS, "lockres %s, level %d => %d, blocking %d\n",
363962306a36Sopenharmony_ci	     lockres->l_name, lockres->l_level, new_level, lockres->l_blocking);
364062306a36Sopenharmony_ci
364162306a36Sopenharmony_ci	lockres->l_action = OCFS2_AST_DOWNCONVERT;
364262306a36Sopenharmony_ci	lockres->l_requested = new_level;
364362306a36Sopenharmony_ci	lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
364462306a36Sopenharmony_ci	return lockres_set_pending(lockres);
364562306a36Sopenharmony_ci}
364662306a36Sopenharmony_ci
364762306a36Sopenharmony_cistatic int ocfs2_downconvert_lock(struct ocfs2_super *osb,
364862306a36Sopenharmony_ci				  struct ocfs2_lock_res *lockres,
364962306a36Sopenharmony_ci				  int new_level,
365062306a36Sopenharmony_ci				  int lvb,
365162306a36Sopenharmony_ci				  unsigned int generation)
365262306a36Sopenharmony_ci{
365362306a36Sopenharmony_ci	int ret;
365462306a36Sopenharmony_ci	u32 dlm_flags = DLM_LKF_CONVERT;
365562306a36Sopenharmony_ci
365662306a36Sopenharmony_ci	mlog(ML_BASTS, "lockres %s, level %d => %d\n", lockres->l_name,
365762306a36Sopenharmony_ci	     lockres->l_level, new_level);
365862306a36Sopenharmony_ci
365962306a36Sopenharmony_ci	/*
366062306a36Sopenharmony_ci	 * On DLM_LKF_VALBLK, fsdlm behaves differently with o2cb. It always
366162306a36Sopenharmony_ci	 * expects DLM_LKF_VALBLK being set if the LKB has LVB, so that
366262306a36Sopenharmony_ci	 * we can recover correctly from node failure. Otherwise, we may get
366362306a36Sopenharmony_ci	 * invalid LVB in LKB, but without DLM_SBF_VALNOTVALID being set.
366462306a36Sopenharmony_ci	 */
366562306a36Sopenharmony_ci	if (ocfs2_userspace_stack(osb) &&
366662306a36Sopenharmony_ci	    lockres->l_ops->flags & LOCK_TYPE_USES_LVB)
366762306a36Sopenharmony_ci		lvb = 1;
366862306a36Sopenharmony_ci
366962306a36Sopenharmony_ci	if (lvb)
367062306a36Sopenharmony_ci		dlm_flags |= DLM_LKF_VALBLK;
367162306a36Sopenharmony_ci
367262306a36Sopenharmony_ci	ret = ocfs2_dlm_lock(osb->cconn,
367362306a36Sopenharmony_ci			     new_level,
367462306a36Sopenharmony_ci			     &lockres->l_lksb,
367562306a36Sopenharmony_ci			     dlm_flags,
367662306a36Sopenharmony_ci			     lockres->l_name,
367762306a36Sopenharmony_ci			     OCFS2_LOCK_ID_MAX_LEN - 1);
367862306a36Sopenharmony_ci	lockres_clear_pending(lockres, generation, osb);
367962306a36Sopenharmony_ci	if (ret) {
368062306a36Sopenharmony_ci		ocfs2_log_dlm_error("ocfs2_dlm_lock", ret, lockres);
368162306a36Sopenharmony_ci		ocfs2_recover_from_dlm_error(lockres, 1);
368262306a36Sopenharmony_ci		goto bail;
368362306a36Sopenharmony_ci	}
368462306a36Sopenharmony_ci
368562306a36Sopenharmony_ci	ret = 0;
368662306a36Sopenharmony_cibail:
368762306a36Sopenharmony_ci	return ret;
368862306a36Sopenharmony_ci}
368962306a36Sopenharmony_ci
369062306a36Sopenharmony_ci/* returns 1 when the caller should unlock and call ocfs2_dlm_unlock */
369162306a36Sopenharmony_cistatic int ocfs2_prepare_cancel_convert(struct ocfs2_super *osb,
369262306a36Sopenharmony_ci				        struct ocfs2_lock_res *lockres)
369362306a36Sopenharmony_ci{
369462306a36Sopenharmony_ci	assert_spin_locked(&lockres->l_lock);
369562306a36Sopenharmony_ci
369662306a36Sopenharmony_ci	if (lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) {
369762306a36Sopenharmony_ci		/* If we're already trying to cancel a lock conversion
369862306a36Sopenharmony_ci		 * then just drop the spinlock and allow the caller to
369962306a36Sopenharmony_ci		 * requeue this lock. */
370062306a36Sopenharmony_ci		mlog(ML_BASTS, "lockres %s, skip convert\n", lockres->l_name);
370162306a36Sopenharmony_ci		return 0;
370262306a36Sopenharmony_ci	}
370362306a36Sopenharmony_ci
370462306a36Sopenharmony_ci	/* were we in a convert when we got the bast fire? */
370562306a36Sopenharmony_ci	BUG_ON(lockres->l_action != OCFS2_AST_CONVERT &&
370662306a36Sopenharmony_ci	       lockres->l_action != OCFS2_AST_DOWNCONVERT);
370762306a36Sopenharmony_ci	/* set things up for the unlockast to know to just
370862306a36Sopenharmony_ci	 * clear out the ast_action and unset busy, etc. */
370962306a36Sopenharmony_ci	lockres->l_unlock_action = OCFS2_UNLOCK_CANCEL_CONVERT;
371062306a36Sopenharmony_ci
371162306a36Sopenharmony_ci	mlog_bug_on_msg(!(lockres->l_flags & OCFS2_LOCK_BUSY),
371262306a36Sopenharmony_ci			"lock %s, invalid flags: 0x%lx\n",
371362306a36Sopenharmony_ci			lockres->l_name, lockres->l_flags);
371462306a36Sopenharmony_ci
371562306a36Sopenharmony_ci	mlog(ML_BASTS, "lockres %s\n", lockres->l_name);
371662306a36Sopenharmony_ci
371762306a36Sopenharmony_ci	return 1;
371862306a36Sopenharmony_ci}
371962306a36Sopenharmony_ci
372062306a36Sopenharmony_cistatic int ocfs2_cancel_convert(struct ocfs2_super *osb,
372162306a36Sopenharmony_ci				struct ocfs2_lock_res *lockres)
372262306a36Sopenharmony_ci{
372362306a36Sopenharmony_ci	int ret;
372462306a36Sopenharmony_ci
372562306a36Sopenharmony_ci	ret = ocfs2_dlm_unlock(osb->cconn, &lockres->l_lksb,
372662306a36Sopenharmony_ci			       DLM_LKF_CANCEL);
372762306a36Sopenharmony_ci	if (ret) {
372862306a36Sopenharmony_ci		ocfs2_log_dlm_error("ocfs2_dlm_unlock", ret, lockres);
372962306a36Sopenharmony_ci		ocfs2_recover_from_dlm_error(lockres, 0);
373062306a36Sopenharmony_ci	}
373162306a36Sopenharmony_ci
373262306a36Sopenharmony_ci	mlog(ML_BASTS, "lockres %s\n", lockres->l_name);
373362306a36Sopenharmony_ci
373462306a36Sopenharmony_ci	return ret;
373562306a36Sopenharmony_ci}
373662306a36Sopenharmony_ci
373762306a36Sopenharmony_cistatic int ocfs2_unblock_lock(struct ocfs2_super *osb,
373862306a36Sopenharmony_ci			      struct ocfs2_lock_res *lockres,
373962306a36Sopenharmony_ci			      struct ocfs2_unblock_ctl *ctl)
374062306a36Sopenharmony_ci{
374162306a36Sopenharmony_ci	unsigned long flags;
374262306a36Sopenharmony_ci	int blocking;
374362306a36Sopenharmony_ci	int new_level;
374462306a36Sopenharmony_ci	int level;
374562306a36Sopenharmony_ci	int ret = 0;
374662306a36Sopenharmony_ci	int set_lvb = 0;
374762306a36Sopenharmony_ci	unsigned int gen;
374862306a36Sopenharmony_ci
374962306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
375062306a36Sopenharmony_ci
375162306a36Sopenharmony_cirecheck:
375262306a36Sopenharmony_ci	/*
375362306a36Sopenharmony_ci	 * Is it still blocking? If not, we have no more work to do.
375462306a36Sopenharmony_ci	 */
375562306a36Sopenharmony_ci	if (!(lockres->l_flags & OCFS2_LOCK_BLOCKED)) {
375662306a36Sopenharmony_ci		BUG_ON(lockres->l_blocking != DLM_LOCK_NL);
375762306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
375862306a36Sopenharmony_ci		ret = 0;
375962306a36Sopenharmony_ci		goto leave;
376062306a36Sopenharmony_ci	}
376162306a36Sopenharmony_ci
376262306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_BUSY) {
376362306a36Sopenharmony_ci		/* XXX
376462306a36Sopenharmony_ci		 * This is a *big* race.  The OCFS2_LOCK_PENDING flag
376562306a36Sopenharmony_ci		 * exists entirely for one reason - another thread has set
376662306a36Sopenharmony_ci		 * OCFS2_LOCK_BUSY, but has *NOT* yet called dlm_lock().
376762306a36Sopenharmony_ci		 *
376862306a36Sopenharmony_ci		 * If we do ocfs2_cancel_convert() before the other thread
376962306a36Sopenharmony_ci		 * calls dlm_lock(), our cancel will do nothing.  We will
377062306a36Sopenharmony_ci		 * get no ast, and we will have no way of knowing the
377162306a36Sopenharmony_ci		 * cancel failed.  Meanwhile, the other thread will call
377262306a36Sopenharmony_ci		 * into dlm_lock() and wait...forever.
377362306a36Sopenharmony_ci		 *
377462306a36Sopenharmony_ci		 * Why forever?  Because another node has asked for the
377562306a36Sopenharmony_ci		 * lock first; that's why we're here in unblock_lock().
377662306a36Sopenharmony_ci		 *
377762306a36Sopenharmony_ci		 * The solution is OCFS2_LOCK_PENDING.  When PENDING is
377862306a36Sopenharmony_ci		 * set, we just requeue the unblock.  Only when the other
377962306a36Sopenharmony_ci		 * thread has called dlm_lock() and cleared PENDING will
378062306a36Sopenharmony_ci		 * we then cancel their request.
378162306a36Sopenharmony_ci		 *
378262306a36Sopenharmony_ci		 * All callers of dlm_lock() must set OCFS2_DLM_PENDING
378362306a36Sopenharmony_ci		 * at the same time they set OCFS2_DLM_BUSY.  They must
378462306a36Sopenharmony_ci		 * clear OCFS2_DLM_PENDING after dlm_lock() returns.
378562306a36Sopenharmony_ci		 */
378662306a36Sopenharmony_ci		if (lockres->l_flags & OCFS2_LOCK_PENDING) {
378762306a36Sopenharmony_ci			mlog(ML_BASTS, "lockres %s, ReQ: Pending\n",
378862306a36Sopenharmony_ci			     lockres->l_name);
378962306a36Sopenharmony_ci			goto leave_requeue;
379062306a36Sopenharmony_ci		}
379162306a36Sopenharmony_ci
379262306a36Sopenharmony_ci		ctl->requeue = 1;
379362306a36Sopenharmony_ci		ret = ocfs2_prepare_cancel_convert(osb, lockres);
379462306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
379562306a36Sopenharmony_ci		if (ret) {
379662306a36Sopenharmony_ci			ret = ocfs2_cancel_convert(osb, lockres);
379762306a36Sopenharmony_ci			if (ret < 0)
379862306a36Sopenharmony_ci				mlog_errno(ret);
379962306a36Sopenharmony_ci		}
380062306a36Sopenharmony_ci		goto leave;
380162306a36Sopenharmony_ci	}
380262306a36Sopenharmony_ci
380362306a36Sopenharmony_ci	/*
380462306a36Sopenharmony_ci	 * This prevents livelocks. OCFS2_LOCK_UPCONVERT_FINISHING flag is
380562306a36Sopenharmony_ci	 * set when the ast is received for an upconvert just before the
380662306a36Sopenharmony_ci	 * OCFS2_LOCK_BUSY flag is cleared. Now if the fs received a bast
380762306a36Sopenharmony_ci	 * on the heels of the ast, we want to delay the downconvert just
380862306a36Sopenharmony_ci	 * enough to allow the up requestor to do its task. Because this
380962306a36Sopenharmony_ci	 * lock is in the blocked queue, the lock will be downconverted
381062306a36Sopenharmony_ci	 * as soon as the requestor is done with the lock.
381162306a36Sopenharmony_ci	 */
381262306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_UPCONVERT_FINISHING)
381362306a36Sopenharmony_ci		goto leave_requeue;
381462306a36Sopenharmony_ci
381562306a36Sopenharmony_ci	/*
381662306a36Sopenharmony_ci	 * How can we block and yet be at NL?  We were trying to upconvert
381762306a36Sopenharmony_ci	 * from NL and got canceled.  The code comes back here, and now
381862306a36Sopenharmony_ci	 * we notice and clear BLOCKING.
381962306a36Sopenharmony_ci	 */
382062306a36Sopenharmony_ci	if (lockres->l_level == DLM_LOCK_NL) {
382162306a36Sopenharmony_ci		BUG_ON(lockres->l_ex_holders || lockres->l_ro_holders);
382262306a36Sopenharmony_ci		mlog(ML_BASTS, "lockres %s, Aborting dc\n", lockres->l_name);
382362306a36Sopenharmony_ci		lockres->l_blocking = DLM_LOCK_NL;
382462306a36Sopenharmony_ci		lockres_clear_flags(lockres, OCFS2_LOCK_BLOCKED);
382562306a36Sopenharmony_ci		spin_unlock_irqrestore(&lockres->l_lock, flags);
382662306a36Sopenharmony_ci		goto leave;
382762306a36Sopenharmony_ci	}
382862306a36Sopenharmony_ci
382962306a36Sopenharmony_ci	/* if we're blocking an exclusive and we have *any* holders,
383062306a36Sopenharmony_ci	 * then requeue. */
383162306a36Sopenharmony_ci	if ((lockres->l_blocking == DLM_LOCK_EX)
383262306a36Sopenharmony_ci	    && (lockres->l_ex_holders || lockres->l_ro_holders)) {
383362306a36Sopenharmony_ci		mlog(ML_BASTS, "lockres %s, ReQ: EX/PR Holders %u,%u\n",
383462306a36Sopenharmony_ci		     lockres->l_name, lockres->l_ex_holders,
383562306a36Sopenharmony_ci		     lockres->l_ro_holders);
383662306a36Sopenharmony_ci		goto leave_requeue;
383762306a36Sopenharmony_ci	}
383862306a36Sopenharmony_ci
383962306a36Sopenharmony_ci	/* If it's a PR we're blocking, then only
384062306a36Sopenharmony_ci	 * requeue if we've got any EX holders */
384162306a36Sopenharmony_ci	if (lockres->l_blocking == DLM_LOCK_PR &&
384262306a36Sopenharmony_ci	    lockres->l_ex_holders) {
384362306a36Sopenharmony_ci		mlog(ML_BASTS, "lockres %s, ReQ: EX Holders %u\n",
384462306a36Sopenharmony_ci		     lockres->l_name, lockres->l_ex_holders);
384562306a36Sopenharmony_ci		goto leave_requeue;
384662306a36Sopenharmony_ci	}
384762306a36Sopenharmony_ci
384862306a36Sopenharmony_ci	/*
384962306a36Sopenharmony_ci	 * Can we get a lock in this state if the holder counts are
385062306a36Sopenharmony_ci	 * zero? The meta data unblock code used to check this.
385162306a36Sopenharmony_ci	 */
385262306a36Sopenharmony_ci	if ((lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH)
385362306a36Sopenharmony_ci	    && (lockres->l_flags & OCFS2_LOCK_REFRESHING)) {
385462306a36Sopenharmony_ci		mlog(ML_BASTS, "lockres %s, ReQ: Lock Refreshing\n",
385562306a36Sopenharmony_ci		     lockres->l_name);
385662306a36Sopenharmony_ci		goto leave_requeue;
385762306a36Sopenharmony_ci	}
385862306a36Sopenharmony_ci
385962306a36Sopenharmony_ci	new_level = ocfs2_highest_compat_lock_level(lockres->l_blocking);
386062306a36Sopenharmony_ci
386162306a36Sopenharmony_ci	if (lockres->l_ops->check_downconvert
386262306a36Sopenharmony_ci	    && !lockres->l_ops->check_downconvert(lockres, new_level)) {
386362306a36Sopenharmony_ci		mlog(ML_BASTS, "lockres %s, ReQ: Checkpointing\n",
386462306a36Sopenharmony_ci		     lockres->l_name);
386562306a36Sopenharmony_ci		goto leave_requeue;
386662306a36Sopenharmony_ci	}
386762306a36Sopenharmony_ci
386862306a36Sopenharmony_ci	/* If we get here, then we know that there are no more
386962306a36Sopenharmony_ci	 * incompatible holders (and anyone asking for an incompatible
387062306a36Sopenharmony_ci	 * lock is blocked). We can now downconvert the lock */
387162306a36Sopenharmony_ci	if (!lockres->l_ops->downconvert_worker)
387262306a36Sopenharmony_ci		goto downconvert;
387362306a36Sopenharmony_ci
387462306a36Sopenharmony_ci	/* Some lockres types want to do a bit of work before
387562306a36Sopenharmony_ci	 * downconverting a lock. Allow that here. The worker function
387662306a36Sopenharmony_ci	 * may sleep, so we save off a copy of what we're blocking as
387762306a36Sopenharmony_ci	 * it may change while we're not holding the spin lock. */
387862306a36Sopenharmony_ci	blocking = lockres->l_blocking;
387962306a36Sopenharmony_ci	level = lockres->l_level;
388062306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
388162306a36Sopenharmony_ci
388262306a36Sopenharmony_ci	ctl->unblock_action = lockres->l_ops->downconvert_worker(lockres, blocking);
388362306a36Sopenharmony_ci
388462306a36Sopenharmony_ci	if (ctl->unblock_action == UNBLOCK_STOP_POST) {
388562306a36Sopenharmony_ci		mlog(ML_BASTS, "lockres %s, UNBLOCK_STOP_POST\n",
388662306a36Sopenharmony_ci		     lockres->l_name);
388762306a36Sopenharmony_ci		goto leave;
388862306a36Sopenharmony_ci	}
388962306a36Sopenharmony_ci
389062306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
389162306a36Sopenharmony_ci	if ((blocking != lockres->l_blocking) || (level != lockres->l_level)) {
389262306a36Sopenharmony_ci		/* If this changed underneath us, then we can't drop
389362306a36Sopenharmony_ci		 * it just yet. */
389462306a36Sopenharmony_ci		mlog(ML_BASTS, "lockres %s, block=%d:%d, level=%d:%d, "
389562306a36Sopenharmony_ci		     "Recheck\n", lockres->l_name, blocking,
389662306a36Sopenharmony_ci		     lockres->l_blocking, level, lockres->l_level);
389762306a36Sopenharmony_ci		goto recheck;
389862306a36Sopenharmony_ci	}
389962306a36Sopenharmony_ci
390062306a36Sopenharmony_cidownconvert:
390162306a36Sopenharmony_ci	ctl->requeue = 0;
390262306a36Sopenharmony_ci
390362306a36Sopenharmony_ci	if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB) {
390462306a36Sopenharmony_ci		if (lockres->l_level == DLM_LOCK_EX)
390562306a36Sopenharmony_ci			set_lvb = 1;
390662306a36Sopenharmony_ci
390762306a36Sopenharmony_ci		/*
390862306a36Sopenharmony_ci		 * We only set the lvb if the lock has been fully
390962306a36Sopenharmony_ci		 * refreshed - otherwise we risk setting stale
391062306a36Sopenharmony_ci		 * data. Otherwise, there's no need to actually clear
391162306a36Sopenharmony_ci		 * out the lvb here as it's value is still valid.
391262306a36Sopenharmony_ci		 */
391362306a36Sopenharmony_ci		if (set_lvb && !(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH))
391462306a36Sopenharmony_ci			lockres->l_ops->set_lvb(lockres);
391562306a36Sopenharmony_ci	}
391662306a36Sopenharmony_ci
391762306a36Sopenharmony_ci	gen = ocfs2_prepare_downconvert(lockres, new_level);
391862306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
391962306a36Sopenharmony_ci	ret = ocfs2_downconvert_lock(osb, lockres, new_level, set_lvb,
392062306a36Sopenharmony_ci				     gen);
392162306a36Sopenharmony_ci	/* The dlm lock convert is being cancelled in background,
392262306a36Sopenharmony_ci	 * ocfs2_cancel_convert() is asynchronous in fs/dlm,
392362306a36Sopenharmony_ci	 * requeue it, try again later.
392462306a36Sopenharmony_ci	 */
392562306a36Sopenharmony_ci	if (ret == -EBUSY) {
392662306a36Sopenharmony_ci		ctl->requeue = 1;
392762306a36Sopenharmony_ci		mlog(ML_BASTS, "lockres %s, ReQ: Downconvert busy\n",
392862306a36Sopenharmony_ci		     lockres->l_name);
392962306a36Sopenharmony_ci		ret = 0;
393062306a36Sopenharmony_ci		msleep(20);
393162306a36Sopenharmony_ci	}
393262306a36Sopenharmony_ci
393362306a36Sopenharmony_cileave:
393462306a36Sopenharmony_ci	if (ret)
393562306a36Sopenharmony_ci		mlog_errno(ret);
393662306a36Sopenharmony_ci	return ret;
393762306a36Sopenharmony_ci
393862306a36Sopenharmony_cileave_requeue:
393962306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
394062306a36Sopenharmony_ci	ctl->requeue = 1;
394162306a36Sopenharmony_ci
394262306a36Sopenharmony_ci	return 0;
394362306a36Sopenharmony_ci}
394462306a36Sopenharmony_ci
394562306a36Sopenharmony_cistatic int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres,
394662306a36Sopenharmony_ci				     int blocking)
394762306a36Sopenharmony_ci{
394862306a36Sopenharmony_ci	struct inode *inode;
394962306a36Sopenharmony_ci	struct address_space *mapping;
395062306a36Sopenharmony_ci	struct ocfs2_inode_info *oi;
395162306a36Sopenharmony_ci
395262306a36Sopenharmony_ci       	inode = ocfs2_lock_res_inode(lockres);
395362306a36Sopenharmony_ci	mapping = inode->i_mapping;
395462306a36Sopenharmony_ci
395562306a36Sopenharmony_ci	if (S_ISDIR(inode->i_mode)) {
395662306a36Sopenharmony_ci		oi = OCFS2_I(inode);
395762306a36Sopenharmony_ci		oi->ip_dir_lock_gen++;
395862306a36Sopenharmony_ci		mlog(0, "generation: %u\n", oi->ip_dir_lock_gen);
395962306a36Sopenharmony_ci		goto out_forget;
396062306a36Sopenharmony_ci	}
396162306a36Sopenharmony_ci
396262306a36Sopenharmony_ci	if (!S_ISREG(inode->i_mode))
396362306a36Sopenharmony_ci		goto out;
396462306a36Sopenharmony_ci
396562306a36Sopenharmony_ci	/*
396662306a36Sopenharmony_ci	 * We need this before the filemap_fdatawrite() so that it can
396762306a36Sopenharmony_ci	 * transfer the dirty bit from the PTE to the
396862306a36Sopenharmony_ci	 * page. Unfortunately this means that even for EX->PR
396962306a36Sopenharmony_ci	 * downconverts, we'll lose our mappings and have to build
397062306a36Sopenharmony_ci	 * them up again.
397162306a36Sopenharmony_ci	 */
397262306a36Sopenharmony_ci	unmap_mapping_range(mapping, 0, 0, 0);
397362306a36Sopenharmony_ci
397462306a36Sopenharmony_ci	if (filemap_fdatawrite(mapping)) {
397562306a36Sopenharmony_ci		mlog(ML_ERROR, "Could not sync inode %llu for downconvert!",
397662306a36Sopenharmony_ci		     (unsigned long long)OCFS2_I(inode)->ip_blkno);
397762306a36Sopenharmony_ci	}
397862306a36Sopenharmony_ci	sync_mapping_buffers(mapping);
397962306a36Sopenharmony_ci	if (blocking == DLM_LOCK_EX) {
398062306a36Sopenharmony_ci		truncate_inode_pages(mapping, 0);
398162306a36Sopenharmony_ci	} else {
398262306a36Sopenharmony_ci		/* We only need to wait on the I/O if we're not also
398362306a36Sopenharmony_ci		 * truncating pages because truncate_inode_pages waits
398462306a36Sopenharmony_ci		 * for us above. We don't truncate pages if we're
398562306a36Sopenharmony_ci		 * blocking anything < EXMODE because we want to keep
398662306a36Sopenharmony_ci		 * them around in that case. */
398762306a36Sopenharmony_ci		filemap_fdatawait(mapping);
398862306a36Sopenharmony_ci	}
398962306a36Sopenharmony_ci
399062306a36Sopenharmony_ciout_forget:
399162306a36Sopenharmony_ci	forget_all_cached_acls(inode);
399262306a36Sopenharmony_ci
399362306a36Sopenharmony_ciout:
399462306a36Sopenharmony_ci	return UNBLOCK_CONTINUE;
399562306a36Sopenharmony_ci}
399662306a36Sopenharmony_ci
399762306a36Sopenharmony_cistatic int ocfs2_ci_checkpointed(struct ocfs2_caching_info *ci,
399862306a36Sopenharmony_ci				 struct ocfs2_lock_res *lockres,
399962306a36Sopenharmony_ci				 int new_level)
400062306a36Sopenharmony_ci{
400162306a36Sopenharmony_ci	int checkpointed = ocfs2_ci_fully_checkpointed(ci);
400262306a36Sopenharmony_ci
400362306a36Sopenharmony_ci	BUG_ON(new_level != DLM_LOCK_NL && new_level != DLM_LOCK_PR);
400462306a36Sopenharmony_ci	BUG_ON(lockres->l_level != DLM_LOCK_EX && !checkpointed);
400562306a36Sopenharmony_ci
400662306a36Sopenharmony_ci	if (checkpointed)
400762306a36Sopenharmony_ci		return 1;
400862306a36Sopenharmony_ci
400962306a36Sopenharmony_ci	ocfs2_start_checkpoint(OCFS2_SB(ocfs2_metadata_cache_get_super(ci)));
401062306a36Sopenharmony_ci	return 0;
401162306a36Sopenharmony_ci}
401262306a36Sopenharmony_ci
401362306a36Sopenharmony_cistatic int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres,
401462306a36Sopenharmony_ci					int new_level)
401562306a36Sopenharmony_ci{
401662306a36Sopenharmony_ci	struct inode *inode = ocfs2_lock_res_inode(lockres);
401762306a36Sopenharmony_ci
401862306a36Sopenharmony_ci	return ocfs2_ci_checkpointed(INODE_CACHE(inode), lockres, new_level);
401962306a36Sopenharmony_ci}
402062306a36Sopenharmony_ci
402162306a36Sopenharmony_cistatic void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres)
402262306a36Sopenharmony_ci{
402362306a36Sopenharmony_ci	struct inode *inode = ocfs2_lock_res_inode(lockres);
402462306a36Sopenharmony_ci
402562306a36Sopenharmony_ci	__ocfs2_stuff_meta_lvb(inode);
402662306a36Sopenharmony_ci}
402762306a36Sopenharmony_ci
402862306a36Sopenharmony_ci/*
402962306a36Sopenharmony_ci * Does the final reference drop on our dentry lock. Right now this
403062306a36Sopenharmony_ci * happens in the downconvert thread, but we could choose to simplify the
403162306a36Sopenharmony_ci * dlmglue API and push these off to the ocfs2_wq in the future.
403262306a36Sopenharmony_ci */
403362306a36Sopenharmony_cistatic void ocfs2_dentry_post_unlock(struct ocfs2_super *osb,
403462306a36Sopenharmony_ci				     struct ocfs2_lock_res *lockres)
403562306a36Sopenharmony_ci{
403662306a36Sopenharmony_ci	struct ocfs2_dentry_lock *dl = ocfs2_lock_res_dl(lockres);
403762306a36Sopenharmony_ci	ocfs2_dentry_lock_put(osb, dl);
403862306a36Sopenharmony_ci}
403962306a36Sopenharmony_ci
404062306a36Sopenharmony_ci/*
404162306a36Sopenharmony_ci * d_delete() matching dentries before the lock downconvert.
404262306a36Sopenharmony_ci *
404362306a36Sopenharmony_ci * At this point, any process waiting to destroy the
404462306a36Sopenharmony_ci * dentry_lock due to last ref count is stopped by the
404562306a36Sopenharmony_ci * OCFS2_LOCK_QUEUED flag.
404662306a36Sopenharmony_ci *
404762306a36Sopenharmony_ci * We have two potential problems
404862306a36Sopenharmony_ci *
404962306a36Sopenharmony_ci * 1) If we do the last reference drop on our dentry_lock (via dput)
405062306a36Sopenharmony_ci *    we'll wind up in ocfs2_release_dentry_lock(), waiting on
405162306a36Sopenharmony_ci *    the downconvert to finish. Instead we take an elevated
405262306a36Sopenharmony_ci *    reference and push the drop until after we've completed our
405362306a36Sopenharmony_ci *    unblock processing.
405462306a36Sopenharmony_ci *
405562306a36Sopenharmony_ci * 2) There might be another process with a final reference,
405662306a36Sopenharmony_ci *    waiting on us to finish processing. If this is the case, we
405762306a36Sopenharmony_ci *    detect it and exit out - there's no more dentries anyway.
405862306a36Sopenharmony_ci */
405962306a36Sopenharmony_cistatic int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
406062306a36Sopenharmony_ci				       int blocking)
406162306a36Sopenharmony_ci{
406262306a36Sopenharmony_ci	struct ocfs2_dentry_lock *dl = ocfs2_lock_res_dl(lockres);
406362306a36Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(dl->dl_inode);
406462306a36Sopenharmony_ci	struct dentry *dentry;
406562306a36Sopenharmony_ci	unsigned long flags;
406662306a36Sopenharmony_ci	int extra_ref = 0;
406762306a36Sopenharmony_ci
406862306a36Sopenharmony_ci	/*
406962306a36Sopenharmony_ci	 * This node is blocking another node from getting a read
407062306a36Sopenharmony_ci	 * lock. This happens when we've renamed within a
407162306a36Sopenharmony_ci	 * directory. We've forced the other nodes to d_delete(), but
407262306a36Sopenharmony_ci	 * we never actually dropped our lock because it's still
407362306a36Sopenharmony_ci	 * valid. The downconvert code will retain a PR for this node,
407462306a36Sopenharmony_ci	 * so there's no further work to do.
407562306a36Sopenharmony_ci	 */
407662306a36Sopenharmony_ci	if (blocking == DLM_LOCK_PR)
407762306a36Sopenharmony_ci		return UNBLOCK_CONTINUE;
407862306a36Sopenharmony_ci
407962306a36Sopenharmony_ci	/*
408062306a36Sopenharmony_ci	 * Mark this inode as potentially orphaned. The code in
408162306a36Sopenharmony_ci	 * ocfs2_delete_inode() will figure out whether it actually
408262306a36Sopenharmony_ci	 * needs to be freed or not.
408362306a36Sopenharmony_ci	 */
408462306a36Sopenharmony_ci	spin_lock(&oi->ip_lock);
408562306a36Sopenharmony_ci	oi->ip_flags |= OCFS2_INODE_MAYBE_ORPHANED;
408662306a36Sopenharmony_ci	spin_unlock(&oi->ip_lock);
408762306a36Sopenharmony_ci
408862306a36Sopenharmony_ci	/*
408962306a36Sopenharmony_ci	 * Yuck. We need to make sure however that the check of
409062306a36Sopenharmony_ci	 * OCFS2_LOCK_FREEING and the extra reference are atomic with
409162306a36Sopenharmony_ci	 * respect to a reference decrement or the setting of that
409262306a36Sopenharmony_ci	 * flag.
409362306a36Sopenharmony_ci	 */
409462306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
409562306a36Sopenharmony_ci	spin_lock(&dentry_attach_lock);
409662306a36Sopenharmony_ci	if (!(lockres->l_flags & OCFS2_LOCK_FREEING)
409762306a36Sopenharmony_ci	    && dl->dl_count) {
409862306a36Sopenharmony_ci		dl->dl_count++;
409962306a36Sopenharmony_ci		extra_ref = 1;
410062306a36Sopenharmony_ci	}
410162306a36Sopenharmony_ci	spin_unlock(&dentry_attach_lock);
410262306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
410362306a36Sopenharmony_ci
410462306a36Sopenharmony_ci	mlog(0, "extra_ref = %d\n", extra_ref);
410562306a36Sopenharmony_ci
410662306a36Sopenharmony_ci	/*
410762306a36Sopenharmony_ci	 * We have a process waiting on us in ocfs2_dentry_iput(),
410862306a36Sopenharmony_ci	 * which means we can't have any more outstanding
410962306a36Sopenharmony_ci	 * aliases. There's no need to do any more work.
411062306a36Sopenharmony_ci	 */
411162306a36Sopenharmony_ci	if (!extra_ref)
411262306a36Sopenharmony_ci		return UNBLOCK_CONTINUE;
411362306a36Sopenharmony_ci
411462306a36Sopenharmony_ci	spin_lock(&dentry_attach_lock);
411562306a36Sopenharmony_ci	while (1) {
411662306a36Sopenharmony_ci		dentry = ocfs2_find_local_alias(dl->dl_inode,
411762306a36Sopenharmony_ci						dl->dl_parent_blkno, 1);
411862306a36Sopenharmony_ci		if (!dentry)
411962306a36Sopenharmony_ci			break;
412062306a36Sopenharmony_ci		spin_unlock(&dentry_attach_lock);
412162306a36Sopenharmony_ci
412262306a36Sopenharmony_ci		if (S_ISDIR(dl->dl_inode->i_mode))
412362306a36Sopenharmony_ci			shrink_dcache_parent(dentry);
412462306a36Sopenharmony_ci
412562306a36Sopenharmony_ci		mlog(0, "d_delete(%pd);\n", dentry);
412662306a36Sopenharmony_ci
412762306a36Sopenharmony_ci		/*
412862306a36Sopenharmony_ci		 * The following dcache calls may do an
412962306a36Sopenharmony_ci		 * iput(). Normally we don't want that from the
413062306a36Sopenharmony_ci		 * downconverting thread, but in this case it's ok
413162306a36Sopenharmony_ci		 * because the requesting node already has an
413262306a36Sopenharmony_ci		 * exclusive lock on the inode, so it can't be queued
413362306a36Sopenharmony_ci		 * for a downconvert.
413462306a36Sopenharmony_ci		 */
413562306a36Sopenharmony_ci		d_delete(dentry);
413662306a36Sopenharmony_ci		dput(dentry);
413762306a36Sopenharmony_ci
413862306a36Sopenharmony_ci		spin_lock(&dentry_attach_lock);
413962306a36Sopenharmony_ci	}
414062306a36Sopenharmony_ci	spin_unlock(&dentry_attach_lock);
414162306a36Sopenharmony_ci
414262306a36Sopenharmony_ci	/*
414362306a36Sopenharmony_ci	 * If we are the last holder of this dentry lock, there is no
414462306a36Sopenharmony_ci	 * reason to downconvert so skip straight to the unlock.
414562306a36Sopenharmony_ci	 */
414662306a36Sopenharmony_ci	if (dl->dl_count == 1)
414762306a36Sopenharmony_ci		return UNBLOCK_STOP_POST;
414862306a36Sopenharmony_ci
414962306a36Sopenharmony_ci	return UNBLOCK_CONTINUE_POST;
415062306a36Sopenharmony_ci}
415162306a36Sopenharmony_ci
415262306a36Sopenharmony_cistatic int ocfs2_check_refcount_downconvert(struct ocfs2_lock_res *lockres,
415362306a36Sopenharmony_ci					    int new_level)
415462306a36Sopenharmony_ci{
415562306a36Sopenharmony_ci	struct ocfs2_refcount_tree *tree =
415662306a36Sopenharmony_ci				ocfs2_lock_res_refcount_tree(lockres);
415762306a36Sopenharmony_ci
415862306a36Sopenharmony_ci	return ocfs2_ci_checkpointed(&tree->rf_ci, lockres, new_level);
415962306a36Sopenharmony_ci}
416062306a36Sopenharmony_ci
416162306a36Sopenharmony_cistatic int ocfs2_refcount_convert_worker(struct ocfs2_lock_res *lockres,
416262306a36Sopenharmony_ci					 int blocking)
416362306a36Sopenharmony_ci{
416462306a36Sopenharmony_ci	struct ocfs2_refcount_tree *tree =
416562306a36Sopenharmony_ci				ocfs2_lock_res_refcount_tree(lockres);
416662306a36Sopenharmony_ci
416762306a36Sopenharmony_ci	ocfs2_metadata_cache_purge(&tree->rf_ci);
416862306a36Sopenharmony_ci
416962306a36Sopenharmony_ci	return UNBLOCK_CONTINUE;
417062306a36Sopenharmony_ci}
417162306a36Sopenharmony_ci
417262306a36Sopenharmony_cistatic void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres)
417362306a36Sopenharmony_ci{
417462306a36Sopenharmony_ci	struct ocfs2_qinfo_lvb *lvb;
417562306a36Sopenharmony_ci	struct ocfs2_mem_dqinfo *oinfo = ocfs2_lock_res_qinfo(lockres);
417662306a36Sopenharmony_ci	struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb,
417762306a36Sopenharmony_ci					    oinfo->dqi_gi.dqi_type);
417862306a36Sopenharmony_ci
417962306a36Sopenharmony_ci	lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
418062306a36Sopenharmony_ci	lvb->lvb_version = OCFS2_QINFO_LVB_VERSION;
418162306a36Sopenharmony_ci	lvb->lvb_bgrace = cpu_to_be32(info->dqi_bgrace);
418262306a36Sopenharmony_ci	lvb->lvb_igrace = cpu_to_be32(info->dqi_igrace);
418362306a36Sopenharmony_ci	lvb->lvb_syncms = cpu_to_be32(oinfo->dqi_syncms);
418462306a36Sopenharmony_ci	lvb->lvb_blocks = cpu_to_be32(oinfo->dqi_gi.dqi_blocks);
418562306a36Sopenharmony_ci	lvb->lvb_free_blk = cpu_to_be32(oinfo->dqi_gi.dqi_free_blk);
418662306a36Sopenharmony_ci	lvb->lvb_free_entry = cpu_to_be32(oinfo->dqi_gi.dqi_free_entry);
418762306a36Sopenharmony_ci}
418862306a36Sopenharmony_ci
418962306a36Sopenharmony_civoid ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex)
419062306a36Sopenharmony_ci{
419162306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
419262306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb);
419362306a36Sopenharmony_ci	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
419462306a36Sopenharmony_ci
419562306a36Sopenharmony_ci	if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb))
419662306a36Sopenharmony_ci		ocfs2_cluster_unlock(osb, lockres, level);
419762306a36Sopenharmony_ci}
419862306a36Sopenharmony_ci
419962306a36Sopenharmony_cistatic int ocfs2_refresh_qinfo(struct ocfs2_mem_dqinfo *oinfo)
420062306a36Sopenharmony_ci{
420162306a36Sopenharmony_ci	struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb,
420262306a36Sopenharmony_ci					    oinfo->dqi_gi.dqi_type);
420362306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
420462306a36Sopenharmony_ci	struct ocfs2_qinfo_lvb *lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
420562306a36Sopenharmony_ci	struct buffer_head *bh = NULL;
420662306a36Sopenharmony_ci	struct ocfs2_global_disk_dqinfo *gdinfo;
420762306a36Sopenharmony_ci	int status = 0;
420862306a36Sopenharmony_ci
420962306a36Sopenharmony_ci	if (ocfs2_dlm_lvb_valid(&lockres->l_lksb) &&
421062306a36Sopenharmony_ci	    lvb->lvb_version == OCFS2_QINFO_LVB_VERSION) {
421162306a36Sopenharmony_ci		info->dqi_bgrace = be32_to_cpu(lvb->lvb_bgrace);
421262306a36Sopenharmony_ci		info->dqi_igrace = be32_to_cpu(lvb->lvb_igrace);
421362306a36Sopenharmony_ci		oinfo->dqi_syncms = be32_to_cpu(lvb->lvb_syncms);
421462306a36Sopenharmony_ci		oinfo->dqi_gi.dqi_blocks = be32_to_cpu(lvb->lvb_blocks);
421562306a36Sopenharmony_ci		oinfo->dqi_gi.dqi_free_blk = be32_to_cpu(lvb->lvb_free_blk);
421662306a36Sopenharmony_ci		oinfo->dqi_gi.dqi_free_entry =
421762306a36Sopenharmony_ci					be32_to_cpu(lvb->lvb_free_entry);
421862306a36Sopenharmony_ci	} else {
421962306a36Sopenharmony_ci		status = ocfs2_read_quota_phys_block(oinfo->dqi_gqinode,
422062306a36Sopenharmony_ci						     oinfo->dqi_giblk, &bh);
422162306a36Sopenharmony_ci		if (status) {
422262306a36Sopenharmony_ci			mlog_errno(status);
422362306a36Sopenharmony_ci			goto bail;
422462306a36Sopenharmony_ci		}
422562306a36Sopenharmony_ci		gdinfo = (struct ocfs2_global_disk_dqinfo *)
422662306a36Sopenharmony_ci					(bh->b_data + OCFS2_GLOBAL_INFO_OFF);
422762306a36Sopenharmony_ci		info->dqi_bgrace = le32_to_cpu(gdinfo->dqi_bgrace);
422862306a36Sopenharmony_ci		info->dqi_igrace = le32_to_cpu(gdinfo->dqi_igrace);
422962306a36Sopenharmony_ci		oinfo->dqi_syncms = le32_to_cpu(gdinfo->dqi_syncms);
423062306a36Sopenharmony_ci		oinfo->dqi_gi.dqi_blocks = le32_to_cpu(gdinfo->dqi_blocks);
423162306a36Sopenharmony_ci		oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(gdinfo->dqi_free_blk);
423262306a36Sopenharmony_ci		oinfo->dqi_gi.dqi_free_entry =
423362306a36Sopenharmony_ci					le32_to_cpu(gdinfo->dqi_free_entry);
423462306a36Sopenharmony_ci		brelse(bh);
423562306a36Sopenharmony_ci		ocfs2_track_lock_refresh(lockres);
423662306a36Sopenharmony_ci	}
423762306a36Sopenharmony_ci
423862306a36Sopenharmony_cibail:
423962306a36Sopenharmony_ci	return status;
424062306a36Sopenharmony_ci}
424162306a36Sopenharmony_ci
424262306a36Sopenharmony_ci/* Lock quota info, this function expects at least shared lock on the quota file
424362306a36Sopenharmony_ci * so that we can safely refresh quota info from disk. */
424462306a36Sopenharmony_ciint ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex)
424562306a36Sopenharmony_ci{
424662306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
424762306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb);
424862306a36Sopenharmony_ci	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
424962306a36Sopenharmony_ci	int status = 0;
425062306a36Sopenharmony_ci
425162306a36Sopenharmony_ci	/* On RO devices, locking really isn't needed... */
425262306a36Sopenharmony_ci	if (ocfs2_is_hard_readonly(osb)) {
425362306a36Sopenharmony_ci		if (ex)
425462306a36Sopenharmony_ci			status = -EROFS;
425562306a36Sopenharmony_ci		goto bail;
425662306a36Sopenharmony_ci	}
425762306a36Sopenharmony_ci	if (ocfs2_mount_local(osb))
425862306a36Sopenharmony_ci		goto bail;
425962306a36Sopenharmony_ci
426062306a36Sopenharmony_ci	status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
426162306a36Sopenharmony_ci	if (status < 0) {
426262306a36Sopenharmony_ci		mlog_errno(status);
426362306a36Sopenharmony_ci		goto bail;
426462306a36Sopenharmony_ci	}
426562306a36Sopenharmony_ci	if (!ocfs2_should_refresh_lock_res(lockres))
426662306a36Sopenharmony_ci		goto bail;
426762306a36Sopenharmony_ci	/* OK, we have the lock but we need to refresh the quota info */
426862306a36Sopenharmony_ci	status = ocfs2_refresh_qinfo(oinfo);
426962306a36Sopenharmony_ci	if (status)
427062306a36Sopenharmony_ci		ocfs2_qinfo_unlock(oinfo, ex);
427162306a36Sopenharmony_ci	ocfs2_complete_lock_res_refresh(lockres, status);
427262306a36Sopenharmony_cibail:
427362306a36Sopenharmony_ci	return status;
427462306a36Sopenharmony_ci}
427562306a36Sopenharmony_ci
427662306a36Sopenharmony_ciint ocfs2_refcount_lock(struct ocfs2_refcount_tree *ref_tree, int ex)
427762306a36Sopenharmony_ci{
427862306a36Sopenharmony_ci	int status;
427962306a36Sopenharmony_ci	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
428062306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &ref_tree->rf_lockres;
428162306a36Sopenharmony_ci	struct ocfs2_super *osb = lockres->l_priv;
428262306a36Sopenharmony_ci
428362306a36Sopenharmony_ci
428462306a36Sopenharmony_ci	if (ocfs2_is_hard_readonly(osb))
428562306a36Sopenharmony_ci		return -EROFS;
428662306a36Sopenharmony_ci
428762306a36Sopenharmony_ci	if (ocfs2_mount_local(osb))
428862306a36Sopenharmony_ci		return 0;
428962306a36Sopenharmony_ci
429062306a36Sopenharmony_ci	status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
429162306a36Sopenharmony_ci	if (status < 0)
429262306a36Sopenharmony_ci		mlog_errno(status);
429362306a36Sopenharmony_ci
429462306a36Sopenharmony_ci	return status;
429562306a36Sopenharmony_ci}
429662306a36Sopenharmony_ci
429762306a36Sopenharmony_civoid ocfs2_refcount_unlock(struct ocfs2_refcount_tree *ref_tree, int ex)
429862306a36Sopenharmony_ci{
429962306a36Sopenharmony_ci	int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
430062306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres = &ref_tree->rf_lockres;
430162306a36Sopenharmony_ci	struct ocfs2_super *osb = lockres->l_priv;
430262306a36Sopenharmony_ci
430362306a36Sopenharmony_ci	if (!ocfs2_mount_local(osb))
430462306a36Sopenharmony_ci		ocfs2_cluster_unlock(osb, lockres, level);
430562306a36Sopenharmony_ci}
430662306a36Sopenharmony_ci
430762306a36Sopenharmony_cistatic void ocfs2_process_blocked_lock(struct ocfs2_super *osb,
430862306a36Sopenharmony_ci				       struct ocfs2_lock_res *lockres)
430962306a36Sopenharmony_ci{
431062306a36Sopenharmony_ci	int status;
431162306a36Sopenharmony_ci	struct ocfs2_unblock_ctl ctl = {0, 0,};
431262306a36Sopenharmony_ci	unsigned long flags;
431362306a36Sopenharmony_ci
431462306a36Sopenharmony_ci	/* Our reference to the lockres in this function can be
431562306a36Sopenharmony_ci	 * considered valid until we remove the OCFS2_LOCK_QUEUED
431662306a36Sopenharmony_ci	 * flag. */
431762306a36Sopenharmony_ci
431862306a36Sopenharmony_ci	BUG_ON(!lockres);
431962306a36Sopenharmony_ci	BUG_ON(!lockres->l_ops);
432062306a36Sopenharmony_ci
432162306a36Sopenharmony_ci	mlog(ML_BASTS, "lockres %s blocked\n", lockres->l_name);
432262306a36Sopenharmony_ci
432362306a36Sopenharmony_ci	/* Detect whether a lock has been marked as going away while
432462306a36Sopenharmony_ci	 * the downconvert thread was processing other things. A lock can
432562306a36Sopenharmony_ci	 * still be marked with OCFS2_LOCK_FREEING after this check,
432662306a36Sopenharmony_ci	 * but short circuiting here will still save us some
432762306a36Sopenharmony_ci	 * performance. */
432862306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
432962306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_FREEING)
433062306a36Sopenharmony_ci		goto unqueue;
433162306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
433262306a36Sopenharmony_ci
433362306a36Sopenharmony_ci	status = ocfs2_unblock_lock(osb, lockres, &ctl);
433462306a36Sopenharmony_ci	if (status < 0)
433562306a36Sopenharmony_ci		mlog_errno(status);
433662306a36Sopenharmony_ci
433762306a36Sopenharmony_ci	spin_lock_irqsave(&lockres->l_lock, flags);
433862306a36Sopenharmony_ciunqueue:
433962306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_FREEING || !ctl.requeue) {
434062306a36Sopenharmony_ci		lockres_clear_flags(lockres, OCFS2_LOCK_QUEUED);
434162306a36Sopenharmony_ci	} else
434262306a36Sopenharmony_ci		ocfs2_schedule_blocked_lock(osb, lockres);
434362306a36Sopenharmony_ci
434462306a36Sopenharmony_ci	mlog(ML_BASTS, "lockres %s, requeue = %s.\n", lockres->l_name,
434562306a36Sopenharmony_ci	     ctl.requeue ? "yes" : "no");
434662306a36Sopenharmony_ci	spin_unlock_irqrestore(&lockres->l_lock, flags);
434762306a36Sopenharmony_ci
434862306a36Sopenharmony_ci	if (ctl.unblock_action != UNBLOCK_CONTINUE
434962306a36Sopenharmony_ci	    && lockres->l_ops->post_unlock)
435062306a36Sopenharmony_ci		lockres->l_ops->post_unlock(osb, lockres);
435162306a36Sopenharmony_ci}
435262306a36Sopenharmony_ci
435362306a36Sopenharmony_cistatic void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb,
435462306a36Sopenharmony_ci					struct ocfs2_lock_res *lockres)
435562306a36Sopenharmony_ci{
435662306a36Sopenharmony_ci	unsigned long flags;
435762306a36Sopenharmony_ci
435862306a36Sopenharmony_ci	assert_spin_locked(&lockres->l_lock);
435962306a36Sopenharmony_ci
436062306a36Sopenharmony_ci	if (lockres->l_flags & OCFS2_LOCK_FREEING) {
436162306a36Sopenharmony_ci		/* Do not schedule a lock for downconvert when it's on
436262306a36Sopenharmony_ci		 * the way to destruction - any nodes wanting access
436362306a36Sopenharmony_ci		 * to the resource will get it soon. */
436462306a36Sopenharmony_ci		mlog(ML_BASTS, "lockres %s won't be scheduled: flags 0x%lx\n",
436562306a36Sopenharmony_ci		     lockres->l_name, lockres->l_flags);
436662306a36Sopenharmony_ci		return;
436762306a36Sopenharmony_ci	}
436862306a36Sopenharmony_ci
436962306a36Sopenharmony_ci	lockres_or_flags(lockres, OCFS2_LOCK_QUEUED);
437062306a36Sopenharmony_ci
437162306a36Sopenharmony_ci	spin_lock_irqsave(&osb->dc_task_lock, flags);
437262306a36Sopenharmony_ci	if (list_empty(&lockres->l_blocked_list)) {
437362306a36Sopenharmony_ci		list_add_tail(&lockres->l_blocked_list,
437462306a36Sopenharmony_ci			      &osb->blocked_lock_list);
437562306a36Sopenharmony_ci		osb->blocked_lock_count++;
437662306a36Sopenharmony_ci	}
437762306a36Sopenharmony_ci	spin_unlock_irqrestore(&osb->dc_task_lock, flags);
437862306a36Sopenharmony_ci}
437962306a36Sopenharmony_ci
438062306a36Sopenharmony_cistatic void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb)
438162306a36Sopenharmony_ci{
438262306a36Sopenharmony_ci	unsigned long processed;
438362306a36Sopenharmony_ci	unsigned long flags;
438462306a36Sopenharmony_ci	struct ocfs2_lock_res *lockres;
438562306a36Sopenharmony_ci
438662306a36Sopenharmony_ci	spin_lock_irqsave(&osb->dc_task_lock, flags);
438762306a36Sopenharmony_ci	/* grab this early so we know to try again if a state change and
438862306a36Sopenharmony_ci	 * wake happens part-way through our work  */
438962306a36Sopenharmony_ci	osb->dc_work_sequence = osb->dc_wake_sequence;
439062306a36Sopenharmony_ci
439162306a36Sopenharmony_ci	processed = osb->blocked_lock_count;
439262306a36Sopenharmony_ci	/*
439362306a36Sopenharmony_ci	 * blocked lock processing in this loop might call iput which can
439462306a36Sopenharmony_ci	 * remove items off osb->blocked_lock_list. Downconvert up to
439562306a36Sopenharmony_ci	 * 'processed' number of locks, but stop short if we had some
439662306a36Sopenharmony_ci	 * removed in ocfs2_mark_lockres_freeing when downconverting.
439762306a36Sopenharmony_ci	 */
439862306a36Sopenharmony_ci	while (processed && !list_empty(&osb->blocked_lock_list)) {
439962306a36Sopenharmony_ci		lockres = list_entry(osb->blocked_lock_list.next,
440062306a36Sopenharmony_ci				     struct ocfs2_lock_res, l_blocked_list);
440162306a36Sopenharmony_ci		list_del_init(&lockres->l_blocked_list);
440262306a36Sopenharmony_ci		osb->blocked_lock_count--;
440362306a36Sopenharmony_ci		spin_unlock_irqrestore(&osb->dc_task_lock, flags);
440462306a36Sopenharmony_ci
440562306a36Sopenharmony_ci		BUG_ON(!processed);
440662306a36Sopenharmony_ci		processed--;
440762306a36Sopenharmony_ci
440862306a36Sopenharmony_ci		ocfs2_process_blocked_lock(osb, lockres);
440962306a36Sopenharmony_ci
441062306a36Sopenharmony_ci		spin_lock_irqsave(&osb->dc_task_lock, flags);
441162306a36Sopenharmony_ci	}
441262306a36Sopenharmony_ci	spin_unlock_irqrestore(&osb->dc_task_lock, flags);
441362306a36Sopenharmony_ci}
441462306a36Sopenharmony_ci
441562306a36Sopenharmony_cistatic int ocfs2_downconvert_thread_lists_empty(struct ocfs2_super *osb)
441662306a36Sopenharmony_ci{
441762306a36Sopenharmony_ci	int empty = 0;
441862306a36Sopenharmony_ci	unsigned long flags;
441962306a36Sopenharmony_ci
442062306a36Sopenharmony_ci	spin_lock_irqsave(&osb->dc_task_lock, flags);
442162306a36Sopenharmony_ci	if (list_empty(&osb->blocked_lock_list))
442262306a36Sopenharmony_ci		empty = 1;
442362306a36Sopenharmony_ci
442462306a36Sopenharmony_ci	spin_unlock_irqrestore(&osb->dc_task_lock, flags);
442562306a36Sopenharmony_ci	return empty;
442662306a36Sopenharmony_ci}
442762306a36Sopenharmony_ci
442862306a36Sopenharmony_cistatic int ocfs2_downconvert_thread_should_wake(struct ocfs2_super *osb)
442962306a36Sopenharmony_ci{
443062306a36Sopenharmony_ci	int should_wake = 0;
443162306a36Sopenharmony_ci	unsigned long flags;
443262306a36Sopenharmony_ci
443362306a36Sopenharmony_ci	spin_lock_irqsave(&osb->dc_task_lock, flags);
443462306a36Sopenharmony_ci	if (osb->dc_work_sequence != osb->dc_wake_sequence)
443562306a36Sopenharmony_ci		should_wake = 1;
443662306a36Sopenharmony_ci	spin_unlock_irqrestore(&osb->dc_task_lock, flags);
443762306a36Sopenharmony_ci
443862306a36Sopenharmony_ci	return should_wake;
443962306a36Sopenharmony_ci}
444062306a36Sopenharmony_ci
444162306a36Sopenharmony_cistatic int ocfs2_downconvert_thread(void *arg)
444262306a36Sopenharmony_ci{
444362306a36Sopenharmony_ci	struct ocfs2_super *osb = arg;
444462306a36Sopenharmony_ci
444562306a36Sopenharmony_ci	/* only quit once we've been asked to stop and there is no more
444662306a36Sopenharmony_ci	 * work available */
444762306a36Sopenharmony_ci	while (!(kthread_should_stop() &&
444862306a36Sopenharmony_ci		ocfs2_downconvert_thread_lists_empty(osb))) {
444962306a36Sopenharmony_ci
445062306a36Sopenharmony_ci		wait_event_interruptible(osb->dc_event,
445162306a36Sopenharmony_ci					 ocfs2_downconvert_thread_should_wake(osb) ||
445262306a36Sopenharmony_ci					 kthread_should_stop());
445362306a36Sopenharmony_ci
445462306a36Sopenharmony_ci		mlog(0, "downconvert_thread: awoken\n");
445562306a36Sopenharmony_ci
445662306a36Sopenharmony_ci		ocfs2_downconvert_thread_do_work(osb);
445762306a36Sopenharmony_ci	}
445862306a36Sopenharmony_ci
445962306a36Sopenharmony_ci	osb->dc_task = NULL;
446062306a36Sopenharmony_ci	return 0;
446162306a36Sopenharmony_ci}
446262306a36Sopenharmony_ci
446362306a36Sopenharmony_civoid ocfs2_wake_downconvert_thread(struct ocfs2_super *osb)
446462306a36Sopenharmony_ci{
446562306a36Sopenharmony_ci	unsigned long flags;
446662306a36Sopenharmony_ci
446762306a36Sopenharmony_ci	spin_lock_irqsave(&osb->dc_task_lock, flags);
446862306a36Sopenharmony_ci	/* make sure the voting thread gets a swipe at whatever changes
446962306a36Sopenharmony_ci	 * the caller may have made to the voting state */
447062306a36Sopenharmony_ci	osb->dc_wake_sequence++;
447162306a36Sopenharmony_ci	spin_unlock_irqrestore(&osb->dc_task_lock, flags);
447262306a36Sopenharmony_ci	wake_up(&osb->dc_event);
447362306a36Sopenharmony_ci}
4474