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