LVB_T_OST = 1,
LVB_T_LQUOTA = 2,
LVB_T_LAYOUT = 3,
+ LVB_T_END
};
/**
* Internal structures per lock type..
*/
union {
- /* LDLM_EXTENT locks only */
- struct {
+ struct { /* LDLM_EXTENT locks only */
/* Originally requested extent for the extent lock. */
struct ldlm_extent l_req_extent;
struct rb_node l_rb;
u64 l_subtree_last;
struct list_head l_same_extent;
};
- /* LDLM_PLAIN and LDLM_IBITS locks */
- struct {
+ struct { /* LDLM_PLAIN and LDLM_IBITS locks */
/**
* Protected by lr_lock, linkages to "skip lists".
- * For more explanations of skip lists see ldlm/ldlm_inodebits.c
+ * For explanations of skip lists see
+ * ldlm/ldlm_inodebits.c
*/
struct list_head l_sl_mode;
struct list_head l_sl_policy;
struct ldlm_ibits_node *l_ibits_node;
+ /* separate ost_lvb used mostly by Data-on-MDT for now.
+ * It is introduced to don't mix with layout lock data.
+ */
+ struct ost_lvb l_ost_lvb;
};
- /* LDLM_FLOCK locks */
- struct {
+ struct { /* LDLM_FLOCK locks */
/**
* Per export hash of flock locks.
* Protected by per-bucket exp->exp_flock_hash locks.
* Protected by per-bucket exp->exp_lock_hash locks.
*/
struct hlist_node l_exp_hash;
+
+ /* Requested mode. Protected by lr_lock. */
+ enum ldlm_mode l_req_mode:9;
+ /* Granted mode, also protected by lr_lock. */
+ enum ldlm_mode l_granted_mode:9;
+
/**
- * Requested mode.
- * Protected by lr_lock.
+ * Whether the blocking AST was sent for this lock.
+ * This is for debugging. Valid values are 0 and 1, if there is an
+ * attempt to send blocking AST more than once, an assertion would be
+ * hit. \see ldlm_work_bl_ast_lock
*/
- enum ldlm_mode l_req_mode;
- /**
- * Granted mode, also protected by lr_lock.
+ unsigned int l_bl_ast_run:1;
+
+ /* content type for lock value block */
+ enum lvb_type l_lvb_type:3;
+ /* unsigned int l_unused_bits:10; */
+ u16 l_lvb_len;
+ /* u16 l_unused; */
+
+ /*
+ * Temporary storage for a LVB received during an enqueue operation.
+ * May be vmalloc'd, so needs to be freed with OBD_FREE_LARGE().
*/
- enum ldlm_mode l_granted_mode;
+ void *l_lvb_data;
+
/** Lock completion handler pointer. Called when lock is granted. */
ldlm_completion_callback l_completion_ast;
/**
*/
ktime_t l_last_used;
- /*
- * Client-side-only members.
- */
-
- enum lvb_type l_lvb_type;
-
- /**
- * Temporary storage for a LVB received during an enqueue operation.
- * May be vmalloc'd, so needs to be freed with OBD_FREE_LARGE().
- */
- __u32 l_lvb_len;
- void *l_lvb_data;
-
/** Private storage for lock user. Opaque to LDLM. */
void *l_ast_data;
time64_t l_blast_sent;
};
- /* separate ost_lvb used mostly by Data-on-MDT for now.
- * It is introduced to don't mix with layout lock data.
- */
- struct ost_lvb l_ost_lvb;
/*
* Server-side-only members.
*/
/** Local PID of process which created this lock. */
__u32 l_pid;
+ /* __u32 l_unused; */
- /**
- * Number of times blocking AST was sent for this lock.
- * This is for debugging. Valid values are 0 and 1, if there is an
- * attempt to send blocking AST more than once, an assertion would be
- * hit. \see ldlm_work_bl_ast_lock
- */
- int l_bl_ast_run;
/** List item ldlm_add_ast_work_item() for case of blocking ASTs. */
struct list_head l_bl_ast;
/** List item ldlm_add_ast_work_item() for case of completion ASTs. */
};
/** Type of locks this resource can hold. Only one type per resource. */
- enum ldlm_type lr_type; /* LDLM_{PLAIN,EXTENT,FLOCK,IBITS} */
+ enum ldlm_type lr_type:4; /* LDLM_{PLAIN,EXTENT,FLOCK,IBITS} */
+ /* unsigned int lr_unused_bits:4; */
+ /* char lr_unused[5]; */
/**
* Server-side-only lock value block elements.
* To serialize lvbo_init.
*/
- int lr_lvb_len;
+ bool lr_lvb_initialized;
+ char lr_lvb_len;
struct mutex lr_lvb_mutex;
/** protected by lr_lock */
void *lr_lvb_data;
- /** is lvb initialized ? */
- bool lr_lvb_initialized;
};
static inline int ldlm_is_granted(struct ldlm_lock *lock)
/** The caller must guarantee that the buffer is large enough. */
int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill,
- enum req_location loc, void *data, int size)
+ enum req_location loc, void *data, int lvb_len)
{
void *lvb;
ENTRY;
LASSERT(data != NULL);
- LASSERT(size >= 0);
+ LASSERT(lvb_len >= 0);
switch (lock->l_lvb_type) {
case LVB_T_OST:
- if (size == sizeof(struct ost_lvb)) {
+ if (lvb_len == sizeof(struct ost_lvb)) {
if (loc == RCL_CLIENT)
lvb = req_capsule_client_swab_get(pill,
&RMF_DLM_LVB,
RETURN(-EPROTO);
}
- memcpy(data, lvb, size);
- } else if (size == sizeof(struct ost_lvb_v1)) {
+ memcpy(data, lvb, lvb_len);
+ } else if (lvb_len == sizeof(struct ost_lvb_v1)) {
struct ost_lvb *olvb = data;
if (loc == RCL_CLIENT)
lustre_swab_ost_lvb_v1);
else
lvb = req_capsule_server_sized_swab_get(pill,
- &RMF_DLM_LVB, size,
+ &RMF_DLM_LVB, lvb_len,
lustre_swab_ost_lvb_v1);
if (unlikely(lvb == NULL)) {
LDLM_ERROR(lock, "no LVB");
RETURN(-EPROTO);
}
- memcpy(data, lvb, size);
+ memcpy(data, lvb, lvb_len);
olvb->lvb_mtime_ns = 0;
olvb->lvb_atime_ns = 0;
olvb->lvb_ctime_ns = 0;
} else {
LDLM_ERROR(lock, "Replied unexpected ost LVB size %d",
- size);
+ lvb_len);
RETURN(-EINVAL);
}
break;
case LVB_T_LQUOTA:
- if (size == sizeof(struct lquota_lvb)) {
+ if (lvb_len == sizeof(struct lquota_lvb)) {
if (loc == RCL_CLIENT)
lvb = req_capsule_client_swab_get(pill,
&RMF_DLM_LVB,
RETURN(-EPROTO);
}
- memcpy(data, lvb, size);
+ memcpy(data, lvb, lvb_len);
} else {
LDLM_ERROR(lock,
"Replied unexpected lquota LVB size %d",
- size);
+ lvb_len);
RETURN(-EINVAL);
}
break;
case LVB_T_LAYOUT:
- if (size == 0)
+ if (lvb_len == 0)
break;
if (loc == RCL_CLIENT)
RETURN(-EPROTO);
}
- memcpy(data, lvb, size);
+ memcpy(data, lvb, lvb_len);
break;
default:
- LDLM_ERROR(lock, "Unknown LVB type: %d", lock->l_lvb_type);
+ LDLM_ERROR(lock, "Unknown LVB type=%d, size=%d",
+ lock->l_lvb_type, lvb_len);
dump_stack();
RETURN(-EINVAL);
}
}
if (lvb_len) {
+ LASSERT(lvb_len < 1 << sizeof(lock->l_lvb_len) * 8);
lock->l_lvb_len = lvb_len;
OBD_ALLOC_LARGE(lock->l_lvb_data, lvb_len);
if (lock->l_lvb_data == NULL)
LASSERT(ldlm_is_ast_sent(lock));
LASSERT(lock->l_bl_ast_run == 0);
- lock->l_bl_ast_run++;
+ lock->l_bl_ast_run = 1;
ldlm_clear_blocking_lock(lock);
unlock_res_and_lock(lock);
if (unlikely(lock->l_lvb_len < lvb_len)) {
LDLM_ERROR(lock,
- "Replied LVB is larger than expectation, expected = %d, replied = %d",
+ "Replied LVB is larger than expectation, expected = %u, replied = %u",
lock->l_lvb_len, lvb_len);
GOTO(out, rc = -EINVAL);
}
int ldlm_init(void)
{
+ BUILD_BUG_ON(LDLM_MAX_TYPE > (1 << 4 /* lr_type bits */));
+ BUILD_BUG_ON(LVB_T_END > (1 << 3 /* l_lvb_type bits */));
+ BUILD_BUG_ON(LCK_MAXMODE > (1 << 9 /* l_req_mode/l_granted_mode */));
+
ldlm_resource_slab = kmem_cache_create("ldlm_resources",
sizeof(struct ldlm_resource), 0,
SLAB_HWCACHE_ALIGN, NULL);
}
LASSERTF(ergo(lvb_len != 0, lvb_len == lock->l_lvb_len),
- "lvb_len = %d, l_lvb_len = %d\n", lvb_len, lock->l_lvb_len);
+ "lvb_len = %u, l_lvb_len = %u\n", lvb_len, lock->l_lvb_len);
if (rc != ELDLM_OK) {
LASSERT(!is_replay);
int rc;
ENTRY;
- CDEBUG(D_INODE, DFID" LVB_READY=%d l_lvb_data=%p l_lvb_len=%d\n",
+ CDEBUG(D_INODE, DFID" LVB_READY=%d l_lvb_data=%p l_lvb_len=%u\n",
PFID(ll_inode2fid(inode)), ldlm_is_lvb_ready(lock),
lock->l_lvb_data, lock->l_lvb_len);
if (lvb == NULL) {
LASSERT(dlmlock != NULL);
+ /* l_ost_lvb is only in the LDLM_IBITS union **/
+ LASSERT(dlmlock->l_resource->lr_type == LDLM_IBITS);
lvb = &dlmlock->l_ost_lvb;
}
cl_lvb2attr(attr, lvb);
/* At this point ols_lvb must be filled with correct LVB either
* by mdc_fill_lvb() above or by ldlm_cli_enqueue_fini().
- * DoM uses l_ost_lvb to store LVB data, so copy it here from
- * just updated ols_lvb.
+ * DoM uses l_ost_lvb to store LVB data (only available with
+ * LDLM_IBITS locks), so copy it here from just updated ols_lvb.
*/
+ LASSERT(lock->l_resource->lr_type == LDLM_IBITS);
lock_res_and_lock(lock);
memcpy(&lock->l_ost_lvb, &ols->ols_lvb,
sizeof(lock->l_ost_lvb));
struct lov_oinfo *oinfo;
ENTRY;
- if (lock->l_ast_data == data) {
- lock->l_ast_data = NULL;
-
- LASSERT(osc != NULL);
- LASSERT(osc->oo_oinfo != NULL);
- LASSERT(lvb != NULL);
-
- /* Updates lvb in lock by the cached oinfo */
- oinfo = osc->oo_oinfo;
-
- LDLM_DEBUG(lock, "update lock size %llu blocks %llu [cma]time: "
- "%llu %llu %llu by oinfo size %llu blocks %llu "
- "[cma]time %llu %llu %llu", lvb->lvb_size,
- lvb->lvb_blocks, lvb->lvb_ctime, lvb->lvb_mtime,
- lvb->lvb_atime, oinfo->loi_lvb.lvb_size,
- oinfo->loi_lvb.lvb_blocks, oinfo->loi_lvb.lvb_ctime,
- oinfo->loi_lvb.lvb_mtime, oinfo->loi_lvb.lvb_atime);
- LASSERT(oinfo->loi_lvb.lvb_size >= oinfo->loi_kms);
-
- cl_object_attr_lock(&osc->oo_cl);
- memcpy(lvb, &oinfo->loi_lvb, sizeof(oinfo->loi_lvb));
- cl_object_attr_unlock(&osc->oo_cl);
- ldlm_clear_lvb_cached(lock);
- }
+ if (lock->l_ast_data != data)
+ RETURN(LDLM_ITER_CONTINUE);
+
+ lock->l_ast_data = NULL;
+
+ LASSERT(osc != NULL);
+ LASSERT(osc->oo_oinfo != NULL);
+
+ /* Updates lvb in lock by the cached oinfo */
+ oinfo = osc->oo_oinfo;
+
+ LDLM_DEBUG(lock,
+ "update lock size %llu blocks %llu [cma]time: %llu %llu %llu by oinfo size %llu blocks %llu [cma]time %llu %llu %llu",
+ lvb->lvb_size, lvb->lvb_blocks, lvb->lvb_ctime,
+ lvb->lvb_mtime, lvb->lvb_atime, oinfo->loi_lvb.lvb_size,
+ oinfo->loi_lvb.lvb_blocks, oinfo->loi_lvb.lvb_ctime,
+ oinfo->loi_lvb.lvb_mtime, oinfo->loi_lvb.lvb_atime);
+ LASSERT(oinfo->loi_lvb.lvb_size >= oinfo->loi_kms);
+
+ cl_object_attr_lock(&osc->oo_cl);
+ /* l_ost_lvb is only in the LDLM_IBITS union **/
+ LASSERT(lock->l_resource->lr_type == LDLM_IBITS);
+ memcpy(lvb, &oinfo->loi_lvb, sizeof(oinfo->loi_lvb));
+ cl_object_attr_unlock(&osc->oo_cl);
+ ldlm_clear_lvb_cached(lock);
+
RETURN(LDLM_ITER_CONTINUE);
}
LDLM_DEBUG(lock, "DoM lock is returned by: %s, size: %llu",
ldlm_it2str(it->it_op), body->mbo_dom_size);
+ /* l_ost_lvb is only in the LDLM_IBITS union **/
+ LASSERT(lock->l_resource->lr_type == LDLM_IBITS);
lock_res_and_lock(lock);
mdc_body2lvb(body, &lock->l_ost_lvb);
ldlm_lock_allow_match_locked(lock);
}
res->lr_lvb_data = lvb;
+ BUILD_BUG_ON(sizeof(*lvb) >= 1<<(sizeof(res->lr_lvb_len)*8-1));
res->lr_lvb_len = sizeof(*lvb);
/* Store error in LVB to inidicate it has no data yet.
info = ofd_info(env);
res->lr_lvb_data = lvb;
+ BUILD_BUG_ON(sizeof(*lvb) >= 1 << (sizeof(res->lr_lvb_len) * 8 - 1));
res->lr_lvb_len = sizeof(*lvb);
ost_fid_from_resid(&info->fti_fid, &res->lr_name,