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>
14 * Author: Fan Yong <fanyong@clusterfs.com>
17 * This file is part of the Lustre file system, http://www.lustre.org
18 * Lustre is a trademark of Cluster File Systems, Inc.
20 * You may have signed or agreed to another license before downloading
21 * this software. If so, you are bound by the terms and conditions
22 * of that agreement, and the following does not apply to you. See the
23 * LICENSE file included with this distribution for more information.
25 * If you did not agree to a different license, then this copy of Lustre
26 * is open source software; you can redistribute it and/or modify it
27 * under the terms of version 2 of the GNU General Public License as
28 * published by the Free Software Foundation.
30 * In either case, Lustre is distributed in the hope that it will be
31 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
32 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * license text for more details.
38 # define EXPORT_SYMTAB
40 #define DEBUG_SUBSYSTEM S_MDS
42 #include "mdt_internal.h"
45 typedef enum ucred_init_type {
51 void mdt_exit_ucred(struct mdt_thread_info *info)
53 struct md_ucred *uc = mdt_ucred(info);
54 struct mdt_device *mdt = info->mti_mdt;
56 if (uc->mu_valid != UCRED_INIT) {
57 uc->mu_suppgids[0] = uc->mu_suppgids[1] = -1;
59 groups_free(uc->mu_ginfo);
62 if (uc->mu_identity) {
63 mdt_identity_put(mdt->mdt_identity_cache,
65 uc->mu_identity = NULL;
67 uc->mu_valid = UCRED_INIT;
71 /* XXX: root_squash will be redesigned in Lustre 1.7.
72 * Do not root_squash for inter-MDS operations */
73 static int mdt_root_squash(struct mdt_thread_info *info)
78 static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
81 struct ptlrpc_request *req = mdt_info_req(info);
82 struct mdt_export_data *med = mdt_req2med(req);
83 struct mdt_device *mdt = info->mti_mdt;
84 struct ptlrpc_user_desc *pud = req->rq_user_desc;
85 struct md_ucred *ucred = mdt_ucred(info);
86 lnet_nid_t peernid = req->rq_peer.nid;
94 LASSERT(req->rq_auth_gss);
95 LASSERT(!req->rq_auth_usr_mdt);
96 LASSERT(req->rq_user_desc);
98 ucred->mu_valid = UCRED_INVALID;
100 ucred->mu_o_uid = pud->pud_uid;
101 ucred->mu_o_gid = pud->pud_gid;
102 ucred->mu_o_fsuid = pud->pud_fsuid;
103 ucred->mu_o_fsgid = pud->pud_fsgid;
105 if (type == BODY_INIT) {
106 struct mdt_body *body = (struct mdt_body *)buf;
108 ucred->mu_suppgids[0] = body->suppgid;
109 ucred->mu_suppgids[1] = -1;
112 /* sanity check: we expect the uid which client claimed is true */
113 if (med->med_rmtclient) {
114 if (req->rq_auth_mapped_uid == INVALID_UID) {
115 CWARN("remote user not mapped, deny access!\n");
119 if (ptlrpc_user_desc_do_idmap(req, pud))
122 if (req->rq_auth_mapped_uid != pud->pud_uid) {
123 CERROR("remote client "LPU64": auth/mapped uid %u/%u "
124 "while client claim %u:%u/%u:%u\n",
125 peernid, req->rq_auth_uid,
126 req->rq_auth_mapped_uid,
127 pud->pud_uid, pud->pud_gid,
128 pud->pud_fsuid, pud->pud_fsgid);
132 if (req->rq_auth_uid != pud->pud_uid) {
133 CERROR("local client "LPU64": auth uid %u "
134 "while client claim %u:%u/%u:%u\n",
135 peernid, req->rq_auth_uid, pud->pud_uid,
136 pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid);
141 if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
142 if (med->med_rmtclient) {
143 CERROR("remote client must run with identity_get "
147 ucred->mu_identity = NULL;
148 perm = CFS_SETUID_PERM | CFS_SETGID_PERM |
152 ucred->mu_identity = mdt_identity_get(mdt->mdt_identity_cache,
154 if (!ucred->mu_identity) {
155 CERROR("Deny access without identity: uid %d\n",
159 perm = mdt_identity_get_perm(ucred->mu_identity,
165 /* find out the setuid/setgid attempt */
166 setuid = (pud->pud_uid != pud->pud_fsuid);
167 setgid = ((pud->pud_gid != pud->pud_fsgid) ||
168 (ucred->mu_identity &&
169 (pud->pud_gid != ucred->mu_identity->mi_gid)));
171 /* check permission of setuid */
172 if (setuid && !(perm & CFS_SETUID_PERM)) {
173 CWARN("mdt blocked setuid attempt (%u -> %u) from "
174 LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
175 GOTO(out, rc = -EACCES);
178 /* check permission of setgid */
179 if (setgid && !(perm & CFS_SETGID_PERM)) {
180 CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
181 "from "LPX64"\n", pud->pud_uid, pud->pud_gid,
182 pud->pud_fsuid, pud->pud_fsgid,
183 ucred->mu_identity->mi_gid, peernid);
184 GOTO(out, rc = -EACCES);
188 * NB: remote client not allowed to setgroups anyway.
190 if (!med->med_rmtclient && perm & CFS_SETGRP_PERM) {
191 if (pud->pud_ngroups) {
192 /* setgroups for local client */
193 ucred->mu_ginfo = groups_alloc(pud->pud_ngroups);
194 if (!ucred->mu_ginfo) {
195 CERROR("failed to alloc %d groups\n",
197 GOTO(out, rc = -ENOMEM);
200 lustre_groups_from_list(ucred->mu_ginfo,
202 lustre_groups_sort(ucred->mu_ginfo);
204 ucred->mu_ginfo = NULL;
207 ucred->mu_suppgids[0] = -1;
208 ucred->mu_suppgids[1] = -1;
209 ucred->mu_ginfo = NULL;
212 ucred->mu_uid = pud->pud_uid;
213 ucred->mu_gid = pud->pud_gid;
214 ucred->mu_fsuid = pud->pud_fsuid;
215 ucred->mu_fsgid = pud->pud_fsgid;
217 /* XXX: need to process root_squash here. */
218 mdt_root_squash(info);
220 /* remove fs privilege for non-root user */
222 ucred->mu_cap = pud->pud_cap & ~CAP_FS_MASK;
224 ucred->mu_cap = pud->pud_cap;
225 ucred->mu_valid = UCRED_NEW;
231 if (ucred->mu_ginfo) {
232 groups_free(ucred->mu_ginfo);
233 ucred->mu_ginfo = NULL;
235 if (ucred->mu_identity) {
236 mdt_identity_put(mdt->mdt_identity_cache,
238 ucred->mu_identity = NULL;
245 int mdt_check_ucred(struct mdt_thread_info *info)
247 struct ptlrpc_request *req = mdt_info_req(info);
248 struct mdt_export_data *med = mdt_req2med(req);
249 struct mdt_device *mdt = info->mti_mdt;
250 struct ptlrpc_user_desc *pud = req->rq_user_desc;
251 struct md_ucred *ucred = mdt_ucred(info);
252 struct md_identity *identity = NULL;
253 lnet_nid_t peernid = req->rq_peer.nid;
261 if ((ucred->mu_valid == UCRED_OLD) || (ucred->mu_valid == UCRED_NEW))
264 if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
267 /* sanity check: if we use strong authentication, we expect the
268 * uid which client claimed is true */
269 if (med->med_rmtclient) {
270 if (req->rq_auth_mapped_uid == INVALID_UID) {
271 CWARN("remote user not mapped, deny access!\n");
275 if (ptlrpc_user_desc_do_idmap(req, pud))
278 if (req->rq_auth_mapped_uid != pud->pud_uid) {
279 CERROR("remote client "LPU64": auth/mapped uid %u/%u "
280 "while client claim %u:%u/%u:%u\n",
281 peernid, req->rq_auth_uid,
282 req->rq_auth_mapped_uid,
283 pud->pud_uid, pud->pud_gid,
284 pud->pud_fsuid, pud->pud_fsgid);
288 if (req->rq_auth_uid != pud->pud_uid) {
289 CERROR("local client "LPU64": auth uid %u "
290 "while client claim %u:%u/%u:%u\n",
291 peernid, req->rq_auth_uid, pud->pud_uid,
292 pud->pud_gid, pud->pud_fsuid,
298 if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
299 if (med->med_rmtclient) {
300 CERROR("remote client must run with identity_get "
307 identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid);
309 CERROR("Deny access without identity: uid %d\n", pud->pud_uid);
313 perm = mdt_identity_get_perm(identity, med->med_rmtclient, peernid);
314 /* find out the setuid/setgid attempt */
315 setuid = (pud->pud_uid != pud->pud_fsuid);
316 setgid = (pud->pud_gid != pud->pud_fsgid ||
317 pud->pud_gid != identity->mi_gid);
319 /* check permission of setuid */
320 if (setuid && !(perm & CFS_SETUID_PERM)) {
321 CWARN("mdt blocked setuid attempt (%u -> %u) from "
322 LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
323 GOTO(out, rc = -EACCES);
326 /* check permission of setgid */
327 if (setgid && !(perm & CFS_SETGID_PERM)) {
328 CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
329 "from "LPX64"\n", pud->pud_uid, pud->pud_gid,
330 pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid,
332 GOTO(out, rc = -EACCES);
338 mdt_identity_put(mdt->mdt_identity_cache, identity);
342 static int old_init_ucred(struct mdt_thread_info *info,
343 struct mdt_body *body)
345 struct md_ucred *uc = mdt_ucred(info);
346 struct mdt_device *mdt = info->mti_mdt;
347 struct md_identity *identity = NULL;
351 uc->mu_valid = UCRED_INVALID;
352 uc->mu_o_uid = uc->mu_uid = body->uid;
353 uc->mu_o_gid = uc->mu_gid = body->gid;
354 uc->mu_o_fsuid = uc->mu_fsuid = body->fsuid;
355 uc->mu_o_fsgid = uc->mu_fsgid = body->fsgid;
356 uc->mu_suppgids[0] = body->suppgid;
357 uc->mu_suppgids[1] = -1;
359 if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
360 identity = mdt_identity_get(mdt->mdt_identity_cache,
363 CERROR("Deny access without identity: uid %d\n",
368 uc->mu_identity = identity;
370 /* XXX: need to process root_squash here. */
371 mdt_root_squash(info);
373 /* remove fs privilege for non-root user */
375 uc->mu_cap = body->capability & ~CAP_FS_MASK;
377 uc->mu_cap = body->capability;
378 uc->mu_valid = UCRED_OLD;
383 static int old_init_ucred_reint(struct mdt_thread_info *info)
385 struct md_ucred *uc = mdt_ucred(info);
386 struct mdt_device *mdt = info->mti_mdt;
387 struct md_identity *identity = NULL;
391 uc->mu_valid = UCRED_INVALID;
392 uc->mu_o_uid = uc->mu_o_fsuid = uc->mu_uid = uc->mu_fsuid;
393 uc->mu_o_gid = uc->mu_o_fsgid = uc->mu_gid = uc->mu_fsgid;
395 if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
396 identity = mdt_identity_get(mdt->mdt_identity_cache,
399 CERROR("Deny access without identity: uid %d\n",
404 uc->mu_identity = identity;
406 /* XXX: need to process root_squash here. */
407 mdt_root_squash(info);
409 /* remove fs privilege for non-root user */
411 uc->mu_cap &= ~CAP_FS_MASK;
412 uc->mu_valid = UCRED_OLD;
417 int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body)
419 struct ptlrpc_request *req = mdt_info_req(info);
420 struct md_ucred *uc = mdt_ucred(info);
422 if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))
425 mdt_exit_ucred(info);
427 if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
428 return old_init_ucred(info, body);
430 return new_init_ucred(info, BODY_INIT, body);
433 int mdt_init_ucred_reint(struct mdt_thread_info *info)
435 struct ptlrpc_request *req = mdt_info_req(info);
436 struct md_ucred *uc = mdt_ucred(info);
438 if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))
441 mdt_exit_ucred(info);
443 if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
444 return old_init_ucred_reint(info);
446 return new_init_ucred(info, REC_INIT, NULL);
449 /* copied from lov/lov_ea.c, just for debugging, will be removed later */
450 void mdt_dump_lmm(int level, const struct lov_mds_md *lmm)
452 const struct lov_ost_data_v1 *lod;
455 le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count);
457 CDEBUG(level, "objid "LPX64", magic 0x%08X, pattern %#X\n",
458 le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic),
459 le32_to_cpu(lmm->lmm_pattern));
460 CDEBUG(level,"stripe_size=0x%x, stripe_count=0x%x\n",
461 le32_to_cpu(lmm->lmm_stripe_size),
462 le32_to_cpu(lmm->lmm_stripe_count));
463 LASSERT(stripe_count <= (__s16)LOV_MAX_STRIPE_COUNT);
464 for (i = 0, lod = lmm->lmm_objects; i < stripe_count; i++, lod++) {
465 CDEBUG(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n",
466 i, le32_to_cpu(lod->l_ost_idx),
467 le64_to_cpu(lod->l_object_gr),
468 le64_to_cpu(lod->l_object_id));
472 void mdt_shrink_reply(struct mdt_thread_info *info)
474 struct req_capsule *pill = &info->mti_pill;
475 struct mdt_body *body;
476 int acl_size, md_size, adjust = 0;
479 body = req_capsule_server_get(pill, &RMF_MDT_BODY);
480 LASSERT(body != NULL);
482 if (body->valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE | OBD_MD_LINKNAME))
483 md_size = body->eadatasize;
487 acl_size = body->aclsize;
489 CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d"
490 " MDSCAPA = %d, OSSCAPA = %d\n",
492 (int)(body->valid & OBD_MD_FLMDSCAPA),
493 (int)(body->valid & OBD_MD_FLOSSCAPA));
497 &RMF_ACL, or &RMF_LOGCOOKIES
498 (optional) &RMF_CAPA1,
499 (optional) &RMF_CAPA2,
500 (optional) something else
502 adjust += req_capsule_shrink(pill, &RMF_MDT_MD,
505 if (req_capsule_has_field(pill, &RMF_ACL, RCL_SERVER))
506 adjust += req_capsule_shrink(pill, &RMF_ACL,
507 acl_size, adjust, 1);
508 else if (req_capsule_has_field(pill, &RMF_LOGCOOKIES, RCL_SERVER))
509 adjust += req_capsule_shrink(pill, &RMF_LOGCOOKIES,
510 acl_size, adjust, 1);
512 /* RMF_CAPA1 on server-side maybe for OBD_MD_FLMDSCAPA or
513 * OBD_MD_FLOSSCAPA. If RMF_CAPA2 exist also, RMF_CAPA1 is
514 * for OBD_MD_FLMDSCAPA only. */
515 if (req_capsule_has_field(pill, &RMF_CAPA1, RCL_SERVER)) {
516 if ((req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) &&
517 !(body->valid & OBD_MD_FLMDSCAPA)) ||
518 (!req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) &&
519 !(body->valid & OBD_MD_FLMDSCAPA) &&
520 !(body->valid & OBD_MD_FLOSSCAPA)))
521 adjust += req_capsule_shrink(pill, &RMF_CAPA1,
525 /* RMF_CAPA2 on server-side is for OBD_MD_FLOSSCAPA only. */
526 if ((req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) &&
527 !(body->valid & OBD_MD_FLOSSCAPA)))
528 adjust += req_capsule_shrink(pill, &RMF_CAPA2, 0, adjust, 0);
531 * Some more field should be shrinked if needed.
532 * This should be done by those who added fields to reply message.
538 /* if object is dying, pack the lov/llog data,
539 * parameter info->mti_attr should be valid at this point! */
540 int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo,
541 const struct md_attr *ma)
543 struct mdt_body *repbody;
544 const struct lu_attr *la = &ma->ma_attr;
547 repbody = req_capsule_server_get(&info->mti_pill, &RMF_MDT_BODY);
548 LASSERT(repbody != NULL);
550 if (ma->ma_valid & MA_INODE)
551 mdt_pack_attr2body(info, repbody, la, mdt_object_fid(mo));
553 if (ma->ma_valid & MA_LOV) {
556 if (mdt_object_exists(mo) < 0)
557 /* If it is a remote object, and we do not retrieve
558 * EA back unlink reg file*/
561 mode = lu_object_attr(&mo->mot_obj.mo_lu);
563 LASSERT(ma->ma_lmm_size);
564 mdt_dump_lmm(D_INFO, ma->ma_lmm);
565 repbody->eadatasize = ma->ma_lmm_size;
567 repbody->valid |= OBD_MD_FLEASIZE;
568 else if (S_ISDIR(mode))
569 repbody->valid |= OBD_MD_FLDIREA;
574 if (ma->ma_cookie_size && (ma->ma_valid & MA_COOKIE)) {
575 repbody->aclsize = ma->ma_cookie_size;
576 repbody->valid |= OBD_MD_FLCOOKIE;
582 static inline unsigned int attr_unpack(__u64 sa_valid) {
583 unsigned int ia_valid = 0;
585 if (sa_valid & MDS_ATTR_MODE)
586 ia_valid |= ATTR_MODE;
587 if (sa_valid & MDS_ATTR_UID)
588 ia_valid |= ATTR_UID;
589 if (sa_valid & MDS_ATTR_GID)
590 ia_valid |= ATTR_GID;
591 if (sa_valid & MDS_ATTR_SIZE)
592 ia_valid |= ATTR_SIZE;
593 if (sa_valid & MDS_ATTR_ATIME)
594 ia_valid |= ATTR_ATIME;
595 if (sa_valid & MDS_ATTR_MTIME)
596 ia_valid |= ATTR_MTIME;
597 if (sa_valid & MDS_ATTR_CTIME)
598 ia_valid |= ATTR_CTIME;
599 if (sa_valid & MDS_ATTR_ATIME_SET)
600 ia_valid |= ATTR_ATIME_SET;
601 if (sa_valid & MDS_ATTR_MTIME_SET)
602 ia_valid |= ATTR_MTIME_SET;
603 if (sa_valid & MDS_ATTR_FORCE)
604 ia_valid |= ATTR_FORCE;
605 if (sa_valid & MDS_ATTR_ATTR_FLAG)
606 ia_valid |= ATTR_ATTR_FLAG;
607 if (sa_valid & MDS_ATTR_KILL_SUID)
608 ia_valid |= ATTR_KILL_SUID;
609 if (sa_valid & MDS_ATTR_KILL_SGID)
610 ia_valid |= ATTR_KILL_SGID;
611 if (sa_valid & MDS_ATTR_CTIME_SET)
612 ia_valid |= ATTR_CTIME_SET;
613 if (sa_valid & MDS_ATTR_FROM_OPEN)
614 ia_valid |= ATTR_FROM_OPEN;
615 if (sa_valid & MDS_ATTR_BLOCKS)
616 ia_valid |= ATTR_BLOCKS;
617 if (sa_valid & MDS_OPEN_OWNEROVERRIDE)
618 ia_valid |= MDS_OPEN_OWNEROVERRIDE;
622 static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
636 if (in & ATTR_BLOCKS)
639 if (in & ATTR_FROM_OPEN)
640 rr->rr_flags |= MRF_SETATTR_LOCKED;
642 if (in & ATTR_ATIME_SET)
645 if (in & ATTR_CTIME_SET)
648 if (in & ATTR_MTIME_SET)
651 if (in & ATTR_ATTR_FLAG)
654 if (in & MDS_OPEN_OWNEROVERRIDE)
655 out |= MDS_OPEN_OWNEROVERRIDE;
657 /*XXX need ATTR_RAW?*/
658 in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
659 ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
660 ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
661 ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE);
663 CERROR("Unknown attr bits: %#llx\n", in);
668 static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
670 struct md_ucred *uc = mdt_ucred(info);
671 struct md_attr *ma = &info->mti_attr;
672 struct lu_attr *la = &ma->ma_attr;
673 struct req_capsule *pill = &info->mti_pill;
674 struct mdt_reint_record *rr = &info->mti_rr;
675 struct mdt_rec_setattr *rec;
678 rec = req_capsule_client_get(pill, &RMF_REC_SETATTR);
682 uc->mu_fsuid = rec->sa_fsuid;
683 uc->mu_fsgid = rec->sa_fsgid;
684 uc->mu_cap = rec->sa_cap;
685 uc->mu_suppgids[0] = rec->sa_suppgid;
686 uc->mu_suppgids[1] = -1;
688 rr->rr_fid1 = &rec->sa_fid;
689 la->la_valid = mdt_attr_valid_xlate(attr_unpack(rec->sa_valid), rr, ma);
690 la->la_mode = rec->sa_mode;
691 la->la_flags = rec->sa_attr_flags;
692 la->la_uid = rec->sa_uid;
693 la->la_gid = rec->sa_gid;
694 la->la_size = rec->sa_size;
695 la->la_blocks = rec->sa_blocks;
696 la->la_ctime = rec->sa_ctime;
697 la->la_atime = rec->sa_atime;
698 la->la_mtime = rec->sa_mtime;
699 ma->ma_valid = MA_INODE;
701 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
702 mdt_set_capainfo(info, 0, rr->rr_fid1,
703 req_capsule_client_get(pill, &RMF_CAPA1));
708 static int mdt_epoch_unpack(struct mdt_thread_info *info)
710 struct req_capsule *pill = &info->mti_pill;
713 if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT))
714 info->mti_epoch = req_capsule_client_get(pill, &RMF_MDT_EPOCH);
716 info->mti_epoch = NULL;
717 RETURN(info->mti_epoch == NULL ? -EFAULT : 0);
720 static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) {
721 struct req_capsule *pill = &info->mti_pill;
723 if (req_capsule_get_size(pill, &RMF_DLM_REQ, RCL_CLIENT)) {
724 info->mti_dlm_req = req_capsule_client_get(pill, &RMF_DLM_REQ);
725 if (info->mti_dlm_req == NULL)
732 static int mdt_setattr_unpack(struct mdt_thread_info *info)
734 struct md_attr *ma = &info->mti_attr;
735 struct req_capsule *pill = &info->mti_pill;
739 rc = mdt_setattr_unpack_rec(info);
743 /* Epoch may be absent */
744 mdt_epoch_unpack(info);
746 ma->ma_lmm_size = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT);
747 if (ma->ma_lmm_size) {
748 ma->ma_lmm = req_capsule_client_get(pill, &RMF_EADATA);
749 ma->ma_valid |= MA_LOV;
752 ma->ma_cookie_size = req_capsule_get_size(pill, &RMF_LOGCOOKIES,
754 if (ma->ma_cookie_size) {
755 ma->ma_cookie = req_capsule_client_get(pill, &RMF_LOGCOOKIES);
756 ma->ma_valid |= MA_COOKIE;
759 rc = mdt_dlmreq_unpack(info);
763 int mdt_close_unpack(struct mdt_thread_info *info)
768 rc = mdt_epoch_unpack(info);
772 RETURN(mdt_setattr_unpack_rec(info));
775 static int mdt_create_unpack(struct mdt_thread_info *info)
777 struct md_ucred *uc = mdt_ucred(info);
778 struct mdt_rec_create *rec;
779 struct lu_attr *attr = &info->mti_attr.ma_attr;
780 struct mdt_reint_record *rr = &info->mti_rr;
781 struct req_capsule *pill = &info->mti_pill;
782 struct md_op_spec *sp = &info->mti_spec;
786 rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
790 uc->mu_fsuid = rec->cr_fsuid;
791 uc->mu_fsgid = rec->cr_fsgid;
792 uc->mu_cap = rec->cr_cap;
793 uc->mu_suppgids[0] = rec->cr_suppgid1;
794 uc->mu_suppgids[1] = -1;
796 rr->rr_fid1 = &rec->cr_fid1;
797 rr->rr_fid2 = &rec->cr_fid2;
798 attr->la_mode = rec->cr_mode;
799 attr->la_rdev = rec->cr_rdev;
800 attr->la_uid = rec->cr_fsuid;
801 attr->la_gid = rec->cr_fsgid;
802 attr->la_ctime = rec->cr_time;
803 attr->la_mtime = rec->cr_time;
804 attr->la_atime = rec->cr_time;
805 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
806 LA_CTIME | LA_MTIME | LA_ATIME;
807 memset(&sp->u, 0, sizeof(sp->u));
808 sp->sp_cr_flags = rec->cr_flags;
809 sp->sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
810 info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
812 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
813 mdt_set_capainfo(info, 0, rr->rr_fid1,
814 req_capsule_client_get(pill, &RMF_CAPA1));
815 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
817 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
818 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
819 LASSERT(rr->rr_namelen > 0);
821 #ifdef CONFIG_FS_POSIX_ACL
822 if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) {
823 if (S_ISDIR(attr->la_mode))
824 sp->u.sp_pfid = rr->rr_fid1;
825 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
826 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
828 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
829 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
831 sp->u.sp_ea.fid = rr->rr_fid1;
835 if (S_ISDIR(attr->la_mode)) {
836 /* pass parent fid for cross-ref cases */
837 sp->u.sp_pfid = rr->rr_fid1;
838 if (sp->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
839 /* create salve object req, need
840 * unpack split ea here
842 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SLAVE);
843 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
845 sp->u.sp_ea.eadata = req_capsule_client_get(pill,
847 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill,
850 sp->u.sp_ea.fid = rr->rr_fid1;
853 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
854 } else if (S_ISLNK(attr->la_mode)) {
855 const char *tgt = NULL;
857 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM);
858 if (req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT)) {
859 tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
860 sp->u.sp_symname = tgt;
865 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
867 rc = mdt_dlmreq_unpack(info);
871 static int mdt_link_unpack(struct mdt_thread_info *info)
873 struct md_ucred *uc = mdt_ucred(info);
874 struct mdt_rec_link *rec;
875 struct lu_attr *attr = &info->mti_attr.ma_attr;
876 struct mdt_reint_record *rr = &info->mti_rr;
877 struct req_capsule *pill = &info->mti_pill;
881 rec = req_capsule_client_get(pill, &RMF_REC_LINK);
885 uc->mu_fsuid = rec->lk_fsuid;
886 uc->mu_fsgid = rec->lk_fsgid;
887 uc->mu_cap = rec->lk_cap;
888 uc->mu_suppgids[0] = rec->lk_suppgid1;
889 uc->mu_suppgids[1] = rec->lk_suppgid2;
891 attr->la_uid = rec->lk_fsuid;
892 attr->la_gid = rec->lk_fsgid;
893 rr->rr_fid1 = &rec->lk_fid1;
894 rr->rr_fid2 = &rec->lk_fid2;
895 attr->la_ctime = rec->lk_time;
896 attr->la_mtime = rec->lk_time;
897 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;
899 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
900 mdt_set_capainfo(info, 0, rr->rr_fid1,
901 req_capsule_client_get(pill, &RMF_CAPA1));
902 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
903 mdt_set_capainfo(info, 1, rr->rr_fid2,
904 req_capsule_client_get(pill, &RMF_CAPA2));
906 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
907 if (rr->rr_name == NULL)
909 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
910 LASSERT(rr->rr_namelen > 0);
911 info->mti_spec.sp_ck_split = !!(rec->lk_bias & MDS_CHECK_SPLIT);
912 info->mti_cross_ref = !!(rec->lk_bias & MDS_CROSS_REF);
914 rc = mdt_dlmreq_unpack(info);
918 static int mdt_unlink_unpack(struct mdt_thread_info *info)
920 struct md_ucred *uc = mdt_ucred(info);
921 struct mdt_rec_unlink *rec;
922 struct md_attr *ma = &info->mti_attr;
923 struct lu_attr *attr = &info->mti_attr.ma_attr;
924 struct mdt_reint_record *rr = &info->mti_rr;
925 struct req_capsule *pill = &info->mti_pill;
929 rec = req_capsule_client_get(pill, &RMF_REC_UNLINK);
933 uc->mu_fsuid = rec->ul_fsuid;
934 uc->mu_fsgid = rec->ul_fsgid;
935 uc->mu_cap = rec->ul_cap;
936 uc->mu_suppgids[0] = rec->ul_suppgid;
937 uc->mu_suppgids[1] = -1;
939 attr->la_uid = rec->ul_fsuid;
940 attr->la_gid = rec->ul_fsgid;
941 rr->rr_fid1 = &rec->ul_fid1;
942 rr->rr_fid2 = &rec->ul_fid2;
943 attr->la_ctime = rec->ul_time;
944 attr->la_mtime = rec->ul_time;
945 attr->la_mode = rec->ul_mode;
946 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
948 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
949 mdt_set_capainfo(info, 0, rr->rr_fid1,
950 req_capsule_client_get(pill, &RMF_CAPA1));
952 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
953 if (rr->rr_name == NULL)
955 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
956 LASSERT(rr->rr_namelen > 0);
957 info->mti_spec.sp_ck_split = !!(rec->ul_bias & MDS_CHECK_SPLIT);
958 info->mti_cross_ref = !!(rec->ul_bias & MDS_CROSS_REF);
959 if (rec->ul_bias & MDS_VTX_BYPASS)
960 ma->ma_attr_flags |= MDS_VTX_BYPASS;
962 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
964 rc = mdt_dlmreq_unpack(info);
968 static int mdt_rename_unpack(struct mdt_thread_info *info)
970 struct md_ucred *uc = mdt_ucred(info);
971 struct mdt_rec_rename *rec;
972 struct md_attr *ma = &info->mti_attr;
973 struct lu_attr *attr = &info->mti_attr.ma_attr;
974 struct mdt_reint_record *rr = &info->mti_rr;
975 struct req_capsule *pill = &info->mti_pill;
979 rec = req_capsule_client_get(pill, &RMF_REC_RENAME);
983 uc->mu_fsuid = rec->rn_fsuid;
984 uc->mu_fsgid = rec->rn_fsgid;
985 uc->mu_cap = rec->rn_cap;
986 uc->mu_suppgids[0] = rec->rn_suppgid1;
987 uc->mu_suppgids[1] = rec->rn_suppgid2;
989 attr->la_uid = rec->rn_fsuid;
990 attr->la_gid = rec->rn_fsgid;
991 rr->rr_fid1 = &rec->rn_fid1;
992 rr->rr_fid2 = &rec->rn_fid2;
993 attr->la_ctime = rec->rn_time;
994 attr->la_mtime = rec->rn_time;
995 /* rename_tgt contains the mode already */
996 attr->la_mode = rec->rn_mode;
997 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
999 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1000 mdt_set_capainfo(info, 0, rr->rr_fid1,
1001 req_capsule_client_get(pill, &RMF_CAPA1));
1002 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
1003 mdt_set_capainfo(info, 1, rr->rr_fid2,
1004 req_capsule_client_get(pill, &RMF_CAPA2));
1006 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1007 rr->rr_tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
1008 if (rr->rr_name == NULL || rr->rr_tgt == NULL)
1010 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1011 LASSERT(rr->rr_namelen > 0);
1012 rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT) - 1;
1013 LASSERT(rr->rr_tgtlen > 0);
1014 info->mti_spec.sp_ck_split = !!(rec->rn_bias & MDS_CHECK_SPLIT);
1015 info->mti_cross_ref = !!(rec->rn_bias & MDS_CROSS_REF);
1016 if (rec->rn_bias & MDS_VTX_BYPASS)
1017 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1019 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1021 rc = mdt_dlmreq_unpack(info);
1025 static int mdt_open_unpack(struct mdt_thread_info *info)
1027 struct md_ucred *uc = mdt_ucred(info);
1028 struct mdt_rec_create *rec;
1029 struct lu_attr *attr = &info->mti_attr.ma_attr;
1030 struct req_capsule *pill = &info->mti_pill;
1031 struct mdt_reint_record *rr = &info->mti_rr;
1032 struct ptlrpc_request *req = mdt_info_req(info);
1033 struct md_op_spec *sp = &info->mti_spec;
1036 rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
1040 uc->mu_fsuid = rec->cr_fsuid;
1041 uc->mu_fsgid = rec->cr_fsgid;
1042 uc->mu_cap = rec->cr_cap;
1043 uc->mu_suppgids[0] = rec->cr_suppgid1;
1044 uc->mu_suppgids[1] = rec->cr_suppgid2;
1046 rr->rr_fid1 = &rec->cr_fid1;
1047 rr->rr_fid2 = &rec->cr_fid2;
1048 rr->rr_handle = &rec->cr_old_handle;
1049 attr->la_mode = rec->cr_mode;
1050 attr->la_rdev = rec->cr_rdev;
1051 attr->la_uid = rec->cr_fsuid;
1052 attr->la_gid = rec->cr_fsgid;
1053 attr->la_ctime = rec->cr_time;
1054 attr->la_mtime = rec->cr_time;
1055 attr->la_atime = rec->cr_time;
1056 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
1057 LA_CTIME | LA_MTIME | LA_ATIME;
1058 memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u));
1059 info->mti_spec.sp_cr_flags = rec->cr_flags;
1060 info->mti_replayepoch = rec->cr_ioepoch;
1062 info->mti_spec.sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
1063 info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
1065 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1066 mdt_set_capainfo(info, 0, rr->rr_fid1,
1067 req_capsule_client_get(pill, &RMF_CAPA1));
1068 if ((lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) &&
1069 (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))) {
1071 mdt_set_capainfo(info, 1, rr->rr_fid2,
1072 req_capsule_client_get(pill, &RMF_CAPA2));
1075 * FIXME: capa in replay open request might have expired,
1076 * bypass capa check. Security hole?
1078 mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
1079 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
1083 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1084 if (rr->rr_name == NULL)
1086 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1088 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
1090 if (sp->u.sp_ea.eadatalen) {
1091 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
1092 if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)
1093 sp->u.sp_ea.no_lov_create = 1;
1099 typedef int (*reint_unpacker)(struct mdt_thread_info *info);
1101 static reint_unpacker mdt_reint_unpackers[REINT_MAX] = {
1102 [REINT_SETATTR] = mdt_setattr_unpack,
1103 [REINT_CREATE] = mdt_create_unpack,
1104 [REINT_LINK] = mdt_link_unpack,
1105 [REINT_UNLINK] = mdt_unlink_unpack,
1106 [REINT_RENAME] = mdt_rename_unpack,
1107 [REINT_OPEN] = mdt_open_unpack
1110 int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op)
1115 memset(&info->mti_rr, 0, sizeof(info->mti_rr));
1116 if (op < REINT_MAX && mdt_reint_unpackers[op] != NULL) {
1117 info->mti_rr.rr_opcode = op;
1118 rc = mdt_reint_unpackers[op](info);
1120 CERROR("Unexpected opcode %d\n", op);