*/
/*
* This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
*/
/** \defgroup LDLM Lustre Distributed Lock Manager
#define LDLM_DEFAULT_MAX_ALIVE 3900 /* 3900 seconds ~65 min */
#define LDLM_CTIME_AGE_LIMIT (10)
/* if client lock is unused for that time it can be cancelled if any other
- * client shows interest in that lock, e.g. glimpse is occured. */
+ * client shows interest in that lock, e.g. glimpse is occured.
+ */
#define LDLM_DIRTY_AGE_LIMIT (10)
#define LDLM_DEFAULT_PARALLEL_AST_LIMIT 1024
+#define LDLM_DEFAULT_LRU_SHRINK_BATCH (16)
+#define LDLM_DEFAULT_SLV_RECALC_PCT (10)
/**
* LDLM non-error return states
* Lock types are described in their respective implementation files:
* ldlm_{extent,flock,inodebits,plain}.c.
*
- * There are six lock modes along with a compatibility matrix to indicate if
+ * There are nine lock modes along with a compatibility matrix to indicate if
* two locks are compatible.
*
* - EX: Exclusive mode. Before a new file is created, MDS requests EX lock
* - CR Concurrent Read mode. When a client performs a path lookup, MDS grants
* an inodebit lock with the CR mode on the intermediate path component.
* - NL Null mode.
+ * - GROUP: Group mode. Locks with the same group ID are compatible with each
+ * other.
+ * - COS: Commit-on-Sharing mode. If Commit-on-Sharing is enabled, PW/EX locks
+ * held in transactions are downgraded to COS mode after transaction stop.
+ * - TXN: Transaction mode. If Commit-on-Sharing is diabled on a DNE system,
+ * PW/EX locks held in transactions are downgraded to TXN mode after
+ * transaction stop.
*
* <PRE>
- * NL CR CW PR PW EX
- * NL 1 1 1 1 1 1
- * CR 1 1 1 1 1 0
- * CW 1 1 1 0 0 0
- * PR 1 1 0 1 0 0
- * PW 1 1 0 0 0 0
- * EX 1 0 0 0 0 0
+ * NL CR CW PR PW EX GROUP COS TXN
+ * NL 1 1 1 1 1 1 1 1 1
+ * CR 1 1 1 1 1 0 0 0 1
+ * CW 1 1 1 0 0 0 0 0 0
+ * PR 1 1 0 1 0 0 0 0 1
+ * PW 1 1 0 0 0 0 0 0 0
+ * EX 1 0 0 0 0 0 0 0 0
+ * GROUP 1 0 0 0 0 0 1 0 0
+ * COS 1 0 0 0 0 0 0 1 0
+ * TXN 1 1 0 1 0 0 0 0 1
* </PRE>
*/
/** @{ */
-#define LCK_COMPAT_EX LCK_NL
-#define LCK_COMPAT_PW (LCK_COMPAT_EX | LCK_CR)
-#define LCK_COMPAT_PR (LCK_COMPAT_PW | LCK_PR)
-#define LCK_COMPAT_CW (LCK_COMPAT_PW | LCK_CW)
-#define LCK_COMPAT_CR (LCK_COMPAT_CW | LCK_PR | LCK_PW)
-#define LCK_COMPAT_NL (LCK_COMPAT_CR | LCK_EX | LCK_GROUP)
-#define LCK_COMPAT_GROUP (LCK_GROUP | LCK_NL)
-#define LCK_COMPAT_COS (LCK_COS)
+#define LCK_COMPAT_EX LCK_NL
+#define LCK_COMPAT_PW (LCK_COMPAT_EX | LCK_CR)
+#define LCK_COMPAT_PR (LCK_COMPAT_PW | LCK_PR | LCK_TXN)
+#define LCK_COMPAT_CW (LCK_COMPAT_PW | LCK_CW)
+#define LCK_COMPAT_CR (LCK_COMPAT_CW | LCK_PR | LCK_PW | LCK_TXN)
+#define LCK_COMPAT_NL (LCK_COMPAT_CR | LCK_EX | LCK_GROUP | LCK_COS)
+#define LCK_COMPAT_GROUP (LCK_NL | LCK_GROUP)
+#define LCK_COMPAT_COS (LCK_NL | LCK_COS)
+#define LCK_COMPAT_TXN LCK_COMPAT_PR
/** @} Lock Compatibility Matrix */
extern enum ldlm_mode lck_compat_array[];
}
/*
- *
* cluster name spaces
- *
*/
-
#define DLM_OST_NAMESPACE 1
#define DLM_MDS_NAMESPACE 2
/* XXX
- - do we just separate this by security domains and use a prefix for
- multiple namespaces in the same domain?
- -
-*/
+ * - do we just separate this by security domains and use a prefix for
+ * multiple namespaces in the same domain?
+ * -
+ */
/**
* Locking rules for LDLM:
*
*/
+/* Cancel lru flag, it indicates we cancel aged locks. */
+enum ldlm_lru_flags {
+ LDLM_LRU_FLAG_NO_WAIT = 0x1, /* Cancel locks w/o blocking (neither
+ * sending nor waiting for any RPCs)
+ */
+ LDLM_LRU_FLAG_CLEANUP = 0x2, /* Used when clearing lru, tells
+ * prepare_lru_list to set discard flag
+ * on PR extent locks so we don't waste
+ * time saving pages that will be
+ * discarded momentarily
+ */
+};
+
struct ldlm_pool;
struct ldlm_lock;
struct ldlm_resource;
*/
struct ldlm_pool_ops {
/** Recalculate pool \a pl usage */
- int (*po_recalc)(struct ldlm_pool *pl);
+ int (*po_recalc)(struct ldlm_pool *pl, bool force);
/** Cancel at least \a nr locks from pool \a pl */
int (*po_shrink)(struct ldlm_pool *pl, int nr, gfp_t gfp_mask);
int (*po_setup)(struct ldlm_pool *pl, int limit);
__u64 pl_server_lock_volume;
/** Current biggest client lock volume. Protected by pl_lock. */
__u64 pl_client_lock_volume;
- /** Lock volume factor. SLV on client is calculated as following:
- * server_slv * lock_volume_factor. */
+ /** Lock volume factor, shown in percents in procfs, but internally
+ * Client SLV calculated as: server_slv * lock_volume_factor >> 8.
+ */
atomic_t pl_lock_volume_factor;
/** Time when last SLV from server was obtained. */
time64_t pl_recalc_time;
* Greedy means release cached locks aggressively
*/
enum ldlm_appetite {
- LDLM_NAMESPACE_GREEDY = 1 << 0,
- LDLM_NAMESPACE_MODEST = 1 << 1
+ LDLM_NAMESPACE_GREEDY = BIT(0),
+ LDLM_NAMESPACE_MODEST = BIT(1),
};
/**
LDLM_NS_TYPE_MGT, /**< MGT namespace */
};
+enum ldlm_namespace_flags {
+ /**
+ * Flag to indicate the LRU cancel is in progress.
+ * Used to limit the process by 1 thread only.
+ */
+ LDLM_LRU_CANCEL = 0
+};
+
/**
* LDLM Namespace.
*
*/
unsigned int ns_max_unused;
- /** Maximum allowed age (last used time) for locks in the LRU */
+ /**
+ * Cancel batch, if unused lock count exceed lru_size
+ * Only be used if LRUR disable.
+ */
+ unsigned int ns_cancel_batch;
+
+ /* How much SLV should decrease in %% to trigger LRU cancel urgently. */
+ unsigned int ns_recalc_pct;
+
+ /** Maximum allowed age (last used time) for locks in the LRU. Set in
+ * seconds from userspace, but stored in ns to avoid repeat conversions.
+ */
ktime_t ns_max_age;
/**
*/
unsigned int ns_timeouts;
/**
- * Number of seconds since the file change time after which the
- * MDT will return an UPDATE lock along with a LOOKUP lock.
+ * Number of seconds since the file change time after which
+ * the MDT will return an UPDATE lock along with a LOOKUP lock.
* This allows the client to start caching negative dentries
* for a directory and may save an RPC for a later stat.
*/
- time64_t ns_ctime_age_limit;
+ timeout_t ns_ctime_age_limit;
/**
- * Number of seconds since the lock was last used. The client may
- * cancel the lock limited by this age and flush related data if
- * any other client shows interest in it doing glimpse request.
- * This allows to cache stat data locally for such files early.
+ * Number of (nano)seconds since the lock was last used. The client
+ * may cancel the lock older than this age and flush related data if
+ * another client shows interest in this lock by doing glimpse request.
+ * This allows to cache stat data locally for such files early. Set in
+ * seconds from userspace, but stored in ns to avoid repeat conversions.
*/
- time64_t ns_dirty_age_limit;
+ ktime_t ns_dirty_age_limit;
/**
* Used to rate-limit ldlm_namespace_dump calls.
* \see ldlm_namespace_dump. Increased by 10 seconds every time
* considered to be contended. Lock enqueues might specify that no
* contended locks should be granted
*/
- unsigned ns_contended_locks;
+ unsigned int ns_contended_locks;
/**
* The resources in this namespace remember contended state during
* \a ns_contention_time, in seconds.
*/
- time64_t ns_contention_time;
+ timeout_t ns_contention_time;
/**
* Limit size of contended extent locks, in bytes.
* caller instructs us not to grant contended locks, we would disregard
* such a request.
*/
- unsigned ns_max_nolock_size;
+ unsigned int ns_max_nolock_size;
/** Limit of parallel AST RPC count. */
- unsigned ns_max_parallel_ast;
+ unsigned int ns_max_parallel_ast;
/**
* Callback to check if a lock is good to be canceled by ELC or
* Flag to indicate namespace is being freed. Used to determine if
* recalculation of LDLM pool statistics should be skipped.
*/
- unsigned ns_stopping:1;
+ unsigned int ns_stopping:1,
+
+ /**
+ * Flag to indicate the LRU recalc on RPC reply is in progress.
+ * Used to limit the process by 1 thread only.
+ */
+ ns_rpc_recalc:1;
/**
* Which bucket should we start with the lock reclaim.
struct kobject ns_kobj; /* sysfs object */
struct completion ns_kobj_unregister;
+
+ /**
+ * To avoid another ns_lock usage, a separate bitops field.
+ */
+ unsigned long ns_flags;
};
/**
*/
static inline int ns_is_client(struct ldlm_namespace *ns)
{
- LASSERT(ns != NULL);
- LASSERT(ns->ns_client == LDLM_NAMESPACE_CLIENT ||
- ns->ns_client == LDLM_NAMESPACE_SERVER);
- return ns->ns_client == LDLM_NAMESPACE_CLIENT;
+ LASSERT(ns != NULL);
+ LASSERT(ns->ns_client == LDLM_NAMESPACE_CLIENT ||
+ ns->ns_client == LDLM_NAMESPACE_SERVER);
+ return ns->ns_client == LDLM_NAMESPACE_CLIENT;
}
/**
*/
static inline int ns_is_server(struct ldlm_namespace *ns)
{
- LASSERT(ns != NULL);
- LASSERT(ns->ns_client == LDLM_NAMESPACE_CLIENT ||
- ns->ns_client == LDLM_NAMESPACE_SERVER);
- return ns->ns_client == LDLM_NAMESPACE_SERVER;
+ LASSERT(ns != NULL);
+ LASSERT(ns->ns_client == LDLM_NAMESPACE_CLIENT ||
+ ns->ns_client == LDLM_NAMESPACE_SERVER);
+ return ns->ns_client == LDLM_NAMESPACE_SERVER;
}
/**
*/
static inline int ns_connect_lru_resize(struct ldlm_namespace *ns)
{
- LASSERT(ns != NULL);
- return !!(ns->ns_connect_flags & OBD_CONNECT_LRU_RESIZE);
+ LASSERT(ns != NULL);
+ return !!(ns->ns_connect_flags & OBD_CONNECT_LRU_RESIZE);
}
static inline void ns_register_cancel(struct ldlm_namespace *ns,
struct ldlm_lock *gl_lock; /* lock to glimpse */
struct list_head gl_list; /* linkage to other gl work structs */
__u32 gl_flags;/* see LDLM_GL_WORK_* below */
- union ldlm_gl_desc *gl_desc; /* glimpse descriptor to be packed in
- * glimpse callback request */
+ /* glimpse descriptor to be packed in glimpse callback request */
+ union ldlm_gl_desc *gl_desc;
ptlrpc_interpterer_t gl_interpret_reply;
void *gl_interpret_data;
};
struct ldlm_bl_desc {
- unsigned int bl_same_client:1,
- bl_cos_incompat:1;
+ unsigned int bl_same_client:1, /* both ops are from the same client. */
+ bl_txn_dependent:1;/* the op that enqueues lock depends on
+ * the op that holds lock.
+ */
};
struct ldlm_cb_set_arg {
/** Interval node data for each LDLM_EXTENT lock. */
struct ldlm_interval {
struct interval_node li_node; /* node for tree management */
- struct list_head li_group; /* the locks which have the same
- * policy - group of the policy */
+ struct list_head li_group; /* locks having same policy */
};
#define to_ldlm_interval(n) container_of(n, struct ldlm_interval, li_node)
struct ldlm_lock *lock;
};
+struct ldlm_flock_node {
+ atomic_t lfn_unlock_pending;
+ bool lfn_needs_reprocess;
+ struct interval_node *lfn_root;
+};
+
/** Whether to track references to exports by LDLM locks. */
#define LUSTRE_TRACKS_LOCK_EXP_REFS (0)
LCF_ASYNC = 0x1, /* Cancel locks asynchronously. */
LCF_LOCAL = 0x2, /* Cancel locks locally, not notifing server */
LCF_BL_AST = 0x4, /* Cancel LDLM_FL_BL_AST locks in the same RPC */
- LCF_CONVERT = 0x8, /* Try to convert IBITS lock before cancel */
};
struct ldlm_flock {
*/
struct portals_handle l_handle;
/**
- * Internal spinlock protects l_resource. We should hold this lock
- * first before taking res_lock.
- */
- spinlock_t l_lock;
- /**
* Pointer to actual resource this lock is in.
- * ldlm_lock_change_resource() can change this.
+ * ldlm_lock_change_resource() can change this on the client.
+ * When this is possible, rcu must be used to stablise
+ * the resource while we lock and check it hasn't been changed.
*/
struct ldlm_resource *l_resource;
/**
};
/* separate ost_lvb used mostly by Data-on-MDT for now.
- * It is introduced to don't mix with layout lock data. */
+ * It is introduced to don't mix with layout lock data.
+ */
struct ost_lvb l_ost_lvb;
/*
* Server-side-only members.
* under this lock.
* \see ost_rw_prolong_locks
*/
- time64_t l_callback_timeout;
+ time64_t l_callback_timestamp;
/** Local PID of process which created this lock. */
__u32 l_pid;
struct list_head l_exp_list;
};
+enum ldlm_match_flags {
+ LDLM_MATCH_UNREF = BIT(0),
+ LDLM_MATCH_AST = BIT(1),
+ LDLM_MATCH_AST_ANY = BIT(2),
+ LDLM_MATCH_RIGHT = BIT(3),
+ LDLM_MATCH_GROUP = BIT(4),
+};
+
/**
* Describe the overlap between two locks. itree_overlap_cb data.
*/
union ldlm_policy_data *lmd_policy;
__u64 lmd_flags;
__u64 lmd_skip_flags;
- int lmd_unref;
- bool lmd_has_ast_data;
+ enum ldlm_match_flags lmd_match;
};
/** For uncommitted cross-MDT lock, store transno this lock belongs to */
#define l_transno l_client_cookie
/** For uncommitted cross-MDT lock, which is client lock, share with l_rk_ast
- * which is for server. */
+ * which is for server.
+ */
#define l_slc_link l_rk_ast
-#define HANDLE_MAP_SIZE ((LMV_MAX_STRIPE_COUNT + 7) >> 3)
-
struct lustre_handle_array {
unsigned int ha_count;
/* ha_map is used as bit flag to indicate handle is remote or local */
- char ha_map[HANDLE_MAP_SIZE];
+ DECLARE_BITMAP(ha_map, LMV_MAX_STRIPE_COUNT);
struct lustre_handle ha_handles[0];
};
/**
* List item for list in namespace hash.
- * protected by ns_lock
+ * protected by ns_lock.
+ * Shared with linkage for RCU-delayed free.
*/
- struct hlist_node lr_hash;
+ union {
+ struct hlist_node lr_hash;
+ struct rcu_head lr_rcu;
+ };
/** Reference count for this resource */
- atomic_t lr_refcount;
+ refcount_t lr_refcount;
/** Spinlock to protect locks under this resource. */
spinlock_t lr_lock;
- /**
- * protected by lr_lock
- * @{ */
+ /* protected by lr_lock */
+
/** List of locks in granted state */
struct list_head lr_granted;
/**
* List of locks that could not be granted due to conflicts and
- * that are waiting for conflicts to go away */
+ * that are waiting for conflicts to go away
+ */
struct list_head lr_waiting;
/** @} */
struct ldlm_res_id lr_name;
union {
- /**
- * Interval trees (only for extent locks) for all modes of
- * this resource
- */
+ /* Interval trees (for extent locks) all modes of resource */
struct ldlm_interval_tree *lr_itree;
struct ldlm_ibits_queues *lr_ibits_queues;
+ struct ldlm_flock_node lr_flock_node;
};
union {
- /**
- * When the resource was considered as contended,
- * used only on server side.
- */
+ /* resource considered as contended, used only on server side*/
time64_t lr_contention_time;
/**
* Associated inode, used only on client side.
static inline struct ldlm_namespace *
ldlm_res_to_ns(struct ldlm_resource *res)
{
- return res->lr_ns_bucket->nsb_namespace;
+ return res->lr_ns_bucket->nsb_namespace;
}
static inline struct ldlm_namespace *
ldlm_lock_to_ns(struct ldlm_lock *lock)
{
- return ldlm_res_to_ns(lock->l_resource);
+ return ldlm_res_to_ns(lock->l_resource);
}
static inline char *
ldlm_lock_to_ns_name(struct ldlm_lock *lock)
{
- return ldlm_ns_name(ldlm_lock_to_ns(lock));
+ return ldlm_ns_name(ldlm_lock_to_ns(lock));
}
static inline struct adaptive_timeout *
ldlm_lock_to_ns_at(struct ldlm_lock *lock)
{
- return &lock->l_resource->lr_ns_bucket->nsb_at_estimate;
+ return &lock->l_resource->lr_ns_bucket->nsb_at_estimate;
}
static inline int ldlm_lvbo_init(struct ldlm_resource *res)
/* init lvb now if not already */
rc = ldlm_lvbo_init(lock->l_resource);
if (rc < 0) {
- CERROR("lock %p: delayed lvb init failed (rc %d)",
+ CERROR("lock %p: delayed lvb init failed (rc %d)\n",
lock, rc);
return rc;
}
void *ei_namespace; /** lock namespace **/
u64 ei_inodebits; /** lock inode bits **/
unsigned int ei_enq_slave:1; /** whether enqueue slave stripes */
- unsigned int ei_enq_slot:1; /** whether acquire rpc slot */
+ unsigned int ei_req_slot:1; /** whether acquire rpc slot */
+ unsigned int ei_mod_slot:1; /** whether acquire mod rpc slot */
};
#define ei_res_id ei_cb_gl
* with a debugging message that is ldlm-related
*/
#define LDLM_DEBUG_NOLOCK(format, a...) \
- CDEBUG(D_DLMTRACE, "### " format "\n" , ##a)
+ CDEBUG(D_DLMTRACE, "### " format "\n", ##a)
/**
* Support function for lock information printing into debug logs.
*/
#ifdef LIBCFS_DEBUG
#define ldlm_lock_debug(msgdata, mask, cdls, lock, fmt, a...) do { \
- CFS_CHECK_STACK(msgdata, mask, cdls); \
- \
- if (((mask) & D_CANTMASK) != 0 || \
- ((libcfs_debug & (mask)) != 0 && \
- (libcfs_subsystem_debug & DEBUG_SUBSYSTEM) != 0)) \
- _ldlm_lock_debug(lock, msgdata, fmt, ##a); \
-} while(0)
+ if (((mask) & D_CANTMASK) != 0 || \
+ ((libcfs_debug & (mask)) != 0 && \
+ (libcfs_subsystem_debug & DEBUG_SUBSYSTEM) != 0)) \
+ _ldlm_lock_debug(lock, msgdata, fmt, ##a); \
+} while (0)
+__printf(3, 4) /* function attribute */
void _ldlm_lock_debug(struct ldlm_lock *lock,
- struct libcfs_debug_msg_data *data,
- const char *fmt, ...)
- __attribute__ ((format (printf, 3, 4)));
+ struct libcfs_debug_msg_data *data,
+ const char *fmt, ...);
/**
* Rate-limited version of lock printing function.
*/
#define LDLM_DEBUG_LIMIT(mask, lock, fmt, a...) do { \
static struct cfs_debug_limit_state _ldlm_cdls; \
- LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, mask, &_ldlm_cdls); \
- ldlm_lock_debug(&msgdata, mask, &_ldlm_cdls, lock, "### " fmt , ##a);\
+ LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, mask, &_ldlm_cdls); \
+ ldlm_lock_debug(&msgdata, mask, &_ldlm_cdls, lock, "### " fmt, ##a); \
} while (0)
#define LDLM_ERROR(lock, fmt, a...) LDLM_DEBUG_LIMIT(D_ERROR, lock, fmt, ## a)
#define LDLM_DEBUG(lock, fmt, a...) do { \
if (likely(lock != NULL)) { \
LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_DLMTRACE, NULL); \
- ldlm_lock_debug(&msgdata, D_DLMTRACE, NULL, lock, \
- "### " fmt , ##a); \
+ ldlm_lock_debug(&msgdata, D_DLMTRACE, NULL, lock, \
+ "### " fmt, ##a); \
} else { \
LDLM_DEBUG_NOLOCK("no dlm lock: " fmt, ##a); \
} \
struct list_head *queue,
struct list_head *work_list,
enum ldlm_process_intention intention,
- struct ldlm_lock *hint);
+ __u64 hint);
/**
* Return values for lock iterators.
*
* LDLM provides for a way to iterate through every lock on a resource or
* namespace or every resource in a namespace.
- * @{ */
+ * @{
+ */
int ldlm_resource_foreach(struct ldlm_resource *res, ldlm_iterator_t iter,
void *closure);
void ldlm_namespace_foreach(struct ldlm_namespace *ns, ldlm_iterator_t iter,
void *closure);
-int ldlm_resource_iterate(struct ldlm_namespace *, const struct ldlm_res_id *,
+int ldlm_resource_iterate(struct ldlm_namespace *ln,
+ const struct ldlm_res_id *lri,
ldlm_iterator_t iter, void *data);
/** @} ldlm_iterator */
struct ldlm_prolong_args {
struct obd_export *lpa_export;
+ struct ptlrpc_request *lpa_req;
struct ldlm_res_id lpa_resid;
struct ldlm_extent lpa_extent;
enum ldlm_mode lpa_mode;
- time64_t lpa_timeout;
int lpa_locks_cnt;
int lpa_blocks_cnt;
};
void ldlm_resource_prolong(struct ldlm_prolong_args *arg);
struct ldlm_callback_suite {
- ldlm_completion_callback lcs_completion;
- ldlm_blocking_callback lcs_blocking;
- ldlm_glimpse_callback lcs_glimpse;
+ ldlm_completion_callback lcs_completion;
+ ldlm_blocking_callback lcs_blocking;
+ ldlm_glimpse_callback lcs_glimpse;
};
/* ldlm_lockd.c */
*/
int ldlm_server_blocking_ast(struct ldlm_lock *, struct ldlm_lock_desc *,
void *data, int flag);
+int tgt_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
+ void *data, int flag);
int ldlm_server_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data);
int ldlm_server_glimpse_ast(struct ldlm_lock *lock, void *data);
int ldlm_glimpse_locks(struct ldlm_resource *res,
* MDT or OST to pass through LDLM requests to LDLM for handling
* @{
*/
-int ldlm_handle_enqueue0(struct ldlm_namespace *ns, struct ptlrpc_request *req,
- const struct ldlm_request *dlm_req,
- const struct ldlm_callback_suite *cbs);
+int ldlm_handle_enqueue(struct ldlm_namespace *ns, struct req_capsule *pill,
+ const struct ldlm_request *dlm_req,
+ const struct ldlm_callback_suite *cbs);
int ldlm_handle_convert0(struct ptlrpc_request *req,
const struct ldlm_request *dlm_req);
int ldlm_handle_cancel(struct ptlrpc_request *req);
/** @} ldlm_handlers */
void ldlm_revoke_export_locks(struct obd_export *exp);
-time64_t ldlm_bl_timeout(struct ldlm_lock *lock);
+timeout_t ldlm_bl_timeout(struct ldlm_lock *lock);
+timeout_t ldlm_bl_timeout_by_rpc(struct ptlrpc_request *req);
#endif
int ldlm_del_waiting_lock(struct ldlm_lock *lock);
-int ldlm_refresh_waiting_lock(struct ldlm_lock *lock, time64_t timeout);
+int ldlm_refresh_waiting_lock(struct ldlm_lock *lock, timeout_t timeout);
int ldlm_get_ref(void);
void ldlm_put_ref(void);
int ldlm_init_export(struct obd_export *exp);
#endif
void ldlm_register_intent(struct ldlm_namespace *ns, ldlm_res_policy arg);
void ldlm_lock2handle(const struct ldlm_lock *lock,
- struct lustre_handle *lockh);
-struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *, __u64 flags);
-void ldlm_cancel_callback(struct ldlm_lock *);
-int ldlm_lock_remove_from_lru(struct ldlm_lock *);
+ struct lustre_handle *lockh);
+struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *lh,
+ __u64 flags);
+void ldlm_cancel_callback(struct ldlm_lock *ll);
+int ldlm_lock_remove_from_lru(struct ldlm_lock *ll);
int ldlm_lock_set_data(const struct lustre_handle *lockh, void *data);
/**
*/
static inline struct ldlm_lock *ldlm_handle2lock(const struct lustre_handle *h)
{
- return __ldlm_handle2lock(h, 0);
+ return __ldlm_handle2lock(h, 0);
}
#define LDLM_LOCK_REF_DEL(lock) \
- lu_ref_del(&lock->l_reference, "handle", current)
+ lu_ref_del(&lock->l_reference, "handle", lock)
static inline struct ldlm_lock *
ldlm_handle2lock_long(const struct lustre_handle *h, __u64 flags)
{
- struct ldlm_lock *lock;
+ struct ldlm_lock *lock;
- lock = __ldlm_handle2lock(h, flags);
- if (lock != NULL)
- LDLM_LOCK_REF_DEL(lock);
- return lock;
+ lock = __ldlm_handle2lock(h, flags);
+ if (lock != NULL)
+ LDLM_LOCK_REF_DEL(lock);
+ return lock;
}
/**
int is_granted_or_cancelled_nolock(struct ldlm_lock *lock);
int ldlm_error2errno(enum ldlm_error error);
-enum ldlm_error ldlm_errno2error(int err_no); /* don't call it `errno': this
- * confuses user-space. */
+/* don't call it `errno': this confuses user-space. */
+enum ldlm_error ldlm_errno2error(int err_no);
#if LUSTRE_TRACKS_LOCK_EXP_REFS
void ldlm_dump_export_locks(struct obd_export *exp);
#endif
-/**
- * Release a temporary lock reference obtained by ldlm_handle2lock() or
- * __ldlm_handle2lock().
- */
+/* Release temporary lock got by ldlm_handle2lock() or __ldlm_handle2lock() */
#define LDLM_LOCK_PUT(lock) \
do { \
- LDLM_LOCK_REF_DEL(lock); \
- /*LDLM_DEBUG((lock), "put");*/ \
- ldlm_lock_put(lock); \
+ LDLM_LOCK_REF_DEL(lock); \
+ /*LDLM_DEBUG((lock), "put");*/ \
+ ldlm_lock_put(lock); \
} while (0)
/**
* Release a lock reference obtained by some other means (see
* LDLM_LOCK_PUT()).
*/
-#define LDLM_LOCK_RELEASE(lock) \
-do { \
- /*LDLM_DEBUG((lock), "put");*/ \
- ldlm_lock_put(lock); \
-} while (0)
+#define LDLM_LOCK_RELEASE(lock) ldlm_lock_put(lock)
#define LDLM_LOCK_GET(lock) \
({ \
- ldlm_lock_get(lock); \
- /*LDLM_DEBUG((lock), "get");*/ \
- lock; \
+ ldlm_lock_get(lock); \
+ /*LDLM_DEBUG((lock), "get");*/ \
+ lock; \
})
#define ldlm_lock_list_put(head, member, count) \
void ldlm_lock_fail_match(struct ldlm_lock *lock);
void ldlm_lock_allow_match(struct ldlm_lock *lock);
void ldlm_lock_allow_match_locked(struct ldlm_lock *lock);
+
enum ldlm_mode ldlm_lock_match_with_skip(struct ldlm_namespace *ns,
__u64 flags, __u64 skip_flags,
const struct ldlm_res_id *res_id,
union ldlm_policy_data *policy,
enum ldlm_mode mode,
struct lustre_handle *lh,
- int unref);
+ enum ldlm_match_flags match_flags);
static inline enum ldlm_mode ldlm_lock_match(struct ldlm_namespace *ns,
__u64 flags,
const struct ldlm_res_id *res_id,
enum ldlm_type type,
union ldlm_policy_data *policy,
enum ldlm_mode mode,
- struct lustre_handle *lh,
- int unref)
+ struct lustre_handle *lh)
{
return ldlm_lock_match_with_skip(ns, flags, 0, res_id, type, policy,
- mode, lh, unref);
+ mode, lh, 0);
}
struct ldlm_lock *search_itree(struct ldlm_resource *res,
struct ldlm_match_data *data);
__u64 *bits);
void ldlm_lock_mode_downgrade(struct ldlm_lock *lock, enum ldlm_mode new_mode);
void ldlm_lock_cancel(struct ldlm_lock *lock);
-void ldlm_reprocess_all(struct ldlm_resource *res, struct ldlm_lock *hint);
+void ldlm_reprocess_all(struct ldlm_resource *res, __u64 hint);
void ldlm_reprocess_recovery_done(struct ldlm_namespace *ns);
void ldlm_lock_dump_handle(int level, const struct lustre_handle *lockh);
void ldlm_unlink_lock_skiplist(struct ldlm_lock *req);
/* resource.c - internal */
struct ldlm_resource *ldlm_resource_get(struct ldlm_namespace *ns,
- struct ldlm_resource *parent,
const struct ldlm_res_id *,
enum ldlm_type type, int create);
struct ldlm_resource *ldlm_resource_getref(struct ldlm_resource *res);
void ldlm_resource_unlink_lock(struct ldlm_lock *lock);
void ldlm_res2desc(struct ldlm_resource *res, struct ldlm_resource_desc *desc);
void ldlm_dump_all_namespaces(enum ldlm_side client, int level);
-void ldlm_namespace_dump(int level, struct ldlm_namespace *);
-void ldlm_resource_dump(int level, struct ldlm_resource *);
-int ldlm_lock_change_resource(struct ldlm_namespace *, struct ldlm_lock *,
- const struct ldlm_res_id *);
+void ldlm_namespace_dump(int level, struct ldlm_namespace *ln);
+void ldlm_resource_dump(int level, struct ldlm_resource *lr);
+int ldlm_lock_change_resource(struct ldlm_namespace *ln, struct ldlm_lock *ll,
+ const struct ldlm_res_id *lri);
-#define LDLM_RESOURCE_ADDREF(res) do { \
- lu_ref_add_atomic(&(res)->lr_reference, __FUNCTION__, current); \
-} while (0)
+#define LDLM_RESOURCE_ADDREF(res) \
+ lu_ref_add_atomic(&(res)->lr_reference, __FUNCTION__, current)
-#define LDLM_RESOURCE_DELREF(res) do { \
- lu_ref_del(&(res)->lr_reference, __FUNCTION__, current); \
-} while (0)
+#define LDLM_RESOURCE_DELREF(res) \
+ lu_ref_del(&(res)->lr_reference, __FUNCTION__, current)
/* ldlm_request.c */
-int ldlm_expired_completion_wait(void *data);
/** \defgroup ldlm_local_ast Default AST handlers for local locks
* These AST handlers are typically used for server-side local locks and are
* also used by client-side lock handlers to perform minimum level base
* processing.
- * @{ */
+ */
int ldlm_blocking_ast_nocheck(struct ldlm_lock *lock);
int ldlm_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
void *data, int flag);
/** \defgroup ldlm_cli_api API to operate on locks from actual LDLM users.
* These are typically used by client and server (*_local versions)
* to obtain and release locks.
- * @{ */
+ */
int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp,
struct ldlm_enqueue_info *einfo,
const struct ldlm_res_id *res_id,
struct list_head *cancels, int count);
struct ptlrpc_request *ldlm_enqueue_pack(struct obd_export *exp, int lvb_len);
-int ldlm_handle_enqueue0(struct ldlm_namespace *ns, struct ptlrpc_request *req,
- const struct ldlm_request *dlm_req,
- const struct ldlm_callback_suite *cbs);
-int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req,
- enum ldlm_type type, __u8 with_policy,
- enum ldlm_mode mode, __u64 *flags, void *lvb,
- __u32 lvb_len,
- const struct lustre_handle *lockh, int rc);
+int ldlm_handle_enqueue(struct ldlm_namespace *ns, struct req_capsule *pill,
+ const struct ldlm_request *dlm_req,
+ const struct ldlm_callback_suite *cbs);
+int ldlm_cli_enqueue_fini(struct obd_export *exp, struct req_capsule *pill,
+ struct ldlm_enqueue_info *einfo, __u8 with_policy,
+ __u64 *flags, void *lvb, __u32 lvb_len,
+ const struct lustre_handle *lockh, int rc,
+ bool request_slot);
int ldlm_cli_enqueue_local(const struct lu_env *env,
struct ldlm_namespace *ns,
const struct ldlm_res_id *res_id,
void *data, __u32 lvb_len, enum lvb_type lvb_type,
const __u64 *client_cookie,
struct lustre_handle *lockh);
-int ldlm_cli_convert(struct ldlm_lock *lock, __u32 *flags);
+int ldlm_cli_lock_create_pack(struct obd_export *exp,
+ struct ldlm_request *dlmreq,
+ struct ldlm_enqueue_info *einfo,
+ const struct ldlm_res_id *res_id,
+ union ldlm_policy_data const *policy,
+ __u64 *flags, void *lvb, __u32 lvb_len,
+ enum lvb_type lvb_type,
+ struct lustre_handle *lockh);
+int ldlm_cli_convert_req(struct ldlm_lock *lock, __u32 *flags, __u64 new_bits);
+int ldlm_cli_convert(struct ldlm_lock *lock,
+ enum ldlm_cancel_flags cancel_flags);
int ldlm_cli_update_pool(struct ptlrpc_request *req);
int ldlm_cli_cancel(const struct lustre_handle *lockh,
enum ldlm_cancel_flags cancel_flags);
-int ldlm_cli_cancel_unused(struct ldlm_namespace *, const struct ldlm_res_id *,
+int ldlm_cli_cancel_unused(struct ldlm_namespace *n,
+ const struct ldlm_res_id *l,
enum ldlm_cancel_flags flags, void *opaque);
int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns,
const struct ldlm_res_id *res_id,
union ldlm_policy_data *policy,
enum ldlm_mode mode,
enum ldlm_cancel_flags flags, void *opaque);
-int ldlm_cli_cancel_req(struct obd_export *exp, struct list_head *head,
- int count, enum ldlm_cancel_flags flags);
+int ldlm_cli_cancel_req(struct obd_export *exp, struct ldlm_lock *lock,
+ struct list_head *head, int count,
+ enum ldlm_cancel_flags flags);
int ldlm_cancel_resource_local(struct ldlm_resource *res,
struct list_head *cancels,
union ldlm_policy_data *policy,
enum ldlm_cancel_flags flags);
int ldlm_inodebits_drop(struct ldlm_lock *lock, __u64 to_drop);
-int ldlm_cli_dropbits(struct ldlm_lock *lock, __u64 drop_bits);
-int ldlm_cli_dropbits_list(struct list_head *converts, __u64 drop_bits);
+int ldlm_cli_inodebits_convert(struct ldlm_lock *lock,
+ enum ldlm_cancel_flags cancel_flags);
/** @} ldlm_cli_api */
+
/* mds/handler.c */
/* This has to be here because recursive inclusion sucks. */
int intent_disposition(struct ldlm_reply *rep, int flag);
* than one lock_res is dead-lock safe.
*/
enum lock_res_type {
- LRT_NORMAL,
- LRT_NEW
+ LRT_NORMAL,
+ LRT_NEW,
};
/** Lock resource. */
assert_spin_locked(&res->lr_lock);
}
-struct ldlm_resource * lock_res_and_lock(struct ldlm_lock *lock);
+struct ldlm_resource *lock_res_and_lock(struct ldlm_lock *lock);
void unlock_res_and_lock(struct ldlm_lock *lock);
/* ldlm_pool.c */
int ldlm_pool_shrink(struct ldlm_pool *pl, int nr, gfp_t gfp_mask);
void ldlm_pool_fini(struct ldlm_pool *pl);
int ldlm_pool_setup(struct ldlm_pool *pl, int limit);
-time64_t ldlm_pool_recalc(struct ldlm_pool *pl);
+time64_t ldlm_pool_recalc(struct ldlm_pool *pl, bool force);
__u32 ldlm_pool_get_lvf(struct ldlm_pool *pl);
__u64 ldlm_pool_get_slv(struct ldlm_pool *pl);
__u64 ldlm_pool_get_clv(struct ldlm_pool *pl);