OBD_CONNECT_LVB_TYPE | OBD_CONNECT_LAYOUTLOCK |\
OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE |\
OBD_CONNECT_FLOCK_DEAD | \
- OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK)
+ OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK | \
+ OBD_CONNECT_OPEN_BY_FID)
#define OST_CONNECT_SUPPORTED (OBD_CONNECT_SRVLOCK | OBD_CONNECT_GRANT | \
OBD_CONNECT_REQPORTAL | OBD_CONNECT_VERSION | \
*/
#define MDS_OPEN_RELEASE 02000000000000ULL /* Open the file for HSM release */
+/* lustre internal open flags, which should not be set from user space */
+#define MDS_OPEN_FL_INTERNAL (MDS_OPEN_HAS_EA | MDS_OPEN_HAS_OBJS | \
+ MDS_OPEN_OWNEROVERRIDE | MDS_OPEN_LOCK | \
+ MDS_OPEN_BY_FID | MDS_OPEN_LEASE | \
+ MDS_OPEN_RELEASE)
+
/* permission for create non-directory file */
#define MAY_CREATE (1 << 7)
/* permission for create directory file */
#include <obd_class.h>
#include <lustre_net.h>
-#include <lustre_mds.h>
#include <lustre_ha.h>
/* 4UL * 1024 * 1024 */
!(flags & MDS_OPEN_LEASE);
}
-/* these are local flags, used only on the client, private */
-#define M_CHECK_STALE 0200000000
-
/** @} mds */
#endif
RETURN(rc);
}
-static int ll_intent_file_open(struct file *file, void *lmm,
- int lmmsize, struct lookup_intent *itp)
+static int ll_intent_file_open(struct file *file, void *lmm, int lmmsize,
+ struct lookup_intent *itp)
{
- struct ll_sb_info *sbi = ll_i2sbi(file->f_dentry->d_inode);
- struct dentry *parent = file->f_dentry->d_parent;
- const char *name = file->f_dentry->d_name.name;
- const int len = file->f_dentry->d_name.len;
- struct md_op_data *op_data;
+ struct dentry *de = file->f_dentry;
+ struct ll_sb_info *sbi = ll_i2sbi(de->d_inode);
+ struct dentry *parent = de->d_parent;
+ const char *name = NULL;
+ int len = 0;
+ struct md_op_data *op_data;
struct ptlrpc_request *req = NULL;
- __u32 opc = LUSTRE_OPC_ANY;
- int rc;
- ENTRY;
+ int rc;
+ ENTRY;
- if (!parent)
- RETURN(-ENOENT);
-
- /* Usually we come here only for NFSD, and we want open lock.
- But we can also get here with pre 2.6.15 patchless kernels, and in
- that case that lock is also ok */
- /* We can also get here if there was cached open handle in revalidate_it
- * but it disappeared while we were getting from there to ll_file_open.
- * But this means this file was closed and immediatelly opened which
- * makes a good candidate for using OPEN lock */
- /* If lmmsize & lmm are not 0, we are just setting stripe info
- * parameters. No need for the open lock */
- if (lmm == NULL && lmmsize == 0) {
- itp->it_flags |= MDS_OPEN_LOCK;
- if (itp->it_flags & FMODE_WRITE)
- opc = LUSTRE_OPC_CREATE;
- }
+ LASSERT(parent != NULL);
+ LASSERT(itp->it_flags & MDS_OPEN_BY_FID);
- op_data = ll_prep_md_op_data(NULL, parent->d_inode,
- file->f_dentry->d_inode, name, len,
- O_RDWR, opc, NULL);
- if (IS_ERR(op_data))
- RETURN(PTR_ERR(op_data));
+ /* if server supports open-by-fid, or file name is invalid, don't pack
+ * name in open request */
+ if (!(exp_connect_flags(sbi->ll_md_exp) & OBD_CONNECT_OPEN_BY_FID) &&
+ lu_name_is_valid_2(de->d_name.name, de->d_name.len)) {
+ name = de->d_name.name;
+ len = de->d_name.len;
+ }
+ op_data = ll_prep_md_op_data(NULL, parent->d_inode, de->d_inode,
+ name, len, 0, LUSTRE_OPC_ANY, NULL);
+ if (IS_ERR(op_data))
+ RETURN(PTR_ERR(op_data));
op_data->op_data = lmm;
op_data->op_data_size = lmmsize;
- itp->it_flags |= MDS_OPEN_BY_FID;
+ if (parent == de) {
+ /*
+ * Fixup for NFS export open.
+ *
+ * We're called in the context of NFS export, and parent
+ * unknown, use parent fid saved in lli_pfid which will
+ * be used by MDS to create data.
+ */
+ struct ll_inode_info *lli = ll_i2info(de->d_inode);
+
+ spin_lock(&lli->lli_lock);
+ op_data->op_fid1 = lli->lli_pfid;
+ spin_unlock(&lli->lli_lock);
+
+ LASSERT(fid_is_sane(&op_data->op_fid1));
+ /** We ignore parent's capability temporary. */
+ if (op_data->op_capa1 != NULL) {
+ capa_put(op_data->op_capa1);
+ op_data->op_capa1 = NULL;
+ }
+ }
+
rc = md_intent_lock(sbi->ll_md_exp, op_data, itp, &req,
&ll_md_blocking_ast, 0);
- ll_finish_md_op_data(op_data);
- if (rc == -ESTALE) {
- /* reason for keep own exit path - don`t flood log
- * with messages with -ESTALE errors.
- */
- if (!it_disposition(itp, DISP_OPEN_OPEN) ||
- it_open_error(DISP_OPEN_OPEN, itp))
- GOTO(out, rc);
- ll_release_openhandle(file->f_dentry, itp);
- GOTO(out, rc);
- }
+ ll_finish_md_op_data(op_data);
+ if (rc == -ESTALE) {
+ /* reason for keep own exit path - don`t flood log
+ * with messages with -ESTALE errors.
+ */
+ if (!it_disposition(itp, DISP_OPEN_OPEN) ||
+ it_open_error(DISP_OPEN_OPEN, itp))
+ GOTO(out, rc);
+ ll_release_openhandle(de, itp);
+ GOTO(out, rc);
+ }
- if (it_disposition(itp, DISP_LOOKUP_NEG))
- GOTO(out, rc = -ENOENT);
+ if (it_disposition(itp, DISP_LOOKUP_NEG))
+ GOTO(out, rc = -ENOENT);
- if (rc != 0 || it_open_error(DISP_OPEN_OPEN, itp)) {
- rc = rc ? rc : it_open_error(DISP_OPEN_OPEN, itp);
- CDEBUG(D_VFSTRACE, "lock enqueue: err: %d\n", rc);
- GOTO(out, rc);
- }
+ if (rc != 0 || it_open_error(DISP_OPEN_OPEN, itp)) {
+ rc = rc ? rc : it_open_error(DISP_OPEN_OPEN, itp);
+ CDEBUG(D_VFSTRACE, "lock enqueue: err: %d\n", rc);
+ GOTO(out, rc);
+ }
- rc = ll_prep_inode(&file->f_dentry->d_inode, req, NULL, itp);
- if (!rc && itp->d.lustre.it_lock_mode)
- ll_set_lock_data(sbi->ll_md_exp, file->f_dentry->d_inode,
- itp, NULL);
+ rc = ll_prep_inode(&de->d_inode, req, NULL, itp);
+ if (!rc && itp->d.lustre.it_lock_mode)
+ ll_set_lock_data(sbi->ll_md_exp, de->d_inode, itp, NULL);
out:
ptlrpc_req_finished(req);
- ll_intent_drop_lock(itp);
+ ll_intent_drop_lock(itp);
- RETURN(rc);
+ RETURN(rc);
}
/**
would attempt to grab och_mutex as well, that would
result in a deadlock */
mutex_unlock(&lli->lli_och_mutex);
- it->it_create_mode |= M_CHECK_STALE;
+ /*
+ * Normally called under two situations:
+ * 1. NFS export.
+ * 2. revalidate with IT_OPEN (revalidate doesn't
+ * execute this intent any more).
+ *
+ * Always fetch MDS_OPEN_LOCK if this is not setstripe.
+ *
+ * Always specify MDS_OPEN_BY_FID because we don't want
+ * to get file with different fid.
+ */
+ it->it_flags |= MDS_OPEN_LOCK | MDS_OPEN_BY_FID;
rc = ll_intent_file_open(file, NULL, 0, it);
- it->it_create_mode &= ~M_CHECK_STALE;
if (rc)
GOTO(out_openerr, rc);
}
ll_inode_size_lock(inode);
+ oit.it_flags |= MDS_OPEN_BY_FID;
rc = ll_intent_file_open(file, lum, lum_size, &oit);
if (rc)
GOTO(out_unlock, rc);
if (IS_ERR(op_data))
RETURN(PTR_ERR(op_data));
- oit.it_create_mode |= M_CHECK_STALE;
rc = md_intent_lock(exp, op_data, &oit, &req,
&ll_md_blocking_ast, 0);
ll_finish_md_op_data(op_data);
- oit.it_create_mode &= ~M_CHECK_STALE;
if (rc < 0) {
rc = ll_inode_revalidate_fini(inode, rc);
GOTO (out, rc);
OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS |
OBD_CONNECT_MAX_EASIZE |
OBD_CONNECT_FLOCK_DEAD |
- OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK;
+ OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK |
+ OBD_CONNECT_OPEN_BY_FID;
if (sbi->ll_flags & LL_SBI_SOM_PREVIEW)
data->ocd_connect_flags |= OBD_CONNECT_SOM;
op_data->op_mds = 0;
op_data->op_data = data;
- /* If the file is being opened after mknod() (normally due to NFS)
- * try to use the default stripe data from parent directory for
- * allocating OST objects. Try to pass the parent FID to MDS. */
- if (opc == LUSTRE_OPC_CREATE && i1 == i2 && S_ISREG(i2->i_mode) &&
- !ll_i2info(i2)->lli_has_smd) {
- struct ll_inode_info *lli = ll_i2info(i2);
-
- spin_lock(&lli->lli_lock);
- if (likely(!lli->lli_has_smd && !fid_is_zero(&lli->lli_pfid)))
- op_data->op_fid1 = lli->lli_pfid;
- spin_unlock(&lli->lli_lock);
- /** We ignore parent's capability temporary. */
- }
-
/* When called by ll_setattr_raw, file is i1. */
if (LLIF_DATA_MODIFIED & ll_i2info(i1)->lli_flags)
op_data->op_bias |= MDS_DATA_MODIFIED;
RETURN(ERR_PTR(-ESTALE));
}
- /**
- * It is an anonymous dentry without OST objects created yet.
- * We have to find the parent to tell MDS how to init lov objects.
- */
- if (S_ISREG(inode->i_mode) && !ll_i2info(inode)->lli_has_smd &&
- parent != NULL && !fid_is_zero(parent)) {
+ result = d_obtain_alias(inode);
+ if (IS_ERR(result)) {
+ iput(inode);
+ RETURN(result);
+ }
+
+ /**
+ * In case d_obtain_alias() found a disconnected dentry, always update
+ * lli_pfid to allow later operation (normally open) have parent fid,
+ * which may be used by MDS to create data.
+ */
+ if (parent != NULL) {
struct ll_inode_info *lli = ll_i2info(inode);
spin_lock(&lli->lli_lock);
spin_unlock(&lli->lli_lock);
}
- result = d_obtain_alias(inode);
- if (IS_ERR(result)) {
- iput(inode);
- RETURN(result);
- }
-
RETURN(result);
}
}
it->it_create_mode = (mode & S_IALLUGO) | S_IFREG;
it->it_flags = (open_flags & ~O_ACCMODE) | OPEN_FMODE(open_flags);
+ it->it_flags &= ~MDS_OPEN_FL_INTERNAL;
/* Dentry added to dcache tree in ll_lookup_it */
de = ll_lookup_it(dir, dentry, it, lookup_flags);
{
struct lookup_intent *it;
- OBD_ALLOC(it, sizeof(*it));
+ OBD_ALLOC_PTR(it);
if (!it)
return ERR_PTR(-ENOMEM);
it->it_op |= IT_CREAT;
it->it_create_mode = (oit->create_mode & S_IALLUGO) | S_IFREG;
it->it_flags = ll_namei_to_lookup_intent_flag(oit->flags);
+ it->it_flags &= ~MDS_OPEN_FL_INTERNAL;
} else {
it->it_op = IT_GETATTR;
}
* see mdt_cross_open */
LASSERT(it->it_op & IT_OPEN);
op_data->op_fid2 = *parent_fid;
- /* Add object FID to op_fid3, in case it needs to check stale
- * (M_CHECK_STALE), see mdc_finish_intent_lock */
- op_data->op_fid3 = body->mbo_fid1;
}
op_data->op_bias = MDS_CROSS_REF;
int rc;
ENTRY;
- /* Note: client might open with some random flags(sanity 33b), so we can
- * not make sure op_fid2 is being initialized with BY_FID flag */
- if (it->it_flags & MDS_OPEN_BY_FID && fid_is_sane(&op_data->op_fid2)) {
- if (op_data->op_mea1 != NULL) {
- struct lmv_stripe_md *lsm = op_data->op_mea1;
- const struct lmv_oinfo *oinfo;
-
- oinfo = lsm_name_to_stripe_info(lsm, op_data->op_name,
- op_data->op_namelen);
- if (IS_ERR(oinfo))
- RETURN(PTR_ERR(oinfo));
- op_data->op_fid1 = oinfo->lmo_fid;
- }
+ if (it->it_flags & MDS_OPEN_BY_FID) {
+ LASSERT(fid_is_sane(&op_data->op_fid2));
+
+ /* for striped directory, we can't know parent stripe fid
+ * without name, but we can set it to child fid, and MDT
+ * will obtain it from linkea in open in such case. */
+ if (op_data->op_mea1 != NULL)
+ op_data->op_fid1 = op_data->op_fid2;
tgt = lmv_find_target(lmv, &op_data->op_fid2);
if (IS_ERR(tgt))
op_data->op_mds = tgt->ltd_idx;
} else {
+ LASSERT(fid_is_sane(&op_data->op_fid1));
+ LASSERT(fid_is_zero(&op_data->op_fid2));
+ LASSERT(op_data->op_name != NULL);
+
tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
if (IS_ERR(tgt))
RETURN(PTR_ERR(tgt));
/* If it is ready to open the file by FID, do not need
* allocate FID at all, otherwise it will confuse MDT */
- if ((it->it_op & IT_CREAT) &&
- !(it->it_flags & MDS_OPEN_BY_FID)) {
+ if ((it->it_op & IT_CREAT) && !(it->it_flags & MDS_OPEN_BY_FID)) {
/*
- * For open with IT_CREATE and for IT_CREATE cases allocate new
- * fid and setup FLD for it.
+ * For lookup(IT_CREATE) cases allocate new fid and setup FLD
+ * for it.
*/
- op_data->op_fid3 = op_data->op_fid2;
rc = lmv_fid_alloc(NULL, exp, &op_data->op_fid2, op_data);
if (rc != 0)
RETURN(rc);
ldlm_blocking_callback cb_blocking,
__u64 extra_lock_flags)
{
- struct obd_device *obd = exp->exp_obd;
- int rc;
- ENTRY;
+ struct obd_device *obd = exp->exp_obd;
+ int rc;
+ ENTRY;
- LASSERT(it != NULL);
- LASSERT(fid_is_sane(&op_data->op_fid1));
+ LASSERT(it != NULL);
+ LASSERT(fid_is_sane(&op_data->op_fid1));
- CDEBUG(D_INODE, "INTENT LOCK '%s' for '%*s' on "DFID"\n",
- LL_IT2STR(it), op_data->op_namelen, op_data->op_name,
- PFID(&op_data->op_fid1));
+ CDEBUG(D_INODE, "INTENT LOCK '%s' for "DFID" '%.*s' on "DFID"\n",
+ LL_IT2STR(it), PFID(&op_data->op_fid2), op_data->op_namelen,
+ op_data->op_name, PFID(&op_data->op_fid1));
- rc = lmv_check_connect(obd);
- if (rc)
- RETURN(rc);
+ rc = lmv_check_connect(obd);
+ if (rc)
+ RETURN(rc);
if (it->it_op & (IT_LOOKUP | IT_GETATTR | IT_LAYOUT))
rc = lmv_intent_lookup(exp, op_data, it, reqp, cb_blocking,
return &lsm->lsm_md_oinfo[stripe_index];
}
-
struct lmv_tgt_desc
*lmv_locate_mds(struct lmv_obd *lmv, struct md_op_data *op_data,
struct lu_fid *fid);
#define _MDC_INTERNAL_H
#include <lustre_mdc.h>
-#include <lustre_mds.h>
#ifdef LPROCFS
extern struct lprocfs_seq_vars lprocfs_mdc_obd_vars[];
static __u64 mds_pack_open_flags(__u64 flags, __u32 mode)
{
__u64 cr_flags = (flags & (FMODE_READ | FMODE_WRITE |
- MDS_OPEN_HAS_EA | MDS_OPEN_HAS_OBJS |
- MDS_OPEN_OWNEROVERRIDE | MDS_OPEN_LOCK |
- MDS_OPEN_BY_FID | MDS_OPEN_LEASE |
- MDS_OPEN_RELEASE));
+ MDS_OPEN_FL_INTERNAL));
+
if (flags & O_CREAT)
cr_flags |= MDS_OPEN_CREAT;
if (flags & O_EXCL)
mdt_body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY);
LASSERT(mdt_body != NULL); /* mdc_enqueue checked */
- /* If we were revalidating a fid/name pair, mark the intent in
- * case we fail and get called again from lookup */
- if (fid_is_sane(&op_data->op_fid2) &&
- it->it_create_mode & M_CHECK_STALE &&
- it->it_op != IT_GETATTR) {
- /* Also: did we find the same inode? */
- /* sever can return one of two fids:
- * op_fid2 - new allocated fid - if file is created.
- * op_fid3 - existent fid - if file only open.
- * op_fid3 is saved in lmv_intent_open */
- if ((!lu_fid_eq(&op_data->op_fid2, &mdt_body->mbo_fid1)) &&
- (!lu_fid_eq(&op_data->op_fid3, &mdt_body->mbo_fid1))) {
- CDEBUG(D_DENTRY, "Found stale data "DFID"("DFID")/"DFID
- "\n", PFID(&op_data->op_fid2),
- PFID(&op_data->op_fid2),
- PFID(&mdt_body->mbo_fid1));
- RETURN(-ESTALE);
- }
- }
-
rc = it_open_error(DISP_LOOKUP_EXECD, it);
if (rc)
RETURN(rc);
GOTO(out, result = -EFAULT);
}
CDEBUG(D_INFO, "No object(1), continue as regular open.\n");
- } else if ((!lu_name_is_valid(&rr->rr_name) &&
- (create_flags & MDS_OPEN_LOCK)) ||
- (create_flags & MDS_OPEN_BY_FID)) {
+ } else if (create_flags & (MDS_OPEN_BY_FID | MDS_OPEN_LOCK)) {
+ /*
+ * MDS_OPEN_LOCK is checked for backward compatibility with 2.1
+ * client.
+ */
result = mdt_open_by_fid_lock(info, ldlm_rep, lhc);
- /* If result is 0 then open by FID has found the file
- * and there is nothing left for us to do here. More
- * generally if it is anything other than -ENOENT or
- * -EREMOTE then we return that now. If -ENOENT and
- * MDS_OPEN_CREAT is set then we must create the file
- * below. If -EREMOTE then we need to return a LOOKUP
- * lock to the client, which we do below. Hence this
- * odd looking condition. See LU-2523. */
- if (!(result == -ENOENT && (create_flags & MDS_OPEN_CREAT)) &&
- result != -EREMOTE)
- GOTO(out, result);
-
- CDEBUG(D_INFO, "No object(2), continue as regular open.\n");
+ if (result < 0)
+ CDEBUG(D_INFO, "no object for "DFID": %d\n",
+ PFID(rr->rr_fid2), result);
+ GOTO(out, result);
}
if (OBD_FAIL_CHECK(OBD_FAIL_MDS_OPEN_PACK))
rm -fr $DIR/d33
test_mkdir -p $DIR/d33
chown $RUNAS_ID $DIR/d33
- $RUNAS $OPENFILE -f 1286739555 $DIR/d33/f33 && error "create" || true
+ $RUNAS $OPENFILE -f 1286739555 $DIR/d33/f33
}
-run_test 33b "test open file with malformed flags (No panic and return error)"
+run_test 33b "test open file with malformed flags (No panic)"
test_33c() {
[ $PARALLEL == "yes" ] && skip "skip parallel run" && return