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