*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
*
* GPL HEADER END
*/
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2010, 2015, Intel Corporation.
+ * Copyright (c) 2010, 2016, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
struct obd_ops;
struct obd_device;
+extern struct kset *ldlm_ns_kset;
+extern struct kset *ldlm_svc_kset;
+
#define OBD_LDLM_DEVICENAME "ldlm"
#define LDLM_DEFAULT_LRU_SIZE (100 * num_online_cpus())
-#define LDLM_DEFAULT_MAX_ALIVE (cfs_time_seconds(3900)) /* 65 min */
+#define LDLM_DEFAULT_MAX_ALIVE 3900 /* 3900 seconds ~65 min */
#define LDLM_CTIME_AGE_LIMIT (10)
#define LDLM_DEFAULT_PARALLEL_AST_LIMIT 1024
* server_slv * lock_volume_factor. */
atomic_t pl_lock_volume_factor;
/** Time when last SLV from server was obtained. */
- time_t pl_recalc_time;
+ time64_t pl_recalc_time;
/** Recalculation period for pool. */
- time_t pl_recalc_period;
+ time64_t pl_recalc_period;
/** Recalculation and shrink operations. */
struct ldlm_pool_ops *pl_ops;
/** Number of planned locks for next period. */
int pl_grant_plan;
/** Pool statistics. */
struct lprocfs_stats *pl_stats;
+
+ /* sysfs object */
+ struct kobject pl_kobj;
+ struct completion pl_kobj_unregister;
};
typedef int (*ldlm_res_policy)(struct ldlm_namespace *, struct ldlm_lock **,
* of ldlm_[res_]lvbo_[init,update,fill]() functions.
*/
struct ldlm_valblock_ops {
- int (*lvbo_init)(struct ldlm_resource *res);
- int (*lvbo_update)(struct ldlm_resource *res,
- struct ptlrpc_request *r,
- int increase);
- int (*lvbo_free)(struct ldlm_resource *res);
+ int (*lvbo_init)(struct ldlm_resource *res);
+ int (*lvbo_update)(struct ldlm_resource *res, struct ldlm_lock *lock,
+ struct ptlrpc_request *r, int increase);
+ int (*lvbo_free)(struct ldlm_resource *res);
/* Return size of lvb data appropriate RPC size can be reserved */
int (*lvbo_size)(struct ldlm_lock *lock);
/* Called to fill in lvb data to RPC buffer @buf */
* controlled by available memory on this client and on server.
*/
unsigned int ns_max_unused;
+
/** Maximum allowed age (last used time) for locks in the LRU */
- unsigned int ns_max_age;
+ ktime_t ns_max_age;
+
/**
* Server only: number of times we evicted clients due to lack of reply
* to ASTs.
* Which bucket should we start with the lock reclaim.
*/
int ns_reclaim_start;
+
+ struct kobject ns_kobj; /* sysfs object */
+ struct completion ns_kobj_unregister;
};
/**
__u32 gl_flags;/* see LDLM_GL_WORK_* below */
union ldlm_gl_desc *gl_desc; /* glimpse descriptor to be packed in
* glimpse callback request */
+ ptlrpc_interpterer_t gl_interpret_reply;
+ void *gl_interpret_data;
+};
+
+struct ldlm_cb_set_arg {
+ struct ptlrpc_request_set *set;
+ int type; /* LDLM_{CP,BL,GL}_CALLBACK */
+ atomic_t restart;
+ struct list_head *list;
+ union ldlm_gl_desc *gl_desc; /* glimpse AST descriptor */
+ ptlrpc_interpterer_t gl_interpret_reply;
+ void *gl_interpret_data;
+};
+
+struct ldlm_cb_async_args {
+ struct ldlm_cb_set_arg *ca_set_arg;
+ struct ldlm_lock *ca_lock;
};
-/** The ldlm_glimpse_work is allocated on the stack and should not be freed. */
-#define LDLM_GL_WORK_NOFREE 0x1
+/** The ldlm_glimpse_work was slab allocated & must be freed accordingly.*/
+#define LDLM_GL_WORK_SLAB_ALLOCATED 0x1
/** Interval node data for each LDLM_EXTENT lock. */
struct ldlm_interval {
__u64 owner;
__u64 blocking_owner;
struct obd_export *blocking_export;
- /* Protected by the hash lock */
- __u32 blocking_refs;
+ atomic_t blocking_refs;
__u32 pid;
};
* Seconds. It will be updated if there is any activity related to
* the lock, e.g. enqueue the lock or send blocking AST.
*/
- cfs_time_t l_last_activity;
+ time64_t l_last_activity;
/**
- * Time last used by e.g. being matched by lock match.
- * Jiffies. Should be converted to time if needed.
+ * Time, in nanoseconds, last used by e.g. being matched by lock match.
*/
- cfs_time_t l_last_used;
+ ktime_t l_last_used;
/** Originally requested extent for the extent lock. */
struct ldlm_extent l_req_extent;
* The lists this could be linked into are:
* waiting_locks_list (protected by waiting_locks_spinlock),
* then if the lock timed out, it is moved to
- * expired_lock_thread.elt_expired_locks for further processing.
- * Protected by elt_lock.
+ * expired_lock_list for further processing.
*/
struct list_head l_pending_chain;
void *ei_cb_gl; /** lock glimpse callback */
void *ei_cbdata; /** Data to be passed into callbacks. */
void *ei_namespace; /** lock namespace **/
- unsigned int ei_enq_slave:1, /** whether enqueue slave stripes */
- ei_nonblock:1; /** non block enqueue */
+ unsigned int ei_enq_slave:1; /** whether enqueue slave stripes */
};
#define ei_res_id ei_cb_gl
* Rate-limited version of lock printing function.
*/
#define LDLM_DEBUG_LIMIT(mask, lock, fmt, a...) do { \
- static cfs_debug_limit_state_t _ldlm_cdls; \
+ 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);\
} while (0)
# define LDLM_ERROR(lock, fmt, a...) ((void)0)
#endif
+/*
+ * Three intentions can be used for the policy functions in
+ * ldlm_processing_policy.
+ *
+ * LDLM_PROCESS_RESCAN:
+ *
+ * It's used when policy functions are called from ldlm_reprocess_queue() to
+ * reprocess the wait & convert list and try to grant locks, blocking ASTs
+ * have already been sent in this situation, completion ASTs need be sent for
+ * the locks being granted.
+ *
+ * LDLM_PROCESS_ENQUEUE:
+ *
+ * It's used when policy functions are called from ldlm_lock_enqueue() to
+ * process the wait & convert list for handling an enqueue request, blocking
+ * ASTs have not been sent yet, so list of conflicting locks would be
+ * collected and ASTs sent.
+ *
+ * LDLM_PROCESS_RECOVERY:
+ *
+ * It's used when policy functions are called from ldlm_reprocess_queue() to
+ * reprocess the wait & convert list when recovery done. In case of blocking
+ * ASTs are lost before recovery, it needs not only to grant locks if
+ * available, but also send blocking ASTs to the locks doesn't have AST sent
+ * flag. Completion ASTs need be sent for the locks being granted.
+ */
+enum ldlm_process_intention {
+ LDLM_PROCESS_RESCAN = 0,
+ LDLM_PROCESS_ENQUEUE = 1,
+ LDLM_PROCESS_RECOVERY = 2,
+};
+
typedef int (*ldlm_processing_policy)(struct ldlm_lock *lock, __u64 *flags,
- int first_enq, enum ldlm_error *err,
+ enum ldlm_process_intention intention,
+ enum ldlm_error *err,
struct list_head *work_list);
/**
/* ldlm_extent.c */
__u64 ldlm_extent_shift_kms(struct ldlm_lock *lock, __u64 old_kms);
+struct ldlm_prolong_args {
+ struct obd_export *lpa_export;
+ struct ldlm_res_id lpa_resid;
+ struct ldlm_extent lpa_extent;
+ enum ldlm_mode lpa_mode;
+ int lpa_timeout;
+ int lpa_locks_cnt;
+ int lpa_blocks_cnt;
+};
+void ldlm_lock_prolong_one(struct ldlm_lock *lock,
+ struct ldlm_prolong_args *arg);
+void ldlm_resource_prolong(struct ldlm_prolong_args *arg);
+
struct ldlm_callback_suite {
ldlm_completion_callback lcs_completion;
ldlm_blocking_callback lcs_blocking;
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 *);
-int ldlm_lock_set_data(struct lustre_handle *, void *);
+int ldlm_lock_set_data(const struct lustre_handle *lockh, void *data);
/**
* Obtain a lock reference by its handle.
* Update Lock Value Block Operations (LVBO) on a resource taking into account
* data from request \a r
*/
-static inline int ldlm_res_lvbo_update(struct ldlm_resource *res,
- struct ptlrpc_request *req, int increase)
+static inline int ldlm_lvbo_update(struct ldlm_resource *res,
+ struct ldlm_lock *lock,
+ struct ptlrpc_request *req, int increase)
{
+ struct ldlm_namespace *ns = ldlm_res_to_ns(res);
int rc;
/* delayed lvb init may be required */
return rc;
}
- if (ldlm_res_to_ns(res)->ns_lvbo &&
- ldlm_res_to_ns(res)->ns_lvbo->lvbo_update) {
- return ldlm_res_to_ns(res)->ns_lvbo->lvbo_update(res, req,
- increase);
- }
+ if (ns->ns_lvbo && ns->ns_lvbo->lvbo_update)
+ return ns->ns_lvbo->lvbo_update(res, lock, req, increase);
+
return 0;
}
+static inline int ldlm_res_lvbo_update(struct ldlm_resource *res,
+ struct ptlrpc_request *req, int increase)
+{
+ return ldlm_lvbo_update(res, NULL, req, increase);
+}
+
int ldlm_error2errno(enum ldlm_error error);
enum ldlm_error ldlm_errno2error(int err_no); /* don't call it `errno': this
* confuses user-space. */
void ldlm_lock_put(struct ldlm_lock *lock);
void ldlm_lock_destroy(struct ldlm_lock *lock);
void ldlm_lock2desc(struct ldlm_lock *lock, struct ldlm_lock_desc *desc);
-void ldlm_lock_addref(struct lustre_handle *lockh, enum ldlm_mode mode);
-int ldlm_lock_addref_try(struct lustre_handle *lockh, enum ldlm_mode mode);
-void ldlm_lock_decref(struct lustre_handle *lockh, enum ldlm_mode mode);
-void ldlm_lock_decref_and_cancel(struct lustre_handle *lockh,
+void ldlm_lock_addref(const struct lustre_handle *lockh, enum ldlm_mode mode);
+int ldlm_lock_addref_try(const struct lustre_handle *lockh,
+ enum ldlm_mode mode);
+void ldlm_lock_decref(const struct lustre_handle *lockh, enum ldlm_mode mode);
+void ldlm_lock_decref_and_cancel(const struct lustre_handle *lockh,
enum ldlm_mode mode);
void ldlm_lock_fail_match_locked(struct ldlm_lock *lock);
void ldlm_lock_fail_match(struct ldlm_lock *lock);
const struct ldlm_res_id *, enum ldlm_type type,
union ldlm_policy_data *, enum ldlm_mode mode,
struct lustre_handle *, int unref);
-enum ldlm_mode ldlm_revalidate_lock_handle(struct lustre_handle *lockh,
+enum ldlm_mode ldlm_revalidate_lock_handle(const struct lustre_handle *lockh,
__u64 *bits);
struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock,
enum ldlm_mode new_mode, __u32 *flags);
void ldlm_lock_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);
-void ldlm_reprocess_all_ns(struct ldlm_namespace *ns);
-void ldlm_lock_dump_handle(int level, struct lustre_handle *);
+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 */
enum ldlm_type type, __u8 with_policy,
enum ldlm_mode mode, __u64 *flags, void *lvb,
__u32 lvb_len,
- struct lustre_handle *lockh, int rc);
+ const struct lustre_handle *lockh, int rc);
int ldlm_cli_enqueue_local(struct ldlm_namespace *ns,
const struct ldlm_res_id *res_id,
enum ldlm_type type, union ldlm_policy_data *policy,
void *data, __u32 lvb_len, enum lvb_type lvb_type,
const __u64 *client_cookie,
struct lustre_handle *lockh);
-int ldlm_server_ast(struct lustre_handle *lockh, struct ldlm_lock_desc *new,
- void *data, __u32 data_len);
-int ldlm_cli_convert(struct lustre_handle *, int new_mode, __u32 *flags);
+int ldlm_cli_convert(const struct lustre_handle *lockh, int new_mode,
+ __u32 *flags);
int ldlm_cli_update_pool(struct ptlrpc_request *req);
-int ldlm_cli_cancel(struct lustre_handle *lockh,
+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 *,
enum ldlm_cancel_flags flags, void *opaque);
void ldlm_pool_del(struct ldlm_pool *pl, struct ldlm_lock *lock);
/** @} */
+static inline int ldlm_extent_overlap(const struct ldlm_extent *ex1,
+ const struct ldlm_extent *ex2)
+{
+ return ex1->start <= ex2->end && ex2->start <= ex1->end;
+}
+
+/* check if @ex1 contains @ex2 */
+static inline int ldlm_extent_contain(const struct ldlm_extent *ex1,
+ const struct ldlm_extent *ex2)
+{
+ return ex1->start <= ex2->start && ex1->end >= ex2->end;
+}
+
#endif
/** @} LDLM */