Whamcloud - gitweb
land b_colibri_devel on HEAD:
[fs/lustre-release.git] / lustre / mdt / mdt_lib.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/mdt/mdt_lib.c
5  *  Lustre Metadata Target (mdt) request unpacking helper.
6  *
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>
15  *
16  *
17  *   This file is part of the Lustre file system, http://www.lustre.org
18  *   Lustre is a trademark of Cluster File Systems, Inc.
19  *
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.
24  *
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.
29  *
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.
34  */
35
36
37 #ifndef EXPORT_SYMTAB
38 # define EXPORT_SYMTAB
39 #endif
40 #define DEBUG_SUBSYSTEM S_MDS
41
42 #include "mdt_internal.h"
43
44
45 typedef enum ucred_init_type {
46         NONE_INIT       = 0,
47         BODY_INIT       = 1,
48         REC_INIT        = 2
49 } ucred_init_type_t;
50
51 void mdt_exit_ucred(struct mdt_thread_info *info)
52 {
53         struct md_ucred   *uc  = mdt_ucred(info);
54         struct mdt_device *mdt = info->mti_mdt;
55
56         if (uc->mu_valid != UCRED_INIT) {
57                 uc->mu_suppgids[0] = uc->mu_suppgids[1] = -1;
58                 if (uc->mu_ginfo) {
59                         groups_free(uc->mu_ginfo);
60                         uc->mu_ginfo = NULL;
61                 }
62                 if (uc->mu_identity) {
63                         mdt_identity_put(mdt->mdt_identity_cache,
64                                          uc->mu_identity);
65                         uc->mu_identity = NULL;
66                 }
67                 uc->mu_valid = UCRED_INIT;
68         }
69 }
70
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)
74 {
75         return 0;
76 }
77
78 static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
79                           void *buf)
80 {
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;
87         __u32                    perm = 0;
88         int                     setuid;
89         int                     setgid;
90         int                     rc = 0;
91
92         ENTRY;
93
94         LASSERT(req->rq_auth_gss);
95         LASSERT(!req->rq_auth_usr_mdt);
96         LASSERT(req->rq_user_desc);
97         
98         ucred->mu_valid = UCRED_INVALID;
99
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;
104
105         if (type == BODY_INIT) {
106                 struct mdt_body *body = (struct mdt_body *)buf;
107
108                 ucred->mu_suppgids[0] = body->suppgid;
109                 ucred->mu_suppgids[1] = -1;
110         }
111
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                         CWARN("remote user not mapped, deny access!\n");
116                         RETURN(-EACCES);
117                 }
118
119                 if (ptlrpc_user_desc_do_idmap(req, pud))
120                         RETURN(-EACCES);
121
122                 if (req->rq_auth_mapped_uid != pud->pud_uid) {
123                         CERROR("remote client "LPU64": auth/mapped uid %u/%u "
124                                "while client claim %u:%u/%u:%u\n",
125                                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);
129                         RETURN(-EACCES);
130                 }
131         } else {
132                 if (req->rq_auth_uid != pud->pud_uid) {
133                         CERROR("local client "LPU64": auth uid %u "
134                                "while client claim %u:%u/%u:%u\n",
135                                peernid, req->rq_auth_uid, pud->pud_uid,
136                                pud->pud_gid, pud->pud_fsuid, pud->pud_fsgid);
137                         RETURN(-EACCES);
138                 }
139         }
140
141         if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
142                 if (med->med_rmtclient) {
143                         CERROR("remote client must run with identity_get "
144                                "enabled!\n");
145                         RETURN(-EACCES);
146                 } else {
147                         ucred->mu_identity = NULL;
148                         perm = CFS_SETUID_PERM | CFS_SETGID_PERM |
149                                CFS_SETGRP_PERM;
150                 }
151         } else {
152                 ucred->mu_identity = mdt_identity_get(mdt->mdt_identity_cache,
153                                                       pud->pud_uid);
154                 if (!ucred->mu_identity) {
155                         CERROR("Deny access without identity: uid %d\n",
156                                pud->pud_uid);
157                 RETURN(-EACCES);
158                 } else {
159                         perm = mdt_identity_get_perm(ucred->mu_identity,
160                                                    med->med_rmtclient,
161                                                    peernid);
162                 }
163         }
164
165         /* find out the setuid/setgid attempt */
166         setuid = (pud->pud_uid != pud->pud_fsuid);
167         setgid = ((pud->pud_gid != pud->pud_fsgid) ||
168                   (ucred->mu_identity &&
169                   (pud->pud_gid != ucred->mu_identity->mi_gid)));
170
171         /* check permission of setuid */
172         if (setuid && !(perm & CFS_SETUID_PERM)) {
173                 CWARN("mdt blocked setuid attempt (%u -> %u) from "
174                       LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
175                 GOTO(out, rc = -EACCES);
176         }
177
178         /* check permission of setgid */
179         if (setgid && !(perm & CFS_SETGID_PERM)) {
180                 CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
181                       "from "LPX64"\n", pud->pud_uid, pud->pud_gid,
182                       pud->pud_fsuid, pud->pud_fsgid,
183                       ucred->mu_identity->mi_gid, peernid);
184                 GOTO(out, rc = -EACCES);
185         }
186
187         /*
188          * NB: remote client not allowed to setgroups anyway.
189          */
190         if (!med->med_rmtclient && perm & CFS_SETGRP_PERM) {
191                 if (pud->pud_ngroups) {
192                 /* setgroups for local client */
193                         ucred->mu_ginfo = groups_alloc(pud->pud_ngroups);
194                         if (!ucred->mu_ginfo) {
195                         CERROR("failed to alloc %d groups\n",
196                                pud->pud_ngroups);
197                         GOTO(out, rc = -ENOMEM);
198                 }
199
200                         lustre_groups_from_list(ucred->mu_ginfo,
201                                                 pud->pud_groups);
202                         lustre_groups_sort(ucred->mu_ginfo);
203         } else {
204                 ucred->mu_ginfo = NULL;
205         }
206         } else {
207                 ucred->mu_suppgids[0] = -1;
208                 ucred->mu_suppgids[1] = -1;
209                 ucred->mu_ginfo = NULL;
210         }
211
212         ucred->mu_uid   = pud->pud_uid;
213         ucred->mu_gid   = pud->pud_gid;
214         ucred->mu_fsuid = pud->pud_fsuid;
215         ucred->mu_fsgid = pud->pud_fsgid;
216
217         /* XXX: need to process root_squash here. */
218         mdt_root_squash(info);
219
220         /* remove fs privilege for non-root user */
221         if (ucred->mu_fsuid)
222                 ucred->mu_cap = pud->pud_cap & ~CAP_FS_MASK;
223         else
224                 ucred->mu_cap = pud->pud_cap;
225         ucred->mu_valid = UCRED_NEW;
226
227         EXIT;
228
229 out:
230         if (rc) {
231                 if (ucred->mu_ginfo) {
232                         groups_free(ucred->mu_ginfo);
233                         ucred->mu_ginfo = NULL;
234                 }
235                 if (ucred->mu_identity) {
236                         mdt_identity_put(mdt->mdt_identity_cache,
237                                          ucred->mu_identity);
238                         ucred->mu_identity = NULL;
239                 }
240         }
241
242         return rc;
243 }
244
245 int mdt_check_ucred(struct mdt_thread_info *info)
246 {
247         struct ptlrpc_request   *req = mdt_info_req(info);
248         struct mdt_export_data  *med = mdt_req2med(req);
249         struct mdt_device       *mdt = info->mti_mdt;
250         struct ptlrpc_user_desc *pud = req->rq_user_desc;
251         struct md_ucred         *ucred = mdt_ucred(info);
252         struct md_identity      *identity = NULL;
253         lnet_nid_t              peernid = req->rq_peer.nid;
254         __u32                    perm = 0;
255         int                      setuid;
256         int                      setgid;
257         int                      rc = 0;
258
259         ENTRY;
260
261         if ((ucred->mu_valid == UCRED_OLD) || (ucred->mu_valid == UCRED_NEW))
262                 RETURN(0);
263
264         if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
265                 RETURN(0);
266
267         /* sanity check: if we use strong authentication, we expect the
268          * uid which client claimed is true */
269                 if (med->med_rmtclient) {
270                         if (req->rq_auth_mapped_uid == INVALID_UID) {
271                                 CWARN("remote user not mapped, deny access!\n");
272                                 RETURN(-EACCES);
273                         }
274
275                         if (ptlrpc_user_desc_do_idmap(req, pud))
276                                 RETURN(-EACCES);
277
278                         if (req->rq_auth_mapped_uid != pud->pud_uid) {
279                         CERROR("remote client "LPU64": auth/mapped uid %u/%u "
280                                        "while client claim %u:%u/%u:%u\n",
281                                peernid, req->rq_auth_uid,
282                                req->rq_auth_mapped_uid,
283                                pud->pud_uid, pud->pud_gid,
284                                pud->pud_fsuid, pud->pud_fsgid);
285                                 RETURN(-EACCES);
286                         }
287                 } else {
288                         if (req->rq_auth_uid != pud->pud_uid) {
289                                 CERROR("local client "LPU64": auth uid %u "
290                                        "while client claim %u:%u/%u:%u\n",
291                                        peernid, req->rq_auth_uid, pud->pud_uid,
292                                        pud->pud_gid, pud->pud_fsuid,
293                                        pud->pud_fsgid);
294                                 RETURN(-EACCES);
295                         }
296                 }
297
298         if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
299                 if (med->med_rmtclient) {
300                         CERROR("remote client must run with identity_get "
301                                "enabled!\n");
302                         RETURN(-EACCES);
303                 }
304                 RETURN(0);
305         }
306
307         identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid);
308         if (!identity) {
309                 CERROR("Deny access without identity: uid %d\n", pud->pud_uid);
310                 RETURN(-EACCES);
311         }
312
313         perm = mdt_identity_get_perm(identity, med->med_rmtclient, peernid);
314         /* find out the setuid/setgid attempt */
315         setuid = (pud->pud_uid != pud->pud_fsuid);
316         setgid = (pud->pud_gid != pud->pud_fsgid ||
317                   pud->pud_gid != identity->mi_gid);
318
319         /* check permission of setuid */
320         if (setuid && !(perm & CFS_SETUID_PERM)) {
321                 CWARN("mdt blocked setuid attempt (%u -> %u) from "
322                       LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
323                 GOTO(out, rc = -EACCES);
324         }
325
326         /* check permission of setgid */
327         if (setgid && !(perm & CFS_SETGID_PERM)) {
328                 CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
329                       "from "LPX64"\n", pud->pud_uid, pud->pud_gid,
330                       pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid,
331                       peernid);
332                 GOTO(out, rc = -EACCES);
333         }
334
335         EXIT;
336
337 out:
338         mdt_identity_put(mdt->mdt_identity_cache, identity);
339         return rc;
340 }
341
342 static int old_init_ucred(struct mdt_thread_info *info,
343                           struct mdt_body *body)
344 {
345         struct md_ucred *uc = mdt_ucred(info);
346         struct mdt_device  *mdt = info->mti_mdt;
347         struct md_identity *identity = NULL;
348
349         ENTRY;
350
351         uc->mu_valid = UCRED_INVALID;
352         uc->mu_o_uid = uc->mu_uid = body->uid;
353         uc->mu_o_gid = uc->mu_gid = body->gid;
354         uc->mu_o_fsuid = uc->mu_fsuid = body->fsuid;
355         uc->mu_o_fsgid = uc->mu_fsgid = body->fsgid;
356         uc->mu_suppgids[0] = body->suppgid;
357         uc->mu_suppgids[1] = -1;
358         uc->mu_ginfo = NULL;
359         if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
360                 identity = mdt_identity_get(mdt->mdt_identity_cache,
361                                             uc->mu_fsuid);
362                 if (!identity) {
363                         CERROR("Deny access without identity: uid %d\n",
364                                uc->mu_fsuid);
365                         RETURN(-EACCES);
366                 }
367         }
368         uc->mu_identity = identity;
369
370         /* XXX: need to process root_squash here. */
371         mdt_root_squash(info);
372
373         /* remove fs privilege for non-root user */
374         if (uc->mu_fsuid)
375                 uc->mu_cap = body->capability & ~CAP_FS_MASK;
376         else
377                 uc->mu_cap = body->capability;
378         uc->mu_valid = UCRED_OLD;
379
380         RETURN(0);
381 }
382
383 static int old_init_ucred_reint(struct mdt_thread_info *info)
384 {
385         struct md_ucred *uc = mdt_ucred(info);
386         struct mdt_device  *mdt = info->mti_mdt;
387         struct md_identity *identity = NULL;
388
389         ENTRY;
390
391         uc->mu_valid = UCRED_INVALID;
392         uc->mu_o_uid = uc->mu_o_fsuid = uc->mu_uid = uc->mu_fsuid;
393         uc->mu_o_gid = uc->mu_o_fsgid = uc->mu_gid = uc->mu_fsgid;
394         uc->mu_ginfo = NULL;
395         if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
396                 identity = mdt_identity_get(mdt->mdt_identity_cache,
397                                             uc->mu_fsuid);
398                 if (!identity) {
399                         CERROR("Deny access without identity: uid %d\n",
400                                uc->mu_fsuid);
401                         RETURN(-EACCES);
402         }
403         }
404         uc->mu_identity = identity;
405
406         /* XXX: need to process root_squash here. */
407         mdt_root_squash(info);
408
409         /* remove fs privilege for non-root user */
410         if (uc->mu_fsuid)
411                 uc->mu_cap &= ~CAP_FS_MASK;
412         uc->mu_valid = UCRED_OLD;
413
414         RETURN(0);
415 }
416
417 int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body)
418 {
419         struct ptlrpc_request *req = mdt_info_req(info);
420         struct md_ucred       *uc  = mdt_ucred(info);
421
422         if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))
423                 return 0;
424
425         mdt_exit_ucred(info);
426
427         if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
428                 return old_init_ucred(info, body);
429         else
430                 return new_init_ucred(info, BODY_INIT, body);
431 }
432
433 int mdt_init_ucred_reint(struct mdt_thread_info *info)
434 {
435         struct ptlrpc_request *req = mdt_info_req(info);
436         struct md_ucred       *uc  = mdt_ucred(info);
437
438         if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))
439                 return 0;
440
441         mdt_exit_ucred(info);
442
443         if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
444                 return old_init_ucred_reint(info);
445         else
446                 return new_init_ucred(info, REC_INIT, NULL);
447 }
448
449 /* copied from lov/lov_ea.c, just for debugging, will be removed later */
450 void mdt_dump_lmm(int level, const struct lov_mds_md *lmm)
451 {
452         const struct lov_ost_data_v1 *lod;
453         int i;
454         __s16 stripe_count =
455                 le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count);
456
457         CDEBUG(level, "objid "LPX64", magic 0x%08X, pattern %#X\n",
458                le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic),
459                le32_to_cpu(lmm->lmm_pattern));
460         CDEBUG(level,"stripe_size=0x%x, stripe_count=0x%x\n",
461                le32_to_cpu(lmm->lmm_stripe_size),
462                le32_to_cpu(lmm->lmm_stripe_count));
463         LASSERT(stripe_count <= (__s16)LOV_MAX_STRIPE_COUNT);
464         for (i = 0, lod = lmm->lmm_objects; i < stripe_count; i++, lod++) {
465                 CDEBUG(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n",
466                        i, le32_to_cpu(lod->l_ost_idx),
467                        le64_to_cpu(lod->l_object_gr),
468                        le64_to_cpu(lod->l_object_id));
469         }
470 }
471
472 void mdt_shrink_reply(struct mdt_thread_info *info)
473 {
474         struct req_capsule    *pill = &info->mti_pill;
475         struct mdt_body       *body;
476         int acl_size, md_size, adjust = 0;
477         ENTRY;
478
479         body = req_capsule_server_get(pill, &RMF_MDT_BODY);
480         LASSERT(body != NULL);
481
482         if (body->valid & (OBD_MD_FLDIREA | OBD_MD_FLEASIZE | OBD_MD_LINKNAME))
483                 md_size = body->eadatasize;
484         else
485                 md_size = 0;
486
487         acl_size = body->aclsize;
488
489         CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d" 
490                         " MDSCAPA = %d, OSSCAPA = %d\n",
491                         md_size, acl_size,
492                         (int)(body->valid & OBD_MD_FLMDSCAPA),
493                         (int)(body->valid & OBD_MD_FLOSSCAPA));
494 /*
495             &RMF_MDT_BODY,
496             &RMF_MDT_MD,
497             &RMF_ACL, or &RMF_LOGCOOKIES
498 (optional)  &RMF_CAPA1,
499 (optional)  &RMF_CAPA2,
500 (optional)  something else
501 */
502         adjust += req_capsule_shrink(pill, &RMF_MDT_MD,
503                                     md_size, adjust, 1);
504
505         if (req_capsule_has_field(pill, &RMF_ACL, RCL_SERVER))
506                 adjust += req_capsule_shrink(pill, &RMF_ACL,
507                                             acl_size, adjust, 1);
508         else if (req_capsule_has_field(pill, &RMF_LOGCOOKIES, RCL_SERVER))
509                 adjust += req_capsule_shrink(pill, &RMF_LOGCOOKIES,
510                                             acl_size, adjust, 1);
511
512         /* RMF_CAPA1 on server-side maybe for OBD_MD_FLMDSCAPA or
513          * OBD_MD_FLOSSCAPA. If RMF_CAPA2 exist also, RMF_CAPA1 is
514          * for OBD_MD_FLMDSCAPA only. */
515         if (req_capsule_has_field(pill, &RMF_CAPA1, RCL_SERVER)) {
516                 if ((req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) &&
517                     !(body->valid & OBD_MD_FLMDSCAPA)) ||
518                     (!req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) &&
519                     !(body->valid & OBD_MD_FLMDSCAPA) &&
520                     !(body->valid & OBD_MD_FLOSSCAPA)))
521                         adjust += req_capsule_shrink(pill, &RMF_CAPA1,
522                                                      0, adjust, 1);
523         }
524
525         /* RMF_CAPA2 on server-side is for OBD_MD_FLOSSCAPA only. */
526         if ((req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) &&
527                 !(body->valid & OBD_MD_FLOSSCAPA)))
528                 adjust += req_capsule_shrink(pill, &RMF_CAPA2, 0, adjust, 0);
529
530         /*
531          * Some more field should be shrinked if needed.
532          * This should be done by those who added fields to reply message.
533          */
534         EXIT;
535 }
536
537
538 /* if object is dying, pack the lov/llog data,
539  * parameter info->mti_attr should be valid at this point! */
540 int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo,
541                            const struct md_attr *ma)
542 {
543         struct mdt_body       *repbody;
544         const struct lu_attr *la = &ma->ma_attr;
545         ENTRY;
546
547         repbody = req_capsule_server_get(&info->mti_pill, &RMF_MDT_BODY);
548         LASSERT(repbody != NULL);
549
550         if (ma->ma_valid & MA_INODE)
551                 mdt_pack_attr2body(info, repbody, la, mdt_object_fid(mo));
552
553         if (ma->ma_valid & MA_LOV) {
554                 __u32 mode;
555
556                 if (mdt_object_exists(mo) < 0)
557                         /* If it is a remote object, and we do not retrieve
558                          * EA back unlink reg file*/
559                         mode = S_IFREG;
560                 else
561                         mode = lu_object_attr(&mo->mot_obj.mo_lu);
562
563                 LASSERT(ma->ma_lmm_size);
564                 mdt_dump_lmm(D_INFO, ma->ma_lmm);
565                 repbody->eadatasize = ma->ma_lmm_size;
566                 if (S_ISREG(mode))
567                         repbody->valid |= OBD_MD_FLEASIZE;
568                 else if (S_ISDIR(mode))
569                         repbody->valid |= OBD_MD_FLDIREA;
570                 else
571                         LBUG();
572         }
573
574         if (ma->ma_cookie_size && (ma->ma_valid & MA_COOKIE)) {
575                 repbody->aclsize = ma->ma_cookie_size;
576                 repbody->valid |= OBD_MD_FLCOOKIE;
577         }
578
579         RETURN(0);
580 }
581
582 static inline unsigned int attr_unpack(__u64 sa_valid) {
583         unsigned int ia_valid = 0;
584
585         if (sa_valid & MDS_ATTR_MODE)
586                 ia_valid |= ATTR_MODE;
587         if (sa_valid & MDS_ATTR_UID)
588                 ia_valid |= ATTR_UID;
589         if (sa_valid & MDS_ATTR_GID)
590                 ia_valid |= ATTR_GID;
591         if (sa_valid & MDS_ATTR_SIZE)
592                 ia_valid |= ATTR_SIZE;
593         if (sa_valid & MDS_ATTR_ATIME)
594                 ia_valid |= ATTR_ATIME;
595         if (sa_valid & MDS_ATTR_MTIME)
596                 ia_valid |= ATTR_MTIME;
597         if (sa_valid & MDS_ATTR_CTIME)
598                 ia_valid |= ATTR_CTIME;
599         if (sa_valid & MDS_ATTR_ATIME_SET)
600                 ia_valid |= ATTR_ATIME_SET;
601         if (sa_valid & MDS_ATTR_MTIME_SET)
602                 ia_valid |= ATTR_MTIME_SET;
603         if (sa_valid & MDS_ATTR_FORCE)
604                 ia_valid |= ATTR_FORCE;
605         if (sa_valid & MDS_ATTR_ATTR_FLAG)
606                 ia_valid |= ATTR_ATTR_FLAG;
607         if (sa_valid & MDS_ATTR_KILL_SUID)
608                 ia_valid |=  ATTR_KILL_SUID;
609         if (sa_valid & MDS_ATTR_KILL_SGID)
610                 ia_valid |= ATTR_KILL_SGID;
611         if (sa_valid & MDS_ATTR_CTIME_SET)
612                 ia_valid |= ATTR_CTIME_SET;
613         if (sa_valid & MDS_ATTR_FROM_OPEN)
614                 ia_valid |= ATTR_FROM_OPEN;
615         if (sa_valid & MDS_ATTR_BLOCKS)
616                 ia_valid |= ATTR_BLOCKS;
617         if (sa_valid & MDS_OPEN_OWNEROVERRIDE)
618                 ia_valid |= MDS_OPEN_OWNEROVERRIDE;
619         return ia_valid;
620 }
621
622 static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
623                                   struct md_attr *ma)
624 {
625         __u64 out;
626
627         out = 0;
628         if (in & ATTR_MODE)
629                 out |= LA_MODE;
630         if (in & ATTR_UID)
631                 out |= LA_UID;
632         if (in & ATTR_GID)
633                 out |= LA_GID;
634         if (in & ATTR_SIZE)
635                 out |= LA_SIZE;
636         if (in & ATTR_BLOCKS)
637                 out |= LA_BLOCKS;
638
639         if (in & ATTR_FROM_OPEN)
640                 rr->rr_flags |= MRF_SETATTR_LOCKED;
641
642         if (in & ATTR_ATIME_SET)
643                 out |= LA_ATIME;
644
645         if (in & ATTR_CTIME_SET)
646                 out |= LA_CTIME;
647
648         if (in & ATTR_MTIME_SET)
649                 out |= LA_MTIME;
650
651         if (in & ATTR_ATTR_FLAG)
652                 out |= LA_FLAGS;
653
654         if (in & MDS_OPEN_OWNEROVERRIDE)
655                 out |= MDS_OPEN_OWNEROVERRIDE;
656
657         /*XXX need ATTR_RAW?*/
658         in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
659                 ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
660                 ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
661                 ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE);
662         if (in != 0)
663                 CERROR("Unknown attr bits: %#llx\n", in);
664         return out;
665 }
666 /* unpacking */
667
668 static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
669 {
670         struct md_ucred         *uc  = mdt_ucred(info);
671         struct md_attr          *ma = &info->mti_attr;
672         struct lu_attr          *la = &ma->ma_attr;
673         struct req_capsule      *pill = &info->mti_pill;
674         struct mdt_reint_record *rr = &info->mti_rr;
675         struct mdt_rec_setattr  *rec;
676         ENTRY;
677
678         rec = req_capsule_client_get(pill, &RMF_REC_SETATTR);
679         if (rec == NULL)
680                 RETURN(-EFAULT);
681
682         uc->mu_fsuid = rec->sa_fsuid;
683         uc->mu_fsgid = rec->sa_fsgid;
684         uc->mu_cap   = rec->sa_cap;
685         uc->mu_suppgids[0] = rec->sa_suppgid;
686         uc->mu_suppgids[1] = -1;
687
688         rr->rr_fid1 = &rec->sa_fid;
689         la->la_valid = mdt_attr_valid_xlate(attr_unpack(rec->sa_valid), rr, ma);
690         la->la_mode  = rec->sa_mode;
691         la->la_flags = rec->sa_attr_flags;
692         la->la_uid   = rec->sa_uid;
693         la->la_gid   = rec->sa_gid;
694         la->la_size  = rec->sa_size;
695         la->la_blocks = rec->sa_blocks;
696         la->la_ctime = rec->sa_ctime;
697         la->la_atime = rec->sa_atime;
698         la->la_mtime = rec->sa_mtime;
699         ma->ma_valid = MA_INODE;
700
701         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
702                 mdt_set_capainfo(info, 0, rr->rr_fid1,
703                                  req_capsule_client_get(pill, &RMF_CAPA1));
704
705         RETURN(0);
706 }
707
708 static int mdt_epoch_unpack(struct mdt_thread_info *info)
709 {
710         struct req_capsule *pill = &info->mti_pill;
711         ENTRY;
712
713         if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT))
714                 info->mti_epoch = req_capsule_client_get(pill, &RMF_MDT_EPOCH);
715         else
716                 info->mti_epoch = NULL;
717         RETURN(info->mti_epoch == NULL ? -EFAULT : 0);
718 }
719
720 static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) {
721         struct req_capsule      *pill = &info->mti_pill;
722
723         if (req_capsule_get_size(pill, &RMF_DLM_REQ, RCL_CLIENT)) {
724                 info->mti_dlm_req = req_capsule_client_get(pill, &RMF_DLM_REQ);
725                 if (info->mti_dlm_req == NULL)
726                         RETURN(-EFAULT);
727         }
728         
729         RETURN(0);
730 }
731
732 static int mdt_setattr_unpack(struct mdt_thread_info *info)
733 {
734         struct md_attr          *ma = &info->mti_attr;
735         struct req_capsule      *pill = &info->mti_pill;
736         int rc;
737         ENTRY;
738
739         rc = mdt_setattr_unpack_rec(info);
740         if (rc)
741                 RETURN(rc);
742
743         /* Epoch may be absent */
744         mdt_epoch_unpack(info);
745
746         ma->ma_lmm_size = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT);
747         if (ma->ma_lmm_size) {
748                 ma->ma_lmm = req_capsule_client_get(pill, &RMF_EADATA);
749                 ma->ma_valid |= MA_LOV;
750         }
751
752         ma->ma_cookie_size = req_capsule_get_size(pill, &RMF_LOGCOOKIES,
753                                                   RCL_CLIENT);
754         if (ma->ma_cookie_size) {
755                 ma->ma_cookie = req_capsule_client_get(pill, &RMF_LOGCOOKIES);
756                 ma->ma_valid |= MA_COOKIE;
757         }
758
759         rc = mdt_dlmreq_unpack(info);
760         RETURN(rc);
761 }
762
763 int mdt_close_unpack(struct mdt_thread_info *info)
764 {
765         int rc;
766         ENTRY;
767
768         rc = mdt_epoch_unpack(info);
769         if (rc)
770                 RETURN(rc);
771
772         RETURN(mdt_setattr_unpack_rec(info));
773 }
774
775 static int mdt_create_unpack(struct mdt_thread_info *info)
776 {
777         struct md_ucred         *uc  = mdt_ucred(info);
778         struct mdt_rec_create   *rec;
779         struct lu_attr          *attr = &info->mti_attr.ma_attr;
780         struct mdt_reint_record *rr = &info->mti_rr;
781         struct req_capsule      *pill = &info->mti_pill;
782         struct md_op_spec       *sp = &info->mti_spec;
783         int rc;
784         ENTRY;
785
786         rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
787         if (rec == NULL)
788                 RETURN(-EFAULT);
789
790         uc->mu_fsuid = rec->cr_fsuid;
791         uc->mu_fsgid = rec->cr_fsgid;
792         uc->mu_cap   = rec->cr_cap;
793         uc->mu_suppgids[0] = rec->cr_suppgid1;
794         uc->mu_suppgids[1] = -1;
795
796         rr->rr_fid1 = &rec->cr_fid1;
797         rr->rr_fid2 = &rec->cr_fid2;
798         attr->la_mode = rec->cr_mode;
799         attr->la_rdev  = rec->cr_rdev;
800         attr->la_uid   = rec->cr_fsuid;
801         attr->la_gid   = rec->cr_fsgid;
802         attr->la_ctime = rec->cr_time;
803         attr->la_mtime = rec->cr_time;
804         attr->la_atime = rec->cr_time;
805         attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
806                          LA_CTIME | LA_MTIME | LA_ATIME;
807         memset(&sp->u, 0, sizeof(sp->u));
808         sp->sp_cr_flags = rec->cr_flags;
809         sp->sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
810         info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
811
812         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
813                 mdt_set_capainfo(info, 0, rr->rr_fid1,
814                                  req_capsule_client_get(pill, &RMF_CAPA1));
815         mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
816
817         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
818         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
819         LASSERT(rr->rr_namelen > 0);
820         
821 #ifdef CONFIG_FS_POSIX_ACL
822         if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) {
823                 if (S_ISDIR(attr->la_mode))
824                         sp->u.sp_pfid = rr->rr_fid1;
825                 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
826                 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
827                                                   RCL_CLIENT));
828                 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
829                 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
830                                                                 RCL_CLIENT);
831                 sp->u.sp_ea.fid = rr->rr_fid1;
832                 RETURN(0);
833         }
834 #endif
835         if (S_ISDIR(attr->la_mode)) {
836                 /* pass parent fid for cross-ref cases */
837                 sp->u.sp_pfid = rr->rr_fid1;
838                 if (sp->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
839                         /* create salve object req, need
840                          * unpack split ea here
841                          */
842                        req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SLAVE);
843                        LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
844                                                          RCL_CLIENT));
845                        sp->u.sp_ea.eadata = req_capsule_client_get(pill,
846                                                                    &RMF_EADATA);
847                        sp->u.sp_ea.eadatalen = req_capsule_get_size(pill,
848                                                                     &RMF_EADATA,
849                                                                     RCL_CLIENT);
850                        sp->u.sp_ea.fid = rr->rr_fid1;
851                        RETURN(0);
852                 }
853                 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
854         } else if (S_ISLNK(attr->la_mode)) {
855                 const char *tgt = NULL;
856
857                 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM);
858                 if (req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT)) {
859                         tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
860                         sp->u.sp_symname = tgt;
861                 }
862                 if (tgt == NULL)
863                         RETURN(-EFAULT);
864         } else {
865                 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
866         }
867         rc = mdt_dlmreq_unpack(info);
868         RETURN(rc);
869 }
870
871 static int mdt_link_unpack(struct mdt_thread_info *info)
872 {
873         struct md_ucred         *uc  = mdt_ucred(info);
874         struct mdt_rec_link     *rec;
875         struct lu_attr          *attr = &info->mti_attr.ma_attr;
876         struct mdt_reint_record *rr = &info->mti_rr;
877         struct req_capsule      *pill = &info->mti_pill;
878         int rc;
879         ENTRY;
880
881         rec = req_capsule_client_get(pill, &RMF_REC_LINK);
882         if (rec == NULL)
883                 RETURN(-EFAULT);
884
885         uc->mu_fsuid = rec->lk_fsuid;
886         uc->mu_fsgid = rec->lk_fsgid;
887         uc->mu_cap   = rec->lk_cap;
888         uc->mu_suppgids[0] = rec->lk_suppgid1;
889         uc->mu_suppgids[1] = rec->lk_suppgid2;
890
891         attr->la_uid = rec->lk_fsuid;
892         attr->la_gid = rec->lk_fsgid;
893         rr->rr_fid1 = &rec->lk_fid1;
894         rr->rr_fid2 = &rec->lk_fid2;
895         attr->la_ctime = rec->lk_time;
896         attr->la_mtime = rec->lk_time;
897         attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;
898
899         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
900                 mdt_set_capainfo(info, 0, rr->rr_fid1,
901                                  req_capsule_client_get(pill, &RMF_CAPA1));
902         if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
903                 mdt_set_capainfo(info, 1, rr->rr_fid2,
904                                  req_capsule_client_get(pill, &RMF_CAPA2));
905
906         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
907         if (rr->rr_name == NULL)
908                 RETURN(-EFAULT);
909         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
910         LASSERT(rr->rr_namelen > 0);
911         info->mti_spec.sp_ck_split = !!(rec->lk_bias & MDS_CHECK_SPLIT);
912         info->mti_cross_ref = !!(rec->lk_bias & MDS_CROSS_REF);
913
914         rc = mdt_dlmreq_unpack(info);
915         RETURN(rc);
916 }
917
918 static int mdt_unlink_unpack(struct mdt_thread_info *info)
919 {
920         struct md_ucred         *uc  = mdt_ucred(info);
921         struct mdt_rec_unlink   *rec;
922         struct md_attr          *ma = &info->mti_attr;
923         struct lu_attr          *attr = &info->mti_attr.ma_attr;
924         struct mdt_reint_record *rr = &info->mti_rr;
925         struct req_capsule      *pill = &info->mti_pill;
926         int rc;
927         ENTRY;
928
929         rec = req_capsule_client_get(pill, &RMF_REC_UNLINK);
930         if (rec == NULL)
931                 RETURN(-EFAULT);
932
933         uc->mu_fsuid = rec->ul_fsuid;
934         uc->mu_fsgid = rec->ul_fsgid;
935         uc->mu_cap   = rec->ul_cap;
936         uc->mu_suppgids[0] = rec->ul_suppgid;
937         uc->mu_suppgids[1] = -1;
938
939         attr->la_uid = rec->ul_fsuid;
940         attr->la_gid = rec->ul_fsgid;
941         rr->rr_fid1 = &rec->ul_fid1;
942         rr->rr_fid2 = &rec->ul_fid2;
943         attr->la_ctime = rec->ul_time;
944         attr->la_mtime = rec->ul_time;
945         attr->la_mode  = rec->ul_mode;
946         attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
947
948         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
949                 mdt_set_capainfo(info, 0, rr->rr_fid1,
950                                  req_capsule_client_get(pill, &RMF_CAPA1));
951
952         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
953         if (rr->rr_name == NULL)
954                 RETURN(-EFAULT);
955         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
956         LASSERT(rr->rr_namelen > 0);
957         info->mti_spec.sp_ck_split = !!(rec->ul_bias & MDS_CHECK_SPLIT);
958         info->mti_cross_ref = !!(rec->ul_bias & MDS_CROSS_REF);
959         if (rec->ul_bias & MDS_VTX_BYPASS)
960                 ma->ma_attr_flags |= MDS_VTX_BYPASS;
961         else
962                 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
963
964         rc = mdt_dlmreq_unpack(info);
965         RETURN(rc);
966 }
967
968 static int mdt_rename_unpack(struct mdt_thread_info *info)
969 {
970         struct md_ucred         *uc = mdt_ucred(info);
971         struct mdt_rec_rename   *rec;
972         struct md_attr          *ma = &info->mti_attr;
973         struct lu_attr          *attr = &info->mti_attr.ma_attr;
974         struct mdt_reint_record *rr = &info->mti_rr;
975         struct req_capsule      *pill = &info->mti_pill;
976         int rc;
977         ENTRY;
978
979         rec = req_capsule_client_get(pill, &RMF_REC_RENAME);
980         if (rec == NULL)
981                 RETURN(-EFAULT);
982
983         uc->mu_fsuid = rec->rn_fsuid;
984         uc->mu_fsgid = rec->rn_fsgid;
985         uc->mu_cap   = rec->rn_cap;
986         uc->mu_suppgids[0] = rec->rn_suppgid1;
987         uc->mu_suppgids[1] = rec->rn_suppgid2;
988
989         attr->la_uid = rec->rn_fsuid;
990         attr->la_gid = rec->rn_fsgid;
991         rr->rr_fid1 = &rec->rn_fid1;
992         rr->rr_fid2 = &rec->rn_fid2;
993         attr->la_ctime = rec->rn_time;
994         attr->la_mtime = rec->rn_time;
995         /* rename_tgt contains the mode already */
996         attr->la_mode = rec->rn_mode;
997         attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
998
999         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1000                 mdt_set_capainfo(info, 0, rr->rr_fid1,
1001                                  req_capsule_client_get(pill, &RMF_CAPA1));
1002         if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
1003                 mdt_set_capainfo(info, 1, rr->rr_fid2,
1004                                  req_capsule_client_get(pill, &RMF_CAPA2));
1005
1006         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1007         rr->rr_tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
1008         if (rr->rr_name == NULL || rr->rr_tgt == NULL)
1009                 RETURN(-EFAULT);
1010         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1011         LASSERT(rr->rr_namelen > 0);
1012         rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT) - 1;
1013         LASSERT(rr->rr_tgtlen > 0);
1014         info->mti_spec.sp_ck_split = !!(rec->rn_bias & MDS_CHECK_SPLIT);
1015         info->mti_cross_ref = !!(rec->rn_bias & MDS_CROSS_REF);
1016         if (rec->rn_bias & MDS_VTX_BYPASS)
1017                 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1018         else
1019                 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1020
1021         rc = mdt_dlmreq_unpack(info);
1022         RETURN(rc);
1023 }
1024
1025 static int mdt_open_unpack(struct mdt_thread_info *info)
1026 {
1027         struct md_ucred         *uc = mdt_ucred(info);
1028         struct mdt_rec_create   *rec;
1029         struct lu_attr          *attr = &info->mti_attr.ma_attr;
1030         struct req_capsule      *pill = &info->mti_pill;
1031         struct mdt_reint_record *rr   = &info->mti_rr;
1032         struct ptlrpc_request   *req  = mdt_info_req(info);
1033         struct md_op_spec       *sp   = &info->mti_spec;
1034         ENTRY;
1035
1036         rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
1037         if (rec == NULL)
1038                 RETURN(-EFAULT);
1039
1040         uc->mu_fsuid = rec->cr_fsuid;
1041         uc->mu_fsgid = rec->cr_fsgid;
1042         uc->mu_cap   = rec->cr_cap;
1043         uc->mu_suppgids[0] = rec->cr_suppgid1;
1044         uc->mu_suppgids[1] = rec->cr_suppgid2;
1045
1046         rr->rr_fid1   = &rec->cr_fid1;
1047         rr->rr_fid2   = &rec->cr_fid2;
1048         rr->rr_handle = &rec->cr_old_handle;
1049         attr->la_mode = rec->cr_mode;
1050         attr->la_rdev  = rec->cr_rdev;
1051         attr->la_uid   = rec->cr_fsuid;
1052         attr->la_gid   = rec->cr_fsgid;
1053         attr->la_ctime = rec->cr_time;
1054         attr->la_mtime = rec->cr_time;
1055         attr->la_atime = rec->cr_time;
1056         attr->la_valid = LA_MODE  | LA_RDEV  | LA_UID   | LA_GID |
1057                          LA_CTIME | LA_MTIME | LA_ATIME;
1058         memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u));
1059         info->mti_spec.sp_cr_flags = rec->cr_flags;
1060         info->mti_replayepoch = rec->cr_ioepoch;
1061
1062         info->mti_spec.sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
1063         info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
1064
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 ((lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) &&
1069             (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))) {
1070 #if 0
1071                 mdt_set_capainfo(info, 1, rr->rr_fid2,
1072                                  req_capsule_client_get(pill, &RMF_CAPA2));
1073 #else
1074                 /*
1075                  * FIXME: capa in replay open request might have expired,
1076                  * bypass capa check. Security hole?
1077                  */
1078                 mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
1079                 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
1080 #endif
1081         }
1082
1083         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1084         if (rr->rr_name == NULL)
1085                 RETURN(-EFAULT);
1086         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1087
1088         sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
1089                                                      RCL_CLIENT);
1090         if (sp->u.sp_ea.eadatalen) {
1091                 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
1092                 if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)
1093                         sp->u.sp_ea.no_lov_create = 1;
1094         }
1095
1096         RETURN(0);
1097 }
1098
1099 typedef int (*reint_unpacker)(struct mdt_thread_info *info);
1100
1101 static reint_unpacker mdt_reint_unpackers[REINT_MAX] = {
1102         [REINT_SETATTR]  = mdt_setattr_unpack,
1103         [REINT_CREATE]   = mdt_create_unpack,
1104         [REINT_LINK]     = mdt_link_unpack,
1105         [REINT_UNLINK]   = mdt_unlink_unpack,
1106         [REINT_RENAME]   = mdt_rename_unpack,
1107         [REINT_OPEN]     = mdt_open_unpack
1108 };
1109
1110 int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op)
1111 {
1112         int rc;
1113         ENTRY;
1114
1115         memset(&info->mti_rr, 0, sizeof(info->mti_rr));
1116         if (op < REINT_MAX && mdt_reint_unpackers[op] != NULL) {
1117                 info->mti_rr.rr_opcode = op;
1118                 rc = mdt_reint_unpackers[op](info);
1119         } else {
1120                 CERROR("Unexpected opcode %d\n", op);
1121                 rc = -EFAULT;
1122         }
1123         RETURN(rc);
1124 }