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         if ((req_capsule_has_field(pill, &RMF_CAPA1, RCL_SERVER) &&
601                !(body->valid & OBD_MD_FLMDSCAPA)))
602                 adjust += req_capsule_shrink(pill, &RMF_CAPA1, 0, adjust, 1);
603
604         if ((req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) &&
605                 !(body->valid & OBD_MD_FLOSSCAPA)))
606                 adjust += req_capsule_shrink(pill, &RMF_CAPA2, 0, adjust, 0);
607
608         /*
609          * Some more field should be shrinked if needed.
610          * This should be done by those who added fields to reply message.
611          */
612         EXIT;
613 }
614
615
616 /* if object is dying, pack the lov/llog data,
617  * parameter info->mti_attr should be valid at this point! */
618 int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo,
619                            const struct md_attr *ma)
620 {
621         struct mdt_body       *repbody;
622         const struct lu_attr *la = &ma->ma_attr;
623         ENTRY;
624
625         repbody = req_capsule_server_get(&info->mti_pill, &RMF_MDT_BODY);
626         LASSERT(repbody != NULL);
627
628         if (ma->ma_valid & MA_INODE)
629                 mdt_pack_attr2body(info, repbody, la, mdt_object_fid(mo));
630
631         if (ma->ma_valid & MA_LOV) {
632                 __u32 mode;
633
634                 if (mdt_object_exists(mo) < 0)
635                         /* If it is a remote object, and we do not retrieve
636                          * EA back unlink reg file*/
637                         mode = S_IFREG;
638                 else
639                         mode = lu_object_attr(&mo->mot_obj.mo_lu);
640
641                 LASSERT(ma->ma_lmm_size);
642                 mdt_dump_lmm(D_INFO, ma->ma_lmm);
643                 repbody->eadatasize = ma->ma_lmm_size;
644                 if (S_ISREG(mode))
645                         repbody->valid |= OBD_MD_FLEASIZE;
646                 else if (S_ISDIR(mode))
647                         repbody->valid |= OBD_MD_FLDIREA;
648                 else
649                         LBUG();
650         }
651
652         if (ma->ma_cookie_size && (ma->ma_valid & MA_COOKIE)) {
653                 repbody->aclsize = ma->ma_cookie_size;
654                 repbody->valid |= OBD_MD_FLCOOKIE;
655         }
656
657         RETURN(0);
658 }
659
660 static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
661                                   struct md_attr *ma)
662 {
663         __u64 out;
664
665         out = 0;
666         if (in & ATTR_MODE)
667                 out |= LA_MODE;
668         if (in & ATTR_UID)
669                 out |= LA_UID;
670         if (in & ATTR_GID)
671                 out |= LA_GID;
672         if (in & ATTR_SIZE)
673                 out |= LA_SIZE;
674         if (in & ATTR_BLOCKS)
675                 out |= LA_BLOCKS;
676
677         if (in & ATTR_FROM_OPEN)
678                 rr->rr_flags |= MRF_SETATTR_LOCKED;
679
680         if (in & ATTR_ATIME_SET)
681                 out |= LA_ATIME;
682
683         if (in & ATTR_CTIME_SET)
684                 out |= LA_CTIME;
685
686         if (in & ATTR_MTIME_SET)
687                 out |= LA_MTIME;
688
689         if (in & ATTR_ATTR_FLAG)
690                 out |= LA_FLAGS;
691
692         if (in & MDS_OPEN_OWNEROVERRIDE)
693                 out |= MDS_OPEN_OWNEROVERRIDE;
694
695         /*XXX need ATTR_RAW?*/
696         in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
697                 ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
698                 ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
699                 ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE);
700         if (in != 0)
701                 CERROR("Unknown attr bits: %#llx\n", in);
702         return out;
703 }
704 /* unpacking */
705
706 static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
707 {
708         struct md_ucred         *uc  = mdt_ucred(info);
709         struct md_attr          *ma = &info->mti_attr;
710         struct lu_attr          *la = &ma->ma_attr;
711         struct req_capsule      *pill = &info->mti_pill;
712         struct mdt_reint_record *rr = &info->mti_rr;
713         struct mdt_rec_setattr  *rec;
714         ENTRY;
715
716         rec = req_capsule_client_get(pill, &RMF_REC_SETATTR);
717         if (rec == NULL)
718                 RETURN(-EFAULT);
719
720         uc->mu_fsuid = rec->sa_fsuid;
721         uc->mu_fsgid = rec->sa_fsgid;
722         uc->mu_cap   = rec->sa_cap;
723         uc->mu_suppgids[0] = rec->sa_suppgid;
724         uc->mu_suppgids[1] = -1;
725
726         rr->rr_fid1 = &rec->sa_fid;
727         la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr, ma);
728         la->la_mode  = rec->sa_mode;
729         la->la_flags = rec->sa_attr_flags;
730         la->la_uid   = rec->sa_uid;
731         la->la_gid   = rec->sa_gid;
732         la->la_size  = rec->sa_size;
733         la->la_blocks = rec->sa_blocks;
734         la->la_ctime = rec->sa_ctime;
735         la->la_atime = rec->sa_atime;
736         la->la_mtime = rec->sa_mtime;
737         ma->ma_valid = MA_INODE;
738
739         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
740                 mdt_set_capainfo(info, 0, rr->rr_fid1,
741                                  req_capsule_client_get(pill, &RMF_CAPA1));
742
743         RETURN(0);
744 }
745
746 static int mdt_epoch_unpack(struct mdt_thread_info *info)
747 {
748         struct req_capsule *pill = &info->mti_pill;
749         ENTRY;
750
751         if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT))
752                 info->mti_epoch = req_capsule_client_get(pill, &RMF_MDT_EPOCH);
753         else
754                 info->mti_epoch = NULL;
755         RETURN(info->mti_epoch == NULL ? -EFAULT : 0);
756 }
757
758 static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) {
759         struct req_capsule      *pill = &info->mti_pill;
760
761         if (req_capsule_get_size(pill, &RMF_DLM_REQ, RCL_CLIENT)) {
762                 info->mti_dlm_req = req_capsule_client_get(pill, &RMF_DLM_REQ);
763                 if (info->mti_dlm_req == NULL)
764                         RETURN(-EFAULT);
765         }
766         
767         RETURN(0);
768 }
769
770 static int mdt_setattr_unpack(struct mdt_thread_info *info)
771 {
772         struct md_attr          *ma = &info->mti_attr;
773         struct req_capsule      *pill = &info->mti_pill;
774         int rc;
775         ENTRY;
776
777         rc = mdt_setattr_unpack_rec(info);
778         if (rc)
779                 RETURN(rc);
780
781         /* Epoch may be absent */
782         mdt_epoch_unpack(info);
783
784         ma->ma_lmm_size = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT);
785         if (ma->ma_lmm_size) {
786                 ma->ma_lmm = req_capsule_client_get(pill, &RMF_EADATA);
787                 ma->ma_valid |= MA_LOV;
788         }
789
790         ma->ma_cookie_size = req_capsule_get_size(pill, &RMF_LOGCOOKIES,
791                                                   RCL_CLIENT);
792         if (ma->ma_cookie_size) {
793                 ma->ma_cookie = req_capsule_client_get(pill, &RMF_LOGCOOKIES);
794                 ma->ma_valid |= MA_COOKIE;
795         }
796
797         rc = mdt_dlmreq_unpack(info);
798         RETURN(rc);
799 }
800
801 int mdt_close_unpack(struct mdt_thread_info *info)
802 {
803         int rc;
804         ENTRY;
805
806         rc = mdt_epoch_unpack(info);
807         if (rc)
808                 RETURN(rc);
809
810         RETURN(mdt_setattr_unpack_rec(info));
811 }
812
813 static int mdt_create_unpack(struct mdt_thread_info *info)
814 {
815         struct md_ucred         *uc  = mdt_ucred(info);
816         struct mdt_rec_create   *rec;
817         struct lu_attr          *attr = &info->mti_attr.ma_attr;
818         struct mdt_reint_record *rr = &info->mti_rr;
819         struct req_capsule      *pill = &info->mti_pill;
820         struct md_op_spec       *sp = &info->mti_spec;
821         int rc;
822         ENTRY;
823
824         rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
825         if (rec == NULL)
826                 RETURN(-EFAULT);
827
828         uc->mu_fsuid = rec->cr_fsuid;
829         uc->mu_fsgid = rec->cr_fsgid;
830         uc->mu_cap   = rec->cr_cap;
831         uc->mu_suppgids[0] = rec->cr_suppgid1;
832         uc->mu_suppgids[1] = -1;
833
834         rr->rr_fid1 = &rec->cr_fid1;
835         rr->rr_fid2 = &rec->cr_fid2;
836         attr->la_mode = rec->cr_mode;
837         attr->la_rdev  = rec->cr_rdev;
838         attr->la_uid   = rec->cr_fsuid;
839         attr->la_gid   = rec->cr_fsgid;
840         attr->la_ctime = rec->cr_time;
841         attr->la_mtime = rec->cr_time;
842         attr->la_atime = rec->cr_time;
843         attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
844                          LA_CTIME | LA_MTIME | LA_ATIME;
845         memset(&sp->u, 0, sizeof(sp->u));
846         sp->sp_cr_flags = rec->cr_flags;
847         sp->sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
848         info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
849
850         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
851                 mdt_set_capainfo(info, 0, rr->rr_fid1,
852                                  req_capsule_client_get(pill, &RMF_CAPA1));
853         mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
854
855         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
856         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
857         LASSERT(rr->rr_namelen > 0);
858         
859 #ifdef CONFIG_FS_POSIX_ACL
860         if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) {
861                 if (S_ISDIR(attr->la_mode))
862                         sp->u.sp_pfid = rr->rr_fid1;
863                 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
864                 LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
865                                                   RCL_CLIENT));
866                 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
867                 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
868                                                                 RCL_CLIENT);
869                 sp->u.sp_ea.fid = rr->rr_fid1;
870                 RETURN(0);
871         }
872 #endif
873         if (S_ISDIR(attr->la_mode)) {
874                 /* pass parent fid for cross-ref cases */
875                 sp->u.sp_pfid = rr->rr_fid1;
876                 if (sp->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
877                         /* create salve object req, need
878                          * unpack split ea here
879                          */
880                        req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SLAVE);
881                        LASSERT(req_capsule_field_present(pill, &RMF_EADATA,
882                                                          RCL_CLIENT));
883                        sp->u.sp_ea.eadata = req_capsule_client_get(pill,
884                                                                    &RMF_EADATA);
885                        sp->u.sp_ea.eadatalen = req_capsule_get_size(pill,
886                                                                     &RMF_EADATA,
887                                                                     RCL_CLIENT);
888                        sp->u.sp_ea.fid = rr->rr_fid1;
889                        RETURN(0);
890                 }
891                 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
892         } else if (S_ISLNK(attr->la_mode)) {
893                 const char *tgt = NULL;
894
895                 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM);
896                 if (req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT)) {
897                         tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
898                         sp->u.sp_symname = tgt;
899                 }
900                 if (tgt == NULL)
901                         RETURN(-EFAULT);
902         } else {
903                 req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
904         }
905         rc = mdt_dlmreq_unpack(info);
906         RETURN(rc);
907 }
908
909 static int mdt_link_unpack(struct mdt_thread_info *info)
910 {
911         struct md_ucred         *uc  = mdt_ucred(info);
912         struct mdt_rec_link     *rec;
913         struct lu_attr          *attr = &info->mti_attr.ma_attr;
914         struct mdt_reint_record *rr = &info->mti_rr;
915         struct req_capsule      *pill = &info->mti_pill;
916         int rc;
917         ENTRY;
918
919         rec = req_capsule_client_get(pill, &RMF_REC_LINK);
920         if (rec == NULL)
921                 RETURN(-EFAULT);
922
923         uc->mu_fsuid = rec->lk_fsuid;
924         uc->mu_fsgid = rec->lk_fsgid;
925         uc->mu_cap   = rec->lk_cap;
926         uc->mu_suppgids[0] = rec->lk_suppgid1;
927         uc->mu_suppgids[1] = rec->lk_suppgid2;
928
929         attr->la_uid = rec->lk_fsuid;
930         attr->la_gid = rec->lk_fsgid;
931         rr->rr_fid1 = &rec->lk_fid1;
932         rr->rr_fid2 = &rec->lk_fid2;
933         attr->la_ctime = rec->lk_time;
934         attr->la_mtime = rec->lk_time;
935         attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;
936
937         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
938                 mdt_set_capainfo(info, 0, rr->rr_fid1,
939                                  req_capsule_client_get(pill, &RMF_CAPA1));
940         if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
941                 mdt_set_capainfo(info, 1, rr->rr_fid2,
942                                  req_capsule_client_get(pill, &RMF_CAPA2));
943
944         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
945         if (rr->rr_name == NULL)
946                 RETURN(-EFAULT);
947         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
948         LASSERT(rr->rr_namelen > 0);
949         info->mti_spec.sp_ck_split = !!(rec->lk_bias & MDS_CHECK_SPLIT);
950         info->mti_cross_ref = !!(rec->lk_bias & MDS_CROSS_REF);
951
952         rc = mdt_dlmreq_unpack(info);
953         RETURN(rc);
954 }
955
956 static int mdt_unlink_unpack(struct mdt_thread_info *info)
957 {
958         struct md_ucred         *uc  = mdt_ucred(info);
959         struct mdt_rec_unlink   *rec;
960         struct md_attr          *ma = &info->mti_attr;
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_UNLINK);
968         if (rec == NULL)
969                 RETURN(-EFAULT);
970
971         uc->mu_fsuid = rec->ul_fsuid;
972         uc->mu_fsgid = rec->ul_fsgid;
973         uc->mu_cap   = rec->ul_cap;
974         uc->mu_suppgids[0] = rec->ul_suppgid;
975         uc->mu_suppgids[1] = -1;
976
977         attr->la_uid = rec->ul_fsuid;
978         attr->la_gid = rec->ul_fsgid;
979         rr->rr_fid1 = &rec->ul_fid1;
980         rr->rr_fid2 = &rec->ul_fid2;
981         attr->la_ctime = rec->ul_time;
982         attr->la_mtime = rec->ul_time;
983         attr->la_mode  = rec->ul_mode;
984         attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
985
986         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
987                 mdt_set_capainfo(info, 0, rr->rr_fid1,
988                                  req_capsule_client_get(pill, &RMF_CAPA1));
989
990         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
991         if (rr->rr_name == NULL)
992                 RETURN(-EFAULT);
993         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
994         LASSERT(rr->rr_namelen > 0);
995         info->mti_spec.sp_ck_split = !!(rec->ul_bias & MDS_CHECK_SPLIT);
996         info->mti_cross_ref = !!(rec->ul_bias & MDS_CROSS_REF);
997         if (rec->ul_bias & MDS_VTX_BYPASS)
998                 ma->ma_attr_flags |= MDS_VTX_BYPASS;
999         else
1000                 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1001
1002         rc = mdt_dlmreq_unpack(info);
1003         RETURN(rc);
1004 }
1005
1006 static int mdt_rename_unpack(struct mdt_thread_info *info)
1007 {
1008         struct md_ucred         *uc = mdt_ucred(info);
1009         struct mdt_rec_rename   *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_RENAME);
1018         if (rec == NULL)
1019                 RETURN(-EFAULT);
1020
1021         uc->mu_fsuid = rec->rn_fsuid;
1022         uc->mu_fsgid = rec->rn_fsgid;
1023         uc->mu_cap   = rec->rn_cap;
1024         uc->mu_suppgids[0] = rec->rn_suppgid1;
1025         uc->mu_suppgids[1] = rec->rn_suppgid2;
1026
1027         attr->la_uid = rec->rn_fsuid;
1028         attr->la_gid = rec->rn_fsgid;
1029         rr->rr_fid1 = &rec->rn_fid1;
1030         rr->rr_fid2 = &rec->rn_fid2;
1031         attr->la_ctime = rec->rn_time;
1032         attr->la_mtime = rec->rn_time;
1033         /* rename_tgt contains the mode already */
1034         attr->la_mode = rec->rn_mode;
1035         attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_MODE;
1036
1037         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1038                 mdt_set_capainfo(info, 0, rr->rr_fid1,
1039                                  req_capsule_client_get(pill, &RMF_CAPA1));
1040         if (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))
1041                 mdt_set_capainfo(info, 1, rr->rr_fid2,
1042                                  req_capsule_client_get(pill, &RMF_CAPA2));
1043
1044         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1045         rr->rr_tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
1046         if (rr->rr_name == NULL || rr->rr_tgt == NULL)
1047                 RETURN(-EFAULT);
1048         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1049         LASSERT(rr->rr_namelen > 0);
1050         rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT) - 1;
1051         LASSERT(rr->rr_tgtlen > 0);
1052         info->mti_spec.sp_ck_split = !!(rec->rn_bias & MDS_CHECK_SPLIT);
1053         info->mti_cross_ref = !!(rec->rn_bias & MDS_CROSS_REF);
1054         if (rec->rn_bias & MDS_VTX_BYPASS)
1055                 ma->ma_attr_flags |= MDS_VTX_BYPASS;
1056         else
1057                 ma->ma_attr_flags &= ~MDS_VTX_BYPASS;
1058
1059         rc = mdt_dlmreq_unpack(info);
1060         RETURN(rc);
1061 }
1062
1063 static int mdt_open_unpack(struct mdt_thread_info *info)
1064 {
1065         struct md_ucred         *uc = mdt_ucred(info);
1066         struct mdt_rec_create   *rec;
1067         struct lu_attr          *attr = &info->mti_attr.ma_attr;
1068         struct req_capsule      *pill = &info->mti_pill;
1069         struct mdt_reint_record *rr   = &info->mti_rr;
1070         struct ptlrpc_request   *req  = mdt_info_req(info);
1071         struct md_op_spec       *sp   = &info->mti_spec;
1072         ENTRY;
1073
1074         rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
1075         if (rec == NULL)
1076                 RETURN(-EFAULT);
1077
1078         uc->mu_fsuid = rec->cr_fsuid;
1079         uc->mu_fsgid = rec->cr_fsgid;
1080         uc->mu_cap   = rec->cr_cap;
1081         uc->mu_suppgids[0] = rec->cr_suppgid1;
1082         uc->mu_suppgids[1] = rec->cr_suppgid2;
1083
1084         rr->rr_fid1   = &rec->cr_fid1;
1085         rr->rr_fid2   = &rec->cr_fid2;
1086         rr->rr_handle = &rec->cr_old_handle;
1087         attr->la_mode = rec->cr_mode;
1088         attr->la_rdev  = rec->cr_rdev;
1089         attr->la_uid   = rec->cr_fsuid;
1090         attr->la_gid   = rec->cr_fsgid;
1091         attr->la_ctime = rec->cr_time;
1092         attr->la_mtime = rec->cr_time;
1093         attr->la_atime = rec->cr_time;
1094         attr->la_valid = LA_MODE  | LA_RDEV  | LA_UID   | LA_GID |
1095                          LA_CTIME | LA_MTIME | LA_ATIME;
1096         memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u));
1097         info->mti_spec.sp_cr_flags = rec->cr_flags;
1098         info->mti_replayepoch = rec->cr_ioepoch;
1099
1100         info->mti_spec.sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT);
1101         info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF);
1102
1103         if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT))
1104                 mdt_set_capainfo(info, 0, rr->rr_fid1,
1105                                  req_capsule_client_get(pill, &RMF_CAPA1));
1106         if ((lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) &&
1107             (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))) {
1108 #if 0
1109                 mdt_set_capainfo(info, 1, rr->rr_fid2,
1110                                  req_capsule_client_get(pill, &RMF_CAPA2));
1111 #else
1112                 /*
1113                  * FIXME: capa in replay open request might have expired,
1114                  * bypass capa check. Security hole?
1115                  */
1116                 mdt_set_capainfo(info, 0, rr->rr_fid1, BYPASS_CAPA);
1117                 mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA);
1118 #endif
1119         }
1120
1121         rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
1122         if (rr->rr_name == NULL)
1123                 RETURN(-EFAULT);
1124         rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1;
1125         LASSERT(rr->rr_namelen > 0);
1126
1127         sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA,
1128                                                      RCL_CLIENT);
1129         if (sp->u.sp_ea.eadatalen) {
1130                 sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA);
1131                 if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)
1132                         sp->u.sp_ea.no_lov_create = 1;
1133         }
1134
1135         RETURN(0);
1136 }
1137
1138 typedef int (*reint_unpacker)(struct mdt_thread_info *info);
1139
1140 static reint_unpacker mdt_reint_unpackers[REINT_MAX] = {
1141         [REINT_SETATTR]  = mdt_setattr_unpack,
1142         [REINT_CREATE]   = mdt_create_unpack,
1143         [REINT_LINK]     = mdt_link_unpack,
1144         [REINT_UNLINK]   = mdt_unlink_unpack,
1145         [REINT_RENAME]   = mdt_rename_unpack,
1146         [REINT_OPEN]     = mdt_open_unpack
1147 };
1148
1149 int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op)
1150 {
1151         int rc;
1152         ENTRY;
1153
1154         memset(&info->mti_rr, 0, sizeof(info->mti_rr));
1155         if (op < REINT_MAX && mdt_reint_unpackers[op] != NULL) {
1156                 info->mti_rr.rr_opcode = op;
1157                 rc = mdt_reint_unpackers[op](info);
1158         } else {
1159                 CERROR("Unexpected opcode %d\n", op);
1160                 rc = -EFAULT;
1161         }
1162         RETURN(rc);
1163 }