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