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 /* RMF_CAPA1 on server-side maybe for OBD_MD_FLMDSCAPA or
601 * OBD_MD_FLOSSCAPA. If RMF_CAPA2 exist also, RMF_CAPA1 is
602 * for OBD_MD_FLMDSCAPA only. */
603 if (req_capsule_has_field(pill, &RMF_CAPA1, RCL_SERVER)) {
604 if ((req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) &&
605 !(body->valid & OBD_MD_FLMDSCAPA)) ||
606 (!req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) &&
607 !(body->valid & OBD_MD_FLMDSCAPA) &&
608 !(body->valid & OBD_MD_FLOSSCAPA)))
609 adjust += req_capsule_shrink(pill, &RMF_CAPA1,
613 /* RMF_CAPA2 on server-side is for OBD_MD_FLOSSCAPA only. */
614 if ((req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) &&
615 !(body->valid & OBD_MD_FLOSSCAPA)))
616 adjust += req_capsule_shrink(pill, &RMF_CAPA2, 0, adjust, 0);
619 * Some more field should be shrinked if needed.
620 * This should be done by those who added fields to reply message.
626 /* if object is dying, pack the lov/llog data,
627 * parameter info->mti_attr should be valid at this point! */
628 int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo,
629 const struct md_attr *ma)
631 struct mdt_body *repbody;
632 const struct lu_attr *la = &ma->ma_attr;
635 repbody = req_capsule_server_get(&info->mti_pill, &RMF_MDT_BODY);
636 LASSERT(repbody != NULL);
638 if (ma->ma_valid & MA_INODE)
639 mdt_pack_attr2body(info, repbody, la, mdt_object_fid(mo));
641 if (ma->ma_valid & MA_LOV) {
644 if (mdt_object_exists(mo) < 0)
645 /* If it is a remote object, and we do not retrieve
646 * EA back unlink reg file*/
649 mode = lu_object_attr(&mo->mot_obj.mo_lu);
651 LASSERT(ma->ma_lmm_size);
652 mdt_dump_lmm(D_INFO, ma->ma_lmm);
653 repbody->eadatasize = ma->ma_lmm_size;
655 repbody->valid |= OBD_MD_FLEASIZE;
656 else if (S_ISDIR(mode))
657 repbody->valid |= OBD_MD_FLDIREA;
662 if (ma->ma_cookie_size && (ma->ma_valid & MA_COOKIE)) {
663 repbody->aclsize = ma->ma_cookie_size;
664 repbody->valid |= OBD_MD_FLCOOKIE;
670 static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
684 if (in & ATTR_BLOCKS)
687 if (in & ATTR_FROM_OPEN)
688 rr->rr_flags |= MRF_SETATTR_LOCKED;
690 if (in & ATTR_ATIME_SET)
693 if (in & ATTR_CTIME_SET)
696 if (in & ATTR_MTIME_SET)
699 if (in & ATTR_ATTR_FLAG)
702 if (in & MDS_OPEN_OWNEROVERRIDE)
703 out |= MDS_OPEN_OWNEROVERRIDE;
705 /*XXX need ATTR_RAW?*/
706 in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
707 ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
708 ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
709 ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE);
711 CERROR("Unknown attr bits: %#llx\n", in);
716 static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
718 struct md_ucred *uc = mdt_ucred(info);
719 struct md_attr *ma = &info->mti_attr;
720 struct lu_attr *la = &ma->ma_attr;
721 struct req_capsule *pill = &info->mti_pill;
722 struct mdt_reint_record *rr = &info->mti_rr;
723 struct mdt_rec_setattr *rec;
726 rec = req_capsule_client_get(pill, &RMF_REC_SETATTR);
730 uc->mu_fsuid = rec->sa_fsuid;
731 uc->mu_fsgid = rec->sa_fsgid;
732 uc->mu_cap = rec->sa_cap;
733 uc->mu_suppgids[0] = rec->sa_suppgid;
734 uc->mu_suppgids[1] = -1;
736 rr->rr_fid1 = &rec->sa_fid;
737 la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr, ma);
738 la->la_mode = rec->sa_mode;
739 la->la_flags = rec->sa_attr_flags;
740 la->la_uid = rec->sa_uid;
741 la->la_gid = rec->sa_gid;
742 la->la_size = rec->sa_size;
743 la->la_blocks = rec->sa_blocks;
744 la->la_ctime = rec->sa_ctime;
745 la->la_atime = rec->sa_atime;
746 la->la_mtime = rec->sa_mtime;
747 ma->ma_valid = MA_INODE;
749 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
750 mdt_set_capainfo(info, 0, rr->rr_fid1,
751 req_capsule_client_get(pill, &RMF_CAPA1));
756 static int mdt_epoch_unpack(struct mdt_thread_info *info)
758 struct req_capsule *pill = &info->mti_pill;
761 if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT))
762 info->mti_epoch = req_capsule_client_get(pill, &RMF_MDT_EPOCH);
764 info->mti_epoch = NULL;
765 RETURN(info->mti_epoch == NULL ? -EFAULT : 0);
768 static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) {
769 struct req_capsule *pill = &info->mti_pill;
771 if (req_capsule_get_size(pill, &RMF_DLM_REQ, RCL_CLIENT)) {
772 info->mti_dlm_req = req_capsule_client_get(pill, &RMF_DLM_REQ);
773 if (info->mti_dlm_req == NULL)
780 static int mdt_setattr_unpack(struct mdt_thread_info *info)
782 struct md_attr *ma = &info->mti_attr;
783 struct req_capsule *pill = &info->mti_pill;
787 rc = mdt_setattr_unpack_rec(info);
791 /* Epoch may be absent */
792 mdt_epoch_unpack(info);
794 ma->ma_lmm_size = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT);
795 if (ma->ma_lmm_size) {
796 ma->ma_lmm = req_capsule_client_get(pill, &RMF_EADATA);
797 ma->ma_valid |= MA_LOV;
800 ma->ma_cookie_size = req_capsule_get_size(pill, &RMF_LOGCOOKIES,
802 if (ma->ma_cookie_size) {
803 ma->ma_cookie = req_capsule_client_get(pill, &RMF_LOGCOOKIES);
804 ma->ma_valid |= MA_COOKIE;
807 rc = mdt_dlmreq_unpack(info);
811 int mdt_close_unpack(struct mdt_thread_info *info)
816 rc = mdt_epoch_unpack(info);
820 RETURN(mdt_setattr_unpack_rec(info));
823 static int mdt_create_unpack(struct mdt_thread_info *info)
825 struct md_ucred *uc = mdt_ucred(info);
826 struct mdt_rec_create *rec;
827 struct lu_attr *attr = &info->mti_attr.ma_attr;
828 struct mdt_reint_record *rr = &info->mti_rr;
829 struct req_capsule *pill = &info->mti_pill;
830 struct md_op_spec *sp = &info->mti_spec;
834 rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
838 uc->mu_fsuid = rec->cr_fsuid;
839 uc->mu_fsgid = rec->cr_fsgid;
840 uc->mu_cap = rec->cr_cap;
841 uc->mu_suppgids[0] = rec->cr_suppgid1;
842 uc->mu_suppgids[1] = -1;
844 rr->rr_fid1 = &rec->cr_fid1;
845 rr->rr_fid2 = &rec->cr_fid2;
846 attr->la_mode = rec->cr_mode;
847 attr->la_rdev = rec->cr_rdev;
848 attr->la_uid = rec->cr_fsuid;
849 attr->la_gid = rec->cr_fsgid;
850 attr->la_ctime = rec->cr_time;
851 attr->la_mtime = rec->cr_time;
852 attr->la_atime = rec->cr_time;
853 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
854 LA_CTIME | LA_MTIME | LA_ATIME;
855 memset(&sp->u, 0, sizeof(sp->u));
856 sp->sp_cr_flags = rec->cr_flags;
857 sp->sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
858 info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
860 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
861 mdt_set_capainfo(info, 0, rr->rr_fid1,
862 req_capsule_client_get(pill, &RMF_CAPA1));
863 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
865 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
866 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
867 LASSERT(rr->rr_namelen > 0);
869 #ifdef CONFIG_FS_POSIX_ACL
870 if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) {
871 if (S_ISDIR(attr->la_mode))
872 sp->u.sp_pfid = rr->rr_fid1;
873 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
874 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
876 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
877 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
879 sp->u.sp_ea.fid = rr->rr_fid1;
883 if (S_ISDIR(attr->la_mode)) {
884 /* pass parent fid for cross-ref cases */
885 sp->u.sp_pfid = rr->rr_fid1;
886 if (sp->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
887 /* create salve object req, need
888 * unpack split ea here
890 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SLAVE);
891 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
893 sp->u.sp_ea.eadata = req_capsule_client_get(pill,
895 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill,
898 sp->u.sp_ea.fid = rr->rr_fid1;
901 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
902 } else if (S_ISLNK(attr->la_mode)) {
903 const char *tgt = NULL;
905 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM);
906 if (req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT)) {
907 tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
908 sp->u.sp_symname = tgt;
913 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
915 rc = mdt_dlmreq_unpack(info);
919 static int mdt_link_unpack(struct mdt_thread_info *info)
921 struct md_ucred *uc = mdt_ucred(info);
922 struct mdt_rec_link *rec;
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_LINK);
933 uc->mu_fsuid = rec->lk_fsuid;
934 uc->mu_fsgid = rec->lk_fsgid;
935 uc->mu_cap = rec->lk_cap;
936 uc->mu_suppgids[0] = rec->lk_suppgid1;
937 uc->mu_suppgids[1] = rec->lk_suppgid2;
939 attr->la_uid = rec->lk_fsuid;
940 attr->la_gid = rec->lk_fsgid;
941 rr->rr_fid1 = &rec->lk_fid1;
942 rr->rr_fid2 = &rec->lk_fid2;
943 attr->la_ctime = rec->lk_time;
944 attr->la_mtime = rec->lk_time;
945 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;
947 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
948 mdt_set_capainfo(info, 0, rr->rr_fid1,
949 req_capsule_client_get(pill, &RMF_CAPA1));
950 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
951 mdt_set_capainfo(info, 1, rr->rr_fid2,
952 req_capsule_client_get(pill, &RMF_CAPA2));
954 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
955 if (rr->rr_name == NULL)
957 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
958 LASSERT(rr->rr_namelen > 0);
959 info->mti_spec.sp_ck_split = !!(rec->lk_bias & MDS_CHECK_SPLIT);
960 info->mti_cross_ref = !!(rec->lk_bias & MDS_CROSS_REF);
962 rc = mdt_dlmreq_unpack(info);
966 static int mdt_unlink_unpack(struct mdt_thread_info *info)
968 struct md_ucred *uc = mdt_ucred(info);
969 struct mdt_rec_unlink *rec;
970 struct md_attr *ma = &info->mti_attr;
971 struct lu_attr *attr = &info->mti_attr.ma_attr;
972 struct mdt_reint_record *rr = &info->mti_rr;
973 struct req_capsule *pill = &info->mti_pill;
977 rec = req_capsule_client_get(pill, &RMF_REC_UNLINK);
981 uc->mu_fsuid = rec->ul_fsuid;
982 uc->mu_fsgid = rec->ul_fsgid;
983 uc->mu_cap = rec->ul_cap;
984 uc->mu_suppgids[0] = rec->ul_suppgid;
985 uc->mu_suppgids[1] = -1;
987 attr->la_uid = rec->ul_fsuid;
988 attr->la_gid = rec->ul_fsgid;
989 rr->rr_fid1 = &rec->ul_fid1;
990 rr->rr_fid2 = &rec->ul_fid2;
991 attr->la_ctime = rec->ul_time;
992 attr->la_mtime = rec->ul_time;
993 attr->la_mode = rec->ul_mode;
994 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
996 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
997 mdt_set_capainfo(info, 0, rr->rr_fid1,
998 req_capsule_client_get(pill, &RMF_CAPA1));
1000 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1001 if (rr->rr_name == NULL)
1003 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1004 LASSERT(rr->rr_namelen > 0);
1005 info->mti_spec.sp_ck_split = !!(rec->ul_bias & MDS_CHECK_SPLIT);
1006 info->mti_cross_ref = !!(rec->ul_bias & MDS_CROSS_REF);
1007 if (rec->ul_bias & MDS_VTX_BYPASS)
1008 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1010 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1012 rc = mdt_dlmreq_unpack(info);
1016 static int mdt_rename_unpack(struct mdt_thread_info *info)
1018 struct md_ucred *uc = mdt_ucred(info);
1019 struct mdt_rec_rename *rec;
1020 struct md_attr *ma = &info->mti_attr;
1021 struct lu_attr *attr = &info->mti_attr.ma_attr;
1022 struct mdt_reint_record *rr = &info->mti_rr;
1023 struct req_capsule *pill = &info->mti_pill;
1027 rec = req_capsule_client_get(pill, &RMF_REC_RENAME);
1031 uc->mu_fsuid = rec->rn_fsuid;
1032 uc->mu_fsgid = rec->rn_fsgid;
1033 uc->mu_cap = rec->rn_cap;
1034 uc->mu_suppgids[0] = rec->rn_suppgid1;
1035 uc->mu_suppgids[1] = rec->rn_suppgid2;
1037 attr->la_uid = rec->rn_fsuid;
1038 attr->la_gid = rec->rn_fsgid;
1039 rr->rr_fid1 = &rec->rn_fid1;
1040 rr->rr_fid2 = &rec->rn_fid2;
1041 attr->la_ctime = rec->rn_time;
1042 attr->la_mtime = rec->rn_time;
1043 /* rename_tgt contains the mode already */
1044 attr->la_mode = rec->rn_mode;
1045 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
1047 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1048 mdt_set_capainfo(info, 0, rr->rr_fid1,
1049 req_capsule_client_get(pill, &RMF_CAPA1));
1050 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
1051 mdt_set_capainfo(info, 1, rr->rr_fid2,
1052 req_capsule_client_get(pill, &RMF_CAPA2));
1054 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1055 rr->rr_tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
1056 if (rr->rr_name == NULL || rr->rr_tgt == NULL)
1058 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1059 LASSERT(rr->rr_namelen > 0);
1060 rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT) - 1;
1061 LASSERT(rr->rr_tgtlen > 0);
1062 info->mti_spec.sp_ck_split = !!(rec->rn_bias & MDS_CHECK_SPLIT);
1063 info->mti_cross_ref = !!(rec->rn_bias & MDS_CROSS_REF);
1064 if (rec->rn_bias & MDS_VTX_BYPASS)
1065 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1067 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1069 rc = mdt_dlmreq_unpack(info);
1073 static int mdt_open_unpack(struct mdt_thread_info *info)
1075 struct md_ucred *uc = mdt_ucred(info);
1076 struct mdt_rec_create *rec;
1077 struct lu_attr *attr = &info->mti_attr.ma_attr;
1078 struct req_capsule *pill = &info->mti_pill;
1079 struct mdt_reint_record *rr = &info->mti_rr;
1080 struct ptlrpc_request *req = mdt_info_req(info);
1081 struct md_op_spec *sp = &info->mti_spec;
1084 rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
1088 uc->mu_fsuid = rec->cr_fsuid;
1089 uc->mu_fsgid = rec->cr_fsgid;
1090 uc->mu_cap = rec->cr_cap;
1091 uc->mu_suppgids[0] = rec->cr_suppgid1;
1092 uc->mu_suppgids[1] = rec->cr_suppgid2;
1094 rr->rr_fid1 = &rec->cr_fid1;
1095 rr->rr_fid2 = &rec->cr_fid2;
1096 rr->rr_handle = &rec->cr_old_handle;
1097 attr->la_mode = rec->cr_mode;
1098 attr->la_rdev = rec->cr_rdev;
1099 attr->la_uid = rec->cr_fsuid;
1100 attr->la_gid = rec->cr_fsgid;
1101 attr->la_ctime = rec->cr_time;
1102 attr->la_mtime = rec->cr_time;
1103 attr->la_atime = rec->cr_time;
1104 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
1105 LA_CTIME | LA_MTIME | LA_ATIME;
1106 memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u));
1107 info->mti_spec.sp_cr_flags = rec->cr_flags;
1108 info->mti_replayepoch = rec->cr_ioepoch;
1110 info->mti_spec.sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
1111 info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
1113 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1114 mdt_set_capainfo(info, 0, rr->rr_fid1,
1115 req_capsule_client_get(pill, &RMF_CAPA1));
1116 if ((lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) &&
1117 (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))) {
1119 mdt_set_capainfo(info, 1, rr->rr_fid2,
1120 req_capsule_client_get(pill, &RMF_CAPA2));
1123 * FIXME: capa in replay open request might have expired,
1124 * bypass capa check. Security hole?
1126 mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
1127 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
1131 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1132 if (rr->rr_name == NULL)
1134 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1135 LASSERT(rr->rr_namelen > 0);
1137 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
1139 if (sp->u.sp_ea.eadatalen) {
1140 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
1141 if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)
1142 sp->u.sp_ea.no_lov_create = 1;
1148 typedef int (*reint_unpacker)(struct mdt_thread_info *info);
1150 static reint_unpacker mdt_reint_unpackers[REINT_MAX] = {
1151 [REINT_SETATTR] = mdt_setattr_unpack,
1152 [REINT_CREATE] = mdt_create_unpack,
1153 [REINT_LINK] = mdt_link_unpack,
1154 [REINT_UNLINK] = mdt_unlink_unpack,
1155 [REINT_RENAME] = mdt_rename_unpack,
1156 [REINT_OPEN] = mdt_open_unpack
1159 int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op)
1164 memset(&info->mti_rr, 0, sizeof(info->mti_rr));
1165 if (op < REINT_MAX && mdt_reint_unpackers[op] != NULL) {
1166 info->mti_rr.rr_opcode = op;
1167 rc = mdt_reint_unpackers[op](info);
1169 CERROR("Unexpected opcode %d\n", op);