コード例 #1
0
int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data,
               struct ptlrpc_request **request)
{
        CFS_LIST_HEAD(cancels);
        struct obd_device *obd = class_exp2obd(exp);
        struct ptlrpc_request *req = *request;
        int count = 0, rc;
        ENTRY;

        LASSERT(req == NULL);

	if ((op_data->op_flags & MF_MDC_CANCEL_FID1) &&
	    (fid_is_sane(&op_data->op_fid1)) &&
	    !OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK_NET))
		count = mdc_resource_get_unused(exp, &op_data->op_fid1,
						&cancels, LCK_EX,
						MDS_INODELOCK_UPDATE);
	if ((op_data->op_flags & MF_MDC_CANCEL_FID3) &&
	    (fid_is_sane(&op_data->op_fid3)) &&
	    !OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK_NET))
		count += mdc_resource_get_unused(exp, &op_data->op_fid3,
						 &cancels, LCK_EX,
						 MDS_INODELOCK_FULL);
        req = ptlrpc_request_alloc(class_exp2cliimp(exp),
                                   &RQF_MDS_REINT_UNLINK);
        if (req == NULL) {
                ldlm_lock_list_put(&cancels, l_bl_ast, count);
                RETURN(-ENOMEM);
        }
        mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
        req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
                             op_data->op_namelen + 1);

	rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
	if (rc) {
		ptlrpc_request_free(req);
		RETURN(rc);
	}

        mdc_unlink_pack(req, op_data);

        req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER,
                             obd->u.cli.cl_max_mds_easize);
        req_capsule_set_size(&req->rq_pill, &RMF_LOGCOOKIES, RCL_SERVER,
                             obd->u.cli.cl_max_mds_cookiesize);
        ptlrpc_request_set_replen(req);

        *request = req;

        rc = mdc_reint(req, obd->u.cli.cl_rpc_lock, LUSTRE_IMP_FULL);
        if (rc == -ERESTARTSYS)
                rc = 0;
        RETURN(rc);
}
コード例 #2
0
ファイル: mdc_reint.c プロジェクト: Xyratex/lustre-stable
int mdc_link(struct obd_export *exp, struct md_op_data *op_data,
             struct ptlrpc_request **request)
{
	struct list_head cancels = LIST_HEAD_INIT(cancels);
        struct ptlrpc_request *req;
        int count = 0, rc;
        ENTRY;

        if ((op_data->op_flags & MF_MDC_CANCEL_FID2) &&
            (fid_is_sane(&op_data->op_fid2)))
                count = mdc_resource_get_unused(exp, &op_data->op_fid2,
                                                &cancels, LCK_EX,
                                                MDS_INODELOCK_UPDATE);
        if ((op_data->op_flags & MF_MDC_CANCEL_FID1) &&
            (fid_is_sane(&op_data->op_fid1)))
                count += mdc_resource_get_unused(exp, &op_data->op_fid1,
                                                 &cancels, LCK_EX,
                                                 MDS_INODELOCK_UPDATE);

        req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_REINT_LINK);
        if (req == NULL) {
                ldlm_lock_list_put(&cancels, l_bl_ast, count);
                RETURN(-ENOMEM);
        }

        req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
                             op_data->op_namelen + 1);

	/* get SELinux policy info if any */
	rc = sptlrpc_get_sepol(req);
	if (rc < 0) {
		ptlrpc_request_free(req);
		RETURN(rc);
	}
	req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT,
			     strlen(req->rq_sepol) ?
			     strlen(req->rq_sepol) + 1 : 0);

	rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
	if (rc) {
		ptlrpc_request_free(req);
		RETURN(rc);
	}

        mdc_link_pack(req, op_data);
        ptlrpc_request_set_replen(req);

	rc = mdc_reint(req, LUSTRE_IMP_FULL);
        *request = req;
        if (rc == -ERESTARTSYS)
                rc = 0;

        RETURN(rc);
}
コード例 #3
0
ファイル: mdc_reint.c プロジェクト: Announcement/linux
int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data,
	       struct ptlrpc_request **request)
{
	LIST_HEAD(cancels);
	struct obd_device *obd = class_exp2obd(exp);
	struct ptlrpc_request *req = *request;
	int count = 0, rc;

	LASSERT(!req);

	if ((op_data->op_flags & MF_MDC_CANCEL_FID1) &&
	    (fid_is_sane(&op_data->op_fid1)))
		count = mdc_resource_get_unused(exp, &op_data->op_fid1,
						&cancels, LCK_EX,
						MDS_INODELOCK_UPDATE);
	if ((op_data->op_flags & MF_MDC_CANCEL_FID3) &&
	    (fid_is_sane(&op_data->op_fid3)))
		count += mdc_resource_get_unused(exp, &op_data->op_fid3,
						 &cancels, LCK_EX,
						 MDS_INODELOCK_FULL);
	req = ptlrpc_request_alloc(class_exp2cliimp(exp),
				   &RQF_MDS_REINT_UNLINK);
	if (!req) {
		ldlm_lock_list_put(&cancels, l_bl_ast, count);
		return -ENOMEM;
	}
	req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
			     op_data->op_namelen + 1);

	rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
	if (rc) {
		ptlrpc_request_free(req);
		return rc;
	}

	mdc_unlink_pack(req, op_data);

	req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER,
			     obd->u.cli.cl_default_mds_easize);
	ptlrpc_request_set_replen(req);

	*request = req;

	rc = mdc_reint(req, LUSTRE_IMP_FULL);
	if (rc == -ERESTARTSYS)
		rc = 0;
	return rc;
}
コード例 #4
0
ファイル: lmv_fld.c プロジェクト: AshishNamdev/linux
int lmv_fld_lookup(struct lmv_obd *lmv, const struct lu_fid *fid, u32 *mds)
{
	struct obd_device *obd = lmv2obd_dev(lmv);
	int rc;

	/*
	 * FIXME: Currently ZFS still use local seq for ROOT unfortunately, and
	 * this fid_is_local check should be removed once LU-2240 is fixed
	 */
	if (!fid_is_sane(fid) || !(fid_seq_in_fldb(fid_seq(fid)) ||
				   fid_seq_is_local_file(fid_seq(fid)))) {
		CERROR("%s: invalid FID " DFID "\n", obd->obd_name, PFID(fid));
		return -EINVAL;
	}

	rc = fld_client_lookup(&lmv->lmv_fld, fid_seq(fid), mds,
			       LU_SEQ_RANGE_MDT, NULL);
	if (rc) {
		CERROR("Error while looking for mds number. Seq %#llx, err = %d\n",
		       fid_seq(fid), rc);
		return rc;
	}

	CDEBUG(D_INODE, "FLD lookup got mds #%x for fid="DFID"\n",
	       *mds, PFID(fid));

	if (*mds >= lmv->desc.ld_tgt_count) {
		CERROR("FLD lookup got invalid mds #%x (max: %x) for fid=" DFID "\n", *mds, lmv->desc.ld_tgt_count,
		       PFID(fid));
		rc = -EINVAL;
	}
	return rc;
}
コード例 #5
0
ファイル: out_handler.c プロジェクト: Lezval/lustre
static int out_destroy(struct tgt_session_info *tsi)
{
	struct tgt_thread_info	*tti = tgt_th_info(tsi->tsi_env);
	struct update		*update = tti->tti_u.update.tti_update;
	struct dt_object	*obj = tti->tti_u.update.tti_dt_object;
	struct lu_fid		*fid;
	int			 rc;
	ENTRY;

	fid = &update->u_fid;
	fid_le_to_cpu(fid, fid);
	if (!fid_is_sane(fid)) {
		CERROR("%s: invalid FID "DFID": rc = %d\n",
		       tgt_name(tsi->tsi_tgt), PFID(fid), -EPROTO);
		RETURN(err_serious(-EPROTO));
	}

	if (!lu_object_exists(&obj->do_lu))
		RETURN(-ENOENT);

	rc = out_tx_destroy(tsi->tsi_env, obj, &tti->tti_tea,
			    tti->tti_u.update.tti_update_reply,
			    tti->tti_u.update.tti_update_reply_index);

	RETURN(rc);
}
コード例 #6
0
ファイル: lmv_intent.c プロジェクト: AkyZero/wrapfs-latest
int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
		    void *lmm, int lmmsize, struct lookup_intent *it,
		    int flags, struct ptlrpc_request **reqp,
		    ldlm_blocking_callback cb_blocking,
		    __u64 extra_lock_flags)
{
	struct obd_device *obd = exp->exp_obd;
	int		rc;

	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));

	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, lmm, lmmsize, it,
				       flags, reqp, cb_blocking,
				       extra_lock_flags);
	else if (it->it_op & IT_OPEN)
		rc = lmv_intent_open(exp, op_data, lmm, lmmsize, it,
				     flags, reqp, cb_blocking,
				     extra_lock_flags);
	else
		LBUG();
	return rc;
}
コード例 #7
0
ファイル: lmv_fld.c プロジェクト: mikuhatsune001/linux2.6.32
int lmv_fld_lookup(struct lmv_obd *lmv,
		   const struct lu_fid *fid,
		   mdsno_t *mds)
{
	int rc;

	/* FIXME: Currently ZFS still use local seq for ROOT unfortunately, and
	 * this fid_is_local check should be removed once LU-2240 is fixed */
	LASSERTF((fid_seq_in_fldb(fid_seq(fid)) ||
		  fid_seq_is_local_file(fid_seq(fid))) &&
		 fid_is_sane(fid), DFID" is insane!\n", PFID(fid));

	rc = fld_client_lookup(&lmv->lmv_fld, fid_seq(fid), mds,
			       LU_SEQ_RANGE_MDT, NULL);
	if (rc) {
		CERROR("Error while looking for mds number. Seq %#llx, err = %d\n",
		       fid_seq(fid), rc);
		return rc;
	}

	CDEBUG(D_INODE, "FLD lookup got mds #%x for fid="DFID"\n",
	       *mds, PFID(fid));

	if (*mds >= lmv->desc.ld_tgt_count) {
		CERROR("FLD lookup got invalid mds #%x (max: %x) "
		       "for fid="DFID"\n", *mds, lmv->desc.ld_tgt_count,
		       PFID(fid));
		rc = -EINVAL;
	}
	return rc;
}
コード例 #8
0
/*
 * This is is_subdir() variant, it is CMD if cmm forwards it to correct
 * target. Source should not be ancestor of target dir. May be other rename
 * checks can be moved here later.
 */
static int mdt_rename_sanity(struct mdt_thread_info *info, struct lu_fid *fid)
{
        struct mdt_reint_record *rr = &info->mti_rr;
        struct lu_fid dst_fid = *rr->rr_fid2;
        struct mdt_object *dst;
        int rc = 0;
        ENTRY;

        do {
                LASSERT(fid_is_sane(&dst_fid));
                dst = mdt_object_find(info->mti_env, info->mti_mdt, &dst_fid);
                if (!IS_ERR(dst)) {
                        rc = mdo_is_subdir(info->mti_env,
                                           mdt_object_child(dst), fid,
                                           &dst_fid);
                        mdt_object_put(info->mti_env, dst);
                        if (rc != -EREMOTE && rc < 0) {
                                CERROR("Failed mdo_is_subdir(), rc %d\n", rc);
                        } else {
                                /* check the found fid */
                                if (lu_fid_eq(&dst_fid, fid))
                                        rc = -EINVAL;
                        }
                } else {
                        rc = PTR_ERR(dst);
                }
        } while (rc == -EREMOTE);

        RETURN(rc);
}
コード例 #9
0
ファイル: ofd_objects.c プロジェクト: hejin/lustre-stable
int ofd_object_ff_load(const struct lu_env *env, struct ofd_object *fo)
{
	struct ofd_thread_info	*info = ofd_info(env);
	struct filter_fid_old	*ff   = &info->fti_mds_fid_old;
	struct lu_buf		*buf  = &info->fti_buf;
	struct lu_fid		*pfid = &fo->ofo_pfid;
	int			 rc   = 0;

	if (fid_is_sane(pfid))
		return 0;

	buf->lb_buf = ff;
	buf->lb_len = sizeof(*ff);
	rc = dt_xattr_get(env, ofd_object_child(fo), buf, XATTR_NAME_FID,
			  BYPASS_CAPA);
	if (rc < 0)
		return rc;

	if (rc < sizeof(struct lu_fid)) {
		fid_zero(pfid);

		return -ENODATA;
	}

	pfid->f_seq = le64_to_cpu(ff->ff_parent.f_seq);
	pfid->f_oid = le32_to_cpu(ff->ff_parent.f_oid);
	/* Currently, the filter_fid::ff_parent::f_ver is not the real parent
	 * MDT-object's FID::f_ver, instead it is the OST-object index in its
	 * parent MDT-object's layout EA. */
	pfid->f_stripe_idx = le32_to_cpu(ff->ff_parent.f_stripe_idx);

	return 0;
}
コード例 #10
0
ファイル: mdc_reint.c プロジェクト: DCteam/lustre
int mdc_link(struct obd_export *exp, struct md_op_data *op_data,
             struct ptlrpc_request **request)
{
        CFS_LIST_HEAD(cancels);
        struct obd_device *obd = exp->exp_obd;
        struct ptlrpc_request *req;
        int count = 0, rc;
        ENTRY;

        if ((op_data->op_flags & MF_MDC_CANCEL_FID2) &&
            (fid_is_sane(&op_data->op_fid2)))
                count = mdc_resource_get_unused(exp, &op_data->op_fid2,
                                                &cancels, LCK_EX,
                                                MDS_INODELOCK_UPDATE);
        if ((op_data->op_flags & MF_MDC_CANCEL_FID1) &&
            (fid_is_sane(&op_data->op_fid1)))
                count += mdc_resource_get_unused(exp, &op_data->op_fid1,
                                                 &cancels, LCK_EX,
                                                 MDS_INODELOCK_UPDATE);

        req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_REINT_LINK);
        if (req == NULL) {
                ldlm_lock_list_put(&cancels, l_bl_ast, count);
                RETURN(-ENOMEM);
        }
        mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
        mdc_set_capa_size(req, &RMF_CAPA2, op_data->op_capa2);
        req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
                             op_data->op_namelen + 1);

        rc = mdc_prep_elc_req(exp, req, &cancels, count);
        if (rc) {
                ptlrpc_request_free(req);
                RETURN(rc);
        }

        mdc_link_pack(req, op_data);
        ptlrpc_request_set_replen(req);

        rc = mdc_reint(req, obd->u.cli.cl_rpc_lock, LUSTRE_IMP_FULL);
        *request = req;
        if (rc == -ERESTARTSYS)
                rc = 0;

        RETURN(rc);
}
コード例 #11
0
ファイル: out_handler.c プロジェクト: KnightKu/lustre-stable
static int out_index_insert(struct tgt_session_info *tsi)
{
	struct tgt_thread_info	*tti	= tgt_th_info(tsi->tsi_env);
	struct object_update	*update	= tti->tti_u.update.tti_update;
	struct dt_object	*obj	= tti->tti_u.update.tti_dt_object;
	struct dt_insert_rec	*rec	= &tti->tti_rec;
	struct lu_fid		*fid;
	char			*name;
	__u32			*ptype;
	int			 rc	= 0;
	size_t			 size;
	ENTRY;

	name = object_update_param_get(update, 0, NULL);
	if (IS_ERR(name)) {
		CERROR("%s: empty name for index insert: rc = %ld\n",
		       tgt_name(tsi->tsi_tgt), PTR_ERR(name));
		RETURN(PTR_ERR(name));
	}

	fid = object_update_param_get(update, 1, &size);
	if (IS_ERR(fid) || size != sizeof(*fid)) {
		CERROR("%s: invalid fid: rc = %ld\n",
		       tgt_name(tsi->tsi_tgt), PTR_ERR(fid));
		RETURN(PTR_ERR(fid));
	}

	if (ptlrpc_req_need_swab(tsi->tsi_pill->rc_req))
		lustre_swab_lu_fid(fid);

	if (!fid_is_sane(fid)) {
		CERROR("%s: invalid FID "DFID": rc = %d\n",
		       tgt_name(tsi->tsi_tgt), PFID(fid), -EPROTO);
		RETURN(-EPROTO);
	}

	ptype = object_update_param_get(update, 2, &size);
	if (IS_ERR(ptype) || size != sizeof(*ptype)) {
		CERROR("%s: invalid type for index insert: rc = %ld\n",
		       tgt_name(tsi->tsi_tgt), PTR_ERR(ptype));
		RETURN(PTR_ERR(ptype));
	}

	if (ptlrpc_req_need_swab(tsi->tsi_pill->rc_req))
		__swab32s(ptype);

	rec->rec_fid = fid;
	rec->rec_type = *ptype;

	rc = out_tx_index_insert(tsi->tsi_env, obj, (const struct dt_rec *)rec,
				 (const struct dt_key *)name, &tti->tti_tea,
				 tti->tti_tea.ta_handle,
				 tti->tti_u.update.tti_update_reply,
				 tti->tti_u.update.tti_update_reply_index);
	RETURN(rc);
}
コード例 #12
0
ファイル: mdc_reint.c プロジェクト: Zealsathish/lustre
int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data,
		void *ea, size_t ealen, struct ptlrpc_request **request)
{
	struct list_head cancels = LIST_HEAD_INIT(cancels);
        struct ptlrpc_request *req;
        struct mdc_rpc_lock *rpc_lock;
        struct obd_device *obd = exp->exp_obd;
        int count = 0, rc;
        __u64 bits;
        ENTRY;

        LASSERT(op_data != NULL);

        bits = MDS_INODELOCK_UPDATE;
        if (op_data->op_attr.ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID))
                bits |= MDS_INODELOCK_LOOKUP;
	if ((op_data->op_flags & MF_MDC_CANCEL_FID1) &&
	    (fid_is_sane(&op_data->op_fid1)))
		count = mdc_resource_get_unused(exp, &op_data->op_fid1,
						&cancels, LCK_EX, bits);
        req = ptlrpc_request_alloc(class_exp2cliimp(exp),
                                   &RQF_MDS_REINT_SETATTR);
        if (req == NULL) {
                ldlm_lock_list_put(&cancels, l_bl_ast, count);
                RETURN(-ENOMEM);
        }
        mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
	req_capsule_set_size(&req->rq_pill, &RMF_MDT_EPOCH, RCL_CLIENT, 0);
	req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_CLIENT, ealen);
	req_capsule_set_size(&req->rq_pill, &RMF_LOGCOOKIES, RCL_CLIENT, 0);

	rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
	if (rc) {
		ptlrpc_request_free(req);
		RETURN(rc);
	}

        rpc_lock = obd->u.cli.cl_rpc_lock;

        if (op_data->op_attr.ia_valid & (ATTR_MTIME | ATTR_CTIME))
                CDEBUG(D_INODE, "setting mtime "CFS_TIME_T
                       ", ctime "CFS_TIME_T"\n",
                       LTIME_S(op_data->op_attr.ia_mtime),
                       LTIME_S(op_data->op_attr.ia_ctime));
	mdc_setattr_pack(req, op_data, ea, ealen);

        ptlrpc_request_set_replen(req);

        rc = mdc_reint(req, rpc_lock, LUSTRE_IMP_FULL);
	if (rc == -ERESTARTSYS)
                rc = 0;

        *request = req;

	RETURN(rc);
}
コード例 #13
0
ファイル: out_handler.c プロジェクト: hejin/lustre-stable
static int out_create(struct tgt_session_info *tsi)
{
	struct tgt_thread_info	*tti = tgt_th_info(tsi->tsi_env);
	struct object_update	*update = tti->tti_u.update.tti_update;
	struct dt_object        *obj = tti->tti_u.update.tti_dt_object;
	struct dt_object_format	*dof = &tti->tti_u.update.tti_update_dof;
	struct obdo		*lobdo = &tti->tti_u.update.tti_obdo;
	struct lu_attr		*attr = &tti->tti_attr;
	struct lu_fid		*fid = NULL;
	struct obdo		*wobdo;
	int			size;
	int			rc;

	ENTRY;

	wobdo = object_update_param_get(update, 0, &size);
	if (wobdo == NULL || size != sizeof(*wobdo)) {
		CERROR("%s: obdo is NULL, invalid RPC: rc = %d\n",
		       tgt_name(tsi->tsi_tgt), -EPROTO);
		RETURN(err_serious(-EPROTO));
	}

	obdo_le_to_cpu(wobdo, wobdo);
	lustre_get_wire_obdo(NULL, lobdo, wobdo);
	la_from_obdo(attr, lobdo, lobdo->o_valid);

	dof->dof_type = dt_mode_to_dft(attr->la_mode);
	if (update->ou_params_count > 1) {
		int size;

		fid = object_update_param_get(update, 1, &size);
		if (fid == NULL || size != sizeof(*fid)) {
			CERROR("%s: invalid fid: rc = %d\n",
			       tgt_name(tsi->tsi_tgt), -EPROTO);
			RETURN(err_serious(-EPROTO));
		}
		if (ptlrpc_req_need_swab(tsi->tsi_pill->rc_req))
			lustre_swab_lu_fid(fid);
		if (!fid_is_sane(fid)) {
			CERROR("%s: invalid fid "DFID": rc = %d\n",
			       tgt_name(tsi->tsi_tgt), PFID(fid), -EPROTO);
			RETURN(err_serious(-EPROTO));
		}
	}

	if (lu_object_exists(&obj->do_lu))
		RETURN(-EEXIST);

	rc = out_tx_create(tsi->tsi_env, obj, attr, fid, dof,
			   &tti->tti_tea,
			   tti->tti_u.update.tti_update_reply,
			   tti->tti_u.update.tti_update_reply_index);

	RETURN(rc);
}
コード例 #14
0
ファイル: lmv_intent.c プロジェクト: dinatale2/lustre-stable
int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
		    struct lookup_intent *it, struct ptlrpc_request **reqp,
		    ldlm_blocking_callback cb_blocking,
		    __u64 extra_lock_flags)
{
	struct obd_device *obd = exp->exp_obd;
	int		   rc;
	ENTRY;

	LASSERT(it != NULL);
	LASSERT(fid_is_sane(&op_data->op_fid1));

	CDEBUG(D_INODE, "INTENT LOCK '%s' for "DFID" '%.*s' on "DFID"\n",
		LL_IT2STR(it), PFID(&op_data->op_fid2),
		(int)op_data->op_namelen, op_data->op_name,
		PFID(&op_data->op_fid1));

	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,
				       extra_lock_flags);
	else if (it->it_op & IT_OPEN)
		rc = lmv_intent_open(exp, op_data, it, reqp, cb_blocking,
				     extra_lock_flags);
	else
		LBUG();

	if (rc < 0) {
		struct lustre_handle lock_handle;

		if (it->d.lustre.it_lock_mode != 0) {
			lock_handle.cookie = it->d.lustre.it_lock_handle;
			ldlm_lock_decref(&lock_handle,
					 it->d.lustre.it_lock_mode);
		}

		it->d.lustre.it_lock_handle = 0;
		it->d.lustre.it_lock_mode = 0;

		if (it->d.lustre.it_remote_lock_mode != 0) {
			lock_handle.cookie = it->d.lustre.it_remote_lock_handle;
			ldlm_lock_decref(&lock_handle,
					 it->d.lustre.it_remote_lock_mode);
		}

		it->d.lustre.it_remote_lock_handle = 0;
		it->d.lustre.it_remote_lock_mode = 0;
	}

	RETURN(rc);
}
コード例 #15
0
static int out_create(struct mdt_thread_info *info)
{
	struct update		*update = info->mti_u.update.mti_update;
	struct dt_object        *obj = info->mti_u.update.mti_dt_object;
	struct dt_object_format	*dof = &info->mti_u.update.mti_update_dof;
	struct obdo		*lobdo = &info->mti_u.update.mti_obdo;
	struct lu_attr		*attr = &info->mti_attr.ma_attr;
	struct lu_fid		*fid = NULL;
	struct obdo		*wobdo;
	int			size;
	int			rc;

	ENTRY;

	wobdo = update_param_buf(update, 0, &size);
	if (wobdo == NULL || size != sizeof(*wobdo)) {
		CERROR("%s: obdo is NULL, invalid RPC: rc = %d\n",
		       mdt_obd_name(info->mti_mdt), -EPROTO);
		RETURN(err_serious(-EPROTO));
	}

	obdo_le_to_cpu(wobdo, wobdo);
	lustre_get_wire_obdo(lobdo, wobdo);
	la_from_obdo(attr, lobdo, lobdo->o_valid);

	dof->dof_type = dt_mode_to_dft(attr->la_mode);
	if (S_ISDIR(attr->la_mode)) {
		int size;

		fid = update_param_buf(update, 1, &size);
		if (fid == NULL || size != sizeof(*fid)) {
			CERROR("%s: invalid fid: rc = %d\n",
			       mdt_obd_name(info->mti_mdt), -EPROTO);
			RETURN(err_serious(-EPROTO));
		}
		fid_le_to_cpu(fid, fid);
		if (!fid_is_sane(fid)) {
			CERROR("%s: invalid fid "DFID": rc = %d\n",
			       mdt_obd_name(info->mti_mdt),
			       PFID(fid), -EPROTO);
			RETURN(err_serious(-EPROTO));
		}
	}

	rc = out_tx_create(info, obj, attr, fid, dof, &info->mti_handle,
			   info->mti_u.update.mti_update_reply,
			   info->mti_u.update.mti_update_reply_index);

	RETURN(rc);
}
コード例 #16
0
ファイル: lmv_intent.c プロジェクト: AkyZero/wrapfs-latest
/*
 * Handler for: getattr, lookup and revalidate cases.
 */
int lmv_intent_lookup(struct obd_export *exp, struct md_op_data *op_data,
		      void *lmm, int lmmsize, struct lookup_intent *it,
		      int flags, struct ptlrpc_request **reqp,
		      ldlm_blocking_callback cb_blocking,
		      __u64 extra_lock_flags)
{
	struct obd_device      *obd = exp->exp_obd;
	struct lmv_obd	 *lmv = &obd->u.lmv;
	struct lmv_tgt_desc    *tgt = NULL;
	struct mdt_body	*body;
	int		     rc = 0;

	tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
	if (IS_ERR(tgt))
		return PTR_ERR(tgt);

	if (!fid_is_sane(&op_data->op_fid2))
		fid_zero(&op_data->op_fid2);

	CDEBUG(D_INODE, "LOOKUP_INTENT with fid1="DFID", fid2="DFID
	       ", name='%s' -> mds #%d\n", PFID(&op_data->op_fid1),
	       PFID(&op_data->op_fid2),
	       op_data->op_name ? op_data->op_name : "<NULL>",
	       tgt->ltd_idx);

	op_data->op_bias &= ~MDS_CROSS_REF;

	rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it,
			     flags, reqp, cb_blocking, extra_lock_flags);

	if (rc < 0 || *reqp == NULL)
		return rc;

	/*
	 * MDS has returned success. Probably name has been resolved in
	 * remote inode. Let's check this.
	 */
	body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY);
	if (body == NULL)
		return -EPROTO;
	/* Not cross-ref case, just get out of here. */
	if (likely(!(body->valid & OBD_MD_MDS)))
		return 0;

	rc = lmv_intent_remote(exp, lmm, lmmsize, it, NULL, flags, reqp,
			       cb_blocking, extra_lock_flags);

	return rc;
}
コード例 #17
0
ファイル: lustre_tools.c プロジェクト: seagate-ssg/robinhood
/** get (name+parent_id) for an entry
 * \param linkno hardlink index
 * \retval -ENODATA after last link
 * \retval -ERANGE if namelen is too small
 */
int Lustre_GetNameParent(const char *path, int linkno,
                         lustre_fid *pfid, char *name,
                         int namelen)
{
    int rc, i, len;
    char buf[4096];
    struct linkea_data     ldata      = { 0 };
    struct lu_buf          lb = { 0 };

    rc = lgetxattr(path, XATTR_NAME_LINK, buf, sizeof(buf));
    if (rc < 0)
        return -errno;

    lb.lb_buf = buf;
    lb.lb_len = sizeof(buf);
    ldata.ld_buf = &lb;
    ldata.ld_leh = (struct link_ea_header *)buf;

    ldata.ld_lee = LINKEA_FIRST_ENTRY(ldata);
    ldata.ld_reclen = (ldata.ld_lee->lee_reclen[0] << 8)
               | ldata.ld_lee->lee_reclen[1];

    if (linkno >= ldata.ld_leh->leh_reccount)
        /* beyond last link */
        return -ENODATA;

    for (i = 0; i < linkno; i++) {
        ldata.ld_lee = LINKEA_NEXT_ENTRY(ldata);
        ldata.ld_reclen = (ldata.ld_lee->lee_reclen[0] << 8)
                   | ldata.ld_lee->lee_reclen[1];
    }

    memcpy(pfid, &ldata.ld_lee->lee_parent_fid, sizeof(*pfid));
    fid_be_to_cpu(pfid, pfid);

    if (!fid_is_sane(pfid))
    {
        DisplayLog(LVL_MAJOR, __func__, "insane fid: "DFID, PFID(pfid));
        return -EPROTO;
    }

    len = ldata.ld_reclen - sizeof(struct link_ea_entry);
    if (len >= namelen)
        return -ERANGE;

    strncpy(name, ldata.ld_lee->lee_name, len);
    name[len] = '\0';
    return 0;
}
コード例 #18
0
ファイル: mdc_reint.c プロジェクト: Announcement/linux
int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data,
		void *ea, size_t ealen, struct ptlrpc_request **request)
{
	LIST_HEAD(cancels);
	struct ptlrpc_request *req;
	int count = 0, rc;
	__u64 bits;

	bits = MDS_INODELOCK_UPDATE;
	if (op_data->op_attr.ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
		bits |= MDS_INODELOCK_LOOKUP;
	if ((op_data->op_flags & MF_MDC_CANCEL_FID1) &&
	    (fid_is_sane(&op_data->op_fid1)))
		count = mdc_resource_get_unused(exp, &op_data->op_fid1,
						&cancels, LCK_EX, bits);
	req = ptlrpc_request_alloc(class_exp2cliimp(exp),
				   &RQF_MDS_REINT_SETATTR);
	if (!req) {
		ldlm_lock_list_put(&cancels, l_bl_ast, count);
		return -ENOMEM;
	}
	req_capsule_set_size(&req->rq_pill, &RMF_MDT_EPOCH, RCL_CLIENT, 0);
	req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_CLIENT, ealen);
	req_capsule_set_size(&req->rq_pill, &RMF_LOGCOOKIES, RCL_CLIENT, 0);

	rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
	if (rc) {
		ptlrpc_request_free(req);
		return rc;
	}

	if (op_data->op_attr.ia_valid & (ATTR_MTIME | ATTR_CTIME))
		CDEBUG(D_INODE, "setting mtime %ld, ctime %ld\n",
		       LTIME_S(op_data->op_attr.ia_mtime),
		       LTIME_S(op_data->op_attr.ia_ctime));
	mdc_setattr_pack(req, op_data, ea, ealen);

	ptlrpc_request_set_replen(req);

	rc = mdc_reint(req, LUSTRE_IMP_FULL);

	if (rc == -ERESTARTSYS)
		rc = 0;

	*request = req;

	return rc;
}
コード例 #19
0
ファイル: mdd_device.c プロジェクト: EMSL-MSC/lustre-release
/**
 * Lookup method for "fid" object. Only filenames with correct SEQ:OID format
 * are valid. We also check if object with passed fid exists or not.
 */
static int obf_lookup(const struct lu_env *env, struct md_object *p,
                      const struct lu_name *lname, struct lu_fid *f,
                      struct md_op_spec *spec)
{
        char *name = (char *)lname->ln_name;
        struct mdd_device *mdd = mdo2mdd(p);
        struct mdd_object *child;
        int rc = 0;

        while (*name == '[')
                name++;

        sscanf(name, SFID, RFID(f));
        if (!fid_is_sane(f)) {
		CWARN("%s: Trying to lookup invalid FID [%s] in %s/%s, FID "
		      "format should be "DFID"\n", mdd2obd_dev(mdd)->obd_name,
		      lname->ln_name, dot_lustre_name, mdd_obf_dir_name,
		      (__u64)FID_SEQ_NORMAL, 1, 0);
                GOTO(out, rc = -EINVAL);
        }

	if (!fid_is_norm(f) && !fid_is_igif(f) && !fid_is_root(f) &&
	    !fid_seq_is_dot(f->f_seq)) {
		CWARN("%s: Trying to lookup invalid FID "DFID" in %s/%s, "
		      "sequence should be >= "LPX64" or within ["LPX64","
		      ""LPX64"].\n", mdd2obd_dev(mdd)->obd_name, PFID(f),
		      dot_lustre_name, mdd_obf_dir_name, (__u64)FID_SEQ_NORMAL,
		      (__u64)FID_SEQ_IGIF, (__u64)FID_SEQ_IGIF_MAX);
		GOTO(out, rc = -EINVAL);
	}

        /* Check if object with this fid exists */
        child = mdd_object_find(env, mdd, f);
        if (child == NULL)
                GOTO(out, rc = 0);
        if (IS_ERR(child))
                GOTO(out, rc = PTR_ERR(child));

        if (mdd_object_exists(child) == 0)
                rc = -ENOENT;

        mdd_object_put(env, child);

out:
        return rc;
}
コード例 #20
0
ファイル: out_handler.c プロジェクト: hejin/lustre-stable
static int out_index_insert(struct tgt_session_info *tsi)
{
	struct tgt_thread_info	*tti = tgt_th_info(tsi->tsi_env);
	struct object_update	*update = tti->tti_u.update.tti_update;
	struct dt_object  *obj = tti->tti_u.update.tti_dt_object;
	struct lu_fid	  *fid;
	char		  *name;
	int		   rc = 0;
	int		   size;

	ENTRY;

	name = object_update_param_get(update, 0, NULL);
	if (name == NULL) {
		CERROR("%s: empty name for index insert: rc = %d\n",
		       tgt_name(tsi->tsi_tgt), -EPROTO);
		RETURN(err_serious(-EPROTO));
	}

	fid = object_update_param_get(update, 1, &size);
	if (fid == NULL || size != sizeof(*fid)) {
		CERROR("%s: invalid fid: rc = %d\n",
		       tgt_name(tsi->tsi_tgt), -EPROTO);
		       RETURN(err_serious(-EPROTO));
	}

	if (ptlrpc_req_need_swab(tsi->tsi_pill->rc_req))
		lustre_swab_lu_fid(fid);

	if (!fid_is_sane(fid)) {
		CERROR("%s: invalid FID "DFID": rc = %d\n",
		       tgt_name(tsi->tsi_tgt), PFID(fid), -EPROTO);
		RETURN(err_serious(-EPROTO));
	}

	rc = out_tx_index_insert(tsi->tsi_env, obj, name, fid,
				 &tti->tti_tea,
				 tti->tti_u.update.tti_update_reply,
				 tti->tti_u.update.tti_update_reply_index);
	RETURN(rc);
}
コード例 #21
0
ファイル: llite_nfs.c プロジェクト: DenisLug/mptcp
static struct dentry *
ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *parent)
{
	struct inode  *inode;
	struct dentry *result;

	CDEBUG(D_INFO, "Get dentry for fid: "DFID"\n", PFID(fid));
	if (!fid_is_sane(fid))
		return ERR_PTR(-ESTALE);

	inode = search_inode_for_lustre(sb, fid);
	if (IS_ERR(inode))
		return ERR_CAST(inode);

	if (is_bad_inode(inode)) {
		/* we didn't find the right inode.. */
		iput(inode);
		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) {
		struct ll_inode_info *lli = ll_i2info(inode);

		spin_lock(&lli->lli_lock);
		lli->lli_pfid = *parent;
		spin_unlock(&lli->lli_lock);
	}

	result = d_obtain_alias(inode);
	if (IS_ERR(result)) {
		iput(inode);
		return result;
	}

	return result;
}
コード例 #22
0
ファイル: ofd_io.c プロジェクト: nkzxw/lustre-stable
/**
 * Verify parent FID of an object.
 *
 * Check the parent FID is sane and start extended
 * verification procedure otherwise.
 *
 * \param[in] env	execution environment
 * \param[in] fo	OFD object
 * \param[in] oa	OBDO structure with PFID
 *
 * \retval		0 on successful verification
 * \retval		-EINPROGRESS if PFID is being repaired
 * \retval		-EPERM if PFID was verified but still insane
 */
int ofd_verify_ff(const struct lu_env *env, struct ofd_object *fo,
		  struct obdo *oa)
{
	struct lu_fid	*pfid	= &fo->ofo_pfid;
	int		 rc	= 0;
	ENTRY;

	if (fid_is_sane(pfid)) {
		if (likely(oa->o_parent_seq == pfid->f_seq &&
			   oa->o_parent_oid == pfid->f_oid &&
			   oa->o_stripe_idx == pfid->f_stripe_idx))
			RETURN(0);

		if (fo->ofo_pfid_verified)
			RETURN(-EPERM);
	}

	/* The OST-object may be inconsistent, and we need further verification.
	 * To avoid block the RPC service thread, return -EINPROGRESS to client
	 * and make it retry later. */
	if (fo->ofo_pfid_checking)
		RETURN(-EINPROGRESS);

	rc = ofd_object_ff_load(env, fo);
	if (rc == -ENODATA)
		RETURN(0);

	if (rc < 0)
		RETURN(rc);

	if (likely(oa->o_parent_seq == pfid->f_seq &&
		   oa->o_parent_oid == pfid->f_oid &&
		   oa->o_stripe_idx == pfid->f_stripe_idx))
		RETURN(0);

	/* Push it to the dedicated thread for further verification. */
	ofd_add_inconsistency_item(env, fo, oa);

	RETURN(-EINPROGRESS);
}
コード例 #23
0
static int out_index_insert(struct mdt_thread_info *info)
{
	struct update	  *update = info->mti_u.update.mti_update;
	struct dt_object  *obj = info->mti_u.update.mti_dt_object;
	struct lu_fid	  *fid;
	char		  *name;
	int		  rc = 0;
	int		  size;
	ENTRY;

	name = (char *)update_param_buf(update, 0, NULL);
	if (name == NULL) {
		CERROR("%s: empty name for index insert: rc = %d\n",
		       mdt_obd_name(info->mti_mdt), -EPROTO);
		RETURN(err_serious(-EPROTO));
	}

	fid = (struct lu_fid *)update_param_buf(update, 1, &size);
	if (fid == NULL || size != sizeof(*fid)) {
		CERROR("%s: invalid fid: rc = %d\n",
		       mdt_obd_name(info->mti_mdt), -EPROTO);
		       RETURN(err_serious(-EPROTO));
	}

	fid_le_to_cpu(fid, fid);
	if (!fid_is_sane(fid)) {
		CERROR("%s: invalid FID "DFID": rc = %d\n",
		       mdt_obd_name(info->mti_mdt), PFID(fid),
		       -EPROTO);
		RETURN(err_serious(-EPROTO));
	}

	rc = out_tx_index_insert(info, obj, name, fid, &info->mti_handle,
				 info->mti_u.update.mti_update_reply,
				 info->mti_u.update.mti_update_reply_index);
	RETURN(rc);
}
コード例 #24
0
ファイル: lmv_fld.c プロジェクト: dmlb2000/lustre-release
int lmv_fld_lookup(struct lmv_obd *lmv,
                   const struct lu_fid *fid,
                   mdsno_t *mds)
{
	int rc;
	ENTRY;

	LASSERTF(fid_is_sane(fid), DFID" is insane!\n", PFID(fid));

	/* FIXME: Because ZFS still use LOCAL fid sequence for root,
	 * and root will always be in MDT0, for local fid, it will
	 * return 0 directly. And it should be removed once the root
	 * FID has been assigned with special sequence */
	if (fid_seq(fid) == FID_SEQ_LOCAL_FILE) {
		*mds = 0;
		RETURN(0);
	}

	rc = fld_client_lookup(&lmv->lmv_fld, fid_seq(fid), mds,
                               LU_SEQ_RANGE_MDT, NULL);
        if (rc) {
                CERROR("Error while looking for mds number. Seq "LPX64
                       ", err = %d\n", fid_seq(fid), rc);
                RETURN(rc);
        }

        CDEBUG(D_INODE, "FLD lookup got mds #%x for fid="DFID"\n",
               *mds, PFID(fid));

        if (*mds >= lmv->desc.ld_tgt_count) {
                CERROR("FLD lookup got invalid mds #%x (max: %x) "
                       "for fid="DFID"\n", *mds, lmv->desc.ld_tgt_count,
                       PFID(fid));
                rc = -EINVAL;
        }
        RETURN(rc);
}
コード例 #25
0
ファイル: osp_precreate.c プロジェクト: Lezval/lustre
static int osp_get_lastfid_from_ost(const struct lu_env *env,
				    struct osp_device *d)
{
	struct ptlrpc_request	*req = NULL;
	struct obd_import	*imp;
	struct lu_fid		*last_fid;
	char			*tmp;
	int			rc;
	ENTRY;

	imp = d->opd_obd->u.cli.cl_import;
	LASSERT(imp);

	req = ptlrpc_request_alloc(imp, &RQF_OST_GET_INFO_LAST_FID);
	if (req == NULL)
		RETURN(-ENOMEM);

	req_capsule_set_size(&req->rq_pill, &RMF_GETINFO_KEY, RCL_CLIENT,
			     sizeof(KEY_LAST_FID));

	rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GET_INFO);
	if (rc) {
		ptlrpc_request_free(req);
		RETURN(rc);
	}

	tmp = req_capsule_client_get(&req->rq_pill, &RMF_GETINFO_KEY);
	memcpy(tmp, KEY_LAST_FID, sizeof(KEY_LAST_FID));

	req->rq_no_delay = req->rq_no_resend = 1;
	last_fid = req_capsule_client_get(&req->rq_pill, &RMF_FID);
	fid_cpu_to_le(last_fid, &d->opd_last_used_fid);

	ptlrpc_request_set_replen(req);

	rc = ptlrpc_queue_wait(req);
	if (rc) {
		/* bad-bad OST.. let sysadm sort this out */
		if (rc == -ENOTSUPP) {
			CERROR("%s: server does not support FID: rc = %d\n",
			       d->opd_obd->obd_name, -ENOTSUPP);
		}
		ptlrpc_set_import_active(imp, 0);
		GOTO(out, rc);
	}

	last_fid = req_capsule_server_get(&req->rq_pill, &RMF_FID);
	if (last_fid == NULL) {
		CERROR("%s: Got last_fid failed.\n", d->opd_obd->obd_name);
		GOTO(out, rc = -EPROTO);
	}

	if (!fid_is_sane(last_fid)) {
		CERROR("%s: Got insane last_fid "DFID"\n",
		       d->opd_obd->obd_name, PFID(last_fid));
		GOTO(out, rc = -EPROTO);
	}

	/* Only update the last used fid, if the OST has objects for
	 * this sequence, i.e. fid_oid > 0 */
	if (fid_oid(last_fid) > 0)
		d->opd_last_used_fid = *last_fid;

	CDEBUG(D_HA, "%s: Got last_fid "DFID"\n", d->opd_obd->obd_name,
	       PFID(last_fid));

out:
	ptlrpc_req_finished(req);
	RETURN(rc);
}
コード例 #26
0
/**
 * delete unreferenced files and directories in the PENDING directory
 *
 * Files that remain in PENDING after client->MDS recovery has completed
 * have to be referenced (opened) by some client during recovery, or they
 * will be deleted here (for clients that did not complete recovery).
 *
 * \param mdd  MDD device finishing recovery
 *
 * \retval 0   success
 * \retval -ve error
 */
static int orph_index_iterate(const struct lu_env *env,
			      struct mdd_device *mdd)
{
	struct dt_object *dor = mdd->mdd_orphans;
	struct lu_dirent *ent = &mdd_env_info(env)->mti_ent;
	const struct dt_it_ops *iops;
	struct dt_it     *it;
	struct lu_fid     fid;
        int               key_sz = 0;
        int               rc;
        __u64             cookie;
        ENTRY;

        /* In recovery phase, do not need for any lock here */
        iops = &dor->do_index_ops->dio_it;
        it = iops->init(env, dor, LUDA_64BITHASH, BYPASS_CAPA);
        if (IS_ERR(it)) {
                rc = PTR_ERR(it);
                CERROR("%s: cannot clean PENDING: rc = %d\n",
		       mdd2obd_dev(mdd)->obd_name, rc);
                GOTO(out, rc);
        }

        rc = iops->load(env, it, 0);
        if (rc < 0)
                GOTO(out_put, rc);
        if (rc == 0) {
                CERROR("%s: error loading iterator to clean PENDING\n",
		       mdd2obd_dev(mdd)->obd_name);
                /* Index contains no zero key? */
                GOTO(out_put, rc = -EIO);
        }

	do {
		key_sz = iops->key_size(env, it);
		/* filter out "." and ".." entries from PENDING dir. */
		if (key_sz < 8)
			goto next;

		rc = iops->rec(env, it, (struct dt_rec *)ent, LUDA_64BITHASH);
		if (rc != 0) {
			CERROR("%s: fail to get FID for orphan it: rc = %d\n",
			       mdd2obd_dev(mdd)->obd_name, rc);
			goto next;
		}

		fid_le_to_cpu(&fid, &ent->lde_fid);
		if (!fid_is_sane(&fid)) {
			CERROR("%s: bad FID "DFID" cleaning PENDING\n",
			       mdd2obd_dev(mdd)->obd_name, PFID(&fid));
			goto next;
		}

		/* kill orphan object */
		cookie = iops->store(env, it);
		iops->put(env, it);
		rc = orph_key_test_and_del(env, mdd, &fid,
					   (struct dt_key *)ent->lde_name);

		/* after index delete reset iterator */
		if (rc == 0)
			rc = iops->get(env, it, (const void *)"");
		else
			rc = iops->load(env, it, cookie);
next:
		rc = iops->next(env, it);
	} while (rc == 0);

	GOTO(out_put, rc = 0);
out_put:
	iops->put(env, it);
	iops->fini(env, it);

out:
	return rc;
}
コード例 #27
0
ファイル: out_handler.c プロジェクト: Lezval/lustre
/**
 * Object updates between Targets. Because all the updates has been
 * dis-assemblied into object updates at sender side, so OUT will
 * call OSD API directly to execute these updates.
 *
 * In DNE phase I all of the updates in the request need to be executed
 * in one transaction, and the transaction has to be synchronously.
 *
 * Please refer to lustre/include/lustre/lustre_idl.h for req/reply
 * format.
 */
int out_handle(struct tgt_session_info *tsi)
{
	const struct lu_env		*env = tsi->tsi_env;
	struct tgt_thread_info		*tti = tgt_th_info(env);
	struct thandle_exec_args	*ta = &tti->tti_tea;
	struct req_capsule		*pill = tsi->tsi_pill;
	struct dt_device		*dt = tsi->tsi_tgt->lut_bottom;
	struct update_buf		*ubuf;
	struct update			*update;
	struct update_reply		*update_reply;
	int				 bufsize;
	int				 count;
	int				 old_batchid = -1;
	unsigned			 off;
	int				 i;
	int				 rc = 0;
	int				 rc1 = 0;

	ENTRY;

	req_capsule_set(pill, &RQF_UPDATE_OBJ);
	bufsize = req_capsule_get_size(pill, &RMF_UPDATE, RCL_CLIENT);
	if (bufsize != UPDATE_BUFFER_SIZE) {
		CERROR("%s: invalid bufsize %d: rc = %d\n",
		       tgt_name(tsi->tsi_tgt), bufsize, -EPROTO);
		RETURN(err_serious(-EPROTO));
	}

	ubuf = req_capsule_client_get(pill, &RMF_UPDATE);
	if (ubuf == NULL) {
		CERROR("%s: No buf!: rc = %d\n", tgt_name(tsi->tsi_tgt),
		       -EPROTO);
		RETURN(err_serious(-EPROTO));
	}

	if (le32_to_cpu(ubuf->ub_magic) != UPDATE_BUFFER_MAGIC) {
		CERROR("%s: invalid magic %x expect %x: rc = %d\n",
		       tgt_name(tsi->tsi_tgt), le32_to_cpu(ubuf->ub_magic),
		       UPDATE_BUFFER_MAGIC, -EPROTO);
		RETURN(err_serious(-EPROTO));
	}

	count = le32_to_cpu(ubuf->ub_count);
	if (count <= 0) {
		CERROR("%s: No update!: rc = %d\n",
		       tgt_name(tsi->tsi_tgt), -EPROTO);
		RETURN(err_serious(-EPROTO));
	}

	req_capsule_set_size(pill, &RMF_UPDATE_REPLY, RCL_SERVER,
			     UPDATE_BUFFER_SIZE);
	rc = req_capsule_server_pack(pill);
	if (rc != 0) {
		CERROR("%s: Can't pack response: rc = %d\n",
		       tgt_name(tsi->tsi_tgt), rc);
		RETURN(rc);
	}

	/* Prepare the update reply buffer */
	update_reply = req_capsule_server_get(pill, &RMF_UPDATE_REPLY);
	if (update_reply == NULL)
		RETURN(err_serious(-EPROTO));
	update_init_reply_buf(update_reply, count);
	tti->tti_u.update.tti_update_reply = update_reply;

	rc = out_tx_start(env, dt, ta);
	if (rc != 0)
		RETURN(rc);

	tti->tti_mult_trans = !req_is_replay(tgt_ses_req(tsi));

	/* Walk through updates in the request to execute them synchronously */
	off = cfs_size_round(offsetof(struct update_buf, ub_bufs[0]));
	for (i = 0; i < count; i++) {
		struct tgt_handler	*h;
		struct dt_object	*dt_obj;

		update = (struct update *)((char *)ubuf + off);
		if (old_batchid == -1) {
			old_batchid = update->u_batchid;
		} else if (old_batchid != update->u_batchid) {
			/* Stop the current update transaction,
			 * create a new one */
			rc = out_tx_end(env, ta);
			if (rc != 0)
				RETURN(rc);

			rc = out_tx_start(env, dt, ta);
			if (rc != 0)
				RETURN(rc);
			old_batchid = update->u_batchid;
		}

		fid_le_to_cpu(&update->u_fid, &update->u_fid);
		if (!fid_is_sane(&update->u_fid)) {
			CERROR("%s: invalid FID "DFID": rc = %d\n",
			       tgt_name(tsi->tsi_tgt), PFID(&update->u_fid),
			       -EPROTO);
			GOTO(out, rc = err_serious(-EPROTO));
		}

		dt_obj = dt_locate(env, dt, &update->u_fid);
		if (IS_ERR(dt_obj))
			GOTO(out, rc = PTR_ERR(dt_obj));

		tti->tti_u.update.tti_dt_object = dt_obj;
		tti->tti_u.update.tti_update = update;
		tti->tti_u.update.tti_update_reply_index = i;

		h = out_handler_find(update->u_type);
		if (likely(h != NULL)) {
			/* For real modification RPC, check if the update
			 * has been executed */
			if (h->th_flags & MUTABOR) {
				struct ptlrpc_request *req = tgt_ses_req(tsi);

				if (out_check_resent(env, dt, dt_obj, req,
						     out_reconstruct,
						     update_reply, i))
					GOTO(next, rc);
			}

			rc = h->th_act(tsi);
		} else {
			CERROR("%s: The unsupported opc: 0x%x\n",
			       tgt_name(tsi->tsi_tgt), update->u_type);
			lu_object_put(env, &dt_obj->do_lu);
			GOTO(out, rc = -ENOTSUPP);
		}
next:
		lu_object_put(env, &dt_obj->do_lu);
		if (rc < 0)
			GOTO(out, rc);
		off += cfs_size_round(update_size(update));
	}
out:
	rc1 = out_tx_end(env, ta);
	if (rc == 0)
		rc = rc1;
	RETURN(rc);
}
コード例 #28
0
ファイル: lmv_intent.c プロジェクト: dinatale2/lustre-stable
/*
 * Handler for: getattr, lookup and revalidate cases.
 */
static int
lmv_intent_lookup(struct obd_export *exp, struct md_op_data *op_data,
		  struct lookup_intent *it, struct ptlrpc_request **reqp,
		  ldlm_blocking_callback cb_blocking,
		  __u64 extra_lock_flags)
{
	struct obd_device	*obd = exp->exp_obd;
	struct lmv_obd		*lmv = &obd->u.lmv;
	struct lmv_tgt_desc	*tgt = NULL;
	struct mdt_body		*body;
	struct lmv_stripe_md	*lsm = op_data->op_mea1;
	int			rc = 0;
	ENTRY;

	/* If it returns ERR_PTR(-EBADFD) then it is an unknown hash type
	 * it will try all stripes to locate the object */
	tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
	if (IS_ERR(tgt) && (PTR_ERR(tgt) != -EBADFD))
		RETURN(PTR_ERR(tgt));

	/* Both migrating dir and unknown hash dir need to try
	 * all of sub-stripes */
	if (lsm != NULL && !lmv_is_known_hash_type(lsm->lsm_md_hash_type)) {
		struct lmv_oinfo *oinfo;

		oinfo = &lsm->lsm_md_oinfo[0];

		op_data->op_fid1 = oinfo->lmo_fid;
		op_data->op_mds = oinfo->lmo_mds;
		tgt = lmv_get_target(lmv, oinfo->lmo_mds, NULL);
		if (IS_ERR(tgt))
			RETURN(PTR_ERR(tgt));
	}

	if (!fid_is_sane(&op_data->op_fid2))
		fid_zero(&op_data->op_fid2);

	CDEBUG(D_INODE, "LOOKUP_INTENT with fid1="DFID", fid2="DFID
	       ", name='%s' -> mds #%u lsm=%p lsm_magic=%x\n",
	       PFID(&op_data->op_fid1), PFID(&op_data->op_fid2),
	       op_data->op_name ? op_data->op_name : "<NULL>",
	       tgt->ltd_idx, lsm, lsm == NULL ? -1 : lsm->lsm_md_magic);

	op_data->op_bias &= ~MDS_CROSS_REF;

	rc = md_intent_lock(tgt->ltd_exp, op_data, it, reqp, cb_blocking,
			    extra_lock_flags);
	if (rc < 0)
		RETURN(rc);

	if (*reqp == NULL) {
		/* If RPC happens, lsm information will be revalidated
		 * during update_inode process (see ll_update_lsm_md) */
		if (op_data->op_mea2 != NULL) {
			rc = lmv_revalidate_slaves(exp, op_data->op_mea2,
						   cb_blocking,
						   extra_lock_flags);
			if (rc != 0)
				RETURN(rc);
		}
		RETURN(rc);
	} else if (it_disposition(it, DISP_LOOKUP_NEG) && lsm != NULL &&
		   lmv_need_try_all_stripes(lsm)) {
		/* For migrating and unknown hash type directory, it will
		 * try to target the entry on other stripes */
		int stripe_index;

		for (stripe_index = 1;
		     stripe_index < lsm->lsm_md_stripe_count &&
		     it_disposition(it, DISP_LOOKUP_NEG); stripe_index++) {
			struct lmv_oinfo *oinfo;

			/* release the previous request */
			ptlrpc_req_finished(*reqp);
			it->d.lustre.it_data = NULL;
			*reqp = NULL;

			oinfo = &lsm->lsm_md_oinfo[stripe_index];
			tgt = lmv_find_target(lmv, &oinfo->lmo_fid);
			if (IS_ERR(tgt))
				RETURN(PTR_ERR(tgt));

			CDEBUG(D_INODE, "Try other stripes " DFID"\n",
			       PFID(&oinfo->lmo_fid));

			op_data->op_fid1 = oinfo->lmo_fid;
			it->d.lustre.it_disposition &= ~DISP_ENQ_COMPLETE;
			rc = md_intent_lock(tgt->ltd_exp, op_data, it, reqp,
					    cb_blocking, extra_lock_flags);
			if (rc != 0)
				RETURN(rc);
		}
	}

	/*
	 * MDS has returned success. Probably name has been resolved in
	 * remote inode. Let's check this.
	 */
	body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY);
	if (body == NULL)
		RETURN(-EPROTO);

	/* Not cross-ref case, just get out of here. */
	if (unlikely((body->mbo_valid & OBD_MD_MDS))) {
		rc = lmv_intent_remote(exp, it, NULL, reqp, cb_blocking,
				       extra_lock_flags);
		if (rc != 0)
			RETURN(rc);
		body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY);
		if (body == NULL)
			RETURN(-EPROTO);
	}

	RETURN(rc);
}
コード例 #29
0
ファイル: lmv_intent.c プロジェクト: dinatale2/lustre-stable
static int lmv_intent_remote(struct obd_export *exp, struct lookup_intent *it,
			     const struct lu_fid *parent_fid,
			     struct ptlrpc_request **reqp,
			     ldlm_blocking_callback cb_blocking,
			     __u64 extra_lock_flags)
{
	struct obd_device	*obd = exp->exp_obd;
	struct lmv_obd		*lmv = &obd->u.lmv;
	struct ptlrpc_request	*req = NULL;
	struct lustre_handle	plock;
	struct md_op_data	*op_data;
	struct lmv_tgt_desc	*tgt;
	struct mdt_body		*body;
	int			pmode;
	int			rc = 0;
	ENTRY;

	body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY);
	if (body == NULL)
		RETURN(-EPROTO);

	LASSERT((body->mbo_valid & OBD_MD_MDS));

	/*
	 * Unfortunately, we have to lie to MDC/MDS to retrieve
	 * attributes llite needs and provideproper locking.
	 */
	if (it->it_op & IT_LOOKUP)
		it->it_op = IT_GETATTR;

	/*
	 * We got LOOKUP lock, but we really need attrs.
	 */
	pmode = it->d.lustre.it_lock_mode;
	if (pmode) {
		plock.cookie = it->d.lustre.it_lock_handle;
		it->d.lustre.it_lock_mode = 0;
		it->d.lustre.it_data = NULL;
	}

	LASSERT(fid_is_sane(&body->mbo_fid1));

	tgt = lmv_find_target(lmv, &body->mbo_fid1);
	if (IS_ERR(tgt))
		GOTO(out, rc = PTR_ERR(tgt));

	OBD_ALLOC_PTR(op_data);
	if (op_data == NULL)
		GOTO(out, rc = -ENOMEM);

	op_data->op_fid1 = body->mbo_fid1;
	/* Sent the parent FID to the remote MDT */
	if (parent_fid != NULL) {
		/* The parent fid is only for remote open to
		 * check whether the open is from OBF,
		 * see mdt_cross_open */
		LASSERT(it->it_op & IT_OPEN);
		op_data->op_fid2 = *parent_fid;
	}

	op_data->op_bias = MDS_CROSS_REF;
	CDEBUG(D_INODE, "REMOTE_INTENT with fid="DFID" -> mds #%u\n",
	       PFID(&body->mbo_fid1), tgt->ltd_idx);

	rc = md_intent_lock(tgt->ltd_exp, op_data, it, &req, cb_blocking,
			    extra_lock_flags);
        if (rc)
                GOTO(out_free_op_data, rc);

	/*
	 * LLite needs LOOKUP lock to track dentry revocation in order to
	 * maintain dcache consistency. Thus drop UPDATE|PERM lock here
	 * and put LOOKUP in request.
	 */
	if (it->d.lustre.it_lock_mode != 0) {
		it->d.lustre.it_remote_lock_handle =
					it->d.lustre.it_lock_handle;
		it->d.lustre.it_remote_lock_mode = it->d.lustre.it_lock_mode;
	}

	if (pmode) {
		it->d.lustre.it_lock_handle = plock.cookie;
		it->d.lustre.it_lock_mode = pmode;
	}

	EXIT;
out_free_op_data:
	OBD_FREE_PTR(op_data);
out:
	if (rc && pmode)
		ldlm_lock_decref(&plock, pmode);

	ptlrpc_req_finished(*reqp);
	*reqp = req;
	return rc;
}
コード例 #30
0
ファイル: out_handler.c プロジェクト: KnightKu/lustre-stable
/**
 * Object updates between Targets. Because all the updates has been
 * dis-assemblied into object updates at sender side, so OUT will
 * call OSD API directly to execute these updates.
 *
 * In DNE phase I all of the updates in the request need to be executed
 * in one transaction, and the transaction has to be synchronously.
 *
 * Please refer to lustre/include/lustre/lustre_idl.h for req/reply
 * format.
 */
int out_handle(struct tgt_session_info *tsi)
{
	const struct lu_env		*env = tsi->tsi_env;
	struct tgt_thread_info		*tti = tgt_th_info(env);
	struct thandle_exec_args	*ta = &tti->tti_tea;
	struct req_capsule		*pill = tsi->tsi_pill;
	struct dt_device		*dt = tsi->tsi_tgt->lut_bottom;
	struct out_update_header	*ouh;
	struct out_update_buffer	*oub = NULL;
	struct object_update		*update;
	struct object_update_reply	*reply;
	struct ptlrpc_bulk_desc		*desc = NULL;
	struct l_wait_info		lwi;
	void				**update_bufs;
	int				current_batchid = -1;
	__u32				update_buf_count;
	unsigned int			i;
	unsigned int			reply_index = 0;
	int				rc = 0;
	int				rc1 = 0;
	int				ouh_size, reply_size;
	int				updates;
	ENTRY;

	req_capsule_set(pill, &RQF_OUT_UPDATE);
	ouh_size = req_capsule_get_size(pill, &RMF_OUT_UPDATE_HEADER,
					RCL_CLIENT);
	if (ouh_size <= 0)
		RETURN(err_serious(-EPROTO));

	ouh = req_capsule_client_get(pill, &RMF_OUT_UPDATE_HEADER);
	if (ouh == NULL)
		RETURN(err_serious(-EPROTO));

	if (ouh->ouh_magic != OUT_UPDATE_HEADER_MAGIC) {
		CERROR("%s: invalid update buffer magic %x expect %x: "
		       "rc = %d\n", tgt_name(tsi->tsi_tgt), ouh->ouh_magic,
		       UPDATE_REQUEST_MAGIC, -EPROTO);
		RETURN(err_serious(-EPROTO));
	}

	update_buf_count = ouh->ouh_count;
	if (update_buf_count == 0)
		RETURN(err_serious(-EPROTO));

	OBD_ALLOC(update_bufs, sizeof(*update_bufs) * update_buf_count);
	if (update_bufs == NULL)
		RETURN(err_serious(-ENOMEM));

	if (ouh->ouh_inline_length > 0) {
		update_bufs[0] = ouh->ouh_inline_data;
	} else {
		struct out_update_buffer *tmp;

		oub = req_capsule_client_get(pill, &RMF_OUT_UPDATE_BUF);
		if (oub == NULL)
			GOTO(out_free, rc = err_serious(-EPROTO));

		desc = ptlrpc_prep_bulk_exp(pill->rc_req, update_buf_count,
					    PTLRPC_BULK_OPS_COUNT,
					    PTLRPC_BULK_GET_SINK |
					    PTLRPC_BULK_BUF_KVEC,
					    MDS_BULK_PORTAL,
					    &ptlrpc_bulk_kvec_ops);
		if (desc == NULL)
			GOTO(out_free, rc = err_serious(-ENOMEM));

		tmp = oub;
		for (i = 0; i < update_buf_count; i++, tmp++) {
			if (tmp->oub_size >= OUT_MAXREQSIZE)
				GOTO(out_free, rc = err_serious(-EPROTO));

			OBD_ALLOC(update_bufs[i], tmp->oub_size);
			if (update_bufs[i] == NULL)
				GOTO(out_free, rc = err_serious(-ENOMEM));

			desc->bd_frag_ops->add_iov_frag(desc, update_bufs[i],
							tmp->oub_size);
		}

		pill->rc_req->rq_bulk_write = 1;
		rc = sptlrpc_svc_prep_bulk(pill->rc_req, desc);
		if (rc != 0)
			GOTO(out_free, rc = err_serious(rc));

		rc = target_bulk_io(pill->rc_req->rq_export, desc, &lwi);
		if (rc < 0)
			GOTO(out_free, rc = err_serious(rc));
	}
	/* validate the request and calculate the total update count and
	 * set it to reply */
	reply_size = 0;
	updates = 0;
	for (i = 0; i < update_buf_count; i++) {
		struct object_update_request	*our;
		int				 j;

		our = update_bufs[i];
		if (ptlrpc_req_need_swab(pill->rc_req))
			lustre_swab_object_update_request(our);

		if (our->ourq_magic != UPDATE_REQUEST_MAGIC) {
			CERROR("%s: invalid update buffer magic %x"
			       " expect %x: rc = %d\n",
			       tgt_name(tsi->tsi_tgt), our->ourq_magic,
			       UPDATE_REQUEST_MAGIC, -EPROTO);
			GOTO(out_free, rc = err_serious(-EPROTO));
		}
		updates += our->ourq_count;

		/* need to calculate reply size */
		for (j = 0; j < our->ourq_count; j++) {
			update = object_update_request_get(our, j, NULL);
			if (update == NULL)
				GOTO(out, rc = err_serious(-EPROTO));
			if (ptlrpc_req_need_swab(pill->rc_req))
				lustre_swab_object_update(update);

			if (!fid_is_sane(&update->ou_fid)) {
				CERROR("%s: invalid FID "DFID": rc = %d\n",
				       tgt_name(tsi->tsi_tgt),
				       PFID(&update->ou_fid), -EPROTO);
				GOTO(out, rc = err_serious(-EPROTO));
			}

			/* XXX: what ou_result_size can be considered safe? */

			reply_size += sizeof(reply->ourp_lens[0]);
			reply_size += sizeof(struct object_update_result);
			reply_size += update->ou_result_size;
		}
 	}
	reply_size += sizeof(*reply);

	if (unlikely(reply_size > ouh->ouh_reply_size)) {
		CERROR("%s: too small reply buf %u for %u, need %u at least\n",
		       tgt_name(tsi->tsi_tgt), ouh->ouh_reply_size,
		       updates, reply_size);
		GOTO(out_free, rc = err_serious(-EPROTO));
	}

	req_capsule_set_size(pill, &RMF_OUT_UPDATE_REPLY, RCL_SERVER,
			     ouh->ouh_reply_size);
	rc = req_capsule_server_pack(pill);
	if (rc != 0) {
		CERROR("%s: Can't pack response: rc = %d\n",
		       tgt_name(tsi->tsi_tgt), rc);
		GOTO(out_free, rc = err_serious(-EPROTO));
	}

	/* Prepare the update reply buffer */
	reply = req_capsule_server_get(pill, &RMF_OUT_UPDATE_REPLY);
	if (reply == NULL)
		GOTO(out_free, rc = -EPROTO);
	reply->ourp_magic = UPDATE_REPLY_MAGIC;
	reply->ourp_count = updates;
	tti->tti_u.update.tti_update_reply = reply;
	tti->tti_mult_trans = !req_is_replay(tgt_ses_req(tsi));
 
	/* Walk through updates in the request to execute them */
	for (i = 0; i < update_buf_count; i++) {
		struct tgt_handler	*h;
		struct dt_object	*dt_obj;
		int			update_count;
		struct object_update_request *our;
		int			j;

		our = update_bufs[i];
		update_count = our->ourq_count;
		for (j = 0; j < update_count; j++) {
			update = object_update_request_get(our, j, NULL);

			dt_obj = dt_locate(env, dt, &update->ou_fid);
			if (IS_ERR(dt_obj))
				GOTO(out, rc = PTR_ERR(dt_obj));

			if (dt->dd_record_fid_accessed) {
				lfsck_pack_rfa(&tti->tti_lr,
					       lu_object_fid(&dt_obj->do_lu),
					       LE_FID_ACCESSED,
					       LFSCK_TYPE_LAYOUT);
				tgt_lfsck_in_notify(env, dt, &tti->tti_lr,
						    NULL);
			}

			tti->tti_u.update.tti_dt_object = dt_obj;
			tti->tti_u.update.tti_update = update;
			tti->tti_u.update.tti_update_reply_index = reply_index;

			h = out_handler_find(update->ou_type);
			if (unlikely(h == NULL)) {
				CERROR("%s: unsupported opc: 0x%x\n",
				       tgt_name(tsi->tsi_tgt), update->ou_type);
				GOTO(next, rc = -ENOTSUPP);
			}

			/* Check resend case only for modifying RPC */
			if (h->th_flags & MUTABOR) {
				struct ptlrpc_request *req = tgt_ses_req(tsi);

				if (out_check_resent(env, dt, dt_obj, req,
						     out_reconstruct, reply,
						     reply_index))
					GOTO(next, rc = 0);
			}

			/* start transaction for modification RPC only */
			if (h->th_flags & MUTABOR && current_batchid == -1) {
				current_batchid = update->ou_batchid;
				rc = out_tx_start(env, dt, ta, tsi->tsi_exp);
				if (rc != 0)
					GOTO(next, rc);

				if (update->ou_flags & UPDATE_FL_SYNC)
					ta->ta_handle->th_sync = 1;
			}

			/* Stop the current update transaction, if the update
			 * has different batchid, or read-only update */
			if (((current_batchid != update->ou_batchid) ||
			     !(h->th_flags & MUTABOR)) &&
			     ta->ta_handle != NULL) {
				rc = out_tx_end(env, ta, rc);
				current_batchid = -1;
				if (rc != 0)
					GOTO(next, rc);

				/* start a new transaction if needed */
				if (h->th_flags & MUTABOR) {
					rc = out_tx_start(env, dt, ta,
							  tsi->tsi_exp);
					if (rc != 0)
						GOTO(next, rc);
					if (update->ou_flags & UPDATE_FL_SYNC)
						ta->ta_handle->th_sync = 1;
					current_batchid = update->ou_batchid;
				}
			}

			rc = h->th_act(tsi);
next:
			reply_index++;
			lu_object_put(env, &dt_obj->do_lu);
			if (rc < 0)
				GOTO(out, rc);
		}
	}
out:
	if (current_batchid != -1) {
		rc1 = out_tx_end(env, ta, rc);
		if (rc == 0)
			rc = rc1;
	}

out_free:
	if (update_bufs != NULL) {
		if (oub != NULL) {
			for (i = 0; i < update_buf_count; i++, oub++) {
				if (update_bufs[i] != NULL)
					OBD_FREE(update_bufs[i], oub->oub_size);
			}
		}

		OBD_FREE(update_bufs, sizeof(*update_bufs) * update_buf_count);
	}

	if (desc != NULL)
		ptlrpc_free_bulk(desc);

	RETURN(rc);
}