Whamcloud - gitweb
- fix from b1_4 in MDS_CHECK_RESENT()
[fs/lustre-release.git] / lustre / mds / mds_lib.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2003 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #define DEBUG_SUBSYSTEM S_MDS
23
24 #include <linux/config.h>
25 #include <linux/module.h>
26 #include <linux/kernel.h>
27 #include <linux/mm.h>
28 #include <linux/string.h>
29 #include <linux/stat.h>
30 #include <linux/errno.h>
31 #include <linux/version.h>
32 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
33 # include <linux/locks.h>   // for wait_on_buffer
34 #else
35 # include <linux/buffer_head.h>   // for wait_on_buffer
36 #endif
37 #include <linux/unistd.h>
38
39 #include <asm/system.h>
40 #include <asm/uaccess.h>
41
42 #include <linux/fs.h>
43 #include <linux/stat.h>
44 #include <asm/uaccess.h>
45 #include <linux/slab.h>
46 #include <asm/segment.h>
47
48 #include <linux/obd_support.h>
49 #include <linux/lustre_lib.h>
50 #include "mds_internal.h"
51
52 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4)
53 struct group_info *groups_alloc(int ngroups)
54 {
55         struct group_info *ginfo;
56
57         LASSERT(ngroups <= NGROUPS_SMALL);
58
59         OBD_ALLOC(ginfo, sizeof(*ginfo) + 1 * sizeof(gid_t *));
60         if (!ginfo)
61                 return NULL;
62         ginfo->ngroups = ngroups;
63         ginfo->nblocks = 1;
64         ginfo->blocks[0] = ginfo->small_block;
65         atomic_set(&ginfo->usage, 1);
66
67         return ginfo;
68 }
69
70 void groups_free(struct group_info *ginfo)
71 {
72         LASSERT(ginfo->ngroups <= NGROUPS_SMALL);
73         LASSERT(ginfo->nblocks == 1);
74         LASSERT(ginfo->blocks[0] == ginfo->small_block);
75
76         OBD_FREE(ginfo, sizeof(*ginfo) + 1 * sizeof(gid_t *));
77 }
78
79 /* for 2.4 the group number is small, so simply search the
80  * whole array.
81  */
82 int groups_search(struct group_info *ginfo, gid_t grp)
83 {
84         int i;
85
86         if (!ginfo)
87                 return 0;
88
89         for (i = 0; i < ginfo->ngroups; i++)
90                 if (GROUP_AT(ginfo, i) == grp)
91                         return 1;
92         return 0;
93 }
94
95 #else /* >= 2.6.4 */
96
97 void groups_sort(struct group_info *ginfo)
98 {
99         int base, max, stride;
100         int gidsetsize = ginfo->ngroups;
101
102         for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1)
103                 ; /* nothing */
104         stride /= 3;
105
106         while (stride) {
107                 max = gidsetsize - stride;
108                 for (base = 0; base < max; base++) {
109                         int left = base;
110                         int right = left + stride;
111                         gid_t tmp = GROUP_AT(ginfo, right);
112                                                                                                     
113                         while (left >= 0 && GROUP_AT(ginfo, left) > tmp) {
114                                 GROUP_AT(ginfo, right) =
115                                     GROUP_AT(ginfo, left);
116                                 right = left;
117                                 left -= stride;
118                         }
119                         GROUP_AT(ginfo, right) = tmp;
120                 }
121                 stride /= 3;
122         }
123 }
124
125 int groups_search(struct group_info *ginfo, gid_t grp)
126 {
127         int left, right;
128
129         if (!ginfo)
130                 return 0;
131
132         left = 0;
133         right = ginfo->ngroups;
134         while (left < right) {
135                 int mid = (left + right) / 2;
136                 int cmp = grp - GROUP_AT(ginfo, mid);
137                 if (cmp > 0)
138                         left = mid + 1;
139                 else if (cmp < 0)
140                         right = mid;
141                 else
142                         return 1;
143         }
144         return 0;
145 }
146 #endif
147
148 void groups_from_buffer(struct group_info *ginfo, __u32 *gids)
149 {
150         int i, ngroups = ginfo->ngroups;
151
152         for (i = 0; i < ginfo->nblocks; i++) {
153                 int count = min(NGROUPS_PER_BLOCK, ngroups);
154
155                 memcpy(ginfo->blocks[i], gids, count * sizeof(__u32));
156                 gids += NGROUPS_PER_BLOCK;
157                 ngroups -= count;
158         }
159 }
160
161 void mds_pack_dentry2id(struct obd_device *obd,
162                         struct lustre_id *id,
163                         struct dentry *dentry)
164 {
165         id_ino(id) = dentry->d_inum;
166         id_gen(id) = dentry->d_generation;
167         id_fid(id) = dentry->d_fid;
168         id_group(id) = dentry->d_mdsnum;
169 }
170
171 void mds_pack_dentry2body(struct obd_device *obd,
172                           struct mds_body *b,
173                           struct dentry *dentry)
174 {
175         b->valid |= OBD_MD_FLID | OBD_MD_FLGENER |
176                 OBD_MD_MDS;
177
178         mds_pack_dentry2id(obd, &b->id1, dentry);
179 }
180
181 int mds_pack_inode2id(struct obd_device *obd,
182                       struct lustre_id *id,
183                       struct inode *inode)
184 {
185         int rc = 0;
186         ENTRY;
187         
188         /* we have to avoid deadlock. */
189         if (!down_trylock(&inode->i_sem)) {
190                 rc = mds_read_inode_sid(obd, inode, id);
191                 up(&inode->i_sem);
192         } else {
193                 rc = mds_read_inode_sid(obd, inode, id);
194         }
195
196         if (rc == 0) {
197                 id_ino(id) = inode->i_ino;
198                 id_gen(id) = inode->i_generation;
199                 id_type(id) = (S_IFMT & inode->i_mode);
200         }
201         RETURN(rc);
202 }
203
204 /* Note that we can copy all of the fields, just some will not be "valid" */
205 void mds_pack_inode2body(struct obd_device *obd, struct mds_body *b,
206                          struct inode *inode)
207 {
208         b->valid |= OBD_MD_FLID | OBD_MD_FLCTIME | OBD_MD_FLUID |
209                 OBD_MD_FLGID | OBD_MD_FLFLAGS | OBD_MD_FLTYPE |
210                 OBD_MD_FLMODE | OBD_MD_FLNLINK | OBD_MD_FLGENER |
211                 OBD_MD_FLATIME | OBD_MD_FLMTIME; /* bug 2020 */
212
213         if (!S_ISREG(inode->i_mode)) {
214                 b->valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS |
215                         OBD_MD_FLATIME | OBD_MD_FLMTIME |
216                         OBD_MD_FLRDEV;
217         }
218         b->atime = LTIME_S(inode->i_atime);
219         b->mtime = LTIME_S(inode->i_mtime);
220         b->ctime = LTIME_S(inode->i_ctime);
221         b->mode = inode->i_mode;
222         b->size = inode->i_size;
223         b->blocks = inode->i_blocks;
224         b->uid = inode->i_uid;
225         b->gid = inode->i_gid;
226         b->flags = inode->i_flags;
227         b->rdev = inode->i_rdev;
228         
229         /* Return the correct link count for orphan inodes */
230         if (mds_inode_is_orphan(inode)) {
231                 b->nlink = 0;
232         } else if (S_ISDIR(inode->i_mode)) {
233                 b->nlink = 1;
234         } else {
235                 b->nlink = inode->i_nlink;
236         }
237         mds_pack_inode2id(obd, &b->id1, inode);
238 }
239
240 /* unpacking */
241 static int mds_setattr_unpack(struct ptlrpc_request *req, int offset,
242                               struct mds_update_record *r)
243 {
244         struct iattr *attr = &r->ur_iattr;
245         struct mds_rec_setattr *rec;
246         ENTRY;
247
248         rec = lustre_swab_reqbuf(req, offset, sizeof(*rec),
249                                  lustre_swab_mds_rec_setattr);
250         if (rec == NULL)
251                 RETURN (-EFAULT);
252
253         r->ur_id1 = &rec->sa_id;
254         attr->ia_valid = rec->sa_valid;
255         attr->ia_mode = rec->sa_mode;
256         attr->ia_uid = rec->sa_uid;
257         attr->ia_gid = rec->sa_gid;
258         attr->ia_size = rec->sa_size;
259         LTIME_S(attr->ia_atime) = rec->sa_atime;
260         LTIME_S(attr->ia_mtime) = rec->sa_mtime;
261         LTIME_S(attr->ia_ctime) = rec->sa_ctime;
262         attr->ia_attr_flags = rec->sa_attr_flags;
263
264         LASSERT_REQSWAB (req, offset + 1);
265         if (req->rq_reqmsg->bufcount > offset + 1) {
266                 r->ur_eadata = lustre_msg_buf (req->rq_reqmsg,
267                                                offset + 1, 0);
268                 if (r->ur_eadata == NULL)
269                         RETURN (-EFAULT);
270                 r->ur_eadatalen = req->rq_reqmsg->buflens[offset + 1];
271         }
272
273         if (req->rq_reqmsg->bufcount > offset + 2) {
274                 r->ur_logcookies = lustre_msg_buf(req->rq_reqmsg, offset + 2, 0);
275                 if (r->ur_eadata == NULL)
276                         RETURN (-EFAULT);
277
278                 r->ur_cookielen = req->rq_reqmsg->buflens[offset + 2];
279         }
280
281         RETURN(0);
282 }
283
284 static int mds_create_unpack(struct ptlrpc_request *req, int offset,
285                              struct mds_update_record *r)
286 {
287         struct mds_rec_create *rec;
288         ENTRY;
289
290         rec = lustre_swab_reqbuf (req, offset, sizeof (*rec),
291                                   lustre_swab_mds_rec_create);
292         if (rec == NULL)
293                 RETURN (-EFAULT);
294
295         r->ur_id1 = &rec->cr_id;
296         r->ur_id2 = &rec->cr_replayid;
297         r->ur_mode = rec->cr_mode;
298         r->ur_rdev = rec->cr_rdev;
299         r->ur_time = rec->cr_time;
300         r->ur_flags = rec->cr_flags;
301
302         LASSERT_REQSWAB (req, offset + 1);
303         r->ur_name = lustre_msg_string (req->rq_reqmsg, offset + 1, 0);
304         if (r->ur_name == NULL)
305                 RETURN (-EFAULT);
306         r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
307
308         LASSERT_REQSWAB (req, offset + 2);
309         if (req->rq_reqmsg->bufcount > offset + 2) {
310                 if (S_ISLNK(r->ur_mode)) {
311                         r->ur_tgt = lustre_msg_string(req->rq_reqmsg,
312                                                       offset + 2, 0);
313                         if (r->ur_tgt == NULL)
314                                 RETURN (-EFAULT);
315                         r->ur_tgtlen = req->rq_reqmsg->buflens[offset + 2];
316                 } else if (S_ISDIR(r->ur_mode)) {
317                         /* Stripe info for mkdir - just a 16bit integer */
318                         if (req->rq_reqmsg->buflens[offset + 2] != 2) {
319                                 CERROR("mkdir stripe info does not match "
320                                        "expected size %d vs 2\n",
321                                        req->rq_reqmsg->buflens[offset + 2]);
322                                 RETURN (-EINVAL);
323                         }
324                         r->ur_eadata = lustre_swab_buf (req->rq_reqmsg,
325                                                offset + 2, 2, __swab16s);
326                         r->ur_eadatalen = req->rq_reqmsg->buflens[offset + 2];
327                 } else {
328                         /* Hm, no other users so far? */
329                         LBUG();
330                 }
331         }
332         RETURN(0);
333 }
334
335 static int mds_link_unpack(struct ptlrpc_request *req, int offset,
336                            struct mds_update_record *r)
337 {
338         struct mds_rec_link *rec;
339         ENTRY;
340
341         rec = lustre_swab_reqbuf (req, offset, sizeof (*rec),
342                                   lustre_swab_mds_rec_link);
343         if (rec == NULL)
344                 RETURN (-EFAULT);
345
346         r->ur_id1 = &rec->lk_id1;
347         r->ur_id2 = &rec->lk_id2;
348         r->ur_time = rec->lk_time;
349
350         LASSERT_REQSWAB (req, offset + 1);
351         r->ur_name = lustre_msg_string (req->rq_reqmsg, offset + 1, 0);
352         if (r->ur_name == NULL)
353                 RETURN (-EFAULT);
354         r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
355         RETURN(0);
356 }
357
358 static int mds_unlink_unpack(struct ptlrpc_request *req, int offset,
359                              struct mds_update_record *r)
360 {
361         struct mds_rec_unlink *rec;
362         ENTRY;
363
364         rec = lustre_swab_reqbuf (req, offset, sizeof (*rec),
365                                   lustre_swab_mds_rec_unlink);
366         if (rec == NULL)
367                 RETURN(-EFAULT);
368
369         r->ur_mode = rec->ul_mode;
370         r->ur_id1 = &rec->ul_id1;
371         r->ur_id2 = &rec->ul_id2;
372         r->ur_time = rec->ul_time;
373
374         LASSERT_REQSWAB (req, offset + 1);
375         r->ur_name = lustre_msg_string(req->rq_reqmsg, offset + 1, 0);
376         if (r->ur_name == NULL)
377                 RETURN(-EFAULT);
378         r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
379         RETURN(0);
380 }
381
382 static int mds_rename_unpack(struct ptlrpc_request *req, int offset,
383                              struct mds_update_record *r)
384 {
385         struct mds_rec_rename *rec;
386         ENTRY;
387
388         rec = lustre_swab_reqbuf (req, offset, sizeof (*rec),
389                                   lustre_swab_mds_rec_rename);
390         if (rec == NULL)
391                 RETURN(-EFAULT);
392
393         r->ur_id1 = &rec->rn_id1;
394         r->ur_id2 = &rec->rn_id2;
395         r->ur_time = rec->rn_time;
396
397         LASSERT_REQSWAB (req, offset + 1);
398         r->ur_name = lustre_msg_string(req->rq_reqmsg, offset + 1, 0);
399         if (r->ur_name == NULL)
400                 RETURN(-EFAULT);
401         r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
402
403         LASSERT_REQSWAB (req, offset + 2);
404         r->ur_tgt = lustre_msg_string(req->rq_reqmsg, offset + 2, 0);
405         if (r->ur_tgt == NULL)
406                 RETURN(-EFAULT);
407         r->ur_tgtlen = req->rq_reqmsg->buflens[offset + 2];
408         RETURN(0);
409 }
410
411 static int mds_open_unpack(struct ptlrpc_request *req, int offset,
412                            struct mds_update_record *r)
413 {
414         struct mds_rec_create *rec;
415         ENTRY;
416
417         rec = lustre_swab_reqbuf (req, offset, sizeof (*rec),
418                                   lustre_swab_mds_rec_create);
419         if (rec == NULL)
420                 RETURN (-EFAULT);
421
422         r->ur_id1 = &rec->cr_id;
423         r->ur_id2 = &rec->cr_replayid;
424         r->ur_mode = rec->cr_mode;
425         r->ur_rdev = rec->cr_rdev;
426         r->ur_time = rec->cr_time;
427         r->ur_flags = rec->cr_flags;
428
429         LASSERT_REQSWAB (req, offset + 1);
430         r->ur_name = lustre_msg_string (req->rq_reqmsg, offset + 1, 0);
431         if (r->ur_name == NULL)
432                 RETURN (-EFAULT);
433         r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
434
435         LASSERT_REQSWAB (req, offset + 2);
436         if (req->rq_reqmsg->bufcount > offset + 2) {
437                 r->ur_eadata = lustre_msg_buf(req->rq_reqmsg, offset + 2, 0);
438                 if (r->ur_eadata == NULL)
439                         RETURN (-EFAULT);
440                 r->ur_eadatalen = req->rq_reqmsg->buflens[offset + 2];
441         }
442         RETURN(0);
443 }
444
445 typedef int (*update_unpacker)(struct ptlrpc_request *req, int offset,
446                                struct mds_update_record *r);
447
448 static update_unpacker mds_unpackers[REINT_MAX + 1] = {
449         [REINT_SETATTR] mds_setattr_unpack,
450         [REINT_CREATE] mds_create_unpack,
451         [REINT_LINK] mds_link_unpack,
452         [REINT_UNLINK] mds_unlink_unpack,
453         [REINT_RENAME] mds_rename_unpack,
454         [REINT_OPEN] mds_open_unpack,
455 };
456
457 int mds_update_unpack(struct ptlrpc_request *req, int offset,
458                       struct mds_update_record *rec)
459 {
460         __u32 *opcodep;
461         __u32  opcode;
462         int rc;
463         ENTRY;
464
465         /*
466          * NB don't lustre_swab_reqbuf() here. We're just taking a peek and we
467          * want to leave it to the specific unpacker once we've identified the
468          * message type.
469          */
470         opcodep = lustre_msg_buf (req->rq_reqmsg, offset, sizeof(*opcodep));
471         if (opcodep == NULL)
472                 RETURN(-EFAULT);
473
474         opcode = *opcodep;
475         if (lustre_msg_swabbed (req->rq_reqmsg))
476                 __swab32s (&opcode);
477
478         if (opcode > REINT_MAX ||
479             mds_unpackers[opcode] == NULL) {
480                 CERROR ("Unexpected opcode %d\n", opcode);
481                 RETURN(-EFAULT);
482         }
483
484         rec->ur_id1 = NULL;
485         rec->ur_id2 = NULL;
486         rec->ur_opcode = opcode;
487
488         rc = mds_unpackers[opcode](req, offset, rec);
489         RETURN(rc);
490 }
491
492 static inline void drop_ucred_ginfo(struct lvfs_ucred *ucred)
493 {
494         if (ucred->luc_ginfo) {
495                 put_group_info(ucred->luc_ginfo);
496                 ucred->luc_ginfo = NULL;
497         }
498 }
499
500 /*
501  * root could set any group_info if we allowed setgroups, while
502  * normal user only could 'reduce' their group members -- which
503  * is somewhat expensive.
504  */
505 int mds_init_ucred(struct lvfs_ucred *ucred, struct mds_req_sec_desc *rsd)
506 {
507         struct group_info *gnew;
508
509         ENTRY;
510         LASSERT(ucred);
511         LASSERT(rsd);
512
513         ucred->luc_fsuid = rsd->rsd_fsuid;
514         ucred->luc_fsgid = rsd->rsd_fsgid;
515         ucred->luc_cap = rsd->rsd_cap;
516         ucred->luc_uid = rsd->rsd_uid;
517         ucred->luc_ghash = mds_get_group_entry(NULL, rsd->rsd_uid);
518         ucred->luc_ginfo = NULL;
519
520         if (ucred->luc_ghash && ucred->luc_ghash->ge_group_info) {
521                 ucred->luc_ginfo = ucred->luc_ghash->ge_group_info;
522                 get_group_info(ucred->luc_ginfo);
523         }
524
525         /* everything is done if we don't allow set groups */
526         if (!mds_allow_setgroups())
527                 RETURN(0);
528
529         if (rsd->rsd_ngroups > LUSTRE_MAX_GROUPS) {
530                 CERROR("client provide too many groups: %d\n",
531                 rsd->rsd_ngroups);
532                 drop_ucred_ginfo(ucred);
533                 mds_put_group_entry(NULL, ucred->luc_ghash);
534                 RETURN(-EFAULT);
535         }
536
537         if (ucred->luc_uid == 0) {
538                 if (rsd->rsd_ngroups == 0) {
539                         drop_ucred_ginfo(ucred);
540                         RETURN(0);
541                 }
542
543                 gnew = groups_alloc(rsd->rsd_ngroups);
544                 if (!gnew) {
545                         CERROR("out of memory\n");
546                         drop_ucred_ginfo(ucred);
547                         mds_put_group_entry(NULL, ucred->luc_ghash);
548                         RETURN(-ENOMEM);
549                 }
550                 groups_from_buffer(gnew, rsd->rsd_groups);
551                 /* can't rely on client to sort them */
552                 groups_sort(gnew);
553
554                 drop_ucred_ginfo(ucred);
555                 ucred->luc_ginfo = gnew;
556         } else {
557                 __u32 set = 0, cur = 0;
558                 struct group_info *ginfo;
559
560                 /* if no group info in hash, we don't
561                  * bother createing new
562                  */
563                 if (!ucred->luc_ginfo)
564                         RETURN(0);
565
566                 /* Note: freeing a group_info count on 'nblocks' instead of
567                  * 'ngroups', thus we can safely alloc enough buffer and reduce
568                  * and ngroups number later.
569                  */
570                 gnew = groups_alloc(rsd->rsd_ngroups);
571                 if (!gnew) {
572                         CERROR("out of memory\n");
573                         drop_ucred_ginfo(ucred);
574                         mds_put_group_entry(NULL, ucred->luc_ghash);
575                         RETURN(-ENOMEM);
576                 }
577
578                 ginfo = ucred->luc_ginfo;
579                 while (cur < rsd->rsd_ngroups) {
580                         if (groups_search(ginfo, rsd->rsd_groups[cur])) {
581                                 GROUP_AT(gnew, set) = rsd->rsd_groups[cur];
582                                 set++;
583                         }
584                         cur++;
585                 }
586                 gnew->ngroups = set;
587
588                 put_group_info(ucred->luc_ginfo);
589                 ucred->luc_ginfo = gnew;
590         }
591         RETURN(0);
592 }
593
594 void mds_exit_ucred(struct lvfs_ucred *ucred)
595 {
596         ENTRY;
597
598         if (ucred->luc_ginfo)
599                 put_group_info(ucred->luc_ginfo);
600         if (ucred->luc_ghash)
601                 mds_put_group_entry(NULL, ucred->luc_ghash);
602
603         EXIT;
604 }