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