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