コード例 #1
0
ファイル: mdt_lib.c プロジェクト: hpc/lustre
int mdt_init_ucred_reint(struct mdt_thread_info *info)
{
        struct ptlrpc_request *req = mdt_info_req(info);
        struct md_ucred       *uc  = mdt_ucred(info);

        if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))
                return 0;

        mdt_exit_ucred(info);

        if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
                return old_init_ucred_reint(info);
        else
                return new_init_ucred(info, REC_INIT, NULL);
}
コード例 #2
0
ファイル: mdt_lib.c プロジェクト: hocks/lustre-release
int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body)
{
        struct ptlrpc_request *req = mdt_info_req(info);
	struct lu_ucred       *uc  = mdt_ucred(info);

	LASSERT(uc != NULL);
	if ((uc->uc_valid == UCRED_OLD) || (uc->uc_valid == UCRED_NEW))
		return 0;

        mdt_exit_ucred(info);

        if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
                return old_init_ucred(info, body);
        else
                return new_init_ucred(info, BODY_INIT, body);
}
コード例 #3
0
ファイル: mdt_hsm.c プロジェクト: bhanug/lustre
/**
 * Retrieve the current HSM flags, archive id and undergoing HSM requests for
 * the fid provided in RPC body.
 *
 * Current requests are read from coordinator states.
 *
 * This is MDS_HSM_STATE_GET RPC handler.
 */
int mdt_hsm_state_get(struct tgt_session_info *tsi)
{
	struct mdt_thread_info	*info = tsi2mdt_info(tsi);
	struct mdt_object	*obj = info->mti_object;
	struct md_attr		*ma  = &info->mti_attr;
	struct hsm_user_state	*hus;
	struct mdt_lock_handle	*lh;
	int			 rc;
	ENTRY;

	if (info->mti_body == NULL || obj == NULL)
		GOTO(out, rc = -EPROTO);

	/* Only valid if client is remote */
	rc = mdt_init_ucred(info, (struct mdt_body *)info->mti_body);
	if (rc < 0)
		GOTO(out, rc = err_serious(rc));

	lh = &info->mti_lh[MDT_LH_CHILD];
	mdt_lock_reg_init(lh, LCK_PR);
	rc = mdt_object_lock(info, obj, lh, MDS_INODELOCK_LOOKUP);
	if (rc < 0)
		GOTO(out_ucred, rc);

	ma->ma_valid = 0;
	ma->ma_need = MA_HSM;
	rc = mdt_attr_get_complex(info, obj, ma);
	if (rc)
		GOTO(out_unlock, rc);

	hus = req_capsule_server_get(tsi->tsi_pill, &RMF_HSM_USER_STATE);
	if (hus == NULL)
		GOTO(out_unlock, rc = -EPROTO);

	/* Current HSM flags */
	hus->hus_states = ma->ma_hsm.mh_flags;
	hus->hus_archive_id = ma->ma_hsm.mh_arch_id;

	EXIT;
out_unlock:
	mdt_object_unlock(info, obj, lh, 1);
out_ucred:
	mdt_exit_ucred(info);
out:
	mdt_thread_info_fini(info);
	return rc;
}
コード例 #4
0
ファイル: mdt_hsm.c プロジェクト: bhanug/lustre
static inline bool mdt_hsm_is_admin(struct mdt_thread_info *info)
{
	bool is_admin;
	int rc;

	if (info->mti_body == NULL)
		return false;

	rc = mdt_init_ucred(info, (struct mdt_body *)info->mti_body);
	if (rc < 0)
		return false;

	is_admin = md_capable(mdt_ucred(info), CFS_CAP_SYS_ADMIN);

	mdt_exit_ucred(info);

	return is_admin;
}
コード例 #5
0
ファイル: mdt_xattr.c プロジェクト: LLNL/lustre
int mdt_reint_setxattr(struct mdt_thread_info *info,
                       struct mdt_lock_handle *unused)
{
        struct ptlrpc_request   *req = mdt_info_req(info);
        struct md_ucred         *uc  = mdt_ucred(info);
        struct mdt_lock_handle  *lh;
        const struct lu_env     *env  = info->mti_env;
        struct lu_buf           *buf  = &info->mti_buf;
        struct mdt_reint_record *rr   = &info->mti_rr;
        struct md_attr          *ma = &info->mti_attr;
        struct lu_attr          *attr = &info->mti_attr.ma_attr;
        struct mdt_object       *obj;
        struct md_object        *child;
        __u64                    valid = attr->la_valid;
        const char              *xattr_name = rr->rr_name;
        int                      xattr_len = rr->rr_eadatalen;
        __u64                    lockpart;
        int                      rc;
        posix_acl_xattr_header  *new_xattr = NULL;
        __u32                    remote = exp_connect_rmtclient(info->mti_exp);
        __u32                    perm;
        ENTRY;

        CDEBUG(D_INODE, "setxattr for "DFID"\n", PFID(rr->rr_fid1));

        if (OBD_FAIL_CHECK(OBD_FAIL_MDS_SETXATTR))
                RETURN(err_serious(-ENOMEM));

        CDEBUG(D_INODE, "%s xattr %s\n",
               valid & OBD_MD_FLXATTR ? "set" : "remove", xattr_name);

        rc = mdt_init_ucred_reint(info);
        if (rc != 0)
                RETURN(rc);

        if (valid & OBD_MD_FLRMTRSETFACL) {
                if (unlikely(!remote))
                        GOTO(out, rc = err_serious(-EINVAL));

                perm = mdt_identity_get_perm(uc->mu_identity, remote,
                                             req->rq_peer.nid);
                if (!(perm & CFS_RMTACL_PERM))
                        GOTO(out, rc = err_serious(-EPERM));
        }

        if (strncmp(xattr_name, XATTR_USER_PREFIX,
                    sizeof(XATTR_USER_PREFIX) - 1) == 0) {
                if (!(req->rq_export->exp_connect_flags & OBD_CONNECT_XATTR))
                        GOTO(out, rc = -EOPNOTSUPP);
                if (strcmp(xattr_name, XATTR_NAME_LOV) == 0)
                        GOTO(out, rc = -EACCES);
                if (strcmp(xattr_name, XATTR_NAME_LMA) == 0)
                        GOTO(out, rc = 0);
                if (strcmp(xattr_name, XATTR_NAME_LINK) == 0)
                        GOTO(out, rc = 0);
        } else if ((valid & OBD_MD_FLXATTR) &&
                   (strncmp(xattr_name, XATTR_NAME_ACL_ACCESS,
                            sizeof(XATTR_NAME_ACL_ACCESS) - 1) == 0 ||
                    strncmp(xattr_name, XATTR_NAME_ACL_DEFAULT,
                            sizeof(XATTR_NAME_ACL_DEFAULT) - 1) == 0)) {
                /* currently lustre limit acl access size */
                if (xattr_len > LUSTRE_POSIX_ACL_MAX_SIZE)
                        GOTO(out, -ERANGE);
        }

        lockpart = MDS_INODELOCK_UPDATE;
        /* Revoke all clients' lookup lock, since the access
         * permissions for this inode is changed when ACL_ACCESS is
         * set. This isn't needed for ACL_DEFAULT, since that does
         * not change the access permissions of this inode, nor any
         * other existing inodes. It is setting the ACLs inherited
         * by new directories/files at create time. */
        if (!strcmp(xattr_name, XATTR_NAME_ACL_ACCESS))
                lockpart |= MDS_INODELOCK_LOOKUP;

        lh = &info->mti_lh[MDT_LH_PARENT];
        /* ACLs were sent to clients under LCK_CR locks, so taking LCK_EX
         * to cancel them. */
        mdt_lock_reg_init(lh, LCK_EX);
        obj = mdt_object_find_lock(info, rr->rr_fid1, lh, lockpart);
        if (IS_ERR(obj))
                GOTO(out, rc =  PTR_ERR(obj));

        info->mti_mos = obj;
        rc = mdt_version_get_check_save(info, obj, 0);
        if (rc)
                GOTO(out_unlock, rc);

        if (unlikely(!(valid & OBD_MD_FLCTIME))) {
                /* This isn't strictly an error, but all current clients
                 * should set OBD_MD_FLCTIME when setting attributes. */
                CWARN("%s: client miss to set OBD_MD_FLCTIME when "
                      "setxattr %s: [object "DFID"] [valid "LPU64"]\n",
                      info->mti_exp->exp_obd->obd_name, xattr_name,
                      PFID(rr->rr_fid1), valid);
                attr->la_ctime = cfs_time_current_sec();
        }
        attr->la_valid = LA_CTIME;
        child = mdt_object_child(obj);
        if (valid & OBD_MD_FLXATTR) {
                char *xattr = (void *)rr->rr_eadata;

                if (xattr_len > 0) {
                        int flags = 0;

                        if (valid & OBD_MD_FLRMTLSETFACL) {
                                if (unlikely(!remote))
                                        GOTO(out_unlock, rc = -EINVAL);

                                xattr_len = mdt_rmtlsetfacl(info, child,
                                                xattr_name,
                                                (ext_acl_xattr_header *)xattr,
                                                &new_xattr);
                                if (xattr_len < 0)
                                        GOTO(out_unlock, rc = xattr_len);

                                xattr = (char *)new_xattr;
                        }

                        if (attr->la_flags & XATTR_REPLACE)
                                flags |= LU_XATTR_REPLACE;

                        if (attr->la_flags & XATTR_CREATE)
                                flags |= LU_XATTR_CREATE;

                        mdt_fail_write(env, info->mti_mdt->mdt_bottom,
                                       OBD_FAIL_MDS_SETXATTR_WRITE);

                        buf->lb_buf = xattr;
                        buf->lb_len = xattr_len;
                        rc = mo_xattr_set(env, child, buf, xattr_name, flags);
                        /* update ctime after xattr changed */
                        if (rc == 0) {
                                ma->ma_attr_flags |= MDS_PERM_BYPASS;
                                mo_attr_set(env, child, ma);
                        }
                }
        } else if (valid & OBD_MD_FLXATTRRM) {
                rc = mo_xattr_del(env, child, xattr_name);
                /* update ctime after xattr changed */
                if (rc == 0) {
                        ma->ma_attr_flags |= MDS_PERM_BYPASS;
                        mo_attr_set(env, child, ma);
                }
        } else {
                CDEBUG(D_INFO, "valid bits: "LPX64"\n", valid);
                rc = -EINVAL;
        }
        if (rc == 0)
                mdt_counter_incr(req->rq_export, LPROC_MDT_SETXATTR);

        EXIT;
out_unlock:
        mdt_object_unlock_put(info, obj, lh, rc);
        if (unlikely(new_xattr != NULL))
                lustre_posix_acl_xattr_free(new_xattr, xattr_len);
out:
        mdt_exit_ucred(info);
        return rc;
}
コード例 #6
0
ファイル: mdt_xattr.c プロジェクト: LLNL/lustre
int mdt_getxattr(struct mdt_thread_info *info)
{
        struct ptlrpc_request  *req = mdt_info_req(info);
        struct mdt_export_data *med = mdt_req2med(req);
        struct md_ucred        *uc  = mdt_ucred(info);
        struct mdt_body        *reqbody;
        struct mdt_body        *repbody = NULL;
        struct md_object       *next;
        struct lu_buf          *buf;
        __u32                   remote = exp_connect_rmtclient(info->mti_exp);
        __u32                   perm;
        int                     easize, rc;
        ENTRY;

        LASSERT(info->mti_object != NULL);
        LASSERT(lu_object_assert_exists(&info->mti_object->mot_obj.mo_lu));

        CDEBUG(D_INODE, "getxattr "DFID"\n", PFID(&info->mti_body->fid1));

        reqbody = req_capsule_client_get(info->mti_pill, &RMF_MDT_BODY);
        if (reqbody == NULL)
                RETURN(err_serious(-EFAULT));

        rc = mdt_init_ucred(info, reqbody);
        if (rc)
                RETURN(err_serious(rc));

        next = mdt_object_child(info->mti_object);

        if (info->mti_body->valid & OBD_MD_FLRMTRGETFACL) {
                if (unlikely(!remote))
                        GOTO(out, rc = err_serious(-EINVAL));

                perm = mdt_identity_get_perm(uc->mu_identity, remote,
                                             req->rq_peer.nid);
                if (!(perm & CFS_RMTACL_PERM))
                        GOTO(out, rc = err_serious(-EPERM));

                rc = mo_permission(info->mti_env, NULL, next, NULL,
                                   MAY_RGETFACL);
                if (rc)
                        GOTO(out, rc = err_serious(rc));
        }

        easize = mdt_getxattr_pack_reply(info);
        if (easize < 0)
                GOTO(out, rc = err_serious(easize));

        repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
        LASSERT(repbody != NULL);

        /* No need further getxattr. */
        if (easize == 0 || reqbody->eadatasize == 0)
                GOTO(out, rc = easize);


        buf = &info->mti_buf;
        buf->lb_buf = req_capsule_server_get(info->mti_pill, &RMF_EADATA);
        buf->lb_len = easize;

        if (info->mti_body->valid & OBD_MD_FLXATTR) {
                int flags = CFS_IC_NOTHING;
                char *xattr_name = req_capsule_client_get(info->mti_pill,
                                                          &RMF_NAME);
                CDEBUG(D_INODE, "getxattr %s\n", xattr_name);

                rc = mo_xattr_get(info->mti_env, next, buf, xattr_name);
                if (rc < 0) {
                        CERROR("getxattr failed: %d\n", rc);
                        GOTO(out, rc);
                }

                if (info->mti_body->valid &
                    (OBD_MD_FLRMTLSETFACL | OBD_MD_FLRMTLGETFACL))
                        flags = CFS_IC_ALL;
                else if (info->mti_body->valid & OBD_MD_FLRMTRGETFACL)
                        flags = CFS_IC_MAPPED;

                if (rc > 0 && flags != CFS_IC_NOTHING) {
                        int rc1;

                        if (unlikely(!remote))
                                GOTO(out, rc = -EINVAL);

                        rc1 = lustre_posix_acl_xattr_id2client(uc,
                                        med->med_idmap,
                                        (posix_acl_xattr_header *)(buf->lb_buf),
                                        rc, flags);
                        if (unlikely(rc1 < 0))
                                rc = rc1;
                }
        } else if (info->mti_body->valid & OBD_MD_FLXATTRLS) {
                CDEBUG(D_INODE, "listxattr\n");

                rc = mo_xattr_list(info->mti_env, next, buf);
                if (rc < 0)
                        CDEBUG(D_INFO, "listxattr failed: %d\n", rc);
        } else
                LBUG();

        EXIT;
out:
        if (rc >= 0) {
                mdt_counter_incr(req->rq_export, LPROC_MDT_GETXATTR);
                repbody->eadatasize = rc;
                rc = 0;
        }
        mdt_exit_ucred(info);
        return rc;
}
コード例 #7
0
ファイル: mdt_xattr.c プロジェクト: hocks/lustre-release
int mdt_getxattr(struct mdt_thread_info *info)
{
	struct ptlrpc_request  *req = mdt_info_req(info);
	struct mdt_export_data *med = mdt_req2med(req);
	struct lu_ucred        *uc  = lu_ucred(info->mti_env);
        struct mdt_body        *reqbody;
        struct mdt_body        *repbody = NULL;
        struct md_object       *next;
        struct lu_buf          *buf;
        __u32                   remote = exp_connect_rmtclient(info->mti_exp);
        __u32                   perm;
        int                     easize, rc;
	obd_valid		valid;
        ENTRY;

        LASSERT(info->mti_object != NULL);
	LASSERT(lu_object_assert_exists(&info->mti_object->mot_obj));

        CDEBUG(D_INODE, "getxattr "DFID"\n", PFID(&info->mti_body->fid1));

        reqbody = req_capsule_client_get(info->mti_pill, &RMF_MDT_BODY);
        if (reqbody == NULL)
                RETURN(err_serious(-EFAULT));

	rc = mdt_init_ucred(info, reqbody);
        if (rc)
                RETURN(err_serious(rc));

        next = mdt_object_child(info->mti_object);

        if (info->mti_body->valid & OBD_MD_FLRMTRGETFACL) {
                if (unlikely(!remote))
                        GOTO(out, rc = err_serious(-EINVAL));

		perm = mdt_identity_get_perm(uc->uc_identity, remote,
					     req->rq_peer.nid);
                if (!(perm & CFS_RMTACL_PERM))
                        GOTO(out, rc = err_serious(-EPERM));

                rc = mo_permission(info->mti_env, NULL, next, NULL,
                                   MAY_RGETFACL);
                if (rc)
                        GOTO(out, rc = err_serious(rc));
        }

        easize = mdt_getxattr_pack_reply(info);
        if (easize < 0)
                GOTO(out, rc = err_serious(easize));

        repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
        LASSERT(repbody != NULL);

        /* No need further getxattr. */
        if (easize == 0 || reqbody->eadatasize == 0)
                GOTO(out, rc = easize);

        buf = &info->mti_buf;
        buf->lb_buf = req_capsule_server_get(info->mti_pill, &RMF_EADATA);
        buf->lb_len = easize;

	valid = info->mti_body->valid & (OBD_MD_FLXATTR | OBD_MD_FLXATTRLS);

	if (valid == OBD_MD_FLXATTR) {
		char *xattr_name = req_capsule_client_get(info->mti_pill,
							  &RMF_NAME);
		rc = mdt_getxattr_one(info, xattr_name, next, buf, med, uc);
	} else if (valid == OBD_MD_FLXATTRLS) {
		CDEBUG(D_INODE, "listxattr\n");

		rc = mo_xattr_list(info->mti_env, next, buf);
		if (rc < 0)
			CDEBUG(D_INFO, "listxattr failed: %d\n", rc);
	} else if (valid == OBD_MD_FLXATTRALL) {
		rc = mdt_getxattr_all(info, reqbody, repbody,
				      buf, next);
	} else
		LBUG();

	EXIT;
out:
	if (rc >= 0) {
		mdt_counter_incr(req, LPROC_MDT_GETXATTR);
		repbody->eadatasize = rc;
		rc = 0;
	}
	mdt_exit_ucred(info);
	return rc;
}
コード例 #8
0
ファイル: mdt_hsm.c プロジェクト: bhanug/lustre
/**
 * Process the HSM actions described in a struct hsm_user_request.
 *
 * The action described in hur will be send to coordinator to be saved and
 * processed later or either handled directly if hur.hur_action is HUA_RELEASE.
 *
 * This is MDS_HSM_REQUEST RPC handler.
 */
int mdt_hsm_request(struct tgt_session_info *tsi)
{
	struct mdt_thread_info		*info;
	struct req_capsule		*pill = tsi->tsi_pill;
	struct hsm_request		*hr;
	struct hsm_user_item		*hui;
	struct hsm_action_list		*hal;
	struct hsm_action_item		*hai;
	const void			*data;
	int				 hui_list_size;
	int				 data_size;
	enum hsm_copytool_action	 action = HSMA_NONE;
	__u64				 compound_id;
	int				 hal_size, i, rc;
	ENTRY;

	hr = req_capsule_client_get(pill, &RMF_MDS_HSM_REQUEST);
	hui = req_capsule_client_get(pill, &RMF_MDS_HSM_USER_ITEM);
	data = req_capsule_client_get(pill, &RMF_GENERIC_DATA);

	if (tsi->tsi_mdt_body == NULL || hr == NULL || hui == NULL || data == NULL)
		RETURN(-EPROTO);

	/* Sanity check. Nothing to do with an empty list */
	if (hr->hr_itemcount == 0)
		RETURN(0);

	hui_list_size = req_capsule_get_size(pill, &RMF_MDS_HSM_USER_ITEM,
					     RCL_CLIENT);
	if (hui_list_size < hr->hr_itemcount * sizeof(*hui))
		RETURN(-EPROTO);

	data_size = req_capsule_get_size(pill, &RMF_GENERIC_DATA, RCL_CLIENT);
	if (data_size != hr->hr_data_len)
		RETURN(-EPROTO);

	info = tsi2mdt_info(tsi);
	/* Only valid if client is remote */
	rc = mdt_init_ucred(info, (struct mdt_body *)info->mti_body);
	if (rc)
		GOTO(out, rc);

	switch (hr->hr_action) {
	/* code to be removed in hsm1_merge and final patch */
	case HUA_RELEASE:
		CERROR("Release action is not working in hsm1_coord\n");
		GOTO(out_ucred, rc = -EINVAL);
		break;
	/* end of code to be removed */
	case HUA_ARCHIVE:
		action = HSMA_ARCHIVE;
		break;
	case HUA_RESTORE:
		action = HSMA_RESTORE;
		break;
	case HUA_REMOVE:
		action = HSMA_REMOVE;
		break;
	case HUA_CANCEL:
		action = HSMA_CANCEL;
		break;
	default:
		CERROR("Unknown hsm action: %d\n", hr->hr_action);
		GOTO(out_ucred, rc = -EINVAL);
	}

	hal_size = sizeof(*hal) + cfs_size_round(MTI_NAME_MAXLEN) /* fsname */ +
		   (sizeof(*hai) + cfs_size_round(hr->hr_data_len)) *
		   hr->hr_itemcount;

	MDT_HSM_ALLOC(hal, hal_size);
	if (hal == NULL)
		GOTO(out_ucred, rc = -ENOMEM);

	hal->hal_version = HAL_VERSION;
	hal->hal_archive_id = hr->hr_archive_id;
	hal->hal_flags = hr->hr_flags;
	obd_uuid2fsname(hal->hal_fsname, mdt_obd_name(info->mti_mdt),
			MTI_NAME_MAXLEN);

	hal->hal_count = 0;
	hai = hai_first(hal);
	for (i = 0; i < hr->hr_itemcount; i++, hai = hai_next(hai)) {
		/* Get rid of duplicate entries. Otherwise we get
		 * duplicated work in the llog. */
		if (is_fid_in_hal(hal, &hui[i].hui_fid))
			continue;

		hai->hai_action = action;
		hai->hai_cookie = 0;
		hai->hai_gid = 0;
		hai->hai_fid = hui[i].hui_fid;
		hai->hai_extent = hui[i].hui_extent;
		memcpy(hai->hai_data, data, hr->hr_data_len);
		hai->hai_len = sizeof(*hai) + hr->hr_data_len;

		hal->hal_count++;
	}

	rc = mdt_hsm_add_actions(info, hal, &compound_id);

	MDT_HSM_FREE(hal, hal_size);

	GOTO(out_ucred, rc);

out_ucred:
	mdt_exit_ucred(info);
out:
	mdt_thread_info_fini(info);
	return rc;
}
コード例 #9
0
ファイル: mdt_hsm.c プロジェクト: bhanug/lustre
/**
 * Retrieve undergoing HSM requests for the fid provided in RPC body.
 * Current requests are read from coordinator states.
 *
 * This is MDS_HSM_ACTION RPC handler.
 */
int mdt_hsm_action(struct tgt_session_info *tsi)
{
	struct mdt_thread_info		*info;
	struct hsm_current_action	*hca;
	struct hsm_action_list		*hal = NULL;
	struct hsm_action_item		*hai;
	int				 hal_size;
	int				 rc;
	ENTRY;

	hca = req_capsule_server_get(tsi->tsi_pill,
				     &RMF_MDS_HSM_CURRENT_ACTION);
	if (hca == NULL)
		RETURN(err_serious(-EPROTO));

	if (tsi->tsi_mdt_body == NULL)
		RETURN(-EPROTO);

	info = tsi2mdt_info(tsi);
	/* Only valid if client is remote */
	rc = mdt_init_ucred(info, (struct mdt_body *)info->mti_body);
	if (rc)
		GOTO(out, rc = err_serious(rc));

	/* Coordinator information */
	hal_size = sizeof(*hal) +
		   cfs_size_round(MTI_NAME_MAXLEN) /* fsname */ +
		   cfs_size_round(sizeof(*hai));

	MDT_HSM_ALLOC(hal, hal_size);
	if (hal == NULL)
		GOTO(out_ucred, rc = -ENOMEM);

	hal->hal_version = HAL_VERSION;
	hal->hal_archive_id = 0;
	hal->hal_flags = 0;
	obd_uuid2fsname(hal->hal_fsname, mdt_obd_name(info->mti_mdt),
			MTI_NAME_MAXLEN);
	hal->hal_count = 1;
	hai = hai_first(hal);
	hai->hai_action = HSMA_NONE;
	hai->hai_cookie = 0;
	hai->hai_gid = 0;
	hai->hai_fid = info->mti_body->mbo_fid1;
	hai->hai_len = sizeof(*hai);

	rc = mdt_hsm_get_actions(info, hal);
	if (rc)
		GOTO(out_free, rc);

	/* cookie is used to give back request status */
	if (hai->hai_cookie == 0)
		hca->hca_state = HPS_WAITING;
	else
		hca->hca_state = HPS_RUNNING;

	switch (hai->hai_action) {
	case HSMA_NONE:
		hca->hca_action = HUA_NONE;
		break;
	case HSMA_ARCHIVE:
		hca->hca_action = HUA_ARCHIVE;
		break;
	case HSMA_RESTORE:
		hca->hca_action = HUA_RESTORE;
		break;
	case HSMA_REMOVE:
		hca->hca_action = HUA_REMOVE;
		break;
	case HSMA_CANCEL:
		hca->hca_action = HUA_CANCEL;
		break;
	default:
		hca->hca_action = HUA_NONE;
		CERROR("%s: Unknown hsm action: %d on "DFID"\n",
		       mdt_obd_name(info->mti_mdt),
		       hai->hai_action, PFID(&hai->hai_fid));
		break;
	}

	hca->hca_location = hai->hai_extent;

	EXIT;
out_free:
	MDT_HSM_FREE(hal, hal_size);
out_ucred:
	mdt_exit_ucred(info);
out:
	mdt_thread_info_fini(info);
	return rc;
}
コード例 #10
0
ファイル: mdt_hsm.c プロジェクト: bhanug/lustre
/**
 * Change HSM state and archive number of a file.
 *
 * Archive number is changed iif the value is not 0.
 * The new flagset that will be computed should result in a coherent state.
 * This function checks that flags are compatible.
 *
 * This is MDS_HSM_STATE_SET RPC handler.
 */
int mdt_hsm_state_set(struct tgt_session_info *tsi)
{
	struct mdt_thread_info	*info = tsi2mdt_info(tsi);
	struct mdt_object	*obj = info->mti_object;
	struct md_attr          *ma = &info->mti_attr;
	struct hsm_state_set	*hss;
	struct mdt_lock_handle	*lh;
	int			 rc;
	__u64			 flags;
	ENTRY;

	hss = req_capsule_client_get(info->mti_pill, &RMF_HSM_STATE_SET);

	if (info->mti_body == NULL || obj == NULL || hss == NULL)
		GOTO(out, rc = -EPROTO);

	/* Only valid if client is remote */
	rc = mdt_init_ucred(info, (struct mdt_body *)info->mti_body);
	if (rc < 0)
		GOTO(out, rc = err_serious(rc));

	lh = &info->mti_lh[MDT_LH_CHILD];
	mdt_lock_reg_init(lh, LCK_PW);
	rc = mdt_object_lock(info, obj, lh, MDS_INODELOCK_LOOKUP |
			     MDS_INODELOCK_XATTR);
	if (rc < 0)
		GOTO(out_ucred, rc);

	/* Detect out-of range masks */
	if ((hss->hss_setmask | hss->hss_clearmask) & ~HSM_FLAGS_MASK) {
		CDEBUG(D_HSM, "Incompatible masks provided (set "LPX64
		       ", clear "LPX64") vs supported set (%#x).\n",
		       hss->hss_setmask, hss->hss_clearmask, HSM_FLAGS_MASK);
		GOTO(out_unlock, rc = -EINVAL);
	}

	/* Non-root users are forbidden to set or clear flags which are
	 * NOT defined in HSM_USER_MASK. */
	if (((hss->hss_setmask | hss->hss_clearmask) & ~HSM_USER_MASK) &&
	    !md_capable(mdt_ucred(info), CFS_CAP_SYS_ADMIN)) {
		CDEBUG(D_HSM, "Incompatible masks provided (set "LPX64
		       ", clear "LPX64") vs unprivileged set (%#x).\n",
		       hss->hss_setmask, hss->hss_clearmask, HSM_USER_MASK);
		GOTO(out_unlock, rc = -EPERM);
	}

	/* Read current HSM info */
	ma->ma_valid = 0;
	ma->ma_need = MA_HSM;
	rc = mdt_attr_get_complex(info, obj, ma);
	if (rc)
		GOTO(out_unlock, rc);

	/* Change HSM flags depending on provided masks */
	if (hss->hss_valid & HSS_SETMASK)
		ma->ma_hsm.mh_flags |= hss->hss_setmask;
	if (hss->hss_valid & HSS_CLEARMASK)
		ma->ma_hsm.mh_flags &= ~hss->hss_clearmask;

	/* Change archive_id if provided. */
	if (hss->hss_valid & HSS_ARCHIVE_ID) {
		if (!(ma->ma_hsm.mh_flags & HS_EXISTS)) {
			CDEBUG(D_HSM, "Could not set an archive number for "
			       DFID "if HSM EXISTS flag is not set.\n",
			       PFID(&info->mti_body->mbo_fid1));
			GOTO(out_unlock, rc);
		}

		/* Detect out-of range archive id */
		if (hss->hss_archive_id > LL_HSM_MAX_ARCHIVE) {
			CDEBUG(D_HSM, "archive id %u exceeds maximum %zu.\n",
			       hss->hss_archive_id, LL_HSM_MAX_ARCHIVE);
			GOTO(out_unlock, rc = -EINVAL);
		}

		ma->ma_hsm.mh_arch_id = hss->hss_archive_id;
	}

	/* Check for inconsistant HSM flagset.
	 * DIRTY without EXISTS: no dirty if no archive was created.
	 * DIRTY and RELEASED: a dirty file could not be released.
	 * RELEASED without ARCHIVED: do not release a non-archived file.
	 * LOST without ARCHIVED: cannot lost a non-archived file.
	 */
	flags = ma->ma_hsm.mh_flags;
	if ((flags & HS_DIRTY    && !(flags & HS_EXISTS)) ||
	    (flags & HS_RELEASED && flags & HS_DIRTY) ||
	    (flags & HS_RELEASED && !(flags & HS_ARCHIVED)) ||
	    (flags & HS_LOST     && !(flags & HS_ARCHIVED))) {
		CDEBUG(D_HSM, "Incompatible flag change on "DFID
			      "flags="LPX64"\n",
		       PFID(&info->mti_body->mbo_fid1), flags);
		GOTO(out_unlock, rc = -EINVAL);
	}

	/* Save the modified flags */
	rc = mdt_hsm_attr_set(info, obj, &ma->ma_hsm);
	if (rc)
		GOTO(out_unlock, rc);

	EXIT;

out_unlock:
	mdt_object_unlock(info, obj, lh, 1);
out_ucred:
	mdt_exit_ucred(info);
out:
	mdt_thread_info_fini(info);
	return rc;
}
コード例 #11
0
ファイル: mdt_xattr.c プロジェクト: Xyratex/lustre-stable
int mdt_reint_setxattr(struct mdt_thread_info *info,
                       struct mdt_lock_handle *unused)
{
	struct ptlrpc_request	*req = mdt_info_req(info);
	struct mdt_lock_handle	*lh;
	const struct lu_env	*env  = info->mti_env;
	struct lu_buf		*buf  = &info->mti_buf;
	struct mdt_reint_record	*rr   = &info->mti_rr;
	struct md_attr		*ma = &info->mti_attr;
	struct lu_attr		*attr = &info->mti_attr.ma_attr;
	struct mdt_object	*obj;
	struct md_object	*child;
	__u64			 valid = attr->la_valid;
	const char		*xattr_name = rr->rr_name.ln_name;
	int			 xattr_len = rr->rr_eadatalen;
	__u64			 lockpart = MDS_INODELOCK_UPDATE;
	int			 rc;
	ENTRY;

	CDEBUG(D_INODE, "setxattr for "DFID": %s %s\n", PFID(rr->rr_fid1),
	       valid & OBD_MD_FLXATTR ? "set" : "remove", xattr_name);

	if (info->mti_dlm_req)
		ldlm_request_cancel(req, info->mti_dlm_req, 0, LATF_SKIP);

        if (OBD_FAIL_CHECK(OBD_FAIL_MDS_SETXATTR))
                RETURN(err_serious(-ENOMEM));

	rc = mdt_init_ucred_reint(info);
        if (rc != 0)
                RETURN(rc);

	if (strncmp(xattr_name, XATTR_USER_PREFIX,
		    sizeof(XATTR_USER_PREFIX) - 1) == 0) {
		if (!(exp_connect_flags(req->rq_export) & OBD_CONNECT_XATTR))
			GOTO(out, rc = -EOPNOTSUPP);
	} else if (strncmp(xattr_name, XATTR_TRUSTED_PREFIX,
		    sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0) {

		/* setxattr(LMV) with lum is used to shrink dir layout */
		if (strcmp(xattr_name, XATTR_NAME_LMV) == 0) {
			__u32 *magic = rr->rr_eadata;

			/* we don't let to remove LMV? */
			if (!rr->rr_eadata)
				GOTO(out, rc = 0);

			if (le32_to_cpu(*magic) == LMV_USER_MAGIC ||
			    le32_to_cpu(*magic) == LMV_USER_MAGIC_SPECIFIC) {
				rc = mdt_dir_layout_shrink(info);
				GOTO(out, rc);
			}
		}

		if (!md_capable(mdt_ucred(info), CFS_CAP_SYS_ADMIN))
			GOTO(out, rc = -EPERM);

		if (strcmp(xattr_name, XATTR_NAME_LOV) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_LMA) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_LMV) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_LINK) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_FID) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_VERSION) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_SOM) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_HSM) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_LFSCK_NAMESPACE) == 0)
			GOTO(out, rc = 0);
	} else if ((valid & OBD_MD_FLXATTR) &&
		   (strcmp(xattr_name, XATTR_NAME_ACL_ACCESS) == 0 ||
		    strcmp(xattr_name, XATTR_NAME_ACL_DEFAULT) == 0)) {
		rc = mdt_nodemap_map_acl(info, rr->rr_eadata, xattr_len,
					 xattr_name, NODEMAP_CLIENT_TO_FS);
		if (rc < 0)
			GOTO(out, rc);
		/* ACLs were mapped out, return an error so the user knows */
		if (rc != xattr_len)
			GOTO(out, rc = -EPERM);
	} else if ((strlen(xattr_name) > strlen(XATTR_LUSTRE_LOV) + 1) &&
		   strncmp(xattr_name, XATTR_LUSTRE_LOV,
			   strlen(XATTR_LUSTRE_LOV)) == 0) {

		if (strncmp(xattr_name, XATTR_LUSTRE_LOV".add",
			    strlen(XATTR_LUSTRE_LOV".add")) &&
		    strncmp(xattr_name, XATTR_LUSTRE_LOV".set",
			    strlen(XATTR_LUSTRE_LOV".set")) &&
		    strncmp(xattr_name, XATTR_LUSTRE_LOV".del",
			    strlen(XATTR_LUSTRE_LOV".del"))) {
			CERROR("%s: invalid xattr name: %s\n",
			       mdt_obd_name(info->mti_mdt), xattr_name);
			GOTO(out, rc = -EINVAL);
		}

		lockpart |= MDS_INODELOCK_LAYOUT;
	}

        /* Revoke all clients' lookup lock, since the access
         * permissions for this inode is changed when ACL_ACCESS is
         * set. This isn't needed for ACL_DEFAULT, since that does
         * not change the access permissions of this inode, nor any
         * other existing inodes. It is setting the ACLs inherited
         * by new directories/files at create time. */
	/* We need revoke both LOOKUP|PERM lock here, see mdt_attr_set. */
        if (!strcmp(xattr_name, XATTR_NAME_ACL_ACCESS))
		lockpart |= MDS_INODELOCK_PERM | MDS_INODELOCK_LOOKUP;
	/* We need to take the lock on behalf of old clients so that newer
	 * clients flush their xattr caches */
	else
		lockpart |= MDS_INODELOCK_XATTR;

        lh = &info->mti_lh[MDT_LH_PARENT];
        /* ACLs were sent to clients under LCK_CR locks, so taking LCK_EX
         * to cancel them. */
        mdt_lock_reg_init(lh, LCK_EX);
        obj = mdt_object_find_lock(info, rr->rr_fid1, lh, lockpart);
	if (IS_ERR(obj))
		GOTO(out, rc = PTR_ERR(obj));

	tgt_vbr_obj_set(env, mdt_obj2dt(obj));
	rc = mdt_version_get_check_save(info, obj, 0);
	if (rc)
		GOTO(out_unlock, rc);

	if (unlikely(!(valid & OBD_MD_FLCTIME))) {
		/* This isn't strictly an error, but all current clients
		 * should set OBD_MD_FLCTIME when setting attributes. */
		CWARN("%s: client miss to set OBD_MD_FLCTIME when "
		      "setxattr %s: [object "DFID"] [valid %llu]\n",
		      mdt_obd_name(info->mti_mdt), xattr_name,
		      PFID(rr->rr_fid1), valid);
		attr->la_ctime = ktime_get_real_seconds();
	}
	attr->la_valid = LA_CTIME;
	child = mdt_object_child(obj);
	if (valid & OBD_MD_FLXATTR) {
		int	flags = 0;

		if (attr->la_flags & XATTR_REPLACE)
			flags |= LU_XATTR_REPLACE;

		if (attr->la_flags & XATTR_CREATE)
			flags |= LU_XATTR_CREATE;

		mdt_fail_write(env, info->mti_mdt->mdt_bottom,
			       OBD_FAIL_MDS_SETXATTR_WRITE);

		buf->lb_buf = rr->rr_eadata;
		buf->lb_len = xattr_len;
		rc = mo_xattr_set(env, child, buf, xattr_name, flags);
		/* update ctime after xattr changed */
		if (rc == 0) {
			ma->ma_attr_flags |= MDS_PERM_BYPASS;
			mo_attr_set(env, child, ma);
		}
        } else if (valid & OBD_MD_FLXATTRRM) {
                rc = mo_xattr_del(env, child, xattr_name);
                /* update ctime after xattr changed */
                if (rc == 0) {
                        ma->ma_attr_flags |= MDS_PERM_BYPASS;
                        mo_attr_set(env, child, ma);
                }
	} else {
		CDEBUG(D_INFO, "valid bits: %#llx\n", valid);
		rc = -EINVAL;
	}

	if (rc == 0)
		mdt_counter_incr(req, LPROC_MDT_SETXATTR);

        EXIT;
out_unlock:
        mdt_object_unlock_put(info, obj, lh, rc);
out:
	mdt_exit_ucred(info);
	return rc;
}
コード例 #12
0
ファイル: mdt_xattr.c プロジェクト: Xyratex/lustre-stable
int mdt_getxattr(struct mdt_thread_info *info)
{
	struct ptlrpc_request  *req = mdt_info_req(info);
        struct mdt_body        *reqbody;
        struct mdt_body        *repbody = NULL;
        struct md_object       *next;
        struct lu_buf          *buf;
        int                     easize, rc;
	u64			valid;
        ENTRY;

        LASSERT(info->mti_object != NULL);
	LASSERT(lu_object_assert_exists(&info->mti_object->mot_obj));

	CDEBUG(D_INODE, "getxattr "DFID"\n", PFID(&info->mti_body->mbo_fid1));

	rc = req_check_sepol(info->mti_pill);
	if (rc)
		RETURN(err_serious(rc));

        reqbody = req_capsule_client_get(info->mti_pill, &RMF_MDT_BODY);
        if (reqbody == NULL)
                RETURN(err_serious(-EFAULT));

	rc = mdt_init_ucred(info, reqbody);
        if (rc)
                RETURN(err_serious(rc));

        next = mdt_object_child(info->mti_object);
        easize = mdt_getxattr_pack_reply(info);
	if (easize == -ENODATA)
		GOTO(out, rc = easize);
	else if (easize < 0)
		GOTO(out, rc = err_serious(easize));

        repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
        LASSERT(repbody != NULL);

        /* No need further getxattr. */
	if (easize == 0 || reqbody->mbo_eadatasize == 0)
		GOTO(out, rc = easize);

	buf = &info->mti_buf;
	buf->lb_buf = req_capsule_server_get(info->mti_pill, &RMF_EADATA);
	buf->lb_len = easize;

	valid = info->mti_body->mbo_valid & (OBD_MD_FLXATTR | OBD_MD_FLXATTRLS);

	if (valid == OBD_MD_FLXATTR) {
		const char *xattr_name = req_capsule_client_get(info->mti_pill,
								&RMF_NAME);
		rc = mo_xattr_get(info->mti_env, next, buf, xattr_name);
		if (rc < 0)
			GOTO(out, rc);

		rc = mdt_nodemap_map_acl(info, buf->lb_buf, rc, xattr_name,
					 NODEMAP_FS_TO_CLIENT);
	} else if (valid == OBD_MD_FLXATTRLS) {
		CDEBUG(D_INODE, "listxattr\n");

		rc = mo_xattr_list(info->mti_env, next, buf);
		if (rc < 0)
			CDEBUG(D_INFO, "listxattr failed: %d\n", rc);
	} else if (valid == OBD_MD_FLXATTRALL) {
		rc = mdt_getxattr_all(info, reqbody, repbody,
				      buf, next);
	} else
		LBUG();

	EXIT;
out:
	if (rc >= 0) {
		mdt_counter_incr(req, LPROC_MDT_GETXATTR);
		/* LU-11109: Set OBD_MD_FLXATTR on success so that
		 * newer clients can distinguish between nonexistent
		 * xattrs and zero length values. */
		repbody->mbo_valid |= OBD_MD_FLXATTR;
		repbody->mbo_eadatasize = rc;
		rc = 0;
	}
	mdt_exit_ucred(info);
	return rc;
}