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 {
49 int groups_from_list(struct group_info *ginfo, gid_t *glist)
52 int count = ginfo->ngroups;
54 /* fill group_info from gid array */
55 for (i = 0; i < ginfo->nblocks; i++) {
56 int cp_count = min(NGROUPS_PER_BLOCK, count);
57 int off = i * NGROUPS_PER_BLOCK;
58 int len = cp_count * sizeof(*glist);
60 if (memcpy(ginfo->blocks[i], glist + off, len))
68 /* groups_sort() is copied from linux kernel! */
69 /* a simple shell-metzner sort */
70 void groups_sort(struct group_info *group_info)
72 int base, max, stride;
73 int gidsetsize = group_info->ngroups;
75 for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1)
80 max = gidsetsize - stride;
81 for (base = 0; base < max; base++) {
83 int right = left + stride;
84 gid_t tmp = GROUP_AT(group_info, right);
86 while (left >= 0 && GROUP_AT(group_info, left) > tmp) {
87 GROUP_AT(group_info, right) =
88 GROUP_AT(group_info, left);
92 GROUP_AT(group_info, right) = tmp;
98 void mdt_exit_ucred(struct mdt_thread_info *info)
100 struct md_ucred *uc = mdt_ucred(info);
101 struct mdt_device *mdt = info->mti_mdt;
103 if (uc->mu_valid != UCRED_INIT) {
104 uc->mu_suppgids[0] = uc->mu_suppgids[1] = -1;
106 groups_free(uc->mu_ginfo);
109 if (uc->mu_identity) {
110 mdt_identity_put(mdt->mdt_identity_cache,
112 uc->mu_identity = NULL;
114 uc->mu_valid = UCRED_INIT;
118 static int old_init_ucred(struct mdt_thread_info *info,
119 struct mdt_body *body)
121 struct md_ucred *uc = mdt_ucred(info);
122 struct mdt_device *mdt = info->mti_mdt;
123 struct mdt_identity *identity = NULL;
127 uc->mu_valid = UCRED_INVALID;
129 if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
130 /* get identity info of this user */
131 identity = mdt_identity_get(mdt->mdt_identity_cache,
134 CERROR("Deny access without identity: uid %d\n",
140 uc->mu_valid = UCRED_OLD;
141 uc->mu_squash = SQUASH_NONE;
142 uc->mu_o_uid = uc->mu_uid = body->uid;
143 uc->mu_o_gid = uc->mu_gid = body->gid;
144 uc->mu_o_fsuid = uc->mu_fsuid = body->fsuid;
145 uc->mu_o_fsgid = uc->mu_fsgid = body->fsgid;
146 uc->mu_suppgids[0] = body->suppgid;
147 uc->mu_suppgids[1] = -1;
148 uc->mu_cap = body->capability;
150 uc->mu_identity = identity;
155 static int old_init_ucred_reint(struct mdt_thread_info *info)
157 struct md_ucred *uc = mdt_ucred(info);
158 struct mdt_device *mdt = info->mti_mdt;
159 struct mdt_identity *identity = NULL;
163 uc->mu_valid = UCRED_INVALID;
165 if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
166 /* get identity info of this user */
167 identity = mdt_identity_get(mdt->mdt_identity_cache,
170 CERROR("Deny access without identity: uid %d\n",
176 uc->mu_valid = UCRED_OLD;
177 uc->mu_squash = SQUASH_NONE;
178 uc->mu_o_uid = uc->mu_o_fsuid = uc->mu_uid = uc->mu_fsuid;
179 uc->mu_o_gid = uc->mu_o_fsgid = uc->mu_gid = uc->mu_fsgid;
181 uc->mu_identity = identity;
186 static int nid_nosquash(struct mdt_device *mdt, lnet_nid_t nid)
188 struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
191 for (i = 0; i < rsi->rsi_n_nosquash_nids; i++)
192 if ((rsi->rsi_nosquash_nids[i] == nid) ||
193 (rsi->rsi_nosquash_nids[i] == LNET_NID_ANY))
199 static int mdt_squash_root(struct mdt_device *mdt, struct md_ucred *ucred,
200 struct ptlrpc_user_desc *pud, lnet_nid_t peernid)
202 struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
204 if (!rsi || (!rsi->rsi_uid && !rsi->rsi_gid) ||
205 nid_nosquash(mdt, peernid))
208 CDEBUG(D_SEC, "squash req from "LPX64":"
209 "(%u:%u-%u:%u/%x)=>(%u:%u-%u:%u/%x)\n", peernid,
210 pud->pud_uid, pud->pud_gid,
211 pud->pud_fsuid, pud->pud_fsgid, pud->pud_cap,
212 pud->pud_uid ? pud->pud_uid : rsi->rsi_uid,
213 pud->pud_uid ? pud->pud_gid : rsi->rsi_gid,
214 pud->pud_fsuid ? pud->pud_fsuid : rsi->rsi_uid,
215 pud->pud_fsuid ? pud->pud_fsgid : rsi->rsi_gid,
216 pud->pud_cap & ~CAP_FS_MASK);
220 ucred->mu_uid = rsi->rsi_uid;
221 ucred->mu_squash |= SQUASH_UID;
223 ucred->mu_uid = pud->pud_uid;
226 if (!pud->pud_fsuid) {
227 ucred->mu_fsuid = rsi->rsi_uid;
228 ucred->mu_squash |= SQUASH_UID;
230 ucred->mu_fsuid = pud->pud_fsuid;
233 ucred->mu_uid = pud->pud_uid;
234 ucred->mu_fsuid = pud->pud_fsuid;
241 ucred->mu_gid = rsi->rsi_gid;
242 ucred->mu_squash |= SQUASH_GID;
244 ucred->mu_gid = pud->pud_gid;
247 if (!pud->pud_fsgid) {
248 ucred->mu_fsgid = rsi->rsi_gid;
249 ucred->mu_squash |= SQUASH_GID;
251 ucred->mu_fsgid = pud->pud_fsgid;
254 for (i = 0; i < 2; i++) {
255 if (!ucred->mu_suppgids[i]) {
256 ucred->mu_suppgids[i] = rsi->rsi_gid;
257 ucred->mu_squash |= SQUASH_GID;
261 for (i = 0; i < pud->pud_ngroups; i++) {
262 if (!pud->pud_groups[i]) {
263 pud->pud_groups[i] = rsi->rsi_gid;
264 ucred->mu_squash |= SQUASH_GID;
268 ucred->mu_gid = pud->pud_gid;
269 ucred->mu_fsgid = pud->pud_fsgid;
272 if ((ucred->mu_squash & SQUASH_UID) || ucred->mu_fsuid)
273 ucred->mu_cap = (pud->pud_cap & ~CAP_FS_MASK);
275 ucred->mu_cap = pud->pud_cap;
280 static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
283 struct ptlrpc_request *req = mdt_info_req(info);
284 struct mdt_export_data *med = mdt_req2med(req);
285 struct mdt_device *mdt = info->mti_mdt;
286 struct ptlrpc_user_desc *pud = req->rq_user_desc;
287 struct md_ucred *ucred = mdt_ucred(info);
288 struct mdt_identity *identity = NULL;
289 lnet_nid_t peernid = req->rq_peer.nid;
290 __u32 setxid_perm = 0;
291 int root_squashed = 0;
298 ucred->mu_valid = UCRED_INVALID;
300 if (req->rq_auth_gss && req->rq_auth_uid == INVALID_UID) {
301 CWARN("user not authenticated, deny access!\n");
305 ucred->mu_o_uid = pud->pud_uid;
306 ucred->mu_o_gid = pud->pud_gid;
307 ucred->mu_o_fsuid = pud->pud_fsuid;
308 ucred->mu_o_fsgid = pud->pud_fsgid;
310 if (type == BODY_INIT) {
311 struct mdt_body *body = (struct mdt_body *)buf;
313 ucred->mu_suppgids[0] = body->suppgid;
314 ucred->mu_suppgids[1] = -1;
317 /* sanity check: if we use strong authentication, we expect the
318 * uid which client claimed is true */
319 if (req->rq_auth_gss) {
320 if (med->med_rmtclient) {
321 if (ptlrpc_user_desc_do_idmap(req, pud))
324 if (req->rq_auth_mapped_uid != pud->pud_uid) {
325 CERROR("remote client "LPU64": auth uid %u "
326 "while client claim %u:%u/%u:%u\n",
327 peernid, req->rq_auth_uid, pud->pud_uid,
328 pud->pud_gid, pud->pud_fsuid,
333 if (req->rq_auth_uid != pud->pud_uid) {
334 CERROR("local client "LPU64": auth uid %u "
335 "while client claim %u:%u/%u:%u\n",
336 peernid, req->rq_auth_uid, pud->pud_uid,
337 pud->pud_gid, pud->pud_fsuid,
344 if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
345 if (med->med_rmtclient) {
346 CERROR("remote client must run with identity_get "
350 setxid_perm |= LUSTRE_SETGRP_PERM;
355 identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid);
357 CERROR("Deny access without identity: uid %d\n", pud->pud_uid);
361 /* find out the setuid/setgid attempt */
362 setuid = (pud->pud_uid != pud->pud_fsuid);
363 setgid = (pud->pud_gid != pud->pud_fsgid ||
364 pud->pud_gid != identity->mi_gid);
366 setxid_perm = mdt_identity_get_setxid_perm(identity,
370 /* check permission of setuid */
371 if (setuid && !(setxid_perm & LUSTRE_SETUID_PERM)) {
372 CWARN("mdt blocked setuid attempt (%u -> %u) from "
373 LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
374 GOTO(out, rc = -EACCES);
377 /* check permission of setgid */
378 if (setgid && !(setxid_perm & LUSTRE_SETGID_PERM)) {
379 CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
380 "from "LPX64"\n", pud->pud_uid, pud->pud_gid,
381 pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid,
383 GOTO(out, rc = -EACCES);
387 /* FIXME: The exact behavior of root_squash is not defined. */
388 ucred->mu_squash = SQUASH_NONE;
389 root_squashed = mdt_squash_root(mdt, ucred, pud, peernid);
390 if (!root_squashed) {
391 ucred->mu_uid = pud->pud_uid;
392 ucred->mu_gid = pud->pud_gid;
393 ucred->mu_fsuid = pud->pud_fsuid;
394 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;
403 * NB: remote client not allowed to setgroups anyway.
405 if (!med->med_rmtclient && pud->pud_ngroups &&
406 (setxid_perm & LUSTRE_SETGRP_PERM)) {
407 struct group_info *ginfo;
409 /* setgroups for local client */
410 ginfo = groups_alloc(pud->pud_ngroups);
412 CERROR("failed to alloc %d groups\n",
414 GOTO(out, rc = -ENOMEM);
416 groups_from_list(ginfo, pud->pud_groups);
418 ucred->mu_ginfo = ginfo;
420 ucred->mu_ginfo = NULL;
423 ucred->mu_identity = identity;
424 ucred->mu_valid = UCRED_NEW;
428 mdt_identity_put(mdt->mdt_identity_cache, identity);
433 int mdt_check_ucred(struct mdt_thread_info *info)
435 struct ptlrpc_request *req = mdt_info_req(info);
436 struct mdt_export_data *med = mdt_req2med(req);
437 struct mdt_device *mdt = info->mti_mdt;
438 struct ptlrpc_user_desc *pud = req->rq_user_desc;
439 struct md_ucred *ucred = mdt_ucred(info);
440 struct mdt_identity *identity;
441 lnet_nid_t peernid = req->rq_peer.nid;
445 if ((ucred->mu_valid == UCRED_OLD) || (ucred->mu_valid == UCRED_NEW))
448 /* !rq_user_desc means null security, maybe inter-mds ops */
449 if (!req->rq_user_desc)
452 if (req->rq_auth_gss && req->rq_auth_uid == INVALID_UID) {
453 CWARN("user not authenticated, deny access!\n");
457 /* sanity check: if we use strong authentication, we expect the
458 * uid which client claimed is true */
459 if (req->rq_auth_gss) {
460 if (med->med_rmtclient) {
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");
494 identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid);
496 CERROR("Deny access without identity: uid %d\n", pud->pud_uid);
500 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 /* !rq_user_desc means null security, maybe inter-mds ops */
516 return req->rq_user_desc ? new_init_ucred(info, BODY_INIT, body) :
517 old_init_ucred(info, body);
520 int mdt_init_ucred_reint(struct mdt_thread_info *info)
522 struct ptlrpc_request *req = mdt_info_req(info);
523 struct md_ucred *uc = mdt_ucred(info);
525 if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))
528 mdt_exit_ucred(info);
530 /* !rq_user_desc means null security, maybe inter-mds ops */
531 return req->rq_user_desc ? new_init_ucred(info, REC_INIT, NULL) :
532 old_init_ucred_reint(info);
535 /* copied from lov/lov_ea.c, just for debugging, will be removed later */
536 void mdt_dump_lmm(int level, const struct lov_mds_md *lmm)
538 const struct lov_ost_data_v1 *lod;
541 le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count);
543 CDEBUG(level, "objid "LPX64", magic 0x%08X, pattern %#X\n",
544 le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic),
545 le32_to_cpu(lmm->lmm_pattern));
546 CDEBUG(level,"stripe_size=0x%x, stripe_count=0x%x\n",
547 le32_to_cpu(lmm->lmm_stripe_size),
548 le32_to_cpu(lmm->lmm_stripe_count));
549 LASSERT(stripe_count < (__s16)LOV_MAX_STRIPE_COUNT);
550 for (i = 0, lod = lmm->lmm_objects; i < stripe_count; i++, lod++) {
551 CDEBUG(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n",
552 i, le32_to_cpu(lod->l_ost_idx),
553 le64_to_cpu(lod->l_object_gr),
554 le64_to_cpu(lod->l_object_id));
558 void mdt_shrink_reply(struct mdt_thread_info *info, int offset,
559 int mdscapa, int osscapa)
561 struct ptlrpc_request *req = mdt_info_req(info);
562 struct mdt_body *body;
563 int acl_size, md_size;
565 body = req_capsule_server_get(&info->mti_pill, &RMF_MDT_BODY);
566 LASSERT(body != NULL);
568 if (body->valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE | OBD_MD_LINKNAME))
569 md_size = body->eadatasize;
573 acl_size = body->aclsize;
575 CDEBUG(D_INFO, "Shrink to md_size %d cookie_size %d \n",
578 lustre_shrink_reply(req, offset, md_size, 1);
580 lustre_shrink_reply(req, offset, acl_size, 1);
581 offset += !!acl_size;
582 if (mdscapa && !(body->valid & OBD_MD_FLMDSCAPA))
583 lustre_shrink_reply(req, offset, 0, 1);
585 if (osscapa && !(body->valid & OBD_MD_FLOSSCAPA))
586 lustre_shrink_reply(req, offset, 0, 0);
591 /* if object is dying, pack the lov/llog data,
592 * parameter info->mti_attr should be valid at this point! */
593 int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo,
594 const struct md_attr *ma)
596 struct mdt_body *repbody;
597 const struct lu_attr *la = &ma->ma_attr;
600 repbody = req_capsule_server_get(&info->mti_pill, &RMF_MDT_BODY);
601 LASSERT(repbody != NULL);
603 if (ma->ma_valid & MA_INODE)
604 mdt_pack_attr2body(info, repbody, la, mdt_object_fid(mo));
606 if (ma->ma_valid & MA_LOV) {
609 if (mdt_object_exists(mo) < 0)
610 /* If it is a remote object, and we do not retrieve
611 * EA back unlink reg file*/
614 mode = lu_object_attr(&mo->mot_obj.mo_lu);
616 LASSERT(ma->ma_lmm_size);
617 mdt_dump_lmm(D_INFO, ma->ma_lmm);
618 repbody->eadatasize = ma->ma_lmm_size;
620 repbody->valid |= OBD_MD_FLEASIZE;
621 else if (S_ISDIR(mode))
622 repbody->valid |= OBD_MD_FLDIREA;
627 if (ma->ma_cookie_size && (ma->ma_valid & MA_COOKIE)) {
628 repbody->aclsize = ma->ma_cookie_size;
629 repbody->valid |= OBD_MD_FLCOOKIE;
635 static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
649 if (in & ATTR_BLOCKS)
652 if (in & ATTR_FROM_OPEN)
653 rr->rr_flags |= MRF_SETATTR_LOCKED;
655 if (in & ATTR_ATIME_SET)
658 if (in & ATTR_CTIME_SET)
661 if (in & ATTR_MTIME_SET)
664 if (in & ATTR_ATTR_FLAG)
667 /*XXX need ATTR_RAW?*/
668 in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
669 ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
670 ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
671 ATTR_ATTR_FLAG|ATTR_RAW);
673 CERROR("Unknown attr bits: %#llx\n", in);
678 static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
680 struct md_ucred *uc = mdt_ucred(info);
681 struct md_attr *ma = &info->mti_attr;
682 struct lu_attr *la = &ma->ma_attr;
683 struct req_capsule *pill = &info->mti_pill;
684 struct mdt_reint_record *rr = &info->mti_rr;
685 struct mdt_rec_setattr *rec;
688 rec = req_capsule_client_get(pill, &RMF_REC_SETATTR);
692 uc->mu_fsuid = rec->sa_fsuid;
693 uc->mu_fsgid = rec->sa_fsgid;
694 uc->mu_cap = rec->sa_cap;
695 uc->mu_suppgids[0] = rec->sa_suppgid;
696 uc->mu_suppgids[1] = -1;
698 rr->rr_fid1 = &rec->sa_fid;
699 la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr, ma);
700 la->la_mode = rec->sa_mode;
701 la->la_flags = rec->sa_attr_flags;
702 la->la_uid = rec->sa_uid;
703 la->la_gid = rec->sa_gid;
704 la->la_size = rec->sa_size;
705 la->la_blocks = rec->sa_blocks;
706 la->la_ctime = rec->sa_ctime;
707 la->la_atime = rec->sa_atime;
708 la->la_mtime = rec->sa_mtime;
709 ma->ma_valid = MA_INODE;
711 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
712 mdt_set_capainfo(info, 0, rr->rr_fid1,
713 req_capsule_client_get(pill, &RMF_CAPA1));
718 static int mdt_epoch_unpack(struct mdt_thread_info *info)
720 struct req_capsule *pill = &info->mti_pill;
723 if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT))
724 info->mti_epoch = req_capsule_client_get(pill, &RMF_MDT_EPOCH);
726 info->mti_epoch = NULL;
727 RETURN(info->mti_epoch == NULL ? -EFAULT : 0);
730 static int mdt_setattr_unpack(struct mdt_thread_info *info)
732 struct md_attr *ma = &info->mti_attr;
733 struct req_capsule *pill = &info->mti_pill;
737 rc = mdt_setattr_unpack_rec(info);
741 /* Epoch may be absent */
742 mdt_epoch_unpack(info);
744 if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) {
745 ma->ma_lmm = req_capsule_client_get(pill, &RMF_EADATA);
746 ma->ma_lmm_size = req_capsule_get_size(pill, &RMF_EADATA,
748 ma->ma_valid |= MA_LOV;
751 if (req_capsule_field_present(pill, &RMF_LOGCOOKIES, RCL_CLIENT)) {
752 ma->ma_cookie = req_capsule_client_get(pill,
754 ma->ma_cookie_size = req_capsule_get_size(pill,
757 ma->ma_valid |= MA_COOKIE;
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;
785 rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
789 uc->mu_fsuid = rec->cr_fsuid;
790 uc->mu_fsgid = rec->cr_fsgid;
791 uc->mu_cap = rec->cr_cap;
792 uc->mu_suppgids[0] = rec->cr_suppgid;
793 uc->mu_suppgids[1] = -1;
795 rr->rr_fid1 = &rec->cr_fid1;
796 rr->rr_fid2 = &rec->cr_fid2;
797 attr->la_mode = rec->cr_mode;
798 attr->la_rdev = rec->cr_rdev;
799 attr->la_uid = rec->cr_fsuid;
800 attr->la_gid = rec->cr_fsgid;
801 attr->la_ctime = rec->cr_time;
802 attr->la_mtime = rec->cr_time;
803 attr->la_atime = rec->cr_time;
804 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
805 LA_CTIME | LA_MTIME | LA_ATIME;
806 memset(&sp->u, 0, sizeof(sp->u));
807 sp->sp_cr_flags = rec->cr_flags;
808 sp->sp_ck_split = rec->cr_cksplit;
810 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
811 mdt_set_capainfo(info, 0, rr->rr_fid1,
812 req_capsule_client_get(pill, &RMF_CAPA1));
813 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
815 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
816 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT);
818 #ifdef CONFIG_FS_POSIX_ACL
819 if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) {
820 if (S_ISDIR(attr->la_mode))
821 sp->u.sp_pfid = rr->rr_fid1;
822 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
823 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
825 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
826 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
831 if (S_ISDIR(attr->la_mode)) {
832 /* pass parent fid for cross-ref cases */
833 sp->u.sp_pfid = rr->rr_fid1;
834 if (sp->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
835 /* create salve object req, need
836 * unpack split ea here
838 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SLAVE);
839 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
841 sp->u.sp_ea.eadata = req_capsule_client_get(pill,
843 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill,
846 sp->u.sp_ea.fid = rr->rr_fid1;
848 } else if (S_ISLNK(attr->la_mode)) {
849 const char *tgt = NULL;
851 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM);
852 if (req_capsule_field_present(pill, &RMF_SYMTGT, RCL_CLIENT)) {
853 tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
854 sp->u.sp_symname = tgt;
862 static int mdt_link_unpack(struct mdt_thread_info *info)
864 struct md_ucred *uc = mdt_ucred(info);
865 struct mdt_rec_link *rec;
866 struct lu_attr *attr = &info->mti_attr.ma_attr;
867 struct mdt_reint_record *rr = &info->mti_rr;
868 struct req_capsule *pill = &info->mti_pill;
871 rec = req_capsule_client_get(pill, &RMF_REC_LINK);
875 uc->mu_fsuid = rec->lk_fsuid;
876 uc->mu_fsgid = rec->lk_fsgid;
877 uc->mu_cap = rec->lk_cap;
878 uc->mu_suppgids[0] = rec->lk_suppgid1;
879 uc->mu_suppgids[1] = rec->lk_suppgid2;
881 attr->la_uid = rec->lk_fsuid;
882 attr->la_gid = rec->lk_fsgid;
883 rr->rr_fid1 = &rec->lk_fid1;
884 rr->rr_fid2 = &rec->lk_fid2;
885 attr->la_ctime = rec->lk_time;
886 attr->la_mtime = rec->lk_time;
887 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;
889 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
890 mdt_set_capainfo(info, 0, rr->rr_fid1,
891 req_capsule_client_get(pill, &RMF_CAPA1));
892 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
893 mdt_set_capainfo(info, 1, rr->rr_fid2,
894 req_capsule_client_get(pill, &RMF_CAPA2));
896 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
897 if (rr->rr_name == NULL)
899 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT);
900 info->mti_spec.sp_ck_split = rec->lk_cksplit;
905 static int mdt_unlink_unpack(struct mdt_thread_info *info)
907 struct md_ucred *uc = mdt_ucred(info);
908 struct mdt_rec_unlink *rec;
909 struct lu_attr *attr = &info->mti_attr.ma_attr;
910 struct mdt_reint_record *rr = &info->mti_rr;
911 struct req_capsule *pill = &info->mti_pill;
914 rec = req_capsule_client_get(pill, &RMF_REC_UNLINK);
918 uc->mu_fsuid = rec->ul_fsuid;
919 uc->mu_fsgid = rec->ul_fsgid;
920 uc->mu_cap = rec->ul_cap;
921 uc->mu_suppgids[0] = rec->ul_suppgid;
922 uc->mu_suppgids[1] = -1;
924 attr->la_uid = rec->ul_fsuid;
925 attr->la_gid = rec->ul_fsgid;
926 rr->rr_fid1 = &rec->ul_fid1;
927 rr->rr_fid2 = &rec->ul_fid2;
928 attr->la_ctime = rec->ul_time;
929 attr->la_mtime = rec->ul_time;
930 attr->la_mode = rec->ul_mode;
931 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
933 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
934 mdt_set_capainfo(info, 0, rr->rr_fid1,
935 req_capsule_client_get(pill, &RMF_CAPA1));
937 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
938 if (rr->rr_name == NULL)
940 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT);
941 info->mti_spec.sp_ck_split = rec->ul_cksplit;
946 static int mdt_rename_unpack(struct mdt_thread_info *info)
948 struct md_ucred *uc = mdt_ucred(info);
949 struct mdt_rec_rename *rec;
950 struct lu_attr *attr = &info->mti_attr.ma_attr;
951 struct mdt_reint_record *rr = &info->mti_rr;
952 struct req_capsule *pill = &info->mti_pill;
955 rec = req_capsule_client_get(pill, &RMF_REC_RENAME);
959 uc->mu_fsuid = rec->rn_fsuid;
960 uc->mu_fsgid = rec->rn_fsgid;
961 uc->mu_cap = rec->rn_cap;
962 uc->mu_suppgids[0] = rec->rn_suppgid1;
963 uc->mu_suppgids[1] = rec->rn_suppgid2;
965 attr->la_uid = rec->rn_fsuid;
966 attr->la_gid = rec->rn_fsgid;
967 rr->rr_fid1 = &rec->rn_fid1;
968 rr->rr_fid2 = &rec->rn_fid2;
969 attr->la_ctime = rec->rn_time;
970 attr->la_mtime = rec->rn_time;
971 /* rename_tgt contains the mode already */
972 attr->la_mode = rec->rn_mode;
973 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
975 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
976 mdt_set_capainfo(info, 0, rr->rr_fid1,
977 req_capsule_client_get(pill, &RMF_CAPA1));
978 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
979 mdt_set_capainfo(info, 1, rr->rr_fid2,
980 req_capsule_client_get(pill, &RMF_CAPA2));
982 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
983 rr->rr_tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
984 if (rr->rr_name == NULL || rr->rr_tgt == NULL)
986 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT);
987 rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT);
988 info->mti_spec.sp_ck_split = rec->rn_cksplit;
993 static int mdt_open_unpack(struct mdt_thread_info *info)
995 struct md_ucred *uc = mdt_ucred(info);
996 struct mdt_rec_create *rec;
997 struct lu_attr *attr = &info->mti_attr.ma_attr;
998 struct req_capsule *pill = &info->mti_pill;
999 struct mdt_reint_record *rr = &info->mti_rr;
1000 struct ptlrpc_request *req = mdt_info_req(info);
1003 rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
1007 uc->mu_fsuid = rec->cr_fsuid;
1008 uc->mu_fsgid = rec->cr_fsgid;
1009 uc->mu_cap = rec->cr_cap;
1010 uc->mu_suppgids[0] = rec->cr_suppgid;
1011 uc->mu_suppgids[1] = -1;
1013 rr->rr_fid1 = &rec->cr_fid1;
1014 rr->rr_fid2 = &rec->cr_fid2;
1015 attr->la_mode = rec->cr_mode;
1016 attr->la_rdev = rec->cr_rdev;
1017 attr->la_uid = rec->cr_fsuid;
1018 attr->la_gid = rec->cr_fsgid;
1019 attr->la_ctime = rec->cr_time;
1020 attr->la_mtime = rec->cr_time;
1021 attr->la_atime = rec->cr_time;
1022 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
1023 LA_CTIME | LA_MTIME | LA_ATIME;
1024 memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u));
1025 info->mti_spec.sp_cr_flags = rec->cr_flags;
1026 info->mti_replayepoch = rec->cr_ioepoch;
1028 info->mti_spec.sp_ck_split = rec->cr_cksplit;
1030 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1031 mdt_set_capainfo(info, 0, rr->rr_fid1,
1032 req_capsule_client_get(pill, &RMF_CAPA1));
1033 if ((lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) &&
1034 (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT)))
1035 mdt_set_capainfo(info, 1, rr->rr_fid2,
1036 req_capsule_client_get(pill, &RMF_CAPA2));
1038 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1039 if (rr->rr_name == NULL)
1041 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT);
1043 if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) {
1044 struct md_op_spec *sp = &info->mti_spec;
1045 sp->u.sp_ea.eadata = req_capsule_client_get(pill,
1047 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill,
1050 if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)
1051 sp->u.sp_ea.no_lov_create = 1;
1057 typedef int (*reint_unpacker)(struct mdt_thread_info *info);
1059 static reint_unpacker mdt_reint_unpackers[REINT_MAX] = {
1060 [REINT_SETATTR] = mdt_setattr_unpack,
1061 [REINT_CREATE] = mdt_create_unpack,
1062 [REINT_LINK] = mdt_link_unpack,
1063 [REINT_UNLINK] = mdt_unlink_unpack,
1064 [REINT_RENAME] = mdt_rename_unpack,
1065 [REINT_OPEN] = mdt_open_unpack
1068 int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op)
1073 memset(&info->mti_rr, 0, sizeof(info->mti_rr));
1074 if (op < REINT_MAX && mdt_reint_unpackers[op] != NULL) {
1075 info->mti_rr.rr_opcode = op;
1076 rc = mdt_reint_unpackers[op](info);
1078 CERROR("Unexpected opcode %d\n", op);