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