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 CDEBUG(D_SEC, "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 CDEBUG(D_SEC, "remote client %s: auth/mapped uid %u/%u "
124 "while client claims %u:%u/%u:%u\n",
125 libcfs_nid2str(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 CDEBUG(D_SEC, "local client %s: auth uid %u "
134 "while client claims %u:%u/%u:%u\n",
135 libcfs_nid2str(peernid), req->rq_auth_uid,
136 pud->pud_uid, pud->pud_gid,
137 pud->pud_fsuid, pud->pud_fsgid);
142 if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
143 if (med->med_rmtclient) {
144 CDEBUG(D_SEC, "remote client must run with identity_get "
148 ucred->mu_identity = NULL;
149 perm = CFS_SETUID_PERM | CFS_SETGID_PERM |
153 struct md_identity *identity;
155 identity = mdt_identity_get(mdt->mdt_identity_cache,
157 if (IS_ERR(identity)) {
158 if (unlikely(PTR_ERR(identity) == -EREMCHG &&
159 !med->med_rmtclient)) {
160 ucred->mu_identity = NULL;
161 perm = CFS_SETUID_PERM | CFS_SETGID_PERM |
164 CDEBUG(D_SEC, "Deny access without identity: uid %u\n",
169 ucred->mu_identity = identity;
170 perm = mdt_identity_get_perm(ucred->mu_identity,
176 /* find out the setuid/setgid attempt */
177 setuid = (pud->pud_uid != pud->pud_fsuid);
178 setgid = ((pud->pud_gid != pud->pud_fsgid) ||
179 (ucred->mu_identity &&
180 (pud->pud_gid != ucred->mu_identity->mi_gid)));
182 /* check permission of setuid */
183 if (setuid && !(perm & CFS_SETUID_PERM)) {
184 CDEBUG(D_SEC, "mdt blocked setuid attempt (%u -> %u) from %s\n",
185 pud->pud_uid, pud->pud_fsuid, libcfs_nid2str(peernid));
186 GOTO(out, rc = -EACCES);
189 /* check permission of setgid */
190 if (setgid && !(perm & CFS_SETGID_PERM)) {
191 CDEBUG(D_SEC, "mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
192 "from %s\n", pud->pud_uid, pud->pud_gid,
193 pud->pud_fsuid, pud->pud_fsgid,
194 ucred->mu_identity->mi_gid, libcfs_nid2str(peernid));
195 GOTO(out, rc = -EACCES);
199 * NB: remote client not allowed to setgroups anyway.
201 if (!med->med_rmtclient && perm & CFS_SETGRP_PERM) {
202 if (pud->pud_ngroups) {
203 /* setgroups for local client */
204 ucred->mu_ginfo = groups_alloc(pud->pud_ngroups);
205 if (!ucred->mu_ginfo) {
206 CERROR("failed to alloc %d groups\n",
208 GOTO(out, rc = -ENOMEM);
211 lustre_groups_from_list(ucred->mu_ginfo,
213 lustre_groups_sort(ucred->mu_ginfo);
215 ucred->mu_ginfo = NULL;
218 ucred->mu_suppgids[0] = -1;
219 ucred->mu_suppgids[1] = -1;
220 ucred->mu_ginfo = NULL;
223 ucred->mu_uid = pud->pud_uid;
224 ucred->mu_gid = pud->pud_gid;
225 ucred->mu_fsuid = pud->pud_fsuid;
226 ucred->mu_fsgid = pud->pud_fsgid;
228 /* XXX: need to process root_squash here. */
229 mdt_root_squash(info);
231 /* remove fs privilege for non-root user */
233 ucred->mu_cap = pud->pud_cap & ~CAP_FS_MASK;
235 ucred->mu_cap = pud->pud_cap;
236 ucred->mu_valid = UCRED_NEW;
242 if (ucred->mu_ginfo) {
243 groups_free(ucred->mu_ginfo);
244 ucred->mu_ginfo = NULL;
246 if (ucred->mu_identity) {
247 mdt_identity_put(mdt->mdt_identity_cache,
249 ucred->mu_identity = NULL;
256 int mdt_check_ucred(struct mdt_thread_info *info)
258 struct ptlrpc_request *req = mdt_info_req(info);
259 struct mdt_export_data *med = mdt_req2med(req);
260 struct mdt_device *mdt = info->mti_mdt;
261 struct ptlrpc_user_desc *pud = req->rq_user_desc;
262 struct md_ucred *ucred = mdt_ucred(info);
263 struct md_identity *identity = NULL;
264 lnet_nid_t peernid = req->rq_peer.nid;
272 if ((ucred->mu_valid == UCRED_OLD) || (ucred->mu_valid == UCRED_NEW))
275 if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
278 /* sanity check: if we use strong authentication, we expect the
279 * uid which client claimed is true */
280 if (med->med_rmtclient) {
281 if (req->rq_auth_mapped_uid == INVALID_UID) {
282 CDEBUG(D_SEC, "remote user not mapped, deny access!\n");
286 if (ptlrpc_user_desc_do_idmap(req, pud))
289 if (req->rq_auth_mapped_uid != pud->pud_uid) {
290 CDEBUG(D_SEC, "remote client %s: auth/mapped uid %u/%u "
291 "while client claims %u:%u/%u:%u\n",
292 libcfs_nid2str(peernid), req->rq_auth_uid,
293 req->rq_auth_mapped_uid,
294 pud->pud_uid, pud->pud_gid,
295 pud->pud_fsuid, pud->pud_fsgid);
299 if (req->rq_auth_uid != pud->pud_uid) {
300 CDEBUG(D_SEC, "local client %s: auth uid %u "
301 "while client claims %u:%u/%u:%u\n",
302 libcfs_nid2str(peernid), req->rq_auth_uid,
303 pud->pud_uid, pud->pud_gid,
304 pud->pud_fsuid, pud->pud_fsgid);
309 if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
310 if (med->med_rmtclient) {
311 CDEBUG(D_SEC, "remote client must run with identity_get "
318 identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid);
319 if (IS_ERR(identity)) {
320 if (unlikely(PTR_ERR(identity) == -EREMCHG &&
321 !med->med_rmtclient)) {
324 CDEBUG(D_SEC, "Deny access without identity: uid %u\n",
330 perm = mdt_identity_get_perm(identity, med->med_rmtclient, peernid);
331 /* find out the setuid/setgid attempt */
332 setuid = (pud->pud_uid != pud->pud_fsuid);
333 setgid = (pud->pud_gid != pud->pud_fsgid ||
334 pud->pud_gid != identity->mi_gid);
336 /* check permission of setuid */
337 if (setuid && !(perm & CFS_SETUID_PERM)) {
338 CDEBUG(D_SEC, "mdt blocked setuid attempt (%u -> %u) from %s\n",
339 pud->pud_uid, pud->pud_fsuid, libcfs_nid2str(peernid));
340 GOTO(out, rc = -EACCES);
343 /* check permission of setgid */
344 if (setgid && !(perm & CFS_SETGID_PERM)) {
345 CDEBUG(D_SEC, "mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
346 "from %s\n", pud->pud_uid, pud->pud_gid,
347 pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid,
348 libcfs_nid2str(peernid));
349 GOTO(out, rc = -EACCES);
355 mdt_identity_put(mdt->mdt_identity_cache, identity);
359 static int old_init_ucred(struct mdt_thread_info *info,
360 struct mdt_body *body)
362 struct md_ucred *uc = mdt_ucred(info);
363 struct mdt_device *mdt = info->mti_mdt;
364 struct md_identity *identity = NULL;
368 uc->mu_valid = UCRED_INVALID;
369 uc->mu_o_uid = uc->mu_uid = body->uid;
370 uc->mu_o_gid = uc->mu_gid = body->gid;
371 uc->mu_o_fsuid = uc->mu_fsuid = body->fsuid;
372 uc->mu_o_fsgid = uc->mu_fsgid = body->fsgid;
373 uc->mu_suppgids[0] = body->suppgid;
374 uc->mu_suppgids[1] = -1;
376 if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
377 identity = mdt_identity_get(mdt->mdt_identity_cache,
379 if (IS_ERR(identity)) {
380 if (unlikely(PTR_ERR(identity) == -EREMCHG)) {
383 CDEBUG(D_SEC, "Deny access without identity: "
384 "uid %u\n", uc->mu_fsuid);
389 uc->mu_identity = identity;
391 /* XXX: need to process root_squash here. */
392 mdt_root_squash(info);
394 /* remove fs privilege for non-root user */
396 uc->mu_cap = body->capability & ~CAP_FS_MASK;
398 uc->mu_cap = body->capability;
399 uc->mu_valid = UCRED_OLD;
404 static int old_init_ucred_reint(struct mdt_thread_info *info)
406 struct md_ucred *uc = mdt_ucred(info);
407 struct mdt_device *mdt = info->mti_mdt;
408 struct md_identity *identity = NULL;
412 uc->mu_valid = UCRED_INVALID;
413 uc->mu_o_uid = uc->mu_o_fsuid = uc->mu_uid = uc->mu_fsuid;
414 uc->mu_o_gid = uc->mu_o_fsgid = uc->mu_gid = uc->mu_fsgid;
416 if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
417 identity = mdt_identity_get(mdt->mdt_identity_cache,
419 if (IS_ERR(identity)) {
420 if (unlikely(PTR_ERR(identity) == -EREMCHG)) {
423 CDEBUG(D_SEC, "Deny access without identity: "
424 "uid %u\n", uc->mu_fsuid);
429 uc->mu_identity = identity;
431 /* XXX: need to process root_squash here. */
432 mdt_root_squash(info);
434 /* remove fs privilege for non-root user */
436 uc->mu_cap &= ~CAP_FS_MASK;
437 uc->mu_valid = UCRED_OLD;
442 int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body)
444 struct ptlrpc_request *req = mdt_info_req(info);
445 struct md_ucred *uc = mdt_ucred(info);
447 if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))
450 mdt_exit_ucred(info);
452 if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
453 return old_init_ucred(info, body);
455 return new_init_ucred(info, BODY_INIT, body);
458 int mdt_init_ucred_reint(struct mdt_thread_info *info)
460 struct ptlrpc_request *req = mdt_info_req(info);
461 struct md_ucred *uc = mdt_ucred(info);
463 if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))
466 mdt_exit_ucred(info);
468 if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
469 return old_init_ucred_reint(info);
471 return new_init_ucred(info, REC_INIT, NULL);
474 /* copied from lov/lov_ea.c, just for debugging, will be removed later */
475 void mdt_dump_lmm(int level, const struct lov_mds_md *lmm)
477 const struct lov_ost_data_v1 *lod;
480 le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count);
482 CDEBUG(level, "objid "LPX64", magic 0x%08X, pattern %#X\n",
483 le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic),
484 le32_to_cpu(lmm->lmm_pattern));
485 CDEBUG(level,"stripe_size=0x%x, stripe_count=0x%x\n",
486 le32_to_cpu(lmm->lmm_stripe_size),
487 le32_to_cpu(lmm->lmm_stripe_count));
488 LASSERT(stripe_count <= (__s16)LOV_MAX_STRIPE_COUNT);
489 for (i = 0, lod = lmm->lmm_objects; i < stripe_count; i++, lod++) {
490 CDEBUG(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n",
491 i, le32_to_cpu(lod->l_ost_idx),
492 le64_to_cpu(lod->l_object_gr),
493 le64_to_cpu(lod->l_object_id));
497 void mdt_shrink_reply(struct mdt_thread_info *info)
499 struct req_capsule *pill = info->mti_pill;
500 struct mdt_body *body;
505 body = req_capsule_server_get(pill, &RMF_MDT_BODY);
506 LASSERT(body != NULL);
508 if (body->valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE | OBD_MD_LINKNAME))
509 md_size = body->eadatasize;
513 acl_size = body->aclsize;
515 CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d"
516 " MDSCAPA = "LPX64", OSSCAPA = "LPX64"\n",
518 body->valid & OBD_MD_FLMDSCAPA,
519 body->valid & OBD_MD_FLOSSCAPA);
523 &RMF_ACL, or &RMF_LOGCOOKIES
524 (optional) &RMF_CAPA1,
525 (optional) &RMF_CAPA2,
526 (optional) something else
529 if (req_capsule_has_field(pill, &RMF_MDT_MD, RCL_SERVER))
530 req_capsule_shrink(pill, &RMF_MDT_MD, md_size,
532 if (req_capsule_has_field(pill, &RMF_ACL, RCL_SERVER))
533 req_capsule_shrink(pill, &RMF_ACL, acl_size, RCL_SERVER);
534 else if (req_capsule_has_field(pill, &RMF_LOGCOOKIES, RCL_SERVER))
535 req_capsule_shrink(pill, &RMF_LOGCOOKIES,
536 acl_size, RCL_SERVER);
538 if (req_capsule_has_field(pill, &RMF_CAPA1, RCL_SERVER) &&
539 !(body->valid & OBD_MD_FLMDSCAPA))
540 req_capsule_shrink(pill, &RMF_CAPA1, 0, RCL_SERVER);
542 if (req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) &&
543 !(body->valid & OBD_MD_FLOSSCAPA))
544 req_capsule_shrink(pill, &RMF_CAPA2, 0, RCL_SERVER);
547 * Some more field should be shrinked if needed.
548 * This should be done by those who added fields to reply message.
554 /* if object is dying, pack the lov/llog data,
555 * parameter info->mti_attr should be valid at this point! */
556 int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo,
557 const struct md_attr *ma)
559 struct mdt_body *repbody;
560 const struct lu_attr *la = &ma->ma_attr;
563 repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
564 LASSERT(repbody != NULL);
566 if (ma->ma_valid & MA_INODE)
567 mdt_pack_attr2body(info, repbody, la, mdt_object_fid(mo));
569 if (ma->ma_valid & MA_LOV) {
572 if (mdt_object_exists(mo) < 0)
573 /* If it is a remote object, and we do not retrieve
574 * EA back unlink reg file*/
577 mode = lu_object_attr(&mo->mot_obj.mo_lu);
579 LASSERT(ma->ma_lmm_size);
580 mdt_dump_lmm(D_INFO, ma->ma_lmm);
581 repbody->eadatasize = ma->ma_lmm_size;
583 repbody->valid |= OBD_MD_FLEASIZE;
584 else if (S_ISDIR(mode))
585 repbody->valid |= OBD_MD_FLDIREA;
590 if (ma->ma_cookie_size && (ma->ma_valid & MA_COOKIE)) {
591 repbody->aclsize = ma->ma_cookie_size;
592 repbody->valid |= OBD_MD_FLCOOKIE;
598 static inline unsigned int attr_unpack(__u64 sa_valid) {
599 unsigned int ia_valid = 0;
601 if (sa_valid & MDS_ATTR_MODE)
602 ia_valid |= ATTR_MODE;
603 if (sa_valid & MDS_ATTR_UID)
604 ia_valid |= ATTR_UID;
605 if (sa_valid & MDS_ATTR_GID)
606 ia_valid |= ATTR_GID;
607 if (sa_valid & MDS_ATTR_SIZE)
608 ia_valid |= ATTR_SIZE;
609 if (sa_valid & MDS_ATTR_ATIME)
610 ia_valid |= ATTR_ATIME;
611 if (sa_valid & MDS_ATTR_MTIME)
612 ia_valid |= ATTR_MTIME;
613 if (sa_valid & MDS_ATTR_CTIME)
614 ia_valid |= ATTR_CTIME;
615 if (sa_valid & MDS_ATTR_ATIME_SET)
616 ia_valid |= ATTR_ATIME_SET;
617 if (sa_valid & MDS_ATTR_MTIME_SET)
618 ia_valid |= ATTR_MTIME_SET;
619 if (sa_valid & MDS_ATTR_FORCE)
620 ia_valid |= ATTR_FORCE;
621 if (sa_valid & MDS_ATTR_ATTR_FLAG)
622 ia_valid |= ATTR_ATTR_FLAG;
623 if (sa_valid & MDS_ATTR_KILL_SUID)
624 ia_valid |= ATTR_KILL_SUID;
625 if (sa_valid & MDS_ATTR_KILL_SGID)
626 ia_valid |= ATTR_KILL_SGID;
627 if (sa_valid & MDS_ATTR_CTIME_SET)
628 ia_valid |= ATTR_CTIME_SET;
629 if (sa_valid & MDS_ATTR_FROM_OPEN)
630 ia_valid |= ATTR_FROM_OPEN;
631 if (sa_valid & MDS_ATTR_BLOCKS)
632 ia_valid |= ATTR_BLOCKS;
633 if (sa_valid & MDS_OPEN_OWNEROVERRIDE)
634 ia_valid |= MDS_OPEN_OWNEROVERRIDE;
638 static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
652 if (in & ATTR_BLOCKS)
655 if (in & ATTR_FROM_OPEN)
656 rr->rr_flags |= MRF_SETATTR_LOCKED;
658 if (in & ATTR_ATIME_SET)
661 if (in & ATTR_CTIME_SET)
664 if (in & ATTR_MTIME_SET)
667 if (in & ATTR_ATTR_FLAG)
670 if (in & MDS_OPEN_OWNEROVERRIDE)
671 out |= MDS_OPEN_OWNEROVERRIDE;
673 /*XXX need ATTR_RAW?*/
674 in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
675 ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
676 ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
677 ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE);
679 CERROR("Unknown attr bits: %#llx\n", in);
684 static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
686 struct md_ucred *uc = mdt_ucred(info);
687 struct md_attr *ma = &info->mti_attr;
688 struct lu_attr *la = &ma->ma_attr;
689 struct req_capsule *pill = info->mti_pill;
690 struct mdt_reint_record *rr = &info->mti_rr;
691 struct mdt_rec_setattr *rec;
694 CLASSERT(sizeof(struct mdt_rec_setattr)== sizeof(struct mdt_rec_reint));
695 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
699 uc->mu_fsuid = rec->sa_fsuid;
700 uc->mu_fsgid = rec->sa_fsgid;
701 uc->mu_cap = rec->sa_cap;
702 uc->mu_suppgids[0] = rec->sa_suppgid;
703 uc->mu_suppgids[1] = -1;
705 rr->rr_fid1 = &rec->sa_fid;
706 la->la_valid = mdt_attr_valid_xlate(attr_unpack(rec->sa_valid), rr, ma);
707 la->la_mode = rec->sa_mode;
708 la->la_flags = rec->sa_attr_flags;
709 la->la_uid = rec->sa_uid;
710 la->la_gid = rec->sa_gid;
711 la->la_size = rec->sa_size;
712 la->la_blocks = rec->sa_blocks;
713 la->la_ctime = rec->sa_ctime;
714 la->la_atime = rec->sa_atime;
715 la->la_mtime = rec->sa_mtime;
716 ma->ma_valid = MA_INODE;
718 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
719 mdt_set_capainfo(info, 0, rr->rr_fid1,
720 req_capsule_client_get(pill, &RMF_CAPA1));
725 static int mdt_epoch_unpack(struct mdt_thread_info *info)
727 struct req_capsule *pill = info->mti_pill;
730 if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT))
731 info->mti_epoch = req_capsule_client_get(pill, &RMF_MDT_EPOCH);
733 info->mti_epoch = NULL;
734 RETURN(info->mti_epoch == NULL ? -EFAULT : 0);
737 static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) {
738 struct req_capsule *pill = info->mti_pill;
740 if (req_capsule_get_size(pill, &RMF_DLM_REQ, RCL_CLIENT)) {
741 info->mti_dlm_req = req_capsule_client_get(pill, &RMF_DLM_REQ);
742 if (info->mti_dlm_req == NULL)
749 static int mdt_setattr_unpack(struct mdt_thread_info *info)
751 struct md_attr *ma = &info->mti_attr;
752 struct req_capsule *pill = info->mti_pill;
756 rc = mdt_setattr_unpack_rec(info);
760 /* Epoch may be absent */
761 mdt_epoch_unpack(info);
763 ma->ma_lmm_size = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT);
764 if (ma->ma_lmm_size) {
765 ma->ma_lmm = req_capsule_client_get(pill, &RMF_EADATA);
766 ma->ma_valid |= MA_LOV;
769 ma->ma_cookie_size = req_capsule_get_size(pill, &RMF_LOGCOOKIES,
771 if (ma->ma_cookie_size) {
772 ma->ma_cookie = req_capsule_client_get(pill, &RMF_LOGCOOKIES);
773 ma->ma_valid |= MA_COOKIE;
776 rc = mdt_dlmreq_unpack(info);
780 int mdt_close_unpack(struct mdt_thread_info *info)
785 rc = mdt_epoch_unpack(info);
789 RETURN(mdt_setattr_unpack_rec(info));
792 static int mdt_create_unpack(struct mdt_thread_info *info)
794 struct md_ucred *uc = mdt_ucred(info);
795 struct mdt_rec_create *rec;
796 struct lu_attr *attr = &info->mti_attr.ma_attr;
797 struct mdt_reint_record *rr = &info->mti_rr;
798 struct req_capsule *pill = info->mti_pill;
799 struct md_op_spec *sp = &info->mti_spec;
803 CLASSERT(sizeof(struct mdt_rec_create) == sizeof(struct mdt_rec_reint));
804 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
808 uc->mu_fsuid = rec->cr_fsuid;
809 uc->mu_fsgid = rec->cr_fsgid;
810 uc->mu_cap = rec->cr_cap;
811 uc->mu_suppgids[0] = rec->cr_suppgid1;
812 uc->mu_suppgids[1] = -1;
814 rr->rr_fid1 = &rec->cr_fid1;
815 rr->rr_fid2 = &rec->cr_fid2;
816 attr->la_mode = rec->cr_mode;
817 attr->la_rdev = rec->cr_rdev;
818 attr->la_uid = rec->cr_fsuid;
819 attr->la_gid = rec->cr_fsgid;
820 attr->la_ctime = rec->cr_time;
821 attr->la_mtime = rec->cr_time;
822 attr->la_atime = rec->cr_time;
823 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
824 LA_CTIME | LA_MTIME | LA_ATIME;
825 memset(&sp->u, 0, sizeof(sp->u));
826 sp->sp_cr_flags = rec->cr_flags;
827 sp->sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
828 info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
830 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
831 mdt_set_capainfo(info, 0, rr->rr_fid1,
832 req_capsule_client_get(pill, &RMF_CAPA1));
833 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
835 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
836 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
837 LASSERT(rr->rr_name && rr->rr_namelen > 0);
839 #ifdef CONFIG_FS_POSIX_ACL
840 if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) {
841 if (S_ISDIR(attr->la_mode))
842 sp->u.sp_pfid = rr->rr_fid1;
843 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
844 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
846 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
847 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
849 sp->u.sp_ea.fid = rr->rr_fid1;
853 if (S_ISDIR(attr->la_mode)) {
854 /* pass parent fid for cross-ref cases */
855 sp->u.sp_pfid = rr->rr_fid1;
856 if (sp->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
857 /* create salve object req, need
858 * unpack split ea here
860 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SLAVE);
861 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
863 sp->u.sp_ea.eadata = req_capsule_client_get(pill,
865 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill,
868 sp->u.sp_ea.fid = rr->rr_fid1;
871 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
872 } else if (S_ISLNK(attr->la_mode)) {
873 const char *tgt = NULL;
875 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM);
876 if (req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT)) {
877 tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
878 sp->u.sp_symname = tgt;
883 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
885 rc = mdt_dlmreq_unpack(info);
889 static int mdt_link_unpack(struct mdt_thread_info *info)
891 struct md_ucred *uc = mdt_ucred(info);
892 struct mdt_rec_link *rec;
893 struct lu_attr *attr = &info->mti_attr.ma_attr;
894 struct mdt_reint_record *rr = &info->mti_rr;
895 struct req_capsule *pill = info->mti_pill;
899 CLASSERT(sizeof(struct mdt_rec_link) == sizeof(struct mdt_rec_reint));
900 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
904 uc->mu_fsuid = rec->lk_fsuid;
905 uc->mu_fsgid = rec->lk_fsgid;
906 uc->mu_cap = rec->lk_cap;
907 uc->mu_suppgids[0] = rec->lk_suppgid1;
908 uc->mu_suppgids[1] = rec->lk_suppgid2;
910 attr->la_uid = rec->lk_fsuid;
911 attr->la_gid = rec->lk_fsgid;
912 rr->rr_fid1 = &rec->lk_fid1;
913 rr->rr_fid2 = &rec->lk_fid2;
914 attr->la_ctime = rec->lk_time;
915 attr->la_mtime = rec->lk_time;
916 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;
918 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
919 mdt_set_capainfo(info, 0, rr->rr_fid1,
920 req_capsule_client_get(pill, &RMF_CAPA1));
921 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
922 mdt_set_capainfo(info, 1, rr->rr_fid2,
923 req_capsule_client_get(pill, &RMF_CAPA2));
925 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
926 if (rr->rr_name == NULL)
928 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
929 LASSERT(rr->rr_namelen > 0);
930 info->mti_spec.sp_ck_split = !!(rec->lk_bias & MDS_CHECK_SPLIT);
931 info->mti_cross_ref = !!(rec->lk_bias & MDS_CROSS_REF);
933 rc = mdt_dlmreq_unpack(info);
937 static int mdt_unlink_unpack(struct mdt_thread_info *info)
939 struct md_ucred *uc = mdt_ucred(info);
940 struct mdt_rec_unlink *rec;
941 struct md_attr *ma = &info->mti_attr;
942 struct lu_attr *attr = &info->mti_attr.ma_attr;
943 struct mdt_reint_record *rr = &info->mti_rr;
944 struct req_capsule *pill = info->mti_pill;
948 CLASSERT(sizeof(struct mdt_rec_unlink) == sizeof(struct mdt_rec_reint));
949 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
953 uc->mu_fsuid = rec->ul_fsuid;
954 uc->mu_fsgid = rec->ul_fsgid;
955 uc->mu_cap = rec->ul_cap;
956 uc->mu_suppgids[0] = rec->ul_suppgid1;
957 uc->mu_suppgids[1] = -1;
959 attr->la_uid = rec->ul_fsuid;
960 attr->la_gid = rec->ul_fsgid;
961 rr->rr_fid1 = &rec->ul_fid1;
962 rr->rr_fid2 = &rec->ul_fid2;
963 attr->la_ctime = rec->ul_time;
964 attr->la_mtime = rec->ul_time;
965 attr->la_mode = rec->ul_mode;
966 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
968 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
969 mdt_set_capainfo(info, 0, rr->rr_fid1,
970 req_capsule_client_get(pill, &RMF_CAPA1));
972 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
973 if (rr->rr_name == NULL)
975 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
976 LASSERT(rr->rr_namelen > 0);
977 info->mti_spec.sp_ck_split = !!(rec->ul_bias & MDS_CHECK_SPLIT);
978 info->mti_cross_ref = !!(rec->ul_bias & MDS_CROSS_REF);
979 if (rec->ul_bias & MDS_VTX_BYPASS)
980 ma->ma_attr_flags |= MDS_VTX_BYPASS;
982 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
984 rc = mdt_dlmreq_unpack(info);
988 static int mdt_rename_unpack(struct mdt_thread_info *info)
990 struct md_ucred *uc = mdt_ucred(info);
991 struct mdt_rec_rename *rec;
992 struct md_attr *ma = &info->mti_attr;
993 struct lu_attr *attr = &info->mti_attr.ma_attr;
994 struct mdt_reint_record *rr = &info->mti_rr;
995 struct req_capsule *pill = info->mti_pill;
999 CLASSERT(sizeof(struct mdt_rec_rename) == sizeof(struct mdt_rec_reint));
1000 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
1004 uc->mu_fsuid = rec->rn_fsuid;
1005 uc->mu_fsgid = rec->rn_fsgid;
1006 uc->mu_cap = rec->rn_cap;
1007 uc->mu_suppgids[0] = rec->rn_suppgid1;
1008 uc->mu_suppgids[1] = rec->rn_suppgid2;
1010 attr->la_uid = rec->rn_fsuid;
1011 attr->la_gid = rec->rn_fsgid;
1012 rr->rr_fid1 = &rec->rn_fid1;
1013 rr->rr_fid2 = &rec->rn_fid2;
1014 attr->la_ctime = rec->rn_time;
1015 attr->la_mtime = rec->rn_time;
1016 /* rename_tgt contains the mode already */
1017 attr->la_mode = rec->rn_mode;
1018 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
1020 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1021 mdt_set_capainfo(info, 0, rr->rr_fid1,
1022 req_capsule_client_get(pill, &RMF_CAPA1));
1023 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
1024 mdt_set_capainfo(info, 1, rr->rr_fid2,
1025 req_capsule_client_get(pill, &RMF_CAPA2));
1027 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1028 rr->rr_tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
1029 if (rr->rr_name == NULL || rr->rr_tgt == NULL)
1031 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1032 LASSERT(rr->rr_namelen > 0);
1033 rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT) - 1;
1034 LASSERT(rr->rr_tgtlen > 0);
1035 info->mti_spec.sp_ck_split = !!(rec->rn_bias & MDS_CHECK_SPLIT);
1036 info->mti_cross_ref = !!(rec->rn_bias & MDS_CROSS_REF);
1037 if (rec->rn_bias & MDS_VTX_BYPASS)
1038 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1040 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1042 rc = mdt_dlmreq_unpack(info);
1046 static int mdt_open_unpack(struct mdt_thread_info *info)
1048 struct md_ucred *uc = mdt_ucred(info);
1049 struct mdt_rec_create *rec;
1050 struct lu_attr *attr = &info->mti_attr.ma_attr;
1051 struct req_capsule *pill = info->mti_pill;
1052 struct mdt_reint_record *rr = &info->mti_rr;
1053 struct ptlrpc_request *req = mdt_info_req(info);
1054 struct md_op_spec *sp = &info->mti_spec;
1057 CLASSERT(sizeof(struct mdt_rec_create) == sizeof(struct mdt_rec_reint));
1058 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
1062 uc->mu_fsuid = rec->cr_fsuid;
1063 uc->mu_fsgid = rec->cr_fsgid;
1064 uc->mu_cap = rec->cr_cap;
1065 uc->mu_suppgids[0] = rec->cr_suppgid1;
1066 uc->mu_suppgids[1] = rec->cr_suppgid2;
1068 rr->rr_fid1 = &rec->cr_fid1;
1069 rr->rr_fid2 = &rec->cr_fid2;
1070 rr->rr_handle = &rec->cr_old_handle;
1071 attr->la_mode = rec->cr_mode;
1072 attr->la_rdev = rec->cr_rdev;
1073 attr->la_uid = rec->cr_fsuid;
1074 attr->la_gid = rec->cr_fsgid;
1075 attr->la_ctime = rec->cr_time;
1076 attr->la_mtime = rec->cr_time;
1077 attr->la_atime = rec->cr_time;
1078 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
1079 LA_CTIME | LA_MTIME | LA_ATIME;
1080 memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u));
1081 info->mti_spec.sp_cr_flags = rec->cr_flags;
1082 info->mti_replayepoch = rec->cr_ioepoch;
1084 info->mti_spec.sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
1085 info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
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 ((lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) &&
1091 (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))) {
1093 mdt_set_capainfo(info, 1, rr->rr_fid2,
1094 req_capsule_client_get(pill, &RMF_CAPA2));
1097 * FIXME: capa in replay open request might have expired,
1098 * bypass capa check. Security hole?
1100 mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
1101 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
1105 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1106 if (rr->rr_name == NULL)
1108 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1110 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
1112 if (sp->u.sp_ea.eadatalen) {
1113 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
1114 if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)
1115 sp->u.sp_ea.no_lov_create = 1;
1121 static int mdt_setxattr_unpack(struct mdt_thread_info *info)
1123 struct mdt_reint_record *rr = &info->mti_rr;
1124 struct md_ucred *uc = mdt_ucred(info);
1125 struct lu_attr *attr = &info->mti_attr.ma_attr;
1126 struct req_capsule *pill = info->mti_pill;
1127 struct mdt_rec_setxattr *rec;
1131 CLASSERT(sizeof(struct mdt_rec_setxattr) ==
1132 sizeof(struct mdt_rec_reint));
1134 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
1138 uc->mu_fsuid = rec->sx_fsuid;
1139 uc->mu_fsgid = rec->sx_fsgid;
1140 uc->mu_cap = rec->sx_cap;
1141 uc->mu_suppgids[0] = uc->mu_suppgids[1] = -1;
1143 rr->rr_opcode = rec->sx_opcode;
1144 rr->rr_fid1 = &rec->sx_fid;
1145 attr->la_valid = rec->sx_valid;
1146 attr->la_size = rec->sx_size;
1147 attr->la_flags = rec->sx_flags;
1149 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1150 mdt_set_capainfo(info, 0, rr->rr_fid1,
1151 req_capsule_client_get(pill, &RMF_CAPA1));
1153 mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
1155 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1156 if (rr->rr_name == NULL)
1158 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1159 LASSERT(rr->rr_namelen > 0);
1161 rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT);
1162 if (rr->rr_eadatalen > 0) {
1163 rr->rr_eadata = req_capsule_client_get(pill, &RMF_EADATA);
1164 if (rr->rr_eadata == NULL)
1172 typedef int (*reint_unpacker)(struct mdt_thread_info *info);
1174 static reint_unpacker mdt_reint_unpackers[REINT_MAX] = {
1175 [REINT_SETATTR] = mdt_setattr_unpack,
1176 [REINT_CREATE] = mdt_create_unpack,
1177 [REINT_LINK] = mdt_link_unpack,
1178 [REINT_UNLINK] = mdt_unlink_unpack,
1179 [REINT_RENAME] = mdt_rename_unpack,
1180 [REINT_OPEN] = mdt_open_unpack,
1181 [REINT_SETXATTR] = mdt_setxattr_unpack
1184 int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op)
1189 memset(&info->mti_rr, 0, sizeof(info->mti_rr));
1190 if (op < REINT_MAX && mdt_reint_unpackers[op] != NULL) {
1191 info->mti_rr.rr_opcode = op;
1192 rc = mdt_reint_unpackers[op](info);
1194 CERROR("Unexpected opcode %d\n", op);