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 inline unsigned int attr_unpack(__u64 sa_valid) {
671 unsigned int ia_valid = 0;
673 if (sa_valid & MDS_ATTR_MODE)
674 ia_valid |= ATTR_MODE;
675 if (sa_valid & MDS_ATTR_UID)
676 ia_valid |= ATTR_UID;
677 if (sa_valid & MDS_ATTR_GID)
678 ia_valid |= ATTR_GID;
679 if (sa_valid & MDS_ATTR_SIZE)
680 ia_valid |= ATTR_SIZE;
681 if (sa_valid & MDS_ATTR_ATIME)
682 ia_valid |= ATTR_ATIME;
683 if (sa_valid & MDS_ATTR_MTIME)
684 ia_valid |= ATTR_MTIME;
685 if (sa_valid & MDS_ATTR_CTIME)
686 ia_valid |= ATTR_CTIME;
687 if (sa_valid & MDS_ATTR_ATIME_SET)
688 ia_valid |= ATTR_ATIME_SET;
689 if (sa_valid & MDS_ATTR_MTIME_SET)
690 ia_valid |= ATTR_MTIME_SET;
691 if (sa_valid & MDS_ATTR_FORCE)
692 ia_valid |= ATTR_FORCE;
693 if (sa_valid & MDS_ATTR_ATTR_FLAG)
694 ia_valid |= ATTR_ATTR_FLAG;
695 if (sa_valid & MDS_ATTR_KILL_SUID)
696 ia_valid |= ATTR_KILL_SUID;
697 if (sa_valid & MDS_ATTR_KILL_SGID)
698 ia_valid |= ATTR_KILL_SGID;
699 if (sa_valid & MDS_ATTR_CTIME_SET)
700 ia_valid |= ATTR_CTIME_SET;
701 if (sa_valid & MDS_ATTR_FROM_OPEN)
702 ia_valid |= ATTR_FROM_OPEN;
703 if (sa_valid & MDS_ATTR_BLOCKS)
704 ia_valid |= ATTR_BLOCKS;
705 if (sa_valid & MDS_OPEN_OWNEROVERRIDE)
706 ia_valid |= MDS_OPEN_OWNEROVERRIDE;
710 static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
724 if (in & ATTR_BLOCKS)
727 if (in & ATTR_FROM_OPEN)
728 rr->rr_flags |= MRF_SETATTR_LOCKED;
730 if (in & ATTR_ATIME_SET)
733 if (in & ATTR_CTIME_SET)
736 if (in & ATTR_MTIME_SET)
739 if (in & ATTR_ATTR_FLAG)
742 if (in & MDS_OPEN_OWNEROVERRIDE)
743 out |= MDS_OPEN_OWNEROVERRIDE;
745 /*XXX need ATTR_RAW?*/
746 in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
747 ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
748 ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
749 ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE);
751 CERROR("Unknown attr bits: %#llx\n", in);
756 static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
758 struct md_ucred *uc = mdt_ucred(info);
759 struct md_attr *ma = &info->mti_attr;
760 struct lu_attr *la = &ma->ma_attr;
761 struct req_capsule *pill = &info->mti_pill;
762 struct mdt_reint_record *rr = &info->mti_rr;
763 struct mdt_rec_setattr *rec;
766 rec = req_capsule_client_get(pill, &RMF_REC_SETATTR);
770 uc->mu_fsuid = rec->sa_fsuid;
771 uc->mu_fsgid = rec->sa_fsgid;
772 uc->mu_cap = rec->sa_cap;
773 uc->mu_suppgids[0] = rec->sa_suppgid;
774 uc->mu_suppgids[1] = -1;
776 rr->rr_fid1 = &rec->sa_fid;
777 la->la_valid = mdt_attr_valid_xlate(attr_unpack(rec->sa_valid), rr, ma);
778 la->la_mode = rec->sa_mode;
779 la->la_flags = rec->sa_attr_flags;
780 la->la_uid = rec->sa_uid;
781 la->la_gid = rec->sa_gid;
782 la->la_size = rec->sa_size;
783 la->la_blocks = rec->sa_blocks;
784 la->la_ctime = rec->sa_ctime;
785 la->la_atime = rec->sa_atime;
786 la->la_mtime = rec->sa_mtime;
787 ma->ma_valid = MA_INODE;
789 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
790 mdt_set_capainfo(info, 0, rr->rr_fid1,
791 req_capsule_client_get(pill, &RMF_CAPA1));
796 static int mdt_epoch_unpack(struct mdt_thread_info *info)
798 struct req_capsule *pill = &info->mti_pill;
801 if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT))
802 info->mti_epoch = req_capsule_client_get(pill, &RMF_MDT_EPOCH);
804 info->mti_epoch = NULL;
805 RETURN(info->mti_epoch == NULL ? -EFAULT : 0);
808 static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) {
809 struct req_capsule *pill = &info->mti_pill;
811 if (req_capsule_get_size(pill, &RMF_DLM_REQ, RCL_CLIENT)) {
812 info->mti_dlm_req = req_capsule_client_get(pill, &RMF_DLM_REQ);
813 if (info->mti_dlm_req == NULL)
820 static int mdt_setattr_unpack(struct mdt_thread_info *info)
822 struct md_attr *ma = &info->mti_attr;
823 struct req_capsule *pill = &info->mti_pill;
827 rc = mdt_setattr_unpack_rec(info);
831 /* Epoch may be absent */
832 mdt_epoch_unpack(info);
834 ma->ma_lmm_size = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT);
835 if (ma->ma_lmm_size) {
836 ma->ma_lmm = req_capsule_client_get(pill, &RMF_EADATA);
837 ma->ma_valid |= MA_LOV;
840 ma->ma_cookie_size = req_capsule_get_size(pill, &RMF_LOGCOOKIES,
842 if (ma->ma_cookie_size) {
843 ma->ma_cookie = req_capsule_client_get(pill, &RMF_LOGCOOKIES);
844 ma->ma_valid |= MA_COOKIE;
847 rc = mdt_dlmreq_unpack(info);
851 int mdt_close_unpack(struct mdt_thread_info *info)
856 rc = mdt_epoch_unpack(info);
860 RETURN(mdt_setattr_unpack_rec(info));
863 static int mdt_create_unpack(struct mdt_thread_info *info)
865 struct md_ucred *uc = mdt_ucred(info);
866 struct mdt_rec_create *rec;
867 struct lu_attr *attr = &info->mti_attr.ma_attr;
868 struct mdt_reint_record *rr = &info->mti_rr;
869 struct req_capsule *pill = &info->mti_pill;
870 struct md_op_spec *sp = &info->mti_spec;
874 rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
878 uc->mu_fsuid = rec->cr_fsuid;
879 uc->mu_fsgid = rec->cr_fsgid;
880 uc->mu_cap = rec->cr_cap;
881 uc->mu_suppgids[0] = rec->cr_suppgid1;
882 uc->mu_suppgids[1] = -1;
884 rr->rr_fid1 = &rec->cr_fid1;
885 rr->rr_fid2 = &rec->cr_fid2;
886 attr->la_mode = rec->cr_mode;
887 attr->la_rdev = rec->cr_rdev;
888 attr->la_uid = rec->cr_fsuid;
889 attr->la_gid = rec->cr_fsgid;
890 attr->la_ctime = rec->cr_time;
891 attr->la_mtime = rec->cr_time;
892 attr->la_atime = rec->cr_time;
893 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
894 LA_CTIME | LA_MTIME | LA_ATIME;
895 memset(&sp->u, 0, sizeof(sp->u));
896 sp->sp_cr_flags = rec->cr_flags;
897 sp->sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
898 info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
900 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
901 mdt_set_capainfo(info, 0, rr->rr_fid1,
902 req_capsule_client_get(pill, &RMF_CAPA1));
903 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
905 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
906 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
907 LASSERT(rr->rr_namelen > 0);
909 #ifdef CONFIG_FS_POSIX_ACL
910 if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) {
911 if (S_ISDIR(attr->la_mode))
912 sp->u.sp_pfid = rr->rr_fid1;
913 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
914 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
916 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
917 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
919 sp->u.sp_ea.fid = rr->rr_fid1;
923 if (S_ISDIR(attr->la_mode)) {
924 /* pass parent fid for cross-ref cases */
925 sp->u.sp_pfid = rr->rr_fid1;
926 if (sp->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
927 /* create salve object req, need
928 * unpack split ea here
930 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SLAVE);
931 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
933 sp->u.sp_ea.eadata = req_capsule_client_get(pill,
935 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill,
938 sp->u.sp_ea.fid = rr->rr_fid1;
941 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
942 } else if (S_ISLNK(attr->la_mode)) {
943 const char *tgt = NULL;
945 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM);
946 if (req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT)) {
947 tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
948 sp->u.sp_symname = tgt;
953 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
955 rc = mdt_dlmreq_unpack(info);
959 static int mdt_link_unpack(struct mdt_thread_info *info)
961 struct md_ucred *uc = mdt_ucred(info);
962 struct mdt_rec_link *rec;
963 struct lu_attr *attr = &info->mti_attr.ma_attr;
964 struct mdt_reint_record *rr = &info->mti_rr;
965 struct req_capsule *pill = &info->mti_pill;
969 rec = req_capsule_client_get(pill, &RMF_REC_LINK);
973 uc->mu_fsuid = rec->lk_fsuid;
974 uc->mu_fsgid = rec->lk_fsgid;
975 uc->mu_cap = rec->lk_cap;
976 uc->mu_suppgids[0] = rec->lk_suppgid1;
977 uc->mu_suppgids[1] = rec->lk_suppgid2;
979 attr->la_uid = rec->lk_fsuid;
980 attr->la_gid = rec->lk_fsgid;
981 rr->rr_fid1 = &rec->lk_fid1;
982 rr->rr_fid2 = &rec->lk_fid2;
983 attr->la_ctime = rec->lk_time;
984 attr->la_mtime = rec->lk_time;
985 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;
987 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
988 mdt_set_capainfo(info, 0, rr->rr_fid1,
989 req_capsule_client_get(pill, &RMF_CAPA1));
990 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
991 mdt_set_capainfo(info, 1, rr->rr_fid2,
992 req_capsule_client_get(pill, &RMF_CAPA2));
994 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
995 if (rr->rr_name == NULL)
997 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
998 LASSERT(rr->rr_namelen > 0);
999 info->mti_spec.sp_ck_split = !!(rec->lk_bias & MDS_CHECK_SPLIT);
1000 info->mti_cross_ref = !!(rec->lk_bias & MDS_CROSS_REF);
1002 rc = mdt_dlmreq_unpack(info);
1006 static int mdt_unlink_unpack(struct mdt_thread_info *info)
1008 struct md_ucred *uc = mdt_ucred(info);
1009 struct mdt_rec_unlink *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_UNLINK);
1021 uc->mu_fsuid = rec->ul_fsuid;
1022 uc->mu_fsgid = rec->ul_fsgid;
1023 uc->mu_cap = rec->ul_cap;
1024 uc->mu_suppgids[0] = rec->ul_suppgid;
1025 uc->mu_suppgids[1] = -1;
1027 attr->la_uid = rec->ul_fsuid;
1028 attr->la_gid = rec->ul_fsgid;
1029 rr->rr_fid1 = &rec->ul_fid1;
1030 rr->rr_fid2 = &rec->ul_fid2;
1031 attr->la_ctime = rec->ul_time;
1032 attr->la_mtime = rec->ul_time;
1033 attr->la_mode = rec->ul_mode;
1034 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
1036 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1037 mdt_set_capainfo(info, 0, rr->rr_fid1,
1038 req_capsule_client_get(pill, &RMF_CAPA1));
1040 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1041 if (rr->rr_name == NULL)
1043 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1044 LASSERT(rr->rr_namelen > 0);
1045 info->mti_spec.sp_ck_split = !!(rec->ul_bias & MDS_CHECK_SPLIT);
1046 info->mti_cross_ref = !!(rec->ul_bias & MDS_CROSS_REF);
1047 if (rec->ul_bias & MDS_VTX_BYPASS)
1048 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1050 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1052 rc = mdt_dlmreq_unpack(info);
1056 static int mdt_rename_unpack(struct mdt_thread_info *info)
1058 struct md_ucred *uc = mdt_ucred(info);
1059 struct mdt_rec_rename *rec;
1060 struct md_attr *ma = &info->mti_attr;
1061 struct lu_attr *attr = &info->mti_attr.ma_attr;
1062 struct mdt_reint_record *rr = &info->mti_rr;
1063 struct req_capsule *pill = &info->mti_pill;
1067 rec = req_capsule_client_get(pill, &RMF_REC_RENAME);
1071 uc->mu_fsuid = rec->rn_fsuid;
1072 uc->mu_fsgid = rec->rn_fsgid;
1073 uc->mu_cap = rec->rn_cap;
1074 uc->mu_suppgids[0] = rec->rn_suppgid1;
1075 uc->mu_suppgids[1] = rec->rn_suppgid2;
1077 attr->la_uid = rec->rn_fsuid;
1078 attr->la_gid = rec->rn_fsgid;
1079 rr->rr_fid1 = &rec->rn_fid1;
1080 rr->rr_fid2 = &rec->rn_fid2;
1081 attr->la_ctime = rec->rn_time;
1082 attr->la_mtime = rec->rn_time;
1083 /* rename_tgt contains the mode already */
1084 attr->la_mode = rec->rn_mode;
1085 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
1087 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1088 mdt_set_capainfo(info, 0, rr->rr_fid1,
1089 req_capsule_client_get(pill, &RMF_CAPA1));
1090 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
1091 mdt_set_capainfo(info, 1, rr->rr_fid2,
1092 req_capsule_client_get(pill, &RMF_CAPA2));
1094 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1095 rr->rr_tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
1096 if (rr->rr_name == NULL || rr->rr_tgt == NULL)
1098 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1099 LASSERT(rr->rr_namelen > 0);
1100 rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT) - 1;
1101 LASSERT(rr->rr_tgtlen > 0);
1102 info->mti_spec.sp_ck_split = !!(rec->rn_bias & MDS_CHECK_SPLIT);
1103 info->mti_cross_ref = !!(rec->rn_bias & MDS_CROSS_REF);
1104 if (rec->rn_bias & MDS_VTX_BYPASS)
1105 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1107 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1109 rc = mdt_dlmreq_unpack(info);
1113 static int mdt_open_unpack(struct mdt_thread_info *info)
1115 struct md_ucred *uc = mdt_ucred(info);
1116 struct mdt_rec_create *rec;
1117 struct lu_attr *attr = &info->mti_attr.ma_attr;
1118 struct req_capsule *pill = &info->mti_pill;
1119 struct mdt_reint_record *rr = &info->mti_rr;
1120 struct ptlrpc_request *req = mdt_info_req(info);
1121 struct md_op_spec *sp = &info->mti_spec;
1124 rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
1128 uc->mu_fsuid = rec->cr_fsuid;
1129 uc->mu_fsgid = rec->cr_fsgid;
1130 uc->mu_cap = rec->cr_cap;
1131 uc->mu_suppgids[0] = rec->cr_suppgid1;
1132 uc->mu_suppgids[1] = rec->cr_suppgid2;
1134 rr->rr_fid1 = &rec->cr_fid1;
1135 rr->rr_fid2 = &rec->cr_fid2;
1136 rr->rr_handle = &rec->cr_old_handle;
1137 attr->la_mode = rec->cr_mode;
1138 attr->la_rdev = rec->cr_rdev;
1139 attr->la_uid = rec->cr_fsuid;
1140 attr->la_gid = rec->cr_fsgid;
1141 attr->la_ctime = rec->cr_time;
1142 attr->la_mtime = rec->cr_time;
1143 attr->la_atime = rec->cr_time;
1144 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
1145 LA_CTIME | LA_MTIME | LA_ATIME;
1146 memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u));
1147 info->mti_spec.sp_cr_flags = rec->cr_flags;
1148 info->mti_replayepoch = rec->cr_ioepoch;
1150 info->mti_spec.sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
1151 info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
1153 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1154 mdt_set_capainfo(info, 0, rr->rr_fid1,
1155 req_capsule_client_get(pill, &RMF_CAPA1));
1156 if ((lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) &&
1157 (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))) {
1159 mdt_set_capainfo(info, 1, rr->rr_fid2,
1160 req_capsule_client_get(pill, &RMF_CAPA2));
1163 * FIXME: capa in replay open request might have expired,
1164 * bypass capa check. Security hole?
1166 mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
1167 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
1171 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1172 if (rr->rr_name == NULL)
1174 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1176 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
1178 if (sp->u.sp_ea.eadatalen) {
1179 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
1180 if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)
1181 sp->u.sp_ea.no_lov_create = 1;
1187 typedef int (*reint_unpacker)(struct mdt_thread_info *info);
1189 static reint_unpacker mdt_reint_unpackers[REINT_MAX] = {
1190 [REINT_SETATTR] = mdt_setattr_unpack,
1191 [REINT_CREATE] = mdt_create_unpack,
1192 [REINT_LINK] = mdt_link_unpack,
1193 [REINT_UNLINK] = mdt_unlink_unpack,
1194 [REINT_RENAME] = mdt_rename_unpack,
1195 [REINT_OPEN] = mdt_open_unpack
1198 int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op)
1203 memset(&info->mti_rr, 0, sizeof(info->mti_rr));
1204 if (op < REINT_MAX && mdt_reint_unpackers[op] != NULL) {
1205 info->mti_rr.rr_opcode = op;
1206 rc = mdt_reint_unpackers[op](info);
1208 CERROR("Unexpected opcode %d\n", op);