Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | /*
* GPL HEADER START
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 only,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is included
* in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; If not, see
* http://www.gnu.org/licenses/gpl-2.0.html
*
* GPL HEADER END
*/
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* Copyright (c) 2011, 2015, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
* Lustre is a trademark of Sun Microsystems, Inc.
*/
#define MAX_STRING_SIZE 128
extern int ldlm_srv_namespace_nr;
extern int ldlm_cli_namespace_nr;
extern struct mutex ldlm_srv_namespace_lock;
extern struct list_head ldlm_srv_namespace_list;
extern struct mutex ldlm_cli_namespace_lock;
extern struct list_head ldlm_cli_active_namespace_list;
static inline int ldlm_namespace_nr_read(enum ldlm_side client)
{
return client == LDLM_NAMESPACE_SERVER ?
ldlm_srv_namespace_nr : ldlm_cli_namespace_nr;
}
static inline void ldlm_namespace_nr_inc(enum ldlm_side client)
{
if (client == LDLM_NAMESPACE_SERVER)
ldlm_srv_namespace_nr++;
else
ldlm_cli_namespace_nr++;
}
static inline void ldlm_namespace_nr_dec(enum ldlm_side client)
{
if (client == LDLM_NAMESPACE_SERVER)
ldlm_srv_namespace_nr--;
else
ldlm_cli_namespace_nr--;
}
static inline struct list_head *ldlm_namespace_list(enum ldlm_side client)
{
return client == LDLM_NAMESPACE_SERVER ?
&ldlm_srv_namespace_list : &ldlm_cli_active_namespace_list;
}
static inline struct mutex *ldlm_namespace_lock(enum ldlm_side client)
{
return client == LDLM_NAMESPACE_SERVER ?
&ldlm_srv_namespace_lock : &ldlm_cli_namespace_lock;
}
/* ns_bref is the number of resources in this namespace */
static inline int ldlm_ns_empty(struct ldlm_namespace *ns)
{
return atomic_read(&ns->ns_bref) == 0;
}
void ldlm_namespace_move_to_active_locked(struct ldlm_namespace *ns,
enum ldlm_side client);
void ldlm_namespace_move_to_inactive_locked(struct ldlm_namespace *ns,
enum ldlm_side client);
struct ldlm_namespace *ldlm_namespace_first_locked(enum ldlm_side client);
/* ldlm_request.c */
/* Cancel lru flag, it indicates we cancel aged locks. */
enum {
LDLM_LRU_FLAG_AGED = BIT(0), /* Cancel aged locks (non lru resize). */
LDLM_LRU_FLAG_PASSED = BIT(1), /* Cancel passed number of locks. */
LDLM_LRU_FLAG_SHRINK = BIT(2), /* Cancel locks from shrinker. */
LDLM_LRU_FLAG_LRUR = BIT(3), /* Cancel locks from lru resize. */
LDLM_LRU_FLAG_NO_WAIT = BIT(4), /* Cancel locks w/o blocking (neither
* sending nor waiting for any rpcs)
*/
LDLM_LRU_FLAG_LRUR_NO_WAIT = BIT(5), /* LRUR + NO_WAIT */
};
int ldlm_cancel_lru(struct ldlm_namespace *ns, int nr,
enum ldlm_cancel_flags sync, int flags);
int ldlm_cancel_lru_local(struct ldlm_namespace *ns,
struct list_head *cancels, int count, int max,
enum ldlm_cancel_flags cancel_flags, int flags);
extern unsigned int ldlm_enqueue_min;
extern unsigned int ldlm_cancel_unused_locks_before_replay;
/* ldlm_resource.c */
int ldlm_resource_putref_locked(struct ldlm_resource *res);
/* ldlm_lock.c */
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 */
};
enum ldlm_desc_ast_t {
LDLM_WORK_BL_AST,
LDLM_WORK_CP_AST,
LDLM_WORK_REVOKE_AST,
LDLM_WORK_GL_AST
};
void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list);
int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill,
enum req_location loc, void *data, int size);
struct ldlm_lock *
ldlm_lock_create(struct ldlm_namespace *ns, const struct ldlm_res_id *id,
enum ldlm_type type, enum ldlm_mode mode,
const struct ldlm_callback_suite *cbs,
void *data, __u32 lvb_len, enum lvb_type lvb_type);
enum ldlm_error ldlm_lock_enqueue(struct ldlm_namespace *ns,
struct ldlm_lock **lock, void *cookie,
__u64 *flags);
void ldlm_lock_addref_internal(struct ldlm_lock *lock, enum ldlm_mode mode);
void ldlm_lock_addref_internal_nolock(struct ldlm_lock *lock,
enum ldlm_mode mode);
void ldlm_lock_decref_internal(struct ldlm_lock *lock, enum ldlm_mode mode);
void ldlm_lock_decref_internal_nolock(struct ldlm_lock *lock,
enum ldlm_mode mode);
int ldlm_run_ast_work(struct ldlm_namespace *ns, struct list_head *rpc_list,
enum ldlm_desc_ast_t ast_type);
int ldlm_lock_remove_from_lru_check(struct ldlm_lock *lock, time_t last_use);
#define ldlm_lock_remove_from_lru(lock) ldlm_lock_remove_from_lru_check(lock, 0)
int ldlm_lock_remove_from_lru_nolock(struct ldlm_lock *lock);
void ldlm_lock_destroy_nolock(struct ldlm_lock *lock);
/* ldlm_lockd.c */
int ldlm_bl_to_thread_lock(struct ldlm_namespace *ns, struct ldlm_lock_desc *ld,
struct ldlm_lock *lock);
int ldlm_bl_to_thread_list(struct ldlm_namespace *ns,
struct ldlm_lock_desc *ld,
struct list_head *cancels, int count,
enum ldlm_cancel_flags cancel_flags);
int ldlm_bl_thread_wakeup(void);
void ldlm_handle_bl_callback(struct ldlm_namespace *ns,
struct ldlm_lock_desc *ld, struct ldlm_lock *lock);
extern struct kmem_cache *ldlm_resource_slab;
extern struct kset *ldlm_ns_kset;
/* ldlm_lockd.c & ldlm_lock.c */
extern struct kmem_cache *ldlm_lock_slab;
/* ldlm_extent.c */
void ldlm_extent_add_lock(struct ldlm_resource *res, struct ldlm_lock *lock);
void ldlm_extent_unlink_lock(struct ldlm_lock *lock);
/* l_lock.c */
void l_check_ns_lock(struct ldlm_namespace *ns);
void l_check_no_ns_lock(struct ldlm_namespace *ns);
extern struct dentry *ldlm_svc_debugfs_dir;
struct ldlm_state {
struct ptlrpc_service *ldlm_cb_service;
struct ptlrpc_service *ldlm_cancel_service;
struct ptlrpc_client *ldlm_client;
struct ptlrpc_connection *ldlm_server_conn;
struct ldlm_bl_pool *ldlm_bl_pool;
};
/* ldlm_pool.c */
__u64 ldlm_pool_get_slv(struct ldlm_pool *pl);
void ldlm_pool_set_clv(struct ldlm_pool *pl, __u64 clv);
__u32 ldlm_pool_get_lvf(struct ldlm_pool *pl);
/* interval tree, for LDLM_EXTENT. */
extern struct kmem_cache *ldlm_interval_slab; /* slab cache for ldlm_interval */
struct ldlm_interval *ldlm_interval_detach(struct ldlm_lock *l);
struct ldlm_interval *ldlm_interval_alloc(struct ldlm_lock *lock);
void ldlm_interval_free(struct ldlm_interval *node);
/* this function must be called with res lock held */
static inline struct ldlm_extent *
ldlm_interval_extent(struct ldlm_interval *node)
{
struct ldlm_lock *lock;
LASSERT(!list_empty(&node->li_group));
lock = list_entry(node->li_group.next, struct ldlm_lock, l_sl_policy);
return &lock->l_policy_data.l_extent;
}
int ldlm_init(void);
void ldlm_exit(void);
enum ldlm_policy_res {
LDLM_POLICY_CANCEL_LOCK,
LDLM_POLICY_KEEP_LOCK,
LDLM_POLICY_SKIP_LOCK
};
#define LDLM_POOL_SYSFS_PRINT_int(v) sprintf(buf, "%d\n", v)
#define LDLM_POOL_SYSFS_SET_int(a, b) { a = b; }
#define LDLM_POOL_SYSFS_PRINT_u64(v) sprintf(buf, "%lld\n", v)
#define LDLM_POOL_SYSFS_SET_u64(a, b) { a = b; }
#define LDLM_POOL_SYSFS_PRINT_atomic(v) sprintf(buf, "%d\n", atomic_read(&v))
#define LDLM_POOL_SYSFS_SET_atomic(a, b) atomic_set(&a, b)
#define LDLM_POOL_SYSFS_READER_SHOW(var, type) \
static ssize_t var##_show(struct kobject *kobj, \
struct attribute *attr, \
char *buf) \
{ \
struct ldlm_pool *pl = container_of(kobj, struct ldlm_pool, \
pl_kobj); \
type tmp; \
\
spin_lock(&pl->pl_lock); \
tmp = pl->pl_##var; \
spin_unlock(&pl->pl_lock); \
\
return LDLM_POOL_SYSFS_PRINT_##type(tmp); \
} \
struct __##var##__dummy_read {; } /* semicolon catcher */
#define LDLM_POOL_SYSFS_WRITER_STORE(var, type) \
static ssize_t var##_store(struct kobject *kobj, \
struct attribute *attr, \
const char *buffer, \
size_t count) \
{ \
struct ldlm_pool *pl = container_of(kobj, struct ldlm_pool, \
pl_kobj); \
unsigned long tmp; \
int rc; \
\
rc = kstrtoul(buffer, 10, &tmp); \
if (rc < 0) { \
return rc; \
} \
\
spin_lock(&pl->pl_lock); \
LDLM_POOL_SYSFS_SET_##type(pl->pl_##var, tmp); \
spin_unlock(&pl->pl_lock); \
\
return count; \
} \
struct __##var##__dummy_write {; } /* semicolon catcher */
#define LDLM_POOL_SYSFS_READER_NOLOCK_SHOW(var, type) \
static ssize_t var##_show(struct kobject *kobj, \
struct attribute *attr, \
char *buf) \
{ \
struct ldlm_pool *pl = container_of(kobj, struct ldlm_pool, \
pl_kobj); \
\
return LDLM_POOL_SYSFS_PRINT_##type(pl->pl_##var); \
} \
struct __##var##__dummy_read {; } /* semicolon catcher */
#define LDLM_POOL_SYSFS_WRITER_NOLOCK_STORE(var, type) \
static ssize_t var##_store(struct kobject *kobj, \
struct attribute *attr, \
const char *buffer, \
size_t count) \
{ \
struct ldlm_pool *pl = container_of(kobj, struct ldlm_pool, \
pl_kobj); \
unsigned long tmp; \
int rc; \
\
rc = kstrtoul(buffer, 10, &tmp); \
if (rc < 0) { \
return rc; \
} \
\
LDLM_POOL_SYSFS_SET_##type(pl->pl_##var, tmp); \
\
return count; \
} \
struct __##var##__dummy_write {; } /* semicolon catcher */
static inline int is_granted_or_cancelled(struct ldlm_lock *lock)
{
int ret = 0;
lock_res_and_lock(lock);
if ((lock->l_req_mode == lock->l_granted_mode) &&
!ldlm_is_cp_reqd(lock))
ret = 1;
else if (ldlm_is_failed(lock) || ldlm_is_cancel(lock))
ret = 1;
unlock_res_and_lock(lock);
return ret;
}
typedef void (*ldlm_policy_wire_to_local_t)(const union ldlm_wire_policy_data *,
union ldlm_policy_data *);
typedef void (*ldlm_policy_local_to_wire_t)(const union ldlm_policy_data *,
union ldlm_wire_policy_data *);
void ldlm_plain_policy_wire_to_local(const union ldlm_wire_policy_data *wpolicy,
union ldlm_policy_data *lpolicy);
void ldlm_plain_policy_local_to_wire(const union ldlm_policy_data *lpolicy,
union ldlm_wire_policy_data *wpolicy);
void ldlm_ibits_policy_wire_to_local(const union ldlm_wire_policy_data *wpolicy,
union ldlm_policy_data *lpolicy);
void ldlm_ibits_policy_local_to_wire(const union ldlm_policy_data *lpolicy,
union ldlm_wire_policy_data *wpolicy);
void ldlm_extent_policy_wire_to_local(const union ldlm_wire_policy_data *wpolicy,
union ldlm_policy_data *lpolicy);
void ldlm_extent_policy_local_to_wire(const union ldlm_policy_data *lpolicy,
union ldlm_wire_policy_data *wpolicy);
void ldlm_flock_policy_wire_to_local(const union ldlm_wire_policy_data *wpolicy,
union ldlm_policy_data *lpolicy);
void ldlm_flock_policy_local_to_wire(const union ldlm_policy_data *lpolicy,
union ldlm_wire_policy_data *wpolicy);
|