1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
5 * Lustre Metadata Target (mdt) request unpacking helper.
7 * Copyright (c) 2006 Cluster File Systems, Inc.
8 * Author: Peter Braam <braam@clusterfs.com>
9 * Author: Andreas Dilger <adilger@clusterfs.com>
10 * Author: Phil Schwan <phil@clusterfs.com>
11 * Author: Mike Shaver <shaver@clusterfs.com>
12 * Author: Nikita Danilov <nikita@clusterfs.com>
13 * Author: Huang Hua <huanghua@clusterfs.com>
16 * This file is part of the Lustre file system, http://www.lustre.org
17 * Lustre is a trademark of Cluster File Systems, Inc.
19 * You may have signed or agreed to another license before downloading
20 * this software. If so, you are bound by the terms and conditions
21 * of that agreement, and the following does not apply to you. See the
22 * LICENSE file included with this distribution for more information.
24 * If you did not agree to a different license, then this copy of Lustre
25 * is open source software; you can redistribute it and/or modify it
26 * under the terms of version 2 of the GNU General Public License as
27 * published by the Free Software Foundation.
29 * In either case, Lustre is distributed in the hope that it will be
30 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
31 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * license text for more details.
37 # define EXPORT_SYMTAB
39 #define DEBUG_SUBSYSTEM S_MDS
41 #include "mdt_internal.h"
44 typedef enum ucred_init_type {
50 int groups_from_list(struct group_info *ginfo, gid_t *glist)
53 int count = ginfo->ngroups;
55 /* fill group_info from gid array */
56 for (i = 0; i < ginfo->nblocks; i++) {
57 int cp_count = min(NGROUPS_PER_BLOCK, count);
58 int off = i * NGROUPS_PER_BLOCK;
59 int len = cp_count * sizeof(*glist);
61 if (memcpy(ginfo->blocks[i], glist + off, len))
69 /* groups_sort() is copied from linux kernel! */
70 /* a simple shell-metzner sort */
71 void groups_sort(struct group_info *group_info)
73 int base, max, stride;
74 int gidsetsize = group_info->ngroups;
76 for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1)
81 max = gidsetsize - stride;
82 for (base = 0; base < max; base++) {
84 int right = left + stride;
85 gid_t tmp = GROUP_AT(group_info, right);
87 while (left >= 0 && GROUP_AT(group_info, left) > tmp) {
88 GROUP_AT(group_info, right) =
89 GROUP_AT(group_info, left);
93 GROUP_AT(group_info, right) = tmp;
99 void mdt_exit_ucred(struct mdt_thread_info *info)
101 struct md_ucred *uc = mdt_ucred(info);
102 struct mdt_device *mdt = info->mti_mdt;
104 if (uc->mu_valid != UCRED_INIT) {
105 uc->mu_suppgids[0] = uc->mu_suppgids[1] = -1;
107 groups_free(uc->mu_ginfo);
110 if (uc->mu_identity) {
111 mdt_identity_put(mdt->mdt_identity_cache,
113 uc->mu_identity = NULL;
115 uc->mu_valid = UCRED_INIT;
119 static int old_init_ucred(struct mdt_thread_info *info,
120 struct mdt_body *body)
122 struct md_ucred *uc = mdt_ucred(info);
123 struct mdt_device *mdt = info->mti_mdt;
124 struct mdt_identity *identity = NULL;
128 uc->mu_valid = UCRED_INVALID;
130 if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
131 /* get identity info of this user */
132 identity = mdt_identity_get(mdt->mdt_identity_cache,
135 CERROR("Deny access without identity: uid %d\n",
141 uc->mu_valid = UCRED_OLD;
142 uc->mu_squash = SQUASH_NONE;
143 uc->mu_o_uid = uc->mu_uid = body->uid;
144 uc->mu_o_gid = uc->mu_gid = body->gid;
145 uc->mu_o_fsuid = uc->mu_fsuid = body->fsuid;
146 uc->mu_o_fsgid = uc->mu_fsgid = body->fsgid;
147 uc->mu_suppgids[0] = body->suppgid;
148 uc->mu_suppgids[1] = -1;
150 uc->mu_cap = body->capability & ~CAP_FS_MASK;
152 uc->mu_cap = body->capability;
154 uc->mu_identity = identity;
159 static int old_init_ucred_reint(struct mdt_thread_info *info)
161 struct md_ucred *uc = mdt_ucred(info);
162 struct mdt_device *mdt = info->mti_mdt;
163 struct mdt_identity *identity = NULL;
167 uc->mu_valid = UCRED_INVALID;
169 if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
170 /* get identity info of this user */
171 identity = mdt_identity_get(mdt->mdt_identity_cache,
174 CERROR("Deny access without identity: uid %d\n",
180 uc->mu_valid = UCRED_OLD;
181 uc->mu_squash = SQUASH_NONE;
182 uc->mu_o_uid = uc->mu_o_fsuid = uc->mu_uid = uc->mu_fsuid;
183 uc->mu_o_gid = uc->mu_o_fsgid = uc->mu_gid = uc->mu_fsgid;
185 uc->mu_cap &= ~CAP_FS_MASK;
187 uc->mu_identity = identity;
192 static int nid_nosquash(struct mdt_device *mdt, lnet_nid_t nid)
194 struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
197 for (i = 0; i < rsi->rsi_n_nosquash_nids; i++)
198 if ((rsi->rsi_nosquash_nids[i] == nid) ||
199 (rsi->rsi_nosquash_nids[i] == LNET_NID_ANY))
205 static int mdt_squash_root(struct mdt_device *mdt, struct md_ucred *ucred,
206 struct ptlrpc_user_desc *pud, lnet_nid_t peernid)
208 struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
210 if (!rsi || (!rsi->rsi_uid && !rsi->rsi_gid) ||
211 nid_nosquash(mdt, peernid))
214 CDEBUG(D_SEC, "squash req from "LPX64":"
215 "(%u:%u-%u:%u/%x)=>(%u:%u-%u:%u/%x)\n", peernid,
216 pud->pud_uid, pud->pud_gid,
217 pud->pud_fsuid, pud->pud_fsgid, pud->pud_cap,
218 pud->pud_uid ? pud->pud_uid : rsi->rsi_uid,
219 pud->pud_uid ? pud->pud_gid : rsi->rsi_gid,
220 pud->pud_fsuid ? pud->pud_fsuid : rsi->rsi_uid,
221 pud->pud_fsuid ? pud->pud_fsgid : rsi->rsi_gid,
222 pud->pud_cap & ~CAP_FS_MASK);
226 ucred->mu_uid = rsi->rsi_uid;
227 ucred->mu_squash |= SQUASH_UID;
229 ucred->mu_uid = pud->pud_uid;
232 if (!pud->pud_fsuid) {
233 ucred->mu_fsuid = rsi->rsi_uid;
234 ucred->mu_squash |= SQUASH_UID;
236 ucred->mu_fsuid = pud->pud_fsuid;
239 ucred->mu_uid = pud->pud_uid;
240 ucred->mu_fsuid = pud->pud_fsuid;
247 ucred->mu_gid = rsi->rsi_gid;
248 ucred->mu_squash |= SQUASH_GID;
250 ucred->mu_gid = pud->pud_gid;
253 if (!pud->pud_fsgid) {
254 ucred->mu_fsgid = rsi->rsi_gid;
255 ucred->mu_squash |= SQUASH_GID;
257 ucred->mu_fsgid = pud->pud_fsgid;
260 for (i = 0; i < 2; i++) {
261 if (!ucred->mu_suppgids[i]) {
262 ucred->mu_suppgids[i] = rsi->rsi_gid;
263 ucred->mu_squash |= SQUASH_GID;
267 for (i = 0; i < pud->pud_ngroups; i++) {
268 if (!pud->pud_groups[i]) {
269 pud->pud_groups[i] = rsi->rsi_gid;
270 ucred->mu_squash |= SQUASH_GID;
274 ucred->mu_gid = pud->pud_gid;
275 ucred->mu_fsgid = pud->pud_fsgid;
281 static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
284 struct ptlrpc_request *req = mdt_info_req(info);
285 struct mdt_export_data *med = mdt_req2med(req);
286 struct mdt_device *mdt = info->mti_mdt;
287 struct ptlrpc_user_desc *pud = req->rq_user_desc;
288 struct md_ucred *ucred = mdt_ucred(info);
289 struct mdt_identity *identity = NULL;
290 lnet_nid_t peernid = req->rq_peer.nid;
291 __u32 setxid_perm = 0;
298 LASSERT(req->rq_auth_gss);
299 LASSERT(!req->rq_auth_usr_mdt);
300 LASSERT(req->rq_user_desc);
302 ucred->mu_valid = UCRED_INVALID;
304 ucred->mu_o_uid = pud->pud_uid;
305 ucred->mu_o_gid = pud->pud_gid;
306 ucred->mu_o_fsuid = pud->pud_fsuid;
307 ucred->mu_o_fsgid = pud->pud_fsgid;
309 if (type == BODY_INIT) {
310 struct mdt_body *body = (struct mdt_body *)buf;
312 ucred->mu_suppgids[0] = body->suppgid;
313 ucred->mu_suppgids[1] = -1;
316 /* sanity check: we expect the uid which client claimed is true */
317 if (med->med_rmtclient) {
318 if (req->rq_auth_mapped_uid == INVALID_UID) {
319 CWARN("remote user not mapped, deny access!\n");
323 if (ptlrpc_user_desc_do_idmap(req, pud))
326 if (req->rq_auth_mapped_uid != pud->pud_uid) {
327 CERROR("remote client "LPU64": auth uid %u "
328 "while client claim %u:%u/%u:%u\n",
329 peernid, req->rq_auth_uid, pud->pud_uid,
330 pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid);
334 if (req->rq_auth_uid != pud->pud_uid) {
335 CERROR("local client "LPU64": auth uid %u "
336 "while client claim %u:%u/%u:%u\n",
337 peernid, req->rq_auth_uid, pud->pud_uid,
338 pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid);
343 if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
344 if (med->med_rmtclient) {
345 CERROR("remote client must run with identity_get "
349 setxid_perm |= LUSTRE_SETGRP_PERM;
354 identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid);
356 CERROR("Deny access without identity: uid %d\n", pud->pud_uid);
360 setxid_perm = mdt_identity_get_setxid_perm(identity,
364 /* find out the setuid/setgid attempt */
365 setuid = (pud->pud_uid != pud->pud_fsuid);
366 setgid = (pud->pud_gid != pud->pud_fsgid ||
367 pud->pud_gid != identity->mi_gid);
369 /* check permission of setuid */
370 if (setuid && !(setxid_perm & LUSTRE_SETUID_PERM)) {
371 CWARN("mdt blocked setuid attempt (%u -> %u) from "
372 LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
373 GOTO(out, rc = -EACCES);
376 /* check permission of setgid */
377 if (setgid && !(setxid_perm & LUSTRE_SETGID_PERM)) {
378 CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
379 "from "LPX64"\n", pud->pud_uid, pud->pud_gid,
380 pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid,
382 GOTO(out, rc = -EACCES);
386 /* FIXME: The exact behavior of root_squash is not defined. */
387 ucred->mu_squash = SQUASH_NONE;
388 if (mdt_squash_root(mdt, ucred, pud, peernid) == 0) {
389 ucred->mu_uid = pud->pud_uid;
390 ucred->mu_gid = pud->pud_gid;
391 ucred->mu_fsuid = pud->pud_fsuid;
392 ucred->mu_fsgid = pud->pud_fsgid;
395 /* remove fs privilege for non-root user */
397 ucred->mu_cap = pud->pud_cap & ~CAP_FS_MASK;
399 ucred->mu_cap = pud->pud_cap;
402 * NB: remote client not allowed to setgroups anyway.
404 if (!med->med_rmtclient && pud->pud_ngroups &&
405 (setxid_perm & LUSTRE_SETGRP_PERM)) {
406 struct group_info *ginfo;
408 /* setgroups for local client */
409 ginfo = groups_alloc(pud->pud_ngroups);
411 CERROR("failed to alloc %d groups\n",
413 GOTO(out, rc = -ENOMEM);
415 groups_from_list(ginfo, pud->pud_groups);
417 ucred->mu_ginfo = ginfo;
419 ucred->mu_ginfo = NULL;
422 ucred->mu_identity = identity;
423 ucred->mu_valid = UCRED_NEW;
429 mdt_identity_put(mdt->mdt_identity_cache, identity);
434 int mdt_check_ucred(struct mdt_thread_info *info)
436 struct ptlrpc_request *req = mdt_info_req(info);
437 struct mdt_export_data *med = mdt_req2med(req);
438 struct mdt_device *mdt = info->mti_mdt;
439 struct ptlrpc_user_desc *pud = req->rq_user_desc;
440 struct md_ucred *ucred = mdt_ucred(info);
441 struct mdt_identity *identity;
442 lnet_nid_t peernid = req->rq_peer.nid;
446 if ((ucred->mu_valid == UCRED_OLD) || (ucred->mu_valid == UCRED_NEW))
449 if (!req->rq_user_desc)
452 /* sanity check: if we use strong authentication, we expect the
453 * uid which client claimed is true */
454 if (req->rq_auth_gss) {
455 if (med->med_rmtclient) {
456 if (req->rq_auth_mapped_uid == INVALID_UID) {
457 CWARN("remote user not mapped, deny access!\n");
461 if (ptlrpc_user_desc_do_idmap(req, pud))
464 if (req->rq_auth_mapped_uid != pud->pud_uid) {
465 CERROR("remote client "LPU64": auth uid %u "
466 "while client claim %u:%u/%u:%u\n",
467 peernid, req->rq_auth_uid, pud->pud_uid,
468 pud->pud_gid, pud->pud_fsuid,
473 if (req->rq_auth_uid != pud->pud_uid) {
474 CERROR("local client "LPU64": auth uid %u "
475 "while client claim %u:%u/%u:%u\n",
476 peernid, req->rq_auth_uid, pud->pud_uid,
477 pud->pud_gid, pud->pud_fsuid,
484 if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
485 if (med->med_rmtclient) {
486 CERROR("remote client must run with "
487 "identity_get enabled!\n");
491 identity = mdt_identity_get(mdt->mdt_identity_cache,
494 CERROR("Deny access without identity: uid %d\n",
499 mdt_identity_put(mdt->mdt_identity_cache, identity);
505 int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body)
507 struct ptlrpc_request *req = mdt_info_req(info);
508 struct md_ucred *uc = mdt_ucred(info);
510 if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))
513 mdt_exit_ucred(info);
515 if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
516 return old_init_ucred(info, body);
518 return new_init_ucred(info, BODY_INIT, body);
521 int mdt_init_ucred_reint(struct mdt_thread_info *info)
523 struct ptlrpc_request *req = mdt_info_req(info);
524 struct md_ucred *uc = mdt_ucred(info);
526 if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))
529 mdt_exit_ucred(info);
531 if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
532 return old_init_ucred_reint(info);
534 return new_init_ucred(info, REC_INIT, NULL);
537 /* copied from lov/lov_ea.c, just for debugging, will be removed later */
538 void mdt_dump_lmm(int level, const struct lov_mds_md *lmm)
540 const struct lov_ost_data_v1 *lod;
543 le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count);
545 CDEBUG(level, "objid "LPX64", magic 0x%08X, pattern %#X\n",
546 le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic),
547 le32_to_cpu(lmm->lmm_pattern));
548 CDEBUG(level,"stripe_size=0x%x, stripe_count=0x%x\n",
549 le32_to_cpu(lmm->lmm_stripe_size),
550 le32_to_cpu(lmm->lmm_stripe_count));
551 LASSERT(stripe_count <= (__s16)LOV_MAX_STRIPE_COUNT);
552 for (i = 0, lod = lmm->lmm_objects; i < stripe_count; i++, lod++) {
553 CDEBUG(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n",
554 i, le32_to_cpu(lod->l_ost_idx),
555 le64_to_cpu(lod->l_object_gr),
556 le64_to_cpu(lod->l_object_id));
560 void mdt_shrink_reply(struct mdt_thread_info *info)
562 struct req_capsule *pill = &info->mti_pill;
563 struct mdt_body *body;
564 int acl_size, md_size, adjust = 0;
567 body = req_capsule_server_get(pill, &RMF_MDT_BODY);
568 LASSERT(body != NULL);
570 if (body->valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE | OBD_MD_LINKNAME))
571 md_size = body->eadatasize;
575 acl_size = body->aclsize;
577 CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d"
578 " MDSCAPA = %d, OSSCAPA = %d\n",
580 (int)(body->valid & OBD_MD_FLMDSCAPA),
581 (int)(body->valid & OBD_MD_FLOSSCAPA));
585 &RMF_ACL, or &RMF_LOGCOOKIES
586 (optional) &RMF_CAPA1,
587 (optional) &RMF_CAPA2,
588 (optional) something else
590 adjust += req_capsule_shrink(pill, &RMF_MDT_MD,
593 if (req_capsule_has_field(pill, &RMF_ACL, RCL_SERVER))
594 adjust += req_capsule_shrink(pill, &RMF_ACL,
595 acl_size, adjust, 1);
596 else if (req_capsule_has_field(pill, &RMF_LOGCOOKIES, RCL_SERVER))
597 adjust += req_capsule_shrink(pill, &RMF_LOGCOOKIES,
598 acl_size, adjust, 1);
600 if ((req_capsule_has_field(pill, &RMF_CAPA1, RCL_SERVER) &&
601 !(body->valid & OBD_MD_FLMDSCAPA)))
602 adjust += req_capsule_shrink(pill, &RMF_CAPA1, 0, adjust, 1);
604 if ((req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) &&
605 !(body->valid & OBD_MD_FLOSSCAPA)))
606 adjust += req_capsule_shrink(pill, &RMF_CAPA2, 0, adjust, 0);
609 * Some more field should be shrinked if needed.
610 * This should be done by those who added fields to reply message.
616 /* if object is dying, pack the lov/llog data,
617 * parameter info->mti_attr should be valid at this point! */
618 int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo,
619 const struct md_attr *ma)
621 struct mdt_body *repbody;
622 const struct lu_attr *la = &ma->ma_attr;
625 repbody = req_capsule_server_get(&info->mti_pill, &RMF_MDT_BODY);
626 LASSERT(repbody != NULL);
628 if (ma->ma_valid & MA_INODE)
629 mdt_pack_attr2body(info, repbody, la, mdt_object_fid(mo));
631 if (ma->ma_valid & MA_LOV) {
634 if (mdt_object_exists(mo) < 0)
635 /* If it is a remote object, and we do not retrieve
636 * EA back unlink reg file*/
639 mode = lu_object_attr(&mo->mot_obj.mo_lu);
641 LASSERT(ma->ma_lmm_size);
642 mdt_dump_lmm(D_INFO, ma->ma_lmm);
643 repbody->eadatasize = ma->ma_lmm_size;
645 repbody->valid |= OBD_MD_FLEASIZE;
646 else if (S_ISDIR(mode))
647 repbody->valid |= OBD_MD_FLDIREA;
652 if (ma->ma_cookie_size && (ma->ma_valid & MA_COOKIE)) {
653 repbody->aclsize = ma->ma_cookie_size;
654 repbody->valid |= OBD_MD_FLCOOKIE;
660 static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
674 if (in & ATTR_BLOCKS)
677 if (in & ATTR_FROM_OPEN)
678 rr->rr_flags |= MRF_SETATTR_LOCKED;
680 if (in & ATTR_ATIME_SET)
683 if (in & ATTR_CTIME_SET)
686 if (in & ATTR_MTIME_SET)
689 if (in & ATTR_ATTR_FLAG)
692 if (in & MDS_OPEN_OWNEROVERRIDE)
693 out |= MDS_OPEN_OWNEROVERRIDE;
695 /*XXX need ATTR_RAW?*/
696 in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
697 ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
698 ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
699 ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE);
701 CERROR("Unknown attr bits: %#llx\n", in);
706 static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
708 struct md_ucred *uc = mdt_ucred(info);
709 struct md_attr *ma = &info->mti_attr;
710 struct lu_attr *la = &ma->ma_attr;
711 struct req_capsule *pill = &info->mti_pill;
712 struct mdt_reint_record *rr = &info->mti_rr;
713 struct mdt_rec_setattr *rec;
716 rec = req_capsule_client_get(pill, &RMF_REC_SETATTR);
720 uc->mu_fsuid = rec->sa_fsuid;
721 uc->mu_fsgid = rec->sa_fsgid;
722 uc->mu_cap = rec->sa_cap;
723 uc->mu_suppgids[0] = rec->sa_suppgid;
724 uc->mu_suppgids[1] = -1;
726 rr->rr_fid1 = &rec->sa_fid;
727 la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr, ma);
728 la->la_mode = rec->sa_mode;
729 la->la_flags = rec->sa_attr_flags;
730 la->la_uid = rec->sa_uid;
731 la->la_gid = rec->sa_gid;
732 la->la_size = rec->sa_size;
733 la->la_blocks = rec->sa_blocks;
734 la->la_ctime = rec->sa_ctime;
735 la->la_atime = rec->sa_atime;
736 la->la_mtime = rec->sa_mtime;
737 ma->ma_valid = MA_INODE;
739 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
740 mdt_set_capainfo(info, 0, rr->rr_fid1,
741 req_capsule_client_get(pill, &RMF_CAPA1));
746 static int mdt_epoch_unpack(struct mdt_thread_info *info)
748 struct req_capsule *pill = &info->mti_pill;
751 if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT))
752 info->mti_epoch = req_capsule_client_get(pill, &RMF_MDT_EPOCH);
754 info->mti_epoch = NULL;
755 RETURN(info->mti_epoch == NULL ? -EFAULT : 0);
758 static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) {
759 struct req_capsule *pill = &info->mti_pill;
761 if (req_capsule_get_size(pill, &RMF_DLM_REQ, RCL_CLIENT)) {
762 info->mti_dlm_req = req_capsule_client_get(pill, &RMF_DLM_REQ);
763 if (info->mti_dlm_req == NULL)
770 static int mdt_setattr_unpack(struct mdt_thread_info *info)
772 struct md_attr *ma = &info->mti_attr;
773 struct req_capsule *pill = &info->mti_pill;
777 rc = mdt_setattr_unpack_rec(info);
781 /* Epoch may be absent */
782 mdt_epoch_unpack(info);
784 ma->ma_lmm_size = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT);
785 if (ma->ma_lmm_size) {
786 ma->ma_lmm = req_capsule_client_get(pill, &RMF_EADATA);
787 ma->ma_valid |= MA_LOV;
790 ma->ma_cookie_size = req_capsule_get_size(pill, &RMF_LOGCOOKIES,
792 if (ma->ma_cookie_size) {
793 ma->ma_cookie = req_capsule_client_get(pill, &RMF_LOGCOOKIES);
794 ma->ma_valid |= MA_COOKIE;
797 rc = mdt_dlmreq_unpack(info);
801 int mdt_close_unpack(struct mdt_thread_info *info)
806 rc = mdt_epoch_unpack(info);
810 RETURN(mdt_setattr_unpack_rec(info));
813 static int mdt_create_unpack(struct mdt_thread_info *info)
815 struct md_ucred *uc = mdt_ucred(info);
816 struct mdt_rec_create *rec;
817 struct lu_attr *attr = &info->mti_attr.ma_attr;
818 struct mdt_reint_record *rr = &info->mti_rr;
819 struct req_capsule *pill = &info->mti_pill;
820 struct md_op_spec *sp = &info->mti_spec;
824 rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
828 uc->mu_fsuid = rec->cr_fsuid;
829 uc->mu_fsgid = rec->cr_fsgid;
830 uc->mu_cap = rec->cr_cap;
831 uc->mu_suppgids[0] = rec->cr_suppgid1;
832 uc->mu_suppgids[1] = -1;
834 rr->rr_fid1 = &rec->cr_fid1;
835 rr->rr_fid2 = &rec->cr_fid2;
836 attr->la_mode = rec->cr_mode;
837 attr->la_rdev = rec->cr_rdev;
838 attr->la_uid = rec->cr_fsuid;
839 attr->la_gid = rec->cr_fsgid;
840 attr->la_ctime = rec->cr_time;
841 attr->la_mtime = rec->cr_time;
842 attr->la_atime = rec->cr_time;
843 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
844 LA_CTIME | LA_MTIME | LA_ATIME;
845 memset(&sp->u, 0, sizeof(sp->u));
846 sp->sp_cr_flags = rec->cr_flags;
847 sp->sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
848 info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
850 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
851 mdt_set_capainfo(info, 0, rr->rr_fid1,
852 req_capsule_client_get(pill, &RMF_CAPA1));
853 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
855 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
856 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
857 LASSERT(rr->rr_namelen > 0);
859 #ifdef CONFIG_FS_POSIX_ACL
860 if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) {
861 if (S_ISDIR(attr->la_mode))
862 sp->u.sp_pfid = rr->rr_fid1;
863 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
864 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
866 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
867 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
869 sp->u.sp_ea.fid = rr->rr_fid1;
873 if (S_ISDIR(attr->la_mode)) {
874 /* pass parent fid for cross-ref cases */
875 sp->u.sp_pfid = rr->rr_fid1;
876 if (sp->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
877 /* create salve object req, need
878 * unpack split ea here
880 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SLAVE);
881 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
883 sp->u.sp_ea.eadata = req_capsule_client_get(pill,
885 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill,
888 sp->u.sp_ea.fid = rr->rr_fid1;
891 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
892 } else if (S_ISLNK(attr->la_mode)) {
893 const char *tgt = NULL;
895 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM);
896 if (req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT)) {
897 tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
898 sp->u.sp_symname = tgt;
903 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
905 rc = mdt_dlmreq_unpack(info);
909 static int mdt_link_unpack(struct mdt_thread_info *info)
911 struct md_ucred *uc = mdt_ucred(info);
912 struct mdt_rec_link *rec;
913 struct lu_attr *attr = &info->mti_attr.ma_attr;
914 struct mdt_reint_record *rr = &info->mti_rr;
915 struct req_capsule *pill = &info->mti_pill;
919 rec = req_capsule_client_get(pill, &RMF_REC_LINK);
923 uc->mu_fsuid = rec->lk_fsuid;
924 uc->mu_fsgid = rec->lk_fsgid;
925 uc->mu_cap = rec->lk_cap;
926 uc->mu_suppgids[0] = rec->lk_suppgid1;
927 uc->mu_suppgids[1] = rec->lk_suppgid2;
929 attr->la_uid = rec->lk_fsuid;
930 attr->la_gid = rec->lk_fsgid;
931 rr->rr_fid1 = &rec->lk_fid1;
932 rr->rr_fid2 = &rec->lk_fid2;
933 attr->la_ctime = rec->lk_time;
934 attr->la_mtime = rec->lk_time;
935 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;
937 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
938 mdt_set_capainfo(info, 0, rr->rr_fid1,
939 req_capsule_client_get(pill, &RMF_CAPA1));
940 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
941 mdt_set_capainfo(info, 1, rr->rr_fid2,
942 req_capsule_client_get(pill, &RMF_CAPA2));
944 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
945 if (rr->rr_name == NULL)
947 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
948 LASSERT(rr->rr_namelen > 0);
949 info->mti_spec.sp_ck_split = !!(rec->lk_bias & MDS_CHECK_SPLIT);
950 info->mti_cross_ref = !!(rec->lk_bias & MDS_CROSS_REF);
952 rc = mdt_dlmreq_unpack(info);
956 static int mdt_unlink_unpack(struct mdt_thread_info *info)
958 struct md_ucred *uc = mdt_ucred(info);
959 struct mdt_rec_unlink *rec;
960 struct md_attr *ma = &info->mti_attr;
961 struct lu_attr *attr = &info->mti_attr.ma_attr;
962 struct mdt_reint_record *rr = &info->mti_rr;
963 struct req_capsule *pill = &info->mti_pill;
967 rec = req_capsule_client_get(pill, &RMF_REC_UNLINK);
971 uc->mu_fsuid = rec->ul_fsuid;
972 uc->mu_fsgid = rec->ul_fsgid;
973 uc->mu_cap = rec->ul_cap;
974 uc->mu_suppgids[0] = rec->ul_suppgid;
975 uc->mu_suppgids[1] = -1;
977 attr->la_uid = rec->ul_fsuid;
978 attr->la_gid = rec->ul_fsgid;
979 rr->rr_fid1 = &rec->ul_fid1;
980 rr->rr_fid2 = &rec->ul_fid2;
981 attr->la_ctime = rec->ul_time;
982 attr->la_mtime = rec->ul_time;
983 attr->la_mode = rec->ul_mode;
984 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
986 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
987 mdt_set_capainfo(info, 0, rr->rr_fid1,
988 req_capsule_client_get(pill, &RMF_CAPA1));
990 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
991 if (rr->rr_name == NULL)
993 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
994 LASSERT(rr->rr_namelen > 0);
995 info->mti_spec.sp_ck_split = !!(rec->ul_bias & MDS_CHECK_SPLIT);
996 info->mti_cross_ref = !!(rec->ul_bias & MDS_CROSS_REF);
997 if (rec->ul_bias & MDS_VTX_BYPASS)
998 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1000 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1002 rc = mdt_dlmreq_unpack(info);
1006 static int mdt_rename_unpack(struct mdt_thread_info *info)
1008 struct md_ucred *uc = mdt_ucred(info);
1009 struct mdt_rec_rename *rec;
1010 struct md_attr *ma = &info->mti_attr;
1011 struct lu_attr *attr = &info->mti_attr.ma_attr;
1012 struct mdt_reint_record *rr = &info->mti_rr;
1013 struct req_capsule *pill = &info->mti_pill;
1017 rec = req_capsule_client_get(pill, &RMF_REC_RENAME);
1021 uc->mu_fsuid = rec->rn_fsuid;
1022 uc->mu_fsgid = rec->rn_fsgid;
1023 uc->mu_cap = rec->rn_cap;
1024 uc->mu_suppgids[0] = rec->rn_suppgid1;
1025 uc->mu_suppgids[1] = rec->rn_suppgid2;
1027 attr->la_uid = rec->rn_fsuid;
1028 attr->la_gid = rec->rn_fsgid;
1029 rr->rr_fid1 = &rec->rn_fid1;
1030 rr->rr_fid2 = &rec->rn_fid2;
1031 attr->la_ctime = rec->rn_time;
1032 attr->la_mtime = rec->rn_time;
1033 /* rename_tgt contains the mode already */
1034 attr->la_mode = rec->rn_mode;
1035 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
1037 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1038 mdt_set_capainfo(info, 0, rr->rr_fid1,
1039 req_capsule_client_get(pill, &RMF_CAPA1));
1040 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
1041 mdt_set_capainfo(info, 1, rr->rr_fid2,
1042 req_capsule_client_get(pill, &RMF_CAPA2));
1044 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1045 rr->rr_tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
1046 if (rr->rr_name == NULL || rr->rr_tgt == NULL)
1048 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1049 LASSERT(rr->rr_namelen > 0);
1050 rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT) - 1;
1051 LASSERT(rr->rr_tgtlen > 0);
1052 info->mti_spec.sp_ck_split = !!(rec->rn_bias & MDS_CHECK_SPLIT);
1053 info->mti_cross_ref = !!(rec->rn_bias & MDS_CROSS_REF);
1054 if (rec->rn_bias & MDS_VTX_BYPASS)
1055 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1057 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1059 rc = mdt_dlmreq_unpack(info);
1063 static int mdt_open_unpack(struct mdt_thread_info *info)
1065 struct md_ucred *uc = mdt_ucred(info);
1066 struct mdt_rec_create *rec;
1067 struct lu_attr *attr = &info->mti_attr.ma_attr;
1068 struct req_capsule *pill = &info->mti_pill;
1069 struct mdt_reint_record *rr = &info->mti_rr;
1070 struct ptlrpc_request *req = mdt_info_req(info);
1071 struct md_op_spec *sp = &info->mti_spec;
1074 rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
1078 uc->mu_fsuid = rec->cr_fsuid;
1079 uc->mu_fsgid = rec->cr_fsgid;
1080 uc->mu_cap = rec->cr_cap;
1081 uc->mu_suppgids[0] = rec->cr_suppgid1;
1082 uc->mu_suppgids[1] = rec->cr_suppgid2;
1084 rr->rr_fid1 = &rec->cr_fid1;
1085 rr->rr_fid2 = &rec->cr_fid2;
1086 rr->rr_handle = &rec->cr_old_handle;
1087 attr->la_mode = rec->cr_mode;
1088 attr->la_rdev = rec->cr_rdev;
1089 attr->la_uid = rec->cr_fsuid;
1090 attr->la_gid = rec->cr_fsgid;
1091 attr->la_ctime = rec->cr_time;
1092 attr->la_mtime = rec->cr_time;
1093 attr->la_atime = rec->cr_time;
1094 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
1095 LA_CTIME | LA_MTIME | LA_ATIME;
1096 memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u));
1097 info->mti_spec.sp_cr_flags = rec->cr_flags;
1098 info->mti_replayepoch = rec->cr_ioepoch;
1100 info->mti_spec.sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
1101 info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
1103 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1104 mdt_set_capainfo(info, 0, rr->rr_fid1,
1105 req_capsule_client_get(pill, &RMF_CAPA1));
1106 if ((lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) &&
1107 (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))) {
1109 mdt_set_capainfo(info, 1, rr->rr_fid2,
1110 req_capsule_client_get(pill, &RMF_CAPA2));
1113 * FIXME: capa in replay open request might have expired,
1114 * bypass capa check. Security hole?
1116 mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
1117 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
1121 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1122 if (rr->rr_name == NULL)
1124 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1125 LASSERT(rr->rr_namelen > 0);
1127 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
1129 if (sp->u.sp_ea.eadatalen) {
1130 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
1131 if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)
1132 sp->u.sp_ea.no_lov_create = 1;
1138 typedef int (*reint_unpacker)(struct mdt_thread_info *info);
1140 static reint_unpacker mdt_reint_unpackers[REINT_MAX] = {
1141 [REINT_SETATTR] = mdt_setattr_unpack,
1142 [REINT_CREATE] = mdt_create_unpack,
1143 [REINT_LINK] = mdt_link_unpack,
1144 [REINT_UNLINK] = mdt_unlink_unpack,
1145 [REINT_RENAME] = mdt_rename_unpack,
1146 [REINT_OPEN] = mdt_open_unpack
1149 int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op)
1154 memset(&info->mti_rr, 0, sizeof(info->mti_rr));
1155 if (op < REINT_MAX && mdt_reint_unpackers[op] != NULL) {
1156 info->mti_rr.rr_opcode = op;
1157 rc = mdt_reint_unpackers[op](info);
1159 CERROR("Unexpected opcode %d\n", op);