4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2012, Whamcloud, Inc.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/mdt/mdt_lib.c
38 * Lustre Metadata Target (mdt) request unpacking helper.
40 * Author: Peter Braam <braam@clusterfs.com>
41 * Author: Andreas Dilger <adilger@clusterfs.com>
42 * Author: Phil Schwan <phil@clusterfs.com>
43 * Author: Mike Shaver <shaver@clusterfs.com>
44 * Author: Nikita Danilov <nikita@clusterfs.com>
45 * Author: Huang Hua <huanghua@clusterfs.com>
46 * Author: Fan Yong <fanyong@clusterfs.com>
49 #define DEBUG_SUBSYSTEM S_MDS
51 #include "mdt_internal.h"
52 #include <lnet/lib-lnet.h>
55 typedef enum ucred_init_type {
61 void mdt_exit_ucred(struct mdt_thread_info *info)
63 struct md_ucred *uc = mdt_ucred(info);
64 struct mdt_device *mdt = info->mti_mdt;
66 if (uc->mu_valid != UCRED_INIT) {
67 uc->mu_suppgids[0] = uc->mu_suppgids[1] = -1;
69 cfs_put_group_info(uc->mu_ginfo);
72 if (uc->mu_identity) {
73 mdt_identity_put(mdt->mdt_identity_cache,
75 uc->mu_identity = NULL;
77 uc->mu_valid = UCRED_INIT;
81 static int match_nosquash_list(cfs_rw_semaphore_t *sem,
88 rc = cfs_match_nid(peernid, nidlist);
93 /* root_squash for inter-MDS operations */
94 static int mdt_root_squash(struct mdt_thread_info *info, lnet_nid_t peernid)
96 struct md_ucred *ucred = mdt_ucred(info);
99 if (!info->mti_mdt->mdt_squash_uid || ucred->mu_fsuid)
102 if (match_nosquash_list(&info->mti_mdt->mdt_squash_sem,
103 &info->mti_mdt->mdt_nosquash_nids,
105 CDEBUG(D_OTHER, "%s is in nosquash_nids list\n",
106 libcfs_nid2str(peernid));
110 CDEBUG(D_OTHER, "squash req from %s, (%d:%d/%x)=>(%d:%d/%x)\n",
111 libcfs_nid2str(peernid),
112 ucred->mu_fsuid, ucred->mu_fsgid, ucred->mu_cap,
113 info->mti_mdt->mdt_squash_uid, info->mti_mdt->mdt_squash_gid,
116 ucred->mu_fsuid = info->mti_mdt->mdt_squash_uid;
117 ucred->mu_fsgid = info->mti_mdt->mdt_squash_gid;
119 ucred->mu_suppgids[0] = -1;
120 ucred->mu_suppgids[1] = -1;
125 static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
128 struct ptlrpc_request *req = mdt_info_req(info);
129 struct mdt_device *mdt = info->mti_mdt;
130 struct ptlrpc_user_desc *pud = req->rq_user_desc;
131 struct md_ucred *ucred = mdt_ucred(info);
132 lnet_nid_t peernid = req->rq_peer.nid;
134 __u32 remote = exp_connect_rmtclient(info->mti_exp);
141 LASSERT(req->rq_auth_gss);
142 LASSERT(!req->rq_auth_usr_mdt);
143 LASSERT(req->rq_user_desc);
145 ucred->mu_valid = UCRED_INVALID;
147 ucred->mu_o_uid = pud->pud_uid;
148 ucred->mu_o_gid = pud->pud_gid;
149 ucred->mu_o_fsuid = pud->pud_fsuid;
150 ucred->mu_o_fsgid = pud->pud_fsgid;
152 if (type == BODY_INIT) {
153 struct mdt_body *body = (struct mdt_body *)buf;
155 ucred->mu_suppgids[0] = body->suppgid;
156 ucred->mu_suppgids[1] = -1;
159 /* sanity check: we expect the uid which client claimed is true */
161 if (req->rq_auth_mapped_uid == INVALID_UID) {
162 CDEBUG(D_SEC, "remote user not mapped, deny access!\n");
166 if (ptlrpc_user_desc_do_idmap(req, pud))
169 if (req->rq_auth_mapped_uid != pud->pud_uid) {
170 CDEBUG(D_SEC, "remote client %s: auth/mapped uid %u/%u "
171 "while client claims %u:%u/%u:%u\n",
172 libcfs_nid2str(peernid), req->rq_auth_uid,
173 req->rq_auth_mapped_uid,
174 pud->pud_uid, pud->pud_gid,
175 pud->pud_fsuid, pud->pud_fsgid);
179 if (req->rq_auth_uid != pud->pud_uid) {
180 CDEBUG(D_SEC, "local client %s: auth uid %u "
181 "while client claims %u:%u/%u:%u\n",
182 libcfs_nid2str(peernid), req->rq_auth_uid,
183 pud->pud_uid, pud->pud_gid,
184 pud->pud_fsuid, pud->pud_fsgid);
189 if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
191 CDEBUG(D_SEC, "remote client must run with identity_get "
195 ucred->mu_identity = NULL;
196 perm = CFS_SETUID_PERM | CFS_SETGID_PERM |
200 struct md_identity *identity;
202 identity = mdt_identity_get(mdt->mdt_identity_cache,
204 if (IS_ERR(identity)) {
205 if (unlikely(PTR_ERR(identity) == -EREMCHG &&
207 ucred->mu_identity = NULL;
208 perm = CFS_SETUID_PERM | CFS_SETGID_PERM |
211 CDEBUG(D_SEC, "Deny access without identity: uid %u\n",
216 ucred->mu_identity = identity;
217 perm = mdt_identity_get_perm(ucred->mu_identity,
222 /* find out the setuid/setgid attempt */
223 setuid = (pud->pud_uid != pud->pud_fsuid);
224 setgid = ((pud->pud_gid != pud->pud_fsgid) ||
225 (ucred->mu_identity &&
226 (pud->pud_gid != ucred->mu_identity->mi_gid)));
228 /* check permission of setuid */
229 if (setuid && !(perm & CFS_SETUID_PERM)) {
230 CDEBUG(D_SEC, "mdt blocked setuid attempt (%u -> %u) from %s\n",
231 pud->pud_uid, pud->pud_fsuid, libcfs_nid2str(peernid));
232 GOTO(out, rc = -EACCES);
235 /* check permission of setgid */
236 if (setgid && !(perm & CFS_SETGID_PERM)) {
237 CDEBUG(D_SEC, "mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
238 "from %s\n", pud->pud_uid, pud->pud_gid,
239 pud->pud_fsuid, pud->pud_fsgid,
240 ucred->mu_identity->mi_gid, libcfs_nid2str(peernid));
241 GOTO(out, rc = -EACCES);
245 * NB: remote client not allowed to setgroups anyway.
247 if (!remote && perm & CFS_SETGRP_PERM) {
248 if (pud->pud_ngroups) {
249 /* setgroups for local client */
250 ucred->mu_ginfo = cfs_groups_alloc(pud->pud_ngroups);
251 if (!ucred->mu_ginfo) {
252 CERROR("failed to alloc %d groups\n",
254 GOTO(out, rc = -ENOMEM);
257 lustre_groups_from_list(ucred->mu_ginfo,
259 lustre_groups_sort(ucred->mu_ginfo);
261 ucred->mu_ginfo = NULL;
264 ucred->mu_suppgids[0] = -1;
265 ucred->mu_suppgids[1] = -1;
266 ucred->mu_ginfo = NULL;
269 ucred->mu_uid = pud->pud_uid;
270 ucred->mu_gid = pud->pud_gid;
271 ucred->mu_fsuid = pud->pud_fsuid;
272 ucred->mu_fsgid = pud->pud_fsgid;
274 /* process root_squash here. */
275 mdt_root_squash(info, peernid);
277 /* remove fs privilege for non-root user. */
279 ucred->mu_cap = pud->pud_cap & ~CFS_CAP_FS_MASK;
281 ucred->mu_cap = pud->pud_cap;
282 if (remote && !(perm & CFS_RMTOWN_PERM))
283 ucred->mu_cap &= ~(CFS_CAP_SYS_RESOURCE_MASK |
285 ucred->mu_valid = UCRED_NEW;
291 if (ucred->mu_ginfo) {
292 cfs_put_group_info(ucred->mu_ginfo);
293 ucred->mu_ginfo = NULL;
295 if (ucred->mu_identity) {
296 mdt_identity_put(mdt->mdt_identity_cache,
298 ucred->mu_identity = NULL;
305 int mdt_check_ucred(struct mdt_thread_info *info)
307 struct ptlrpc_request *req = mdt_info_req(info);
308 struct mdt_device *mdt = info->mti_mdt;
309 struct ptlrpc_user_desc *pud = req->rq_user_desc;
310 struct md_ucred *ucred = mdt_ucred(info);
311 struct md_identity *identity = NULL;
312 lnet_nid_t peernid = req->rq_peer.nid;
314 __u32 remote = exp_connect_rmtclient(info->mti_exp);
321 if ((ucred->mu_valid == UCRED_OLD) || (ucred->mu_valid == UCRED_NEW))
324 if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
327 /* sanity check: if we use strong authentication, we expect the
328 * uid which client claimed is true */
330 if (req->rq_auth_mapped_uid == INVALID_UID) {
331 CDEBUG(D_SEC, "remote user not mapped, deny access!\n");
335 if (ptlrpc_user_desc_do_idmap(req, pud))
338 if (req->rq_auth_mapped_uid != pud->pud_uid) {
339 CDEBUG(D_SEC, "remote client %s: auth/mapped uid %u/%u "
340 "while client claims %u:%u/%u:%u\n",
341 libcfs_nid2str(peernid), req->rq_auth_uid,
342 req->rq_auth_mapped_uid,
343 pud->pud_uid, pud->pud_gid,
344 pud->pud_fsuid, pud->pud_fsgid);
348 if (req->rq_auth_uid != pud->pud_uid) {
349 CDEBUG(D_SEC, "local client %s: auth uid %u "
350 "while client claims %u:%u/%u:%u\n",
351 libcfs_nid2str(peernid), req->rq_auth_uid,
352 pud->pud_uid, pud->pud_gid,
353 pud->pud_fsuid, pud->pud_fsgid);
358 if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
360 CDEBUG(D_SEC, "remote client must run with identity_get "
367 identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid);
368 if (IS_ERR(identity)) {
369 if (unlikely(PTR_ERR(identity) == -EREMCHG &&
373 CDEBUG(D_SEC, "Deny access without identity: uid %u\n",
379 perm = mdt_identity_get_perm(identity, remote, peernid);
380 /* find out the setuid/setgid attempt */
381 setuid = (pud->pud_uid != pud->pud_fsuid);
382 setgid = (pud->pud_gid != pud->pud_fsgid ||
383 pud->pud_gid != identity->mi_gid);
385 /* check permission of setuid */
386 if (setuid && !(perm & CFS_SETUID_PERM)) {
387 CDEBUG(D_SEC, "mdt blocked setuid attempt (%u -> %u) from %s\n",
388 pud->pud_uid, pud->pud_fsuid, libcfs_nid2str(peernid));
389 GOTO(out, rc = -EACCES);
392 /* check permission of setgid */
393 if (setgid && !(perm & CFS_SETGID_PERM)) {
394 CDEBUG(D_SEC, "mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
395 "from %s\n", pud->pud_uid, pud->pud_gid,
396 pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid,
397 libcfs_nid2str(peernid));
398 GOTO(out, rc = -EACCES);
404 mdt_identity_put(mdt->mdt_identity_cache, identity);
408 static int old_init_ucred(struct mdt_thread_info *info,
409 struct mdt_body *body)
411 struct md_ucred *uc = mdt_ucred(info);
412 struct mdt_device *mdt = info->mti_mdt;
413 struct md_identity *identity = NULL;
417 uc->mu_valid = UCRED_INVALID;
418 uc->mu_o_uid = uc->mu_uid = body->uid;
419 uc->mu_o_gid = uc->mu_gid = body->gid;
420 uc->mu_o_fsuid = uc->mu_fsuid = body->fsuid;
421 uc->mu_o_fsgid = uc->mu_fsgid = body->fsgid;
422 uc->mu_suppgids[0] = body->suppgid;
423 uc->mu_suppgids[1] = -1;
425 if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
426 identity = mdt_identity_get(mdt->mdt_identity_cache,
428 if (IS_ERR(identity)) {
429 if (unlikely(PTR_ERR(identity) == -EREMCHG)) {
432 CDEBUG(D_SEC, "Deny access without identity: "
433 "uid %u\n", uc->mu_fsuid);
438 uc->mu_identity = identity;
440 /* process root_squash here. */
441 mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid);
443 /* remove fs privilege for non-root user. */
445 uc->mu_cap = body->capability & ~CFS_CAP_FS_MASK;
447 uc->mu_cap = body->capability;
448 uc->mu_valid = UCRED_OLD;
453 static int old_init_ucred_reint(struct mdt_thread_info *info)
455 struct md_ucred *uc = mdt_ucred(info);
456 struct mdt_device *mdt = info->mti_mdt;
457 struct md_identity *identity = NULL;
461 uc->mu_valid = UCRED_INVALID;
462 uc->mu_o_uid = uc->mu_o_fsuid = uc->mu_uid = uc->mu_fsuid;
463 uc->mu_o_gid = uc->mu_o_fsgid = uc->mu_gid = uc->mu_fsgid;
465 if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
466 identity = mdt_identity_get(mdt->mdt_identity_cache,
468 if (IS_ERR(identity)) {
469 if (unlikely(PTR_ERR(identity) == -EREMCHG)) {
472 CDEBUG(D_SEC, "Deny access without identity: "
473 "uid %u\n", uc->mu_fsuid);
478 uc->mu_identity = identity;
480 /* process root_squash here. */
481 mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid);
483 /* remove fs privilege for non-root user. */
485 uc->mu_cap &= ~CFS_CAP_FS_MASK;
486 uc->mu_valid = UCRED_OLD;
491 int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body)
493 struct ptlrpc_request *req = mdt_info_req(info);
494 struct md_ucred *uc = mdt_ucred(info);
496 if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))
499 mdt_exit_ucred(info);
501 if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
502 return old_init_ucred(info, body);
504 return new_init_ucred(info, BODY_INIT, body);
507 int mdt_init_ucred_reint(struct mdt_thread_info *info)
509 struct ptlrpc_request *req = mdt_info_req(info);
510 struct md_ucred *uc = mdt_ucred(info);
512 if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))
515 mdt_exit_ucred(info);
517 if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
518 return old_init_ucred_reint(info);
520 return new_init_ucred(info, REC_INIT, NULL);
523 /* copied from lov/lov_ea.c, just for debugging, will be removed later */
524 void mdt_dump_lmm(int level, const struct lov_mds_md *lmm)
526 const struct lov_ost_data_v1 *lod;
530 count = le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count);
532 CDEBUG(level, "objid "LPX64", magic 0x%08X, pattern %#X\n",
533 le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic),
534 le32_to_cpu(lmm->lmm_pattern));
535 CDEBUG(level,"stripe_size=0x%x, stripe_count=0x%x\n",
536 le32_to_cpu(lmm->lmm_stripe_size), count);
537 if (count == LOV_ALL_STRIPES)
539 LASSERT(count <= LOV_MAX_STRIPE_COUNT);
540 for (i = 0, lod = lmm->lmm_objects; i < count; i++, lod++)
541 CDEBUG(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n",
542 i, le32_to_cpu(lod->l_ost_idx),
543 le64_to_cpu(lod->l_object_seq),
544 le64_to_cpu(lod->l_object_id));
547 /* Shrink and/or grow reply buffers */
548 int mdt_fix_reply(struct mdt_thread_info *info)
550 struct req_capsule *pill = info->mti_pill;
551 struct mdt_body *body;
552 int md_size, md_packed = 0;
557 body = req_capsule_server_get(pill, &RMF_MDT_BODY);
558 LASSERT(body != NULL);
560 if (body->valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE | OBD_MD_LINKNAME))
561 md_size = body->eadatasize;
565 acl_size = body->aclsize;
567 /* this replay - not send info to client */
568 if (info->mti_spec.no_create == 1) {
573 CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d"
574 " MDSCAPA = %llx, OSSCAPA = %llx\n",
576 (unsigned long long)(body->valid & OBD_MD_FLMDSCAPA),
577 (unsigned long long)(body->valid & OBD_MD_FLOSSCAPA));
581 &RMF_ACL, or &RMF_LOGCOOKIES
582 (optional) &RMF_CAPA1,
583 (optional) &RMF_CAPA2,
584 (optional) something else
587 /* MDT_MD buffer may be bigger than packed value, let's shrink all
588 * buffers before growing it */
589 if (info->mti_attr.ma_big_lmm_used) {
590 LASSERT(req_capsule_has_field(pill, &RMF_MDT_MD, RCL_SERVER));
591 md_packed = req_capsule_get_size(pill, &RMF_MDT_MD,
593 LASSERT(md_packed > 0);
594 /* buffer must be allocated separately */
595 LASSERT(info->mti_attr.ma_lmm !=
596 req_capsule_server_get(pill, &RMF_MDT_MD));
597 req_capsule_shrink(pill, &RMF_MDT_MD, 0, RCL_SERVER);
598 /* free big lmm if md_size is not needed */
600 info->mti_attr.ma_big_lmm_used = 0;
601 } else if (req_capsule_has_field(pill, &RMF_MDT_MD, RCL_SERVER)) {
602 req_capsule_shrink(pill, &RMF_MDT_MD, md_size, RCL_SERVER);
605 if (req_capsule_has_field(pill, &RMF_ACL, RCL_SERVER))
606 req_capsule_shrink(pill, &RMF_ACL, acl_size, RCL_SERVER);
607 else if (req_capsule_has_field(pill, &RMF_LOGCOOKIES, RCL_SERVER))
608 req_capsule_shrink(pill, &RMF_LOGCOOKIES,
609 acl_size, RCL_SERVER);
611 if (req_capsule_has_field(pill, &RMF_CAPA1, RCL_SERVER) &&
612 !(body->valid & OBD_MD_FLMDSCAPA))
613 req_capsule_shrink(pill, &RMF_CAPA1, 0, RCL_SERVER);
615 if (req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) &&
616 !(body->valid & OBD_MD_FLOSSCAPA))
617 req_capsule_shrink(pill, &RMF_CAPA2, 0, RCL_SERVER);
620 * Some more field should be shrinked if needed.
621 * This should be done by those who added fields to reply message.
624 /* Grow MD buffer if needed finally */
625 if (info->mti_attr.ma_big_lmm_used) {
628 LASSERT(md_size > md_packed);
629 CDEBUG(D_INFO, "Enlarge reply buffer, need extra %d bytes\n",
630 md_size - md_packed);
631 rc = req_capsule_server_grow(pill, &RMF_MDT_MD, md_size);
633 /* we can't answer with proper LOV EA, drop flags,
634 * the rc is also returned so this request is
635 * considered as failed */
636 body->valid &= ~(OBD_MD_FLDIREA | OBD_MD_FLEASIZE);
637 /* don't return transno along with error */
638 lustre_msg_set_transno(pill->rc_req->rq_repmsg, 0);
640 /* now we need to pack right LOV EA */
641 lmm = req_capsule_server_get(pill, &RMF_MDT_MD);
642 LASSERT(req_capsule_get_size(pill, &RMF_MDT_MD,
644 info->mti_attr.ma_lmm_size);
645 memcpy(lmm, info->mti_attr.ma_lmm,
646 info->mti_attr.ma_lmm_size);
648 /* update mdt_max_mdsize so clients will be aware about that */
649 if (info->mti_mdt->mdt_max_mdsize < info->mti_attr.ma_lmm_size)
650 info->mti_mdt->mdt_max_mdsize =
651 info->mti_attr.ma_lmm_size;
652 info->mti_attr.ma_big_lmm_used = 0;
658 /* if object is dying, pack the lov/llog data,
659 * parameter info->mti_attr should be valid at this point! */
660 int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo,
661 const struct md_attr *ma)
663 struct mdt_body *repbody;
664 const struct lu_attr *la = &ma->ma_attr;
668 repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
669 LASSERT(repbody != NULL);
671 if (ma->ma_valid & MA_INODE)
672 mdt_pack_attr2body(info, repbody, la, mdt_object_fid(mo));
674 if (ma->ma_valid & MA_LOV) {
677 if (mdt_object_exists(mo) < 0)
678 /* If it is a remote object, and we do not retrieve
679 * EA back unlink reg file*/
682 mode = lu_object_attr(&mo->mot_obj.mo_lu);
684 LASSERT(ma->ma_lmm_size);
685 mdt_dump_lmm(D_INFO, ma->ma_lmm);
686 repbody->eadatasize = ma->ma_lmm_size;
688 repbody->valid |= OBD_MD_FLEASIZE;
689 else if (S_ISDIR(mode))
690 repbody->valid |= OBD_MD_FLDIREA;
695 if (ma->ma_cookie_size && (ma->ma_valid & MA_COOKIE)) {
696 repbody->aclsize = ma->ma_cookie_size;
697 repbody->valid |= OBD_MD_FLCOOKIE;
700 if (info->mti_mdt->mdt_opts.mo_oss_capa &&
701 info->mti_exp->exp_connect_flags & OBD_CONNECT_OSS_CAPA &&
702 repbody->valid & OBD_MD_FLEASIZE) {
703 struct lustre_capa *capa;
705 capa = req_capsule_server_get(info->mti_pill, &RMF_CAPA2);
707 capa->lc_opc = CAPA_OPC_OSS_DESTROY;
708 rc = mo_capa_get(info->mti_env, mdt_object_child(mo), capa, 0);
712 repbody->valid |= OBD_MD_FLOSSCAPA;
718 static inline unsigned int attr_unpack(__u64 sa_valid) {
719 unsigned int ia_valid = 0;
721 if (sa_valid & MDS_ATTR_MODE)
722 ia_valid |= ATTR_MODE;
723 if (sa_valid & MDS_ATTR_UID)
724 ia_valid |= ATTR_UID;
725 if (sa_valid & MDS_ATTR_GID)
726 ia_valid |= ATTR_GID;
727 if (sa_valid & MDS_ATTR_SIZE)
728 ia_valid |= ATTR_SIZE;
729 if (sa_valid & MDS_ATTR_ATIME)
730 ia_valid |= ATTR_ATIME;
731 if (sa_valid & MDS_ATTR_MTIME)
732 ia_valid |= ATTR_MTIME;
733 if (sa_valid & MDS_ATTR_CTIME)
734 ia_valid |= ATTR_CTIME;
735 if (sa_valid & MDS_ATTR_ATIME_SET)
736 ia_valid |= ATTR_ATIME_SET;
737 if (sa_valid & MDS_ATTR_MTIME_SET)
738 ia_valid |= ATTR_MTIME_SET;
739 if (sa_valid & MDS_ATTR_FORCE)
740 ia_valid |= ATTR_FORCE;
741 if (sa_valid & MDS_ATTR_ATTR_FLAG)
742 ia_valid |= ATTR_ATTR_FLAG;
743 if (sa_valid & MDS_ATTR_KILL_SUID)
744 ia_valid |= ATTR_KILL_SUID;
745 if (sa_valid & MDS_ATTR_KILL_SGID)
746 ia_valid |= ATTR_KILL_SGID;
747 if (sa_valid & MDS_ATTR_CTIME_SET)
748 ia_valid |= ATTR_CTIME_SET;
749 if (sa_valid & MDS_ATTR_FROM_OPEN)
750 ia_valid |= ATTR_FROM_OPEN;
751 if (sa_valid & MDS_ATTR_BLOCKS)
752 ia_valid |= ATTR_BLOCKS;
753 if (sa_valid & MDS_OPEN_OWNEROVERRIDE)
754 ia_valid |= MDS_OPEN_OWNEROVERRIDE;
758 static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
772 if (in & ATTR_BLOCKS)
775 if (in & ATTR_FROM_OPEN)
776 rr->rr_flags |= MRF_OPEN_TRUNC;
778 if (in & ATTR_ATIME_SET)
781 if (in & ATTR_CTIME_SET)
784 if (in & ATTR_MTIME_SET)
787 if (in & ATTR_ATTR_FLAG)
790 if (in & ATTR_KILL_SUID)
793 if (in & ATTR_KILL_SGID)
796 if (in & MDS_OPEN_OWNEROVERRIDE)
797 ma->ma_attr_flags |= MDS_OPEN_OWNEROVERRIDE;
800 ma->ma_attr_flags |= MDS_PERM_BYPASS;
802 /*XXX need ATTR_RAW?*/
803 in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
804 ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
805 ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
806 ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE|
807 ATTR_FORCE|ATTR_KILL_SUID|ATTR_KILL_SGID);
809 CERROR("Unknown attr bits: "LPX64"\n", in);
814 static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
816 struct md_ucred *uc = mdt_ucred(info);
817 struct md_attr *ma = &info->mti_attr;
818 struct lu_attr *la = &ma->ma_attr;
819 struct req_capsule *pill = info->mti_pill;
820 struct mdt_reint_record *rr = &info->mti_rr;
821 struct mdt_rec_setattr *rec;
824 CLASSERT(sizeof(struct mdt_rec_setattr)== sizeof(struct mdt_rec_reint));
825 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
829 uc->mu_fsuid = rec->sa_fsuid;
830 uc->mu_fsgid = rec->sa_fsgid;
831 uc->mu_cap = rec->sa_cap;
832 uc->mu_suppgids[0] = rec->sa_suppgid;
833 uc->mu_suppgids[1] = -1;
835 rr->rr_fid1 = &rec->sa_fid;
836 la->la_valid = mdt_attr_valid_xlate(attr_unpack(rec->sa_valid), rr, ma);
837 la->la_mode = rec->sa_mode;
838 la->la_flags = rec->sa_attr_flags;
839 la->la_uid = rec->sa_uid;
840 la->la_gid = rec->sa_gid;
841 la->la_size = rec->sa_size;
842 la->la_blocks = rec->sa_blocks;
843 la->la_ctime = rec->sa_ctime;
844 la->la_atime = rec->sa_atime;
845 la->la_mtime = rec->sa_mtime;
846 ma->ma_valid = MA_INODE;
848 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
849 mdt_set_capainfo(info, 0, rr->rr_fid1,
850 req_capsule_client_get(pill, &RMF_CAPA1));
855 static int mdt_ioepoch_unpack(struct mdt_thread_info *info)
857 struct req_capsule *pill = info->mti_pill;
860 if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT))
862 req_capsule_client_get(pill, &RMF_MDT_EPOCH);
864 info->mti_ioepoch = NULL;
865 RETURN(info->mti_ioepoch == NULL ? -EFAULT : 0);
868 static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) {
869 struct req_capsule *pill = info->mti_pill;
871 if (req_capsule_get_size(pill, &RMF_DLM_REQ, RCL_CLIENT)) {
872 info->mti_dlm_req = req_capsule_client_get(pill, &RMF_DLM_REQ);
873 if (info->mti_dlm_req == NULL)
880 static int mdt_setattr_unpack(struct mdt_thread_info *info)
882 struct mdt_reint_record *rr = &info->mti_rr;
883 struct md_attr *ma = &info->mti_attr;
884 struct req_capsule *pill = info->mti_pill;
888 rc = mdt_setattr_unpack_rec(info);
892 /* Epoch may be absent */
893 mdt_ioepoch_unpack(info);
895 if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) {
896 rr->rr_eadata = req_capsule_client_get(pill, &RMF_EADATA);
897 rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
899 ma->ma_lmm_size = rr->rr_eadatalen;
900 if (ma->ma_lmm_size > 0) {
901 ma->ma_lmm = (void *)rr->rr_eadata;
902 ma->ma_valid |= MA_LOV;
906 ma->ma_cookie_size = req_capsule_get_size(pill, &RMF_LOGCOOKIES,
908 if (ma->ma_cookie_size) {
909 ma->ma_cookie = req_capsule_client_get(pill, &RMF_LOGCOOKIES);
910 ma->ma_valid |= MA_COOKIE;
913 rc = mdt_dlmreq_unpack(info);
917 int mdt_close_unpack(struct mdt_thread_info *info)
922 rc = mdt_ioepoch_unpack(info);
926 RETURN(mdt_setattr_unpack_rec(info));
929 static int mdt_create_unpack(struct mdt_thread_info *info)
931 struct md_ucred *uc = mdt_ucred(info);
932 struct mdt_rec_create *rec;
933 struct lu_attr *attr = &info->mti_attr.ma_attr;
934 struct mdt_reint_record *rr = &info->mti_rr;
935 struct req_capsule *pill = info->mti_pill;
936 struct md_op_spec *sp = &info->mti_spec;
940 CLASSERT(sizeof(struct mdt_rec_create) == sizeof(struct mdt_rec_reint));
941 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
945 uc->mu_fsuid = rec->cr_fsuid;
946 uc->mu_fsgid = rec->cr_fsgid;
947 uc->mu_cap = rec->cr_cap;
948 uc->mu_suppgids[0] = rec->cr_suppgid1;
949 uc->mu_suppgids[1] = -1;
951 rr->rr_fid1 = &rec->cr_fid1;
952 rr->rr_fid2 = &rec->cr_fid2;
953 attr->la_mode = rec->cr_mode;
954 attr->la_rdev = rec->cr_rdev;
955 attr->la_uid = rec->cr_fsuid;
956 attr->la_gid = rec->cr_fsgid;
957 attr->la_ctime = rec->cr_time;
958 attr->la_mtime = rec->cr_time;
959 attr->la_atime = rec->cr_time;
960 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
961 LA_CTIME | LA_MTIME | LA_ATIME;
962 memset(&sp->u, 0, sizeof(sp->u));
963 sp->sp_cr_flags = get_mrc_cr_flags(rec);
964 sp->sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
965 info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
967 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
968 mdt_set_capainfo(info, 0, rr->rr_fid1,
969 req_capsule_client_get(pill, &RMF_CAPA1));
970 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
972 if (!info->mti_cross_ref) {
973 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
974 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME,
976 LASSERT(rr->rr_name && rr->rr_namelen > 0);
982 #ifdef CONFIG_FS_POSIX_ACL
983 if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) {
984 if (S_ISDIR(attr->la_mode))
985 sp->u.sp_pfid = rr->rr_fid1;
986 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
987 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
989 rr->rr_eadata = req_capsule_client_get(pill, &RMF_EADATA);
990 rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
992 sp->u.sp_ea.eadata = rr->rr_eadata;
993 sp->u.sp_ea.eadatalen = rr->rr_eadatalen;
994 sp->u.sp_ea.fid = rr->rr_fid1;
998 if (S_ISDIR(attr->la_mode)) {
999 /* pass parent fid for cross-ref cases */
1000 sp->u.sp_pfid = rr->rr_fid1;
1001 if (sp->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
1002 /* create salve object req, need
1003 * unpack split ea here
1005 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SLAVE);
1006 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
1008 rr->rr_eadata = req_capsule_client_get(pill,
1010 rr->rr_eadatalen = req_capsule_get_size(pill,
1013 sp->u.sp_ea.eadata = rr->rr_eadata;
1014 sp->u.sp_ea.eadatalen = rr->rr_eadatalen;
1015 sp->u.sp_ea.fid = rr->rr_fid1;
1018 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
1019 } else if (S_ISLNK(attr->la_mode)) {
1020 const char *tgt = NULL;
1022 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM);
1023 if (req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT)) {
1024 tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
1025 sp->u.sp_symname = tgt;
1030 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
1032 rc = mdt_dlmreq_unpack(info);
1036 static int mdt_link_unpack(struct mdt_thread_info *info)
1038 struct md_ucred *uc = mdt_ucred(info);
1039 struct mdt_rec_link *rec;
1040 struct lu_attr *attr = &info->mti_attr.ma_attr;
1041 struct mdt_reint_record *rr = &info->mti_rr;
1042 struct req_capsule *pill = info->mti_pill;
1046 CLASSERT(sizeof(struct mdt_rec_link) == sizeof(struct mdt_rec_reint));
1047 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
1051 uc->mu_fsuid = rec->lk_fsuid;
1052 uc->mu_fsgid = rec->lk_fsgid;
1053 uc->mu_cap = rec->lk_cap;
1054 uc->mu_suppgids[0] = rec->lk_suppgid1;
1055 uc->mu_suppgids[1] = rec->lk_suppgid2;
1057 attr->la_uid = rec->lk_fsuid;
1058 attr->la_gid = rec->lk_fsgid;
1059 rr->rr_fid1 = &rec->lk_fid1;
1060 rr->rr_fid2 = &rec->lk_fid2;
1061 attr->la_ctime = rec->lk_time;
1062 attr->la_mtime = rec->lk_time;
1063 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;
1065 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1066 mdt_set_capainfo(info, 0, rr->rr_fid1,
1067 req_capsule_client_get(pill, &RMF_CAPA1));
1068 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
1069 mdt_set_capainfo(info, 1, rr->rr_fid2,
1070 req_capsule_client_get(pill, &RMF_CAPA2));
1072 info->mti_spec.sp_ck_split = !!(rec->lk_bias & MDS_CHECK_SPLIT);
1073 info->mti_cross_ref = !!(rec->lk_bias & MDS_CROSS_REF);
1074 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1075 if (rr->rr_name == NULL)
1077 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1078 if (!info->mti_cross_ref)
1079 LASSERT(rr->rr_namelen > 0);
1081 rc = mdt_dlmreq_unpack(info);
1085 static int mdt_unlink_unpack(struct mdt_thread_info *info)
1087 struct md_ucred *uc = mdt_ucred(info);
1088 struct mdt_rec_unlink *rec;
1089 struct md_attr *ma = &info->mti_attr;
1090 struct lu_attr *attr = &info->mti_attr.ma_attr;
1091 struct mdt_reint_record *rr = &info->mti_rr;
1092 struct req_capsule *pill = info->mti_pill;
1096 CLASSERT(sizeof(struct mdt_rec_unlink) == sizeof(struct mdt_rec_reint));
1097 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
1101 uc->mu_fsuid = rec->ul_fsuid;
1102 uc->mu_fsgid = rec->ul_fsgid;
1103 uc->mu_cap = rec->ul_cap;
1104 uc->mu_suppgids[0] = rec->ul_suppgid1;
1105 uc->mu_suppgids[1] = -1;
1107 attr->la_uid = rec->ul_fsuid;
1108 attr->la_gid = rec->ul_fsgid;
1109 rr->rr_fid1 = &rec->ul_fid1;
1110 rr->rr_fid2 = &rec->ul_fid2;
1111 attr->la_ctime = rec->ul_time;
1112 attr->la_mtime = rec->ul_time;
1113 attr->la_mode = rec->ul_mode;
1114 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
1116 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1117 mdt_set_capainfo(info, 0, rr->rr_fid1,
1118 req_capsule_client_get(pill, &RMF_CAPA1));
1120 info->mti_cross_ref = !!(rec->ul_bias & MDS_CROSS_REF);
1121 if (!info->mti_cross_ref) {
1122 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1123 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1124 if (rr->rr_name == NULL || rr->rr_namelen == 0)
1130 info->mti_spec.sp_ck_split = !!(rec->ul_bias & MDS_CHECK_SPLIT);
1131 if (rec->ul_bias & MDS_VTX_BYPASS)
1132 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1134 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1136 info->mti_spec.no_create = !!req_is_replay(mdt_info_req(info));
1137 /* last unlink need LOV EA sent back */
1138 rr->rr_eadatalen = info->mti_mdt->mdt_max_mdsize;
1140 rc = mdt_dlmreq_unpack(info);
1144 static int mdt_rename_unpack(struct mdt_thread_info *info)
1146 struct md_ucred *uc = mdt_ucred(info);
1147 struct mdt_rec_rename *rec;
1148 struct md_attr *ma = &info->mti_attr;
1149 struct lu_attr *attr = &info->mti_attr.ma_attr;
1150 struct mdt_reint_record *rr = &info->mti_rr;
1151 struct req_capsule *pill = info->mti_pill;
1155 CLASSERT(sizeof(struct mdt_rec_rename) == sizeof(struct mdt_rec_reint));
1156 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
1160 uc->mu_fsuid = rec->rn_fsuid;
1161 uc->mu_fsgid = rec->rn_fsgid;
1162 uc->mu_cap = rec->rn_cap;
1163 uc->mu_suppgids[0] = rec->rn_suppgid1;
1164 uc->mu_suppgids[1] = rec->rn_suppgid2;
1166 attr->la_uid = rec->rn_fsuid;
1167 attr->la_gid = rec->rn_fsgid;
1168 rr->rr_fid1 = &rec->rn_fid1;
1169 rr->rr_fid2 = &rec->rn_fid2;
1170 attr->la_ctime = rec->rn_time;
1171 attr->la_mtime = rec->rn_time;
1172 /* rename_tgt contains the mode already */
1173 attr->la_mode = rec->rn_mode;
1174 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
1176 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1177 mdt_set_capainfo(info, 0, rr->rr_fid1,
1178 req_capsule_client_get(pill, &RMF_CAPA1));
1179 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
1180 mdt_set_capainfo(info, 1, rr->rr_fid2,
1181 req_capsule_client_get(pill, &RMF_CAPA2));
1183 info->mti_spec.sp_ck_split = !!(rec->rn_bias & MDS_CHECK_SPLIT);
1184 info->mti_cross_ref = !!(rec->rn_bias & MDS_CROSS_REF);
1185 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1186 rr->rr_tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
1187 if (rr->rr_name == NULL || rr->rr_tgt == NULL)
1189 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1190 rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT) - 1;
1191 if (!info->mti_cross_ref)
1192 LASSERT(rr->rr_namelen > 0 && rr->rr_tgtlen > 0);
1193 if (rec->rn_bias & MDS_VTX_BYPASS)
1194 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1196 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1198 info->mti_spec.no_create = !!req_is_replay(mdt_info_req(info));
1199 /* rename may contain unlink so we might need LOV EA sent back */
1200 rr->rr_eadatalen = info->mti_mdt->mdt_max_mdsize;
1202 rc = mdt_dlmreq_unpack(info);
1206 static int mdt_open_unpack(struct mdt_thread_info *info)
1208 struct md_ucred *uc = mdt_ucred(info);
1209 struct mdt_rec_create *rec;
1210 struct lu_attr *attr = &info->mti_attr.ma_attr;
1211 struct req_capsule *pill = info->mti_pill;
1212 struct mdt_reint_record *rr = &info->mti_rr;
1213 struct ptlrpc_request *req = mdt_info_req(info);
1214 struct md_op_spec *sp = &info->mti_spec;
1217 CLASSERT(sizeof(struct mdt_rec_create) == sizeof(struct mdt_rec_reint));
1218 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
1222 uc->mu_fsuid = rec->cr_fsuid;
1223 uc->mu_fsgid = rec->cr_fsgid;
1224 uc->mu_cap = rec->cr_cap;
1225 uc->mu_suppgids[0] = rec->cr_suppgid1;
1226 uc->mu_suppgids[1] = rec->cr_suppgid2;
1228 rr->rr_fid1 = &rec->cr_fid1;
1229 rr->rr_fid2 = &rec->cr_fid2;
1230 rr->rr_handle = &rec->cr_old_handle;
1231 attr->la_mode = rec->cr_mode;
1232 attr->la_rdev = rec->cr_rdev;
1233 attr->la_uid = rec->cr_fsuid;
1234 attr->la_gid = rec->cr_fsgid;
1235 attr->la_ctime = rec->cr_time;
1236 attr->la_mtime = rec->cr_time;
1237 attr->la_atime = rec->cr_time;
1238 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
1239 LA_CTIME | LA_MTIME | LA_ATIME;
1240 memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u));
1241 info->mti_spec.sp_cr_flags = get_mrc_cr_flags(rec);
1242 /* Do not trigger ASSERTION if client miss to set such flags. */
1243 if (unlikely(info->mti_spec.sp_cr_flags == 0))
1245 info->mti_replayepoch = rec->cr_ioepoch;
1247 info->mti_spec.sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
1248 info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
1250 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1251 mdt_set_capainfo(info, 0, rr->rr_fid1,
1252 req_capsule_client_get(pill, &RMF_CAPA1));
1253 if (req_is_replay(req) &&
1254 req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT)) {
1256 mdt_set_capainfo(info, 1, rr->rr_fid2,
1257 req_capsule_client_get(pill, &RMF_CAPA2));
1260 * FIXME: capa in replay open request might have expired,
1261 * bypass capa check. Security hole?
1263 mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
1264 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
1268 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1269 if (rr->rr_name == NULL)
1271 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1273 if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) {
1274 rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
1276 if (rr->rr_eadatalen > 0) {
1277 rr->rr_eadata = req_capsule_client_get(pill,
1279 sp->u.sp_ea.eadatalen = rr->rr_eadatalen;
1280 sp->u.sp_ea.eadata = rr->rr_eadata;
1281 sp->no_create = !!req_is_replay(req);
1285 * Client default md_size may be 0 right after client start,
1286 * until all osc are connected, set here just some reasonable
1287 * value to prevent misbehavior.
1289 if (rr->rr_eadatalen == 0 &&
1290 !(info->mti_spec.sp_cr_flags & MDS_OPEN_DELAY_CREATE))
1291 rr->rr_eadatalen = MIN_MD_SIZE; }
1296 static int mdt_setxattr_unpack(struct mdt_thread_info *info)
1298 struct mdt_reint_record *rr = &info->mti_rr;
1299 struct md_ucred *uc = mdt_ucred(info);
1300 struct lu_attr *attr = &info->mti_attr.ma_attr;
1301 struct req_capsule *pill = info->mti_pill;
1302 struct mdt_rec_setxattr *rec;
1306 CLASSERT(sizeof(struct mdt_rec_setxattr) ==
1307 sizeof(struct mdt_rec_reint));
1309 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
1313 uc->mu_fsuid = rec->sx_fsuid;
1314 uc->mu_fsgid = rec->sx_fsgid;
1315 uc->mu_cap = rec->sx_cap;
1316 uc->mu_suppgids[0] = rec->sx_suppgid1;
1317 uc->mu_suppgids[1] = -1;
1319 rr->rr_opcode = rec->sx_opcode;
1320 rr->rr_fid1 = &rec->sx_fid;
1321 attr->la_valid = rec->sx_valid;
1322 attr->la_ctime = rec->sx_time;
1323 attr->la_size = rec->sx_size;
1324 attr->la_flags = rec->sx_flags;
1326 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1327 mdt_set_capainfo(info, 0, rr->rr_fid1,
1328 req_capsule_client_get(pill, &RMF_CAPA1));
1330 mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
1332 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1333 if (rr->rr_name == NULL)
1335 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1336 LASSERT(rr->rr_namelen > 0);
1338 if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) {
1339 rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
1341 if (rr->rr_eadatalen > 0) {
1342 rr->rr_eadata = req_capsule_client_get(pill,
1344 if (rr->rr_eadata == NULL)
1347 rr->rr_eadata = NULL;
1349 } else if (!(attr->la_valid & OBD_MD_FLXATTRRM)) {
1350 CDEBUG(D_INFO, "no xattr data supplied\n");
1358 typedef int (*reint_unpacker)(struct mdt_thread_info *info);
1360 static reint_unpacker mdt_reint_unpackers[REINT_MAX] = {
1361 [REINT_SETATTR] = mdt_setattr_unpack,
1362 [REINT_CREATE] = mdt_create_unpack,
1363 [REINT_LINK] = mdt_link_unpack,
1364 [REINT_UNLINK] = mdt_unlink_unpack,
1365 [REINT_RENAME] = mdt_rename_unpack,
1366 [REINT_OPEN] = mdt_open_unpack,
1367 [REINT_SETXATTR] = mdt_setxattr_unpack
1370 int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op)
1375 memset(&info->mti_rr, 0, sizeof(info->mti_rr));
1376 if (op < REINT_MAX && mdt_reint_unpackers[op] != NULL) {
1377 info->mti_rr.rr_opcode = op;
1378 rc = mdt_reint_unpackers[op](info);
1380 CERROR("Unexpected opcode %d\n", op);