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