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(struct rw_semaphore *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_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_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_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_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) {
675 CERROR("No need in LOV EA upon unlink\n");
678 repbody->eadatasize = 0;
680 if (ma->ma_cookie_size && (ma->ma_valid & MA_COOKIE)) {
681 repbody->aclsize = ma->ma_cookie_size;
682 repbody->valid |= OBD_MD_FLCOOKIE;
685 if (info->mti_mdt->mdt_opts.mo_oss_capa &&
686 info->mti_exp->exp_connect_flags & OBD_CONNECT_OSS_CAPA &&
687 repbody->valid & OBD_MD_FLEASIZE) {
688 struct lustre_capa *capa;
690 capa = req_capsule_server_get(info->mti_pill, &RMF_CAPA2);
692 capa->lc_opc = CAPA_OPC_OSS_DESTROY;
693 rc = mo_capa_get(info->mti_env, mdt_object_child(mo), capa, 0);
697 repbody->valid |= OBD_MD_FLOSSCAPA;
703 static inline unsigned int attr_unpack(__u64 sa_valid) {
704 unsigned int ia_valid = 0;
706 if (sa_valid & MDS_ATTR_MODE)
707 ia_valid |= ATTR_MODE;
708 if (sa_valid & MDS_ATTR_UID)
709 ia_valid |= ATTR_UID;
710 if (sa_valid & MDS_ATTR_GID)
711 ia_valid |= ATTR_GID;
712 if (sa_valid & MDS_ATTR_SIZE)
713 ia_valid |= ATTR_SIZE;
714 if (sa_valid & MDS_ATTR_ATIME)
715 ia_valid |= ATTR_ATIME;
716 if (sa_valid & MDS_ATTR_MTIME)
717 ia_valid |= ATTR_MTIME;
718 if (sa_valid & MDS_ATTR_CTIME)
719 ia_valid |= ATTR_CTIME;
720 if (sa_valid & MDS_ATTR_ATIME_SET)
721 ia_valid |= ATTR_ATIME_SET;
722 if (sa_valid & MDS_ATTR_MTIME_SET)
723 ia_valid |= ATTR_MTIME_SET;
724 if (sa_valid & MDS_ATTR_FORCE)
725 ia_valid |= ATTR_FORCE;
726 if (sa_valid & MDS_ATTR_ATTR_FLAG)
727 ia_valid |= ATTR_ATTR_FLAG;
728 if (sa_valid & MDS_ATTR_KILL_SUID)
729 ia_valid |= ATTR_KILL_SUID;
730 if (sa_valid & MDS_ATTR_KILL_SGID)
731 ia_valid |= ATTR_KILL_SGID;
732 if (sa_valid & MDS_ATTR_CTIME_SET)
733 ia_valid |= ATTR_CTIME_SET;
734 if (sa_valid & MDS_ATTR_FROM_OPEN)
735 ia_valid |= ATTR_FROM_OPEN;
736 if (sa_valid & MDS_ATTR_BLOCKS)
737 ia_valid |= ATTR_BLOCKS;
738 if (sa_valid & MDS_OPEN_OWNEROVERRIDE)
739 ia_valid |= MDS_OPEN_OWNEROVERRIDE;
743 static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
757 if (in & ATTR_BLOCKS)
760 if (in & ATTR_FROM_OPEN)
761 rr->rr_flags |= MRF_OPEN_TRUNC;
763 if (in & ATTR_ATIME_SET)
766 if (in & ATTR_CTIME_SET)
769 if (in & ATTR_MTIME_SET)
772 if (in & ATTR_ATTR_FLAG)
775 if (in & ATTR_KILL_SUID)
778 if (in & ATTR_KILL_SGID)
781 if (in & MDS_OPEN_OWNEROVERRIDE)
782 ma->ma_attr_flags |= MDS_OPEN_OWNEROVERRIDE;
785 ma->ma_attr_flags |= MDS_PERM_BYPASS;
787 /*XXX need ATTR_RAW?*/
788 in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
789 ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
790 ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
791 ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE|
792 ATTR_FORCE|ATTR_KILL_SUID|ATTR_KILL_SGID);
794 CERROR("Unknown attr bits: "LPX64"\n", in);
799 static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
801 struct md_ucred *uc = mdt_ucred(info);
802 struct md_attr *ma = &info->mti_attr;
803 struct lu_attr *la = &ma->ma_attr;
804 struct req_capsule *pill = info->mti_pill;
805 struct mdt_reint_record *rr = &info->mti_rr;
806 struct mdt_rec_setattr *rec;
809 CLASSERT(sizeof(struct mdt_rec_setattr)== sizeof(struct mdt_rec_reint));
810 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
814 uc->mu_fsuid = rec->sa_fsuid;
815 uc->mu_fsgid = rec->sa_fsgid;
816 uc->mu_cap = rec->sa_cap;
817 uc->mu_suppgids[0] = rec->sa_suppgid;
818 uc->mu_suppgids[1] = -1;
820 rr->rr_fid1 = &rec->sa_fid;
821 la->la_valid = mdt_attr_valid_xlate(attr_unpack(rec->sa_valid), rr, ma);
822 la->la_mode = rec->sa_mode;
823 la->la_flags = rec->sa_attr_flags;
824 la->la_uid = rec->sa_uid;
825 la->la_gid = rec->sa_gid;
826 la->la_size = rec->sa_size;
827 la->la_blocks = rec->sa_blocks;
828 la->la_ctime = rec->sa_ctime;
829 la->la_atime = rec->sa_atime;
830 la->la_mtime = rec->sa_mtime;
831 ma->ma_valid = MA_INODE;
833 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
834 mdt_set_capainfo(info, 0, rr->rr_fid1,
835 req_capsule_client_get(pill, &RMF_CAPA1));
840 static int mdt_ioepoch_unpack(struct mdt_thread_info *info)
842 struct req_capsule *pill = info->mti_pill;
845 if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT))
847 req_capsule_client_get(pill, &RMF_MDT_EPOCH);
849 info->mti_ioepoch = NULL;
850 RETURN(info->mti_ioepoch == NULL ? -EFAULT : 0);
853 static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) {
854 struct req_capsule *pill = info->mti_pill;
856 if (req_capsule_get_size(pill, &RMF_DLM_REQ, RCL_CLIENT)) {
857 info->mti_dlm_req = req_capsule_client_get(pill, &RMF_DLM_REQ);
858 if (info->mti_dlm_req == NULL)
865 static int mdt_setattr_unpack(struct mdt_thread_info *info)
867 struct mdt_reint_record *rr = &info->mti_rr;
868 struct md_attr *ma = &info->mti_attr;
869 struct req_capsule *pill = info->mti_pill;
873 rc = mdt_setattr_unpack_rec(info);
877 /* Epoch may be absent */
878 mdt_ioepoch_unpack(info);
880 if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) {
881 rr->rr_eadata = req_capsule_client_get(pill, &RMF_EADATA);
882 rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
884 ma->ma_lmm_size = rr->rr_eadatalen;
885 if (ma->ma_lmm_size > 0) {
886 ma->ma_lmm = (void *)rr->rr_eadata;
887 ma->ma_valid |= MA_LOV;
891 rc = mdt_dlmreq_unpack(info);
895 int mdt_close_unpack(struct mdt_thread_info *info)
900 rc = mdt_ioepoch_unpack(info);
904 RETURN(mdt_setattr_unpack_rec(info));
907 static int mdt_create_unpack(struct mdt_thread_info *info)
909 struct md_ucred *uc = mdt_ucred(info);
910 struct mdt_rec_create *rec;
911 struct lu_attr *attr = &info->mti_attr.ma_attr;
912 struct mdt_reint_record *rr = &info->mti_rr;
913 struct req_capsule *pill = info->mti_pill;
914 struct md_op_spec *sp = &info->mti_spec;
918 CLASSERT(sizeof(struct mdt_rec_create) == sizeof(struct mdt_rec_reint));
919 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
923 uc->mu_fsuid = rec->cr_fsuid;
924 uc->mu_fsgid = rec->cr_fsgid;
925 uc->mu_cap = rec->cr_cap;
926 uc->mu_suppgids[0] = rec->cr_suppgid1;
927 uc->mu_suppgids[1] = -1;
928 uc->mu_umask = rec->cr_umask;
930 rr->rr_fid1 = &rec->cr_fid1;
931 rr->rr_fid2 = &rec->cr_fid2;
932 attr->la_mode = rec->cr_mode;
933 attr->la_rdev = rec->cr_rdev;
934 attr->la_uid = rec->cr_fsuid;
935 attr->la_gid = rec->cr_fsgid;
936 attr->la_ctime = rec->cr_time;
937 attr->la_mtime = rec->cr_time;
938 attr->la_atime = rec->cr_time;
939 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
940 LA_CTIME | LA_MTIME | LA_ATIME;
941 memset(&sp->u, 0, sizeof(sp->u));
942 sp->sp_cr_flags = get_mrc_cr_flags(rec);
944 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
945 mdt_set_capainfo(info, 0, rr->rr_fid1,
946 req_capsule_client_get(pill, &RMF_CAPA1));
947 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
949 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
950 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME,
952 LASSERT(rr->rr_name && rr->rr_namelen > 0);
954 if (S_ISLNK(attr->la_mode)) {
955 const char *tgt = NULL;
957 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM);
958 if (req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT)) {
959 tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
960 sp->u.sp_symname = tgt;
965 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
968 rc = mdt_dlmreq_unpack(info);
972 static int mdt_link_unpack(struct mdt_thread_info *info)
974 struct md_ucred *uc = mdt_ucred(info);
975 struct mdt_rec_link *rec;
976 struct lu_attr *attr = &info->mti_attr.ma_attr;
977 struct mdt_reint_record *rr = &info->mti_rr;
978 struct req_capsule *pill = info->mti_pill;
982 CLASSERT(sizeof(struct mdt_rec_link) == sizeof(struct mdt_rec_reint));
983 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
987 uc->mu_fsuid = rec->lk_fsuid;
988 uc->mu_fsgid = rec->lk_fsgid;
989 uc->mu_cap = rec->lk_cap;
990 uc->mu_suppgids[0] = rec->lk_suppgid1;
991 uc->mu_suppgids[1] = rec->lk_suppgid2;
993 attr->la_uid = rec->lk_fsuid;
994 attr->la_gid = rec->lk_fsgid;
995 rr->rr_fid1 = &rec->lk_fid1;
996 rr->rr_fid2 = &rec->lk_fid2;
997 attr->la_ctime = rec->lk_time;
998 attr->la_mtime = rec->lk_time;
999 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;
1001 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1002 mdt_set_capainfo(info, 0, rr->rr_fid1,
1003 req_capsule_client_get(pill, &RMF_CAPA1));
1004 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
1005 mdt_set_capainfo(info, 1, rr->rr_fid2,
1006 req_capsule_client_get(pill, &RMF_CAPA2));
1008 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1009 if (rr->rr_name == NULL)
1011 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1013 LASSERT(rr->rr_namelen > 0);
1015 rc = mdt_dlmreq_unpack(info);
1019 static int mdt_unlink_unpack(struct mdt_thread_info *info)
1021 struct md_ucred *uc = mdt_ucred(info);
1022 struct mdt_rec_unlink *rec;
1023 struct md_attr *ma = &info->mti_attr;
1024 struct lu_attr *attr = &info->mti_attr.ma_attr;
1025 struct mdt_reint_record *rr = &info->mti_rr;
1026 struct req_capsule *pill = info->mti_pill;
1030 CLASSERT(sizeof(struct mdt_rec_unlink) == sizeof(struct mdt_rec_reint));
1031 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
1035 uc->mu_fsuid = rec->ul_fsuid;
1036 uc->mu_fsgid = rec->ul_fsgid;
1037 uc->mu_cap = rec->ul_cap;
1038 uc->mu_suppgids[0] = rec->ul_suppgid1;
1039 uc->mu_suppgids[1] = -1;
1041 attr->la_uid = rec->ul_fsuid;
1042 attr->la_gid = rec->ul_fsgid;
1043 rr->rr_fid1 = &rec->ul_fid1;
1044 rr->rr_fid2 = &rec->ul_fid2;
1045 attr->la_ctime = rec->ul_time;
1046 attr->la_mtime = rec->ul_time;
1047 attr->la_mode = rec->ul_mode;
1048 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
1050 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1051 mdt_set_capainfo(info, 0, rr->rr_fid1,
1052 req_capsule_client_get(pill, &RMF_CAPA1));
1054 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1055 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1056 if (rr->rr_name == NULL || rr->rr_namelen == 0)
1059 if (rec->ul_bias & MDS_VTX_BYPASS)
1060 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1062 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1064 info->mti_spec.no_create = !!req_is_replay(mdt_info_req(info));
1066 rc = mdt_dlmreq_unpack(info);
1070 static int mdt_rename_unpack(struct mdt_thread_info *info)
1072 struct md_ucred *uc = mdt_ucred(info);
1073 struct mdt_rec_rename *rec;
1074 struct md_attr *ma = &info->mti_attr;
1075 struct lu_attr *attr = &info->mti_attr.ma_attr;
1076 struct mdt_reint_record *rr = &info->mti_rr;
1077 struct req_capsule *pill = info->mti_pill;
1081 CLASSERT(sizeof(struct mdt_rec_rename) == sizeof(struct mdt_rec_reint));
1082 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
1086 uc->mu_fsuid = rec->rn_fsuid;
1087 uc->mu_fsgid = rec->rn_fsgid;
1088 uc->mu_cap = rec->rn_cap;
1089 uc->mu_suppgids[0] = rec->rn_suppgid1;
1090 uc->mu_suppgids[1] = rec->rn_suppgid2;
1092 attr->la_uid = rec->rn_fsuid;
1093 attr->la_gid = rec->rn_fsgid;
1094 rr->rr_fid1 = &rec->rn_fid1;
1095 rr->rr_fid2 = &rec->rn_fid2;
1096 attr->la_ctime = rec->rn_time;
1097 attr->la_mtime = rec->rn_time;
1098 /* rename_tgt contains the mode already */
1099 attr->la_mode = rec->rn_mode;
1100 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
1102 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1103 mdt_set_capainfo(info, 0, rr->rr_fid1,
1104 req_capsule_client_get(pill, &RMF_CAPA1));
1105 if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
1106 mdt_set_capainfo(info, 1, rr->rr_fid2,
1107 req_capsule_client_get(pill, &RMF_CAPA2));
1109 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1110 rr->rr_tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
1111 if (rr->rr_name == NULL || rr->rr_tgt == NULL)
1113 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1114 rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT) - 1;
1115 LASSERT(rr->rr_namelen > 0 && rr->rr_tgtlen > 0);
1117 if (rec->rn_bias & MDS_VTX_BYPASS)
1118 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1120 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1122 info->mti_spec.no_create = !!req_is_replay(mdt_info_req(info));
1124 rc = mdt_dlmreq_unpack(info);
1129 * please see comment above LOV_MAGIC_V1_DEF
1131 static void mdt_fix_lov_magic(struct mdt_thread_info *info)
1133 struct mdt_reint_record *rr = &info->mti_rr;
1134 struct lov_user_md_v1 *v1;
1136 v1 = (void *)rr->rr_eadata;
1139 if (unlikely(req_is_replay(mdt_info_req(info)))) {
1140 if (v1->lmm_magic == LOV_USER_MAGIC_V1) {
1141 v1->lmm_magic = LOV_MAGIC_V1_DEF;
1142 } else if (v1->lmm_magic == __swab32(LOV_USER_MAGIC_V1)) {
1143 v1->lmm_magic = __swab32(LOV_MAGIC_V1_DEF);
1144 } else if (v1->lmm_magic == LOV_USER_MAGIC_V3) {
1145 v1->lmm_magic = LOV_MAGIC_V3_DEF;
1146 } else if (v1->lmm_magic == __swab32(LOV_USER_MAGIC_V3)) {
1147 v1->lmm_magic = __swab32(LOV_MAGIC_V3_DEF);
1152 static int mdt_open_unpack(struct mdt_thread_info *info)
1154 struct md_ucred *uc = mdt_ucred(info);
1155 struct mdt_rec_create *rec;
1156 struct lu_attr *attr = &info->mti_attr.ma_attr;
1157 struct req_capsule *pill = info->mti_pill;
1158 struct mdt_reint_record *rr = &info->mti_rr;
1159 struct ptlrpc_request *req = mdt_info_req(info);
1160 struct md_op_spec *sp = &info->mti_spec;
1163 CLASSERT(sizeof(struct mdt_rec_create) == sizeof(struct mdt_rec_reint));
1164 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
1168 uc->mu_fsuid = rec->cr_fsuid;
1169 uc->mu_fsgid = rec->cr_fsgid;
1170 uc->mu_cap = rec->cr_cap;
1171 uc->mu_suppgids[0] = rec->cr_suppgid1;
1172 uc->mu_suppgids[1] = rec->cr_suppgid2;
1173 uc->mu_umask = rec->cr_umask;
1175 rr->rr_fid1 = &rec->cr_fid1;
1176 rr->rr_fid2 = &rec->cr_fid2;
1177 rr->rr_handle = &rec->cr_old_handle;
1178 attr->la_mode = rec->cr_mode;
1179 attr->la_rdev = rec->cr_rdev;
1180 attr->la_uid = rec->cr_fsuid;
1181 attr->la_gid = rec->cr_fsgid;
1182 attr->la_ctime = rec->cr_time;
1183 attr->la_mtime = rec->cr_time;
1184 attr->la_atime = rec->cr_time;
1185 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
1186 LA_CTIME | LA_MTIME | LA_ATIME;
1187 memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u));
1188 info->mti_spec.sp_cr_flags = get_mrc_cr_flags(rec);
1189 /* Do not trigger ASSERTION if client miss to set such flags. */
1190 if (unlikely(info->mti_spec.sp_cr_flags == 0))
1192 info->mti_replayepoch = rec->cr_ioepoch;
1194 info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
1196 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1197 mdt_set_capainfo(info, 0, rr->rr_fid1,
1198 req_capsule_client_get(pill, &RMF_CAPA1));
1199 if (req_is_replay(req) &&
1200 req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT)) {
1202 mdt_set_capainfo(info, 1, rr->rr_fid2,
1203 req_capsule_client_get(pill, &RMF_CAPA2));
1206 * FIXME: capa in replay open request might have expired,
1207 * bypass capa check. Security hole?
1209 mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
1210 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
1214 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1215 if (rr->rr_name == NULL)
1217 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1219 if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) {
1220 rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
1222 if (rr->rr_eadatalen > 0) {
1223 rr->rr_eadata = req_capsule_client_get(pill,
1225 sp->u.sp_ea.eadatalen = rr->rr_eadatalen;
1226 sp->u.sp_ea.eadata = rr->rr_eadata;
1227 sp->no_create = !!req_is_replay(req);
1228 mdt_fix_lov_magic(info);
1232 * Client default md_size may be 0 right after client start,
1233 * until all osc are connected, set here just some reasonable
1234 * value to prevent misbehavior.
1236 if (rr->rr_eadatalen == 0 &&
1237 !(info->mti_spec.sp_cr_flags & MDS_OPEN_DELAY_CREATE))
1238 rr->rr_eadatalen = MIN_MD_SIZE;
1244 static int mdt_setxattr_unpack(struct mdt_thread_info *info)
1246 struct mdt_reint_record *rr = &info->mti_rr;
1247 struct md_ucred *uc = mdt_ucred(info);
1248 struct lu_attr *attr = &info->mti_attr.ma_attr;
1249 struct req_capsule *pill = info->mti_pill;
1250 struct mdt_rec_setxattr *rec;
1254 CLASSERT(sizeof(struct mdt_rec_setxattr) ==
1255 sizeof(struct mdt_rec_reint));
1257 rec = req_capsule_client_get(pill, &RMF_REC_REINT);
1261 uc->mu_fsuid = rec->sx_fsuid;
1262 uc->mu_fsgid = rec->sx_fsgid;
1263 uc->mu_cap = rec->sx_cap;
1264 uc->mu_suppgids[0] = rec->sx_suppgid1;
1265 uc->mu_suppgids[1] = -1;
1267 rr->rr_opcode = rec->sx_opcode;
1268 rr->rr_fid1 = &rec->sx_fid;
1269 attr->la_valid = rec->sx_valid;
1270 attr->la_ctime = rec->sx_time;
1271 attr->la_size = rec->sx_size;
1272 attr->la_flags = rec->sx_flags;
1274 if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1275 mdt_set_capainfo(info, 0, rr->rr_fid1,
1276 req_capsule_client_get(pill, &RMF_CAPA1));
1278 mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
1280 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1281 if (rr->rr_name == NULL)
1283 rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1284 LASSERT(rr->rr_namelen > 0);
1286 if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) {
1287 rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
1289 if (rr->rr_eadatalen > 0) {
1290 rr->rr_eadata = req_capsule_client_get(pill,
1292 if (rr->rr_eadata == NULL)
1295 rr->rr_eadata = NULL;
1297 } else if (!(attr->la_valid & OBD_MD_FLXATTRRM)) {
1298 CDEBUG(D_INFO, "no xattr data supplied\n");
1306 typedef int (*reint_unpacker)(struct mdt_thread_info *info);
1308 static reint_unpacker mdt_reint_unpackers[REINT_MAX] = {
1309 [REINT_SETATTR] = mdt_setattr_unpack,
1310 [REINT_CREATE] = mdt_create_unpack,
1311 [REINT_LINK] = mdt_link_unpack,
1312 [REINT_UNLINK] = mdt_unlink_unpack,
1313 [REINT_RENAME] = mdt_rename_unpack,
1314 [REINT_OPEN] = mdt_open_unpack,
1315 [REINT_SETXATTR] = mdt_setxattr_unpack
1318 int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op)
1323 memset(&info->mti_rr, 0, sizeof(info->mti_rr));
1324 if (op < REINT_MAX && mdt_reint_unpackers[op] != NULL) {
1325 info->mti_rr.rr_opcode = op;
1326 rc = mdt_reint_unpackers[op](info);
1328 CERROR("Unexpected opcode %d\n", op);