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