* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2011, 2014, Intel Corporation.
+ * Copyright (c) 2011, 2015, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
* If \a bias is MDS_CLOSE_LAYOUT_SWAP then \a data is a pointer to the inode to
* swap layouts with.
*/
-static int ll_close_inode_openhandle(struct obd_export *md_exp,
+static int ll_close_inode_openhandle(struct inode *inode,
struct obd_client_handle *och,
- struct inode *inode,
- enum mds_op_bias bias,
- void *data)
+ enum mds_op_bias bias, void *data)
{
- struct obd_export *exp = ll_i2mdexp(inode);
- struct md_op_data *op_data;
- struct ptlrpc_request *req = NULL;
- struct obd_device *obd = class_exp2obd(exp);
- int rc;
+ struct obd_export *md_exp = ll_i2mdexp(inode);
+ const struct ll_inode_info *lli = ll_i2info(inode);
+ struct md_op_data *op_data;
+ struct ptlrpc_request *req = NULL;
+ int rc;
ENTRY;
- if (obd == NULL) {
- /*
- * XXX: in case of LMV, is this correct to access
- * ->exp_handle?
- */
- CERROR("Invalid MDC connection handle "LPX64"\n",
- ll_i2mdexp(inode)->exp_handle.h_cookie);
+ if (class_exp2obd(md_exp) == NULL) {
+ CERROR("%s: invalid MDC connection handle closing "DFID"\n",
+ ll_get_fsname(inode->i_sb, NULL, 0),
+ PFID(&lli->lli_fid));
GOTO(out, rc = 0);
}
OBD_ALLOC_PTR(op_data);
+ /* We leak openhandle and request here on error, but not much to be
+ * done in OOM case since app won't retry close on error either. */
if (op_data == NULL)
- /* XXX We leak openhandle and request here. */
GOTO(out, rc = -ENOMEM);
ll_prepare_close(inode, op_data, och);
break;
}
- rc = md_close(md_exp, op_data, och->och_mod, &req);
- if (rc) {
+ rc = md_close(md_exp, op_data, och->och_mod, &req);
+ if (rc != 0 && rc != -EINTR)
CERROR("%s: inode "DFID" mdc close failed: rc = %d\n",
- ll_i2mdexp(inode)->exp_obd->obd_name,
- PFID(ll_inode2fid(inode)), rc);
- }
+ md_exp->exp_obd->obd_name, PFID(&lli->lli_fid), rc);
if (rc == 0 &&
op_data->op_bias & (MDS_HSM_RELEASE | MDS_CLOSE_LAYOUT_SWAP)) {
och->och_fh.cookie = DEAD_HANDLE_MAGIC;
OBD_FREE_PTR(och);
- if (req) /* This is close request */
- ptlrpc_req_finished(req);
- return rc;
+ ptlrpc_req_finished(req); /* This is close request */
+ return rc;
}
int ll_md_real_close(struct inode *inode, fmode_t fmode)
if (och != NULL) {
/* There might be a race and this handle may already
* be closed. */
- rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp,
- och, inode, 0, NULL);
+ rc = ll_close_inode_openhandle(inode, och, 0, NULL);
}
RETURN(rc);
}
-static int ll_md_close(struct obd_export *md_exp, struct inode *inode,
- struct file *file)
+static int ll_md_close(struct inode *inode, struct file *file)
{
- ldlm_policy_data_t policy = {
+ union ldlm_policy_data policy = {
.l_inodebits = { MDS_INODELOCK_OPEN },
};
__u64 flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_TEST_LOCK;
struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
struct ll_inode_info *lli = ll_i2info(inode);
struct lustre_handle lockh;
- int lockmode;
+ enum ldlm_mode lockmode;
int rc = 0;
ENTRY;
}
if (fd->fd_och != NULL) {
- rc = ll_close_inode_openhandle(md_exp, fd->fd_och, inode, 0,
- NULL);
+ rc = ll_close_inode_openhandle(inode, fd->fd_och, 0, NULL);
fd->fd_och = NULL;
GOTO(out, rc);
}
}
mutex_unlock(&lli->lli_och_mutex);
- if (!md_lock_match(md_exp, flags, ll_inode2fid(inode),
+ if (!md_lock_match(ll_i2mdexp(inode), flags, ll_inode2fid(inode),
LDLM_IBITS, &policy, lockmode, &lockh))
rc = ll_md_real_close(inode, fd->fd_omode);
ll_deauthorize_statahead(inode, fd);
if (inode->i_sb->s_root == file->f_path.dentry) {
- LUSTRE_FPRIVATE(file) = NULL;
- ll_file_data_put(fd);
- RETURN(0);
- }
+ LUSTRE_FPRIVATE(file) = NULL;
+ ll_file_data_put(fd);
+ RETURN(0);
+ }
- if (!S_ISDIR(inode->i_mode)) {
+ if (!S_ISDIR(inode->i_mode)) {
if (lli->lli_clob != NULL)
lov_read_and_clear_async_rc(lli->lli_clob);
- lli->lli_async_rc = 0;
- }
+ lli->lli_async_rc = 0;
+ }
- rc = ll_md_close(sbi->ll_md_exp, inode, file);
+ rc = ll_md_close(inode, file);
- if (CFS_FAIL_TIMEOUT_MS(OBD_FAIL_PTLRPC_DUMP_LOG, cfs_fail_val))
- libcfs_debug_dumplog();
+ if (CFS_FAIL_TIMEOUT_MS(OBD_FAIL_PTLRPC_DUMP_LOG, cfs_fail_val))
+ libcfs_debug_dumplog();
- RETURN(rc);
+ RETURN(rc);
}
static int ll_intent_file_open(struct file *file, void *lmm, int lmmsize,
it.d.lustre.it_lock_mode = 0;
och->och_lease_handle.cookie = 0ULL;
}
- rc2 = ll_close_inode_openhandle(sbi->ll_md_exp, och, inode, 0, NULL);
+ rc2 = ll_close_inode_openhandle(inode, och, 0, NULL);
if (rc2 < 0)
CERROR("%s: error closing file "DFID": %d\n",
ll_get_fsname(inode->i_sb, NULL, 0),
/* Close the file and swap layouts between inode & inode2.
* NB: lease lock handle is released in mdc_close_layout_swap_pack()
* because we still need it to pack l_remote_handle to MDT. */
- rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, och, inode,
- MDS_CLOSE_LAYOUT_SWAP, inode2);
+ rc = ll_close_inode_openhandle(inode, och, MDS_CLOSE_LAYOUT_SWAP,
+ inode2);
och = NULL; /* freed in ll_close_inode_openhandle() */
if (lease_broken != NULL)
*lease_broken = cancelled;
- rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, och, inode,
- 0, NULL);
-
+ rc = ll_close_inode_openhandle(inode, och, 0, NULL);
RETURN(rc);
}
ll_stats_ops_tally(ll_i2sbi(inode),
LPROC_LL_WRITE_BYTES, result);
fd->fd_write_failed = false;
+ } else if (result == 0 && rc == 0) {
+ rc = io->ci_result;
+ if (rc < 0)
+ fd->fd_write_failed = true;
+ else
+ fd->fd_write_failed = false;
} else if (rc != -ERESTARTSYS) {
fd->fd_write_failed = true;
}
struct vvp_io_args *args;
struct lu_env *env;
ssize_t result;
- int refcheck;
+ __u16 refcheck;
env = cl_env_get(&refcheck);
if (IS_ERR(env))
struct vvp_io_args *args;
struct lu_env *env;
ssize_t result;
- int refcheck;
+ __u16 refcheck;
env = cl_env_get(&refcheck);
if (IS_ERR(env))
struct iov_iter *to;
size_t iov_count;
ssize_t result;
+ struct lu_env *env = NULL;
+ __u16 refcheck;
ENTRY;
result = ll_file_get_iov_count(iov, &nr_segs, &iov_count);
RETURN(result);
if (nr_segs == 1) {
- struct lu_env *env;
- int refcheck;
env = cl_env_get(&refcheck);
if (IS_ERR(env))
local_iov = &ll_env_info(env)->lti_local_iov;
*local_iov = *iov;
- cl_env_put(env, &refcheck);
} else {
OBD_ALLOC(local_iov, sizeof(*iov) * nr_segs);
if (local_iov == NULL)
OBD_FREE_PTR(to);
out:
- if (nr_segs > 1)
+ if (nr_segs == 1)
+ cl_env_put(env, &refcheck);
+ else
OBD_FREE(local_iov, sizeof(*iov) * nr_segs);
RETURN(result);
struct iovec iov = { .iov_base = buf, .iov_len = count };
struct kiocb *kiocb;
ssize_t result;
- int refcheck;
+ __u16 refcheck;
ENTRY;
env = cl_env_get(&refcheck);
struct iov_iter *from;
size_t iov_count;
ssize_t result;
+ struct lu_env *env = NULL;
+ __u16 refcheck;
ENTRY;
result = ll_file_get_iov_count(iov, &nr_segs, &iov_count);
RETURN(result);
if (nr_segs == 1) {
- struct lu_env *env;
- int refcheck;
-
env = cl_env_get(&refcheck);
if (IS_ERR(env))
RETURN(PTR_ERR(env));
local_iov = &ll_env_info(env)->lti_local_iov;
*local_iov = *iov;
-
- cl_env_put(env, &refcheck);
} else {
OBD_ALLOC(local_iov, sizeof(*iov) * nr_segs);
if (local_iov == NULL)
OBD_FREE_PTR(from);
out:
- if (nr_segs > 1)
+ if (nr_segs == 1)
+ cl_env_put(env, &refcheck);
+ else
OBD_FREE(local_iov, sizeof(*iov) * nr_segs);
RETURN(result);
.iov_len = count };
struct kiocb *kiocb;
ssize_t result;
- int refcheck;
+ __u16 refcheck;
ENTRY;
env = cl_env_get(&refcheck);
struct lu_env *env;
struct vvp_io_args *args;
ssize_t result;
- int refcheck;
+ __u16 refcheck;
ENTRY;
env = cl_env_get(&refcheck);
struct lov_user_md __user *lum)
{
struct lu_env *env;
- int refcheck;
+ __u16 refcheck;
int rc;
ENTRY;
ll_och_fill(ll_i2sbi(inode)->ll_md_exp, it, och);
- rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp,
- och, inode, 0, NULL);
+ rc = ll_close_inode_openhandle(inode, och, 0, NULL);
out:
/* this one is in place of ll_file_open */
if (it_disposition(it, DISP_ENQ_OPEN_REF)) {
size_t num_bytes)
{
struct lu_env *env;
- int refcheck;
+ __u16 refcheck;
int rc = 0;
struct ll_fiemap_info_key fmkey = { .lfik_name = KEY_FIEMAP, };
ENTRY;
struct cl_object *obj = ll_i2info(inode)->lli_clob;
struct lu_env *env;
struct cl_io *io;
- int refcheck;
+ __u16 refcheck;
int result;
ENTRY;
/* Release the file.
* NB: lease lock handle is released in mdc_hsm_release_pack() because
* we still need it to pack l_remote_handle to MDT. */
- rc = ll_close_inode_openhandle(ll_i2sbi(inode)->ll_md_exp, och, inode,
- MDS_HSM_RELEASE, &data_version);
+ rc = ll_close_inode_openhandle(inode, och, MDS_HSM_RELEASE,
+ &data_version);
och = NULL;
EXIT;
((fmode & FMODE_WRITE) ? LL_LEASE_WRLCK : 0);
}
+static int ll_file_futimes_3(struct file *file, const struct ll_futimes_3 *lfu)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct iattr ia = {
+ .ia_valid = ATTR_ATIME | ATTR_ATIME_SET |
+ ATTR_MTIME | ATTR_MTIME_SET |
+ ATTR_CTIME | ATTR_CTIME_SET,
+ .ia_atime = {
+ .tv_sec = lfu->lfu_atime_sec,
+ .tv_nsec = lfu->lfu_atime_nsec,
+ },
+ .ia_mtime = {
+ .tv_sec = lfu->lfu_mtime_sec,
+ .tv_nsec = lfu->lfu_mtime_nsec,
+ },
+ .ia_ctime = {
+ .tv_sec = lfu->lfu_ctime_sec,
+ .tv_nsec = lfu->lfu_ctime_nsec,
+ },
+ };
+ int rc;
+ ENTRY;
+
+ if (!capable(CAP_SYS_ADMIN))
+ RETURN(-EPERM);
+
+ if (!S_ISREG(inode->i_mode))
+ RETURN(-EINVAL);
+
+ mutex_lock(&inode->i_mutex);
+ rc = ll_setattr_raw(file->f_path.dentry, &ia, false);
+ mutex_unlock(&inode->i_mutex);
+
+ RETURN(rc);
+}
+
static long
ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
OBD_FREE_PTR(hui);
RETURN(rc);
}
+ case LL_IOC_FUTIMES_3: {
+ struct ll_futimes_3 lfu;
+
+ if (copy_from_user(&lfu,
+ (const struct ll_futimes_3 __user *)arg,
+ sizeof(lfu)))
+ RETURN(-EFAULT);
+ RETURN(ll_file_futimes_3(file, &lfu));
+ }
default: {
int err;
.ei_cbdata = file_lock,
};
struct md_op_data *op_data;
- struct lustre_handle lockh = {0};
- ldlm_policy_data_t flock = {{0}};
+ struct lustre_handle lockh = { 0 };
+ union ldlm_policy_data flock = { { 0 } };
int fl_type = file_lock->fl_type;
__u64 flags = 0;
int rc;
}
int ll_get_fid_by_name(struct inode *parent, const char *name,
- int namelen, struct lu_fid *fid)
+ int namelen, struct lu_fid *fid,
+ struct inode **inode)
{
struct md_op_data *op_data = NULL;
struct mdt_body *body;
if (IS_ERR(op_data))
RETURN(PTR_ERR(op_data));
- op_data->op_valid = OBD_MD_FLID;
+ op_data->op_valid = OBD_MD_FLID | OBD_MD_FLTYPE;
rc = md_getattr_name(ll_i2sbi(parent)->ll_md_exp, op_data, &req);
ll_finish_md_op_data(op_data);
if (rc < 0)
GOTO(out_req, rc = -EFAULT);
if (fid != NULL)
*fid = body->mbo_fid1;
+
+ if (inode != NULL)
+ rc = ll_prep_inode(inode, req, parent->i_sb, NULL);
out_req:
ptlrpc_req_finished(req);
RETURN(rc);
struct inode *child_inode = NULL;
struct md_op_data *op_data;
struct ptlrpc_request *request = NULL;
+ struct obd_client_handle *och = NULL;
struct qstr qstr;
+ struct mdt_body *body;
int rc;
+ __u64 data_version = 0;
ENTRY;
CDEBUG(D_VFSTRACE, "migrate %s under "DFID" to MDT%04x\n",
qstr.len = namelen;
dchild = d_lookup(file->f_path.dentry, &qstr);
if (dchild != NULL) {
- if (dchild->d_inode != NULL) {
+ if (dchild->d_inode != NULL)
child_inode = igrab(dchild->d_inode);
- if (child_inode != NULL) {
- mutex_lock(&child_inode->i_mutex);
- op_data->op_fid3 = *ll_inode2fid(child_inode);
- ll_invalidate_aliases(child_inode);
- }
- }
dput(dchild);
- } else {
+ }
+
+ if (child_inode == NULL) {
rc = ll_get_fid_by_name(parent, name, namelen,
- &op_data->op_fid3);
+ &op_data->op_fid3, &child_inode);
if (rc != 0)
GOTO(out_free, rc);
}
+ if (child_inode == NULL)
+ GOTO(out_free, rc = -EINVAL);
+
+ mutex_lock(&child_inode->i_mutex);
+ op_data->op_fid3 = *ll_inode2fid(child_inode);
if (!fid_is_sane(&op_data->op_fid3)) {
- CERROR("%s: migrate %s , but fid "DFID" is insane\n",
+ CERROR("%s: migrate %s, but FID "DFID" is insane\n",
ll_get_fsname(parent->i_sb, NULL, 0), name,
PFID(&op_data->op_fid3));
- GOTO(out_free, rc = -EINVAL);
+ GOTO(out_unlock, rc = -EINVAL);
}
rc = ll_get_mdt_idx_by_fid(ll_i2sbi(parent), &op_data->op_fid3);
if (rc < 0)
- GOTO(out_free, rc);
+ GOTO(out_unlock, rc);
if (rc == mdtidx) {
- CDEBUG(D_INFO, "%s:"DFID" is already on MDT%d.\n", name,
+ CDEBUG(D_INFO, "%s: "DFID" is already on MDT%04x\n", name,
PFID(&op_data->op_fid3), mdtidx);
- GOTO(out_free, rc = 0);
+ GOTO(out_unlock, rc = 0);
+ }
+again:
+ if (S_ISREG(child_inode->i_mode)) {
+ och = ll_lease_open(child_inode, NULL, FMODE_WRITE, 0);
+ if (IS_ERR(och)) {
+ rc = PTR_ERR(och);
+ och = NULL;
+ GOTO(out_unlock, rc);
+ }
+
+ rc = ll_data_version(child_inode, &data_version,
+ LL_DV_WR_FLUSH);
+ if (rc != 0)
+ GOTO(out_close, rc);
+
+ op_data->op_handle = och->och_fh;
+ op_data->op_data = och->och_mod;
+ op_data->op_data_version = data_version;
+ op_data->op_lease_handle = och->och_lease_handle;
+ op_data->op_bias |= MDS_RENAME_MIGRATE;
}
op_data->op_mds = mdtidx;
if (rc == 0)
ll_update_times(request, parent);
- ptlrpc_req_finished(request);
- if (rc != 0)
- GOTO(out_free, rc);
+ if (request != NULL) {
+ body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY);
+ if (body == NULL) {
+ ptlrpc_req_finished(request);
+ GOTO(out_close, rc = -EPROTO);
+ }
-out_free:
- if (child_inode != NULL) {
- clear_nlink(child_inode);
- mutex_unlock(&child_inode->i_mutex);
- iput(child_inode);
+ /* If the server does release layout lock, then we cleanup
+ * the client och here, otherwise release it in out_close: */
+ if (och != NULL &&
+ body->mbo_valid & OBD_MD_CLOSE_INTENT_EXECED) {
+ obd_mod_put(och->och_mod);
+ md_clear_open_replay_data(ll_i2sbi(parent)->ll_md_exp,
+ och);
+ och->och_fh.cookie = DEAD_HANDLE_MAGIC;
+ OBD_FREE_PTR(och);
+ och = NULL;
+ }
+ ptlrpc_req_finished(request);
}
+ /* Try again if the file layout has changed. */
+ if (rc == -EAGAIN && S_ISREG(child_inode->i_mode)) {
+ request = NULL;
+ goto again;
+ }
+out_close:
+ if (och != NULL) /* close the file */
+ ll_lease_close(och, child_inode, NULL);
+ if (rc == 0)
+ clear_nlink(child_inode);
+out_unlock:
+ mutex_unlock(&child_inode->i_mutex);
+ iput(child_inode);
+out_free:
ll_finish_md_op_data(op_data);
RETURN(rc);
}
* \param l_req_mode [IN] searched lock mode
* \retval boolean, true iff all bits are found
*/
-int ll_have_md_lock(struct inode *inode, __u64 *bits, ldlm_mode_t l_req_mode)
+int ll_have_md_lock(struct inode *inode, __u64 *bits, enum ldlm_mode l_req_mode)
{
- struct lustre_handle lockh;
- ldlm_policy_data_t policy;
- ldlm_mode_t mode = (l_req_mode == LCK_MINMODE) ?
- (LCK_CR|LCK_CW|LCK_PR|LCK_PW) : l_req_mode;
- struct lu_fid *fid;
+ struct lustre_handle lockh;
+ union ldlm_policy_data policy;
+ enum ldlm_mode mode = (l_req_mode == LCK_MINMODE) ?
+ (LCK_CR | LCK_CW | LCK_PR | LCK_PW) : l_req_mode;
+ struct lu_fid *fid;
__u64 flags;
- int i;
- ENTRY;
+ int i;
+ ENTRY;
if (!inode)
RETURN(0);
RETURN(*bits == 0);
}
-ldlm_mode_t ll_take_md_lock(struct inode *inode, __u64 bits,
- struct lustre_handle *lockh, __u64 flags,
- ldlm_mode_t mode)
+enum ldlm_mode ll_take_md_lock(struct inode *inode, __u64 bits,
+ struct lustre_handle *lockh, __u64 flags,
+ enum ldlm_mode mode)
{
- ldlm_policy_data_t policy = { .l_inodebits = {bits}};
- struct lu_fid *fid;
- ldlm_mode_t rc;
- ENTRY;
+ union ldlm_policy_data policy = { .l_inodebits = { bits } };
+ struct lu_fid *fid;
+ enum ldlm_mode rc;
+ ENTRY;
- fid = &ll_i2info(inode)->lli_fid;
- CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid));
+ fid = &ll_i2info(inode)->lli_fid;
+ CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid));
rc = md_lock_match(ll_i2mdexp(inode), LDLM_FL_BLOCK_GRANTED|flags,
fid, LDLM_IBITS, &policy, mode, lockh);
/* Already unlinked. Just update nlink and return success */
if (rc == -ENOENT) {
clear_nlink(inode);
+ /* If it is striped directory, and there is bad stripe
+ * Let's revalidate the dentry again, instead of returning
+ * error */
+ if (S_ISDIR(inode->i_mode) &&
+ ll_i2info(inode)->lli_lsm_md != NULL)
+ return 0;
+
/* This path cannot be hit for regular files unless in
* case of obscure races, so no need to to validate
* size. */
/* -o localflock - only provides locally consistent flock locks */
struct file_operations ll_file_operations = {
#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
+# ifdef HAVE_SYNC_READ_WRITE
.read = new_sync_read,
- .read_iter = ll_file_read_iter,
.write = new_sync_write,
+# endif
+ .read_iter = ll_file_read_iter,
.write_iter = ll_file_write_iter,
#else /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
.read = ll_file_read,
struct file_operations ll_file_operations_flock = {
#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
+# ifdef HAVE_SYNC_READ_WRITE
.read = new_sync_read,
- .read_iter = ll_file_read_iter,
.write = new_sync_write,
+# endif /* HAVE_SYNC_READ_WRITE */
+ .read_iter = ll_file_read_iter,
.write_iter = ll_file_write_iter,
#else /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
.read = ll_file_read,
/* These are for -o noflock - to return ENOSYS on flock calls */
struct file_operations ll_file_operations_noflock = {
#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
+# ifdef HAVE_SYNC_READ_WRITE
.read = new_sync_read,
- .read_iter = ll_file_read_iter,
.write = new_sync_write,
+# endif /* HAVE_SYNC_READ_WRITE */
+ .read_iter = ll_file_read_iter,
.write_iter = ll_file_write_iter,
#else /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
.read = ll_file_read,
* Apply the layout to the inode. Layout lock is held and will be released
* in this function.
*/
-static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode,
+static int ll_layout_lock_set(struct lustre_handle *lockh, enum ldlm_mode mode,
struct inode *inode)
{
struct ll_inode_info *lli = ll_i2info(inode);
struct ll_inode_info *lli = ll_i2info(inode);
struct ll_sb_info *sbi = ll_i2sbi(inode);
struct md_op_data *op_data;
- struct lookup_intent it;
- struct lustre_handle lockh;
- ldlm_mode_t mode;
+ struct lookup_intent it;
+ struct lustre_handle lockh;
+ enum ldlm_mode mode;
struct ldlm_enqueue_info einfo = {
.ei_type = LDLM_IBITS,
.ei_mode = LCK_CR,