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