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