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