Whamcloud - gitweb
28500c9c0ffae6644eb4f8cc4c7d954781d6e261
[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 inline unsigned int attr_unpack(__u64 sa_valid) {
671         unsigned int ia_valid = 0;
672
673         if (sa_valid & MDS_ATTR_MODE)
674                 ia_valid |= ATTR_MODE;
675         if (sa_valid & MDS_ATTR_UID)
676                 ia_valid |= ATTR_UID;
677         if (sa_valid & MDS_ATTR_GID)
678                 ia_valid |= ATTR_GID;
679         if (sa_valid & MDS_ATTR_SIZE)
680                 ia_valid |= ATTR_SIZE;
681         if (sa_valid & MDS_ATTR_ATIME)
682                 ia_valid |= ATTR_ATIME;
683         if (sa_valid & MDS_ATTR_MTIME)
684                 ia_valid |= ATTR_MTIME;
685         if (sa_valid & MDS_ATTR_CTIME)
686                 ia_valid |= ATTR_CTIME;
687         if (sa_valid & MDS_ATTR_ATIME_SET)
688                 ia_valid |= ATTR_ATIME_SET;
689         if (sa_valid & MDS_ATTR_MTIME_SET)
690                 ia_valid |= ATTR_MTIME_SET;
691         if (sa_valid & MDS_ATTR_FORCE)
692                 ia_valid |= ATTR_FORCE;
693         if (sa_valid & MDS_ATTR_ATTR_FLAG)
694                 ia_valid |= ATTR_ATTR_FLAG;
695         if (sa_valid & MDS_ATTR_KILL_SUID)
696                 ia_valid |=  ATTR_KILL_SUID;
697         if (sa_valid & MDS_ATTR_KILL_SGID)
698                 ia_valid |= ATTR_KILL_SGID;
699         if (sa_valid & MDS_ATTR_CTIME_SET)
700                 ia_valid |= ATTR_CTIME_SET;
701         if (sa_valid & MDS_ATTR_FROM_OPEN)
702                 ia_valid |= ATTR_FROM_OPEN;
703         if (sa_valid & MDS_ATTR_BLOCKS)
704                 ia_valid |= ATTR_BLOCKS;
705         if (sa_valid & MDS_OPEN_OWNEROVERRIDE)
706                 ia_valid |= MDS_OPEN_OWNEROVERRIDE;
707         return ia_valid;
708 }
709
710 static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
711                                   struct md_attr *ma)
712 {
713         __u64 out;
714
715         out = 0;
716         if (in & ATTR_MODE)
717                 out |= LA_MODE;
718         if (in & ATTR_UID)
719                 out |= LA_UID;
720         if (in & ATTR_GID)
721                 out |= LA_GID;
722         if (in & ATTR_SIZE)
723                 out |= LA_SIZE;
724         if (in & ATTR_BLOCKS)
725                 out |= LA_BLOCKS;
726
727         if (in & ATTR_FROM_OPEN)
728                 rr->rr_flags |= MRF_SETATTR_LOCKED;
729
730         if (in & ATTR_ATIME_SET)
731                 out |= LA_ATIME;
732
733         if (in & ATTR_CTIME_SET)
734                 out |= LA_CTIME;
735
736         if (in & ATTR_MTIME_SET)
737                 out |= LA_MTIME;
738
739         if (in & ATTR_ATTR_FLAG)
740                 out |= LA_FLAGS;
741
742         if (in & MDS_OPEN_OWNEROVERRIDE)
743                 out |= MDS_OPEN_OWNEROVERRIDE;
744
745         /*XXX need ATTR_RAW?*/
746         in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
747                 ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
748                 ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
749                 ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE);
750         if (in != 0)
751                 CERROR("Unknown attr bits: %#llx\n", in);
752         return out;
753 }
754 /* unpacking */
755
756 static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
757 {
758         struct md_ucred         *uc  = mdt_ucred(info);
759         struct md_attr          *ma = &info->mti_attr;
760         struct lu_attr          *la = &ma->ma_attr;
761         struct req_capsule      *pill = &info->mti_pill;
762         struct mdt_reint_record *rr = &info->mti_rr;
763         struct mdt_rec_setattr  *rec;
764         ENTRY;
765
766         rec = req_capsule_client_get(pill, &RMF_REC_SETATTR);
767         if (rec == NULL)
768                 RETURN(-EFAULT);
769
770         uc->mu_fsuid = rec->sa_fsuid;
771         uc->mu_fsgid = rec->sa_fsgid;
772         uc->mu_cap   = rec->sa_cap;
773         uc->mu_suppgids[0] = rec->sa_suppgid;
774         uc->mu_suppgids[1] = -1;
775
776         rr->rr_fid1 = &rec->sa_fid;
777         la->la_valid = mdt_attr_valid_xlate(attr_unpack(rec->sa_valid), rr, ma);
778         la->la_mode  = rec->sa_mode;
779         la->la_flags = rec->sa_attr_flags;
780         la->la_uid   = rec->sa_uid;
781         la->la_gid   = rec->sa_gid;
782         la->la_size  = rec->sa_size;
783         la->la_blocks = rec->sa_blocks;
784         la->la_ctime = rec->sa_ctime;
785         la->la_atime = rec->sa_atime;
786         la->la_mtime = rec->sa_mtime;
787         ma->ma_valid = MA_INODE;
788
789         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
790                 mdt_set_capainfo(info, 0, rr->rr_fid1,
791                                  req_capsule_client_get(pill, &RMF_CAPA1));
792
793         RETURN(0);
794 }
795
796 static int mdt_epoch_unpack(struct mdt_thread_info *info)
797 {
798         struct req_capsule *pill = &info->mti_pill;
799         ENTRY;
800
801         if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT))
802                 info->mti_epoch = req_capsule_client_get(pill, &RMF_MDT_EPOCH);
803         else
804                 info->mti_epoch = NULL;
805         RETURN(info->mti_epoch == NULL ? -EFAULT : 0);
806 }
807
808 static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) {
809         struct req_capsule      *pill = &info->mti_pill;
810
811         if (req_capsule_get_size(pill, &RMF_DLM_REQ, RCL_CLIENT)) {
812                 info->mti_dlm_req = req_capsule_client_get(pill, &RMF_DLM_REQ);
813                 if (info->mti_dlm_req == NULL)
814                         RETURN(-EFAULT);
815         }
816         
817         RETURN(0);
818 }
819
820 static int mdt_setattr_unpack(struct mdt_thread_info *info)
821 {
822         struct md_attr          *ma = &info->mti_attr;
823         struct req_capsule      *pill = &info->mti_pill;
824         int rc;
825         ENTRY;
826
827         rc = mdt_setattr_unpack_rec(info);
828         if (rc)
829                 RETURN(rc);
830
831         /* Epoch may be absent */
832         mdt_epoch_unpack(info);
833
834         ma->ma_lmm_size = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT);
835         if (ma->ma_lmm_size) {
836                 ma->ma_lmm = req_capsule_client_get(pill, &RMF_EADATA);
837                 ma->ma_valid |= MA_LOV;
838         }
839
840         ma->ma_cookie_size = req_capsule_get_size(pill, &RMF_LOGCOOKIES,
841                                                   RCL_CLIENT);
842         if (ma->ma_cookie_size) {
843                 ma->ma_cookie = req_capsule_client_get(pill, &RMF_LOGCOOKIES);
844                 ma->ma_valid |= MA_COOKIE;
845         }
846
847         rc = mdt_dlmreq_unpack(info);
848         RETURN(rc);
849 }
850
851 int mdt_close_unpack(struct mdt_thread_info *info)
852 {
853         int rc;
854         ENTRY;
855
856         rc = mdt_epoch_unpack(info);
857         if (rc)
858                 RETURN(rc);
859
860         RETURN(mdt_setattr_unpack_rec(info));
861 }
862
863 static int mdt_create_unpack(struct mdt_thread_info *info)
864 {
865         struct md_ucred         *uc  = mdt_ucred(info);
866         struct mdt_rec_create   *rec;
867         struct lu_attr          *attr = &info->mti_attr.ma_attr;
868         struct mdt_reint_record *rr = &info->mti_rr;
869         struct req_capsule      *pill = &info->mti_pill;
870         struct md_op_spec       *sp = &info->mti_spec;
871         int rc;
872         ENTRY;
873
874         rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
875         if (rec == NULL)
876                 RETURN(-EFAULT);
877
878         uc->mu_fsuid = rec->cr_fsuid;
879         uc->mu_fsgid = rec->cr_fsgid;
880         uc->mu_cap   = rec->cr_cap;
881         uc->mu_suppgids[0] = rec->cr_suppgid1;
882         uc->mu_suppgids[1] = -1;
883
884         rr->rr_fid1 = &rec->cr_fid1;
885         rr->rr_fid2 = &rec->cr_fid2;
886         attr->la_mode = rec->cr_mode;
887         attr->la_rdev  = rec->cr_rdev;
888         attr->la_uid   = rec->cr_fsuid;
889         attr->la_gid   = rec->cr_fsgid;
890         attr->la_ctime = rec->cr_time;
891         attr->la_mtime = rec->cr_time;
892         attr->la_atime = rec->cr_time;
893         attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
894                          LA_CTIME | LA_MTIME | LA_ATIME;
895         memset(&sp->u, 0, sizeof(sp->u));
896         sp->sp_cr_flags = rec->cr_flags;
897         sp->sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
898         info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
899
900         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
901                 mdt_set_capainfo(info, 0, rr->rr_fid1,
902                                  req_capsule_client_get(pill, &RMF_CAPA1));
903         mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
904
905         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
906         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
907         LASSERT(rr->rr_namelen > 0);
908         
909 #ifdef CONFIG_FS_POSIX_ACL
910         if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) {
911                 if (S_ISDIR(attr->la_mode))
912                         sp->u.sp_pfid = rr->rr_fid1;
913                 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
914                 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
915                                                   RCL_CLIENT));
916                 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
917                 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
918                                                                 RCL_CLIENT);
919                 sp->u.sp_ea.fid = rr->rr_fid1;
920                 RETURN(0);
921         }
922 #endif
923         if (S_ISDIR(attr->la_mode)) {
924                 /* pass parent fid for cross-ref cases */
925                 sp->u.sp_pfid = rr->rr_fid1;
926                 if (sp->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
927                         /* create salve object req, need
928                          * unpack split ea here
929                          */
930                        req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SLAVE);
931                        LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
932                                                          RCL_CLIENT));
933                        sp->u.sp_ea.eadata = req_capsule_client_get(pill,
934                                                                    &RMF_EADATA);
935                        sp->u.sp_ea.eadatalen = req_capsule_get_size(pill,
936                                                                     &RMF_EADATA,
937                                                                     RCL_CLIENT);
938                        sp->u.sp_ea.fid = rr->rr_fid1;
939                        RETURN(0);
940                 }
941                 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
942         } else if (S_ISLNK(attr->la_mode)) {
943                 const char *tgt = NULL;
944
945                 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM);
946                 if (req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT)) {
947                         tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
948                         sp->u.sp_symname = tgt;
949                 }
950                 if (tgt == NULL)
951                         RETURN(-EFAULT);
952         } else {
953                 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
954         }
955         rc = mdt_dlmreq_unpack(info);
956         RETURN(rc);
957 }
958
959 static int mdt_link_unpack(struct mdt_thread_info *info)
960 {
961         struct md_ucred         *uc  = mdt_ucred(info);
962         struct mdt_rec_link     *rec;
963         struct lu_attr          *attr = &info->mti_attr.ma_attr;
964         struct mdt_reint_record *rr = &info->mti_rr;
965         struct req_capsule      *pill = &info->mti_pill;
966         int rc;
967         ENTRY;
968
969         rec = req_capsule_client_get(pill, &RMF_REC_LINK);
970         if (rec == NULL)
971                 RETURN(-EFAULT);
972
973         uc->mu_fsuid = rec->lk_fsuid;
974         uc->mu_fsgid = rec->lk_fsgid;
975         uc->mu_cap   = rec->lk_cap;
976         uc->mu_suppgids[0] = rec->lk_suppgid1;
977         uc->mu_suppgids[1] = rec->lk_suppgid2;
978
979         attr->la_uid = rec->lk_fsuid;
980         attr->la_gid = rec->lk_fsgid;
981         rr->rr_fid1 = &rec->lk_fid1;
982         rr->rr_fid2 = &rec->lk_fid2;
983         attr->la_ctime = rec->lk_time;
984         attr->la_mtime = rec->lk_time;
985         attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;
986
987         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
988                 mdt_set_capainfo(info, 0, rr->rr_fid1,
989                                  req_capsule_client_get(pill, &RMF_CAPA1));
990         if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
991                 mdt_set_capainfo(info, 1, rr->rr_fid2,
992                                  req_capsule_client_get(pill, &RMF_CAPA2));
993
994         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
995         if (rr->rr_name == NULL)
996                 RETURN(-EFAULT);
997         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
998         LASSERT(rr->rr_namelen > 0);
999         info->mti_spec.sp_ck_split = !!(rec->lk_bias & MDS_CHECK_SPLIT);
1000         info->mti_cross_ref = !!(rec->lk_bias & MDS_CROSS_REF);
1001
1002         rc = mdt_dlmreq_unpack(info);
1003         RETURN(rc);
1004 }
1005
1006 static int mdt_unlink_unpack(struct mdt_thread_info *info)
1007 {
1008         struct md_ucred         *uc  = mdt_ucred(info);
1009         struct mdt_rec_unlink   *rec;
1010         struct md_attr          *ma = &info->mti_attr;
1011         struct lu_attr          *attr = &info->mti_attr.ma_attr;
1012         struct mdt_reint_record *rr = &info->mti_rr;
1013         struct req_capsule      *pill = &info->mti_pill;
1014         int rc;
1015         ENTRY;
1016
1017         rec = req_capsule_client_get(pill, &RMF_REC_UNLINK);
1018         if (rec == NULL)
1019                 RETURN(-EFAULT);
1020
1021         uc->mu_fsuid = rec->ul_fsuid;
1022         uc->mu_fsgid = rec->ul_fsgid;
1023         uc->mu_cap   = rec->ul_cap;
1024         uc->mu_suppgids[0] = rec->ul_suppgid;
1025         uc->mu_suppgids[1] = -1;
1026
1027         attr->la_uid = rec->ul_fsuid;
1028         attr->la_gid = rec->ul_fsgid;
1029         rr->rr_fid1 = &rec->ul_fid1;
1030         rr->rr_fid2 = &rec->ul_fid2;
1031         attr->la_ctime = rec->ul_time;
1032         attr->la_mtime = rec->ul_time;
1033         attr->la_mode  = rec->ul_mode;
1034         attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
1035
1036         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1037                 mdt_set_capainfo(info, 0, rr->rr_fid1,
1038                                  req_capsule_client_get(pill, &RMF_CAPA1));
1039
1040         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1041         if (rr->rr_name == NULL)
1042                 RETURN(-EFAULT);
1043         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1044         LASSERT(rr->rr_namelen > 0);
1045         info->mti_spec.sp_ck_split = !!(rec->ul_bias & MDS_CHECK_SPLIT);
1046         info->mti_cross_ref = !!(rec->ul_bias & MDS_CROSS_REF);
1047         if (rec->ul_bias & MDS_VTX_BYPASS)
1048                 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1049         else
1050                 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1051
1052         rc = mdt_dlmreq_unpack(info);
1053         RETURN(rc);
1054 }
1055
1056 static int mdt_rename_unpack(struct mdt_thread_info *info)
1057 {
1058         struct md_ucred         *uc = mdt_ucred(info);
1059         struct mdt_rec_rename   *rec;
1060         struct md_attr          *ma = &info->mti_attr;
1061         struct lu_attr          *attr = &info->mti_attr.ma_attr;
1062         struct mdt_reint_record *rr = &info->mti_rr;
1063         struct req_capsule      *pill = &info->mti_pill;
1064         int rc;
1065         ENTRY;
1066
1067         rec = req_capsule_client_get(pill, &RMF_REC_RENAME);
1068         if (rec == NULL)
1069                 RETURN(-EFAULT);
1070
1071         uc->mu_fsuid = rec->rn_fsuid;
1072         uc->mu_fsgid = rec->rn_fsgid;
1073         uc->mu_cap   = rec->rn_cap;
1074         uc->mu_suppgids[0] = rec->rn_suppgid1;
1075         uc->mu_suppgids[1] = rec->rn_suppgid2;
1076
1077         attr->la_uid = rec->rn_fsuid;
1078         attr->la_gid = rec->rn_fsgid;
1079         rr->rr_fid1 = &rec->rn_fid1;
1080         rr->rr_fid2 = &rec->rn_fid2;
1081         attr->la_ctime = rec->rn_time;
1082         attr->la_mtime = rec->rn_time;
1083         /* rename_tgt contains the mode already */
1084         attr->la_mode = rec->rn_mode;
1085         attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
1086
1087         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1088                 mdt_set_capainfo(info, 0, rr->rr_fid1,
1089                                  req_capsule_client_get(pill, &RMF_CAPA1));
1090         if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
1091                 mdt_set_capainfo(info, 1, rr->rr_fid2,
1092                                  req_capsule_client_get(pill, &RMF_CAPA2));
1093
1094         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1095         rr->rr_tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
1096         if (rr->rr_name == NULL || rr->rr_tgt == NULL)
1097                 RETURN(-EFAULT);
1098         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1099         LASSERT(rr->rr_namelen > 0);
1100         rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT) - 1;
1101         LASSERT(rr->rr_tgtlen > 0);
1102         info->mti_spec.sp_ck_split = !!(rec->rn_bias & MDS_CHECK_SPLIT);
1103         info->mti_cross_ref = !!(rec->rn_bias & MDS_CROSS_REF);
1104         if (rec->rn_bias & MDS_VTX_BYPASS)
1105                 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1106         else
1107                 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1108
1109         rc = mdt_dlmreq_unpack(info);
1110         RETURN(rc);
1111 }
1112
1113 static int mdt_open_unpack(struct mdt_thread_info *info)
1114 {
1115         struct md_ucred         *uc = mdt_ucred(info);
1116         struct mdt_rec_create   *rec;
1117         struct lu_attr          *attr = &info->mti_attr.ma_attr;
1118         struct req_capsule      *pill = &info->mti_pill;
1119         struct mdt_reint_record *rr   = &info->mti_rr;
1120         struct ptlrpc_request   *req  = mdt_info_req(info);
1121         struct md_op_spec       *sp   = &info->mti_spec;
1122         ENTRY;
1123
1124         rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
1125         if (rec == NULL)
1126                 RETURN(-EFAULT);
1127
1128         uc->mu_fsuid = rec->cr_fsuid;
1129         uc->mu_fsgid = rec->cr_fsgid;
1130         uc->mu_cap   = rec->cr_cap;
1131         uc->mu_suppgids[0] = rec->cr_suppgid1;
1132         uc->mu_suppgids[1] = rec->cr_suppgid2;
1133
1134         rr->rr_fid1   = &rec->cr_fid1;
1135         rr->rr_fid2   = &rec->cr_fid2;
1136         rr->rr_handle = &rec->cr_old_handle;
1137         attr->la_mode = rec->cr_mode;
1138         attr->la_rdev  = rec->cr_rdev;
1139         attr->la_uid   = rec->cr_fsuid;
1140         attr->la_gid   = rec->cr_fsgid;
1141         attr->la_ctime = rec->cr_time;
1142         attr->la_mtime = rec->cr_time;
1143         attr->la_atime = rec->cr_time;
1144         attr->la_valid = LA_MODE  | LA_RDEV  | LA_UID   | LA_GID |
1145                          LA_CTIME | LA_MTIME | LA_ATIME;
1146         memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u));
1147         info->mti_spec.sp_cr_flags = rec->cr_flags;
1148         info->mti_replayepoch = rec->cr_ioepoch;
1149
1150         info->mti_spec.sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
1151         info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
1152
1153         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1154                 mdt_set_capainfo(info, 0, rr->rr_fid1,
1155                                  req_capsule_client_get(pill, &RMF_CAPA1));
1156         if ((lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) &&
1157             (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))) {
1158 #if 0
1159                 mdt_set_capainfo(info, 1, rr->rr_fid2,
1160                                  req_capsule_client_get(pill, &RMF_CAPA2));
1161 #else
1162                 /*
1163                  * FIXME: capa in replay open request might have expired,
1164                  * bypass capa check. Security hole?
1165                  */
1166                 mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
1167                 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
1168 #endif
1169         }
1170
1171         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1172         if (rr->rr_name == NULL)
1173                 RETURN(-EFAULT);
1174         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1175
1176         sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
1177                                                      RCL_CLIENT);
1178         if (sp->u.sp_ea.eadatalen) {
1179                 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
1180                 if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)
1181                         sp->u.sp_ea.no_lov_create = 1;
1182         }
1183
1184         RETURN(0);
1185 }
1186
1187 typedef int (*reint_unpacker)(struct mdt_thread_info *info);
1188
1189 static reint_unpacker mdt_reint_unpackers[REINT_MAX] = {
1190         [REINT_SETATTR]  = mdt_setattr_unpack,
1191         [REINT_CREATE]   = mdt_create_unpack,
1192         [REINT_LINK]     = mdt_link_unpack,
1193         [REINT_UNLINK]   = mdt_unlink_unpack,
1194         [REINT_RENAME]   = mdt_rename_unpack,
1195         [REINT_OPEN]     = mdt_open_unpack
1196 };
1197
1198 int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op)
1199 {
1200         int rc;
1201         ENTRY;
1202
1203         memset(&info->mti_rr, 0, sizeof(info->mti_rr));
1204         if (op < REINT_MAX && mdt_reint_unpackers[op] != NULL) {
1205                 info->mti_rr.rr_opcode = op;
1206                 rc = mdt_reint_unpackers[op](info);
1207         } else {
1208                 CERROR("Unexpected opcode %d\n", op);
1209                 rc = -EFAULT;
1210         }
1211         RETURN(rc);
1212 }