OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [intermezzo/] [fileset.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2
 * vim:expandtab:shiftwidth=8:tabstop=8:
3
 *
4
 *  Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
5
 *
6
 *   This file is part of InterMezzo, http://www.inter-mezzo.org.
7
 *
8
 *   InterMezzo 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
 *   InterMezzo 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 InterMezzo; if not, write to the Free Software
19
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
 *
21
 *  Managing filesets
22
 *
23
 */
24
 
25
#define __NO_VERSION__
26
#include <stdarg.h>
27
 
28
#include <asm/bitops.h>
29
#include <asm/uaccess.h>
30
#include <asm/system.h>
31
 
32
#include <linux/errno.h>
33
#include <linux/fs.h>
34
#include <linux/ext2_fs.h>
35
#include <linux/slab.h>
36
#include <linux/vmalloc.h>
37
#include <linux/sched.h>
38
#include <linux/stat.h>
39
#include <linux/string.h>
40
#include <linux/locks.h>
41
#include <linux/blkdev.h>
42
#include <linux/init.h>
43
#include <linux/module.h>
44
 
45
#include <linux/intermezzo_fs.h>
46
#include <linux/intermezzo_psdev.h>
47
 
48
static inline struct presto_file_set *presto_dentry2fset(struct dentry *dentry)
49
{
50
        if (presto_d2d(dentry) == NULL) {
51
                EXIT;
52
                return NULL;
53
        }
54
        return presto_d2d(dentry)->dd_fset;
55
}
56
 
57
/* find the fileset dentry for this dentry */
58
struct presto_file_set *presto_fset(struct dentry *de)
59
{
60
        struct dentry *fsde;
61
        ENTRY;
62
        if ( !de->d_inode ) {
63
                /* FIXME: is this ok to be NULL? */
64
                CDEBUG(D_INODE,"presto_fset: warning %*s has NULL inode.\n",
65
                de->d_name.len, de->d_name.name);
66
        }
67
        for (fsde = de;; fsde = fsde->d_parent) {
68
                if ( presto_dentry2fset(fsde) ) {
69
                        EXIT;
70
                        return presto_dentry2fset(fsde);
71
                }
72
                if (fsde->d_parent == fsde)
73
                        break;
74
        }
75
        EXIT;
76
        return NULL;
77
}
78
 
79
int presto_get_lastrecno(char *path, off_t *recno)
80
{
81
        struct nameidata nd;
82
        struct presto_file_set *fset;
83
        struct dentry *dentry;
84
        int error;
85
        ENTRY;
86
 
87
        error = presto_walk(path, &nd);
88
        if (error) {
89
                EXIT;
90
                return error;
91
        }
92
 
93
        dentry = nd.dentry;
94
 
95
        error = -ENXIO;
96
        if ( !presto_ispresto(dentry->d_inode) ) {
97
                EXIT;
98
                goto kml_out;
99
        }
100
 
101
        error = -EINVAL;
102
        if ( ! presto_dentry2fset(dentry)) {
103
                EXIT;
104
                goto kml_out;
105
        }
106
 
107
        fset = presto_dentry2fset(dentry);
108
        if (!fset) {
109
                EXIT;
110
                goto kml_out;
111
        }
112
        error = 0;
113
        *recno = fset->fset_kml.fd_recno;
114
 
115
 kml_out:
116
        path_release(&nd);
117
        return error;
118
}
119
 
120
static char * _izo_make_path(char *fsetname, char *name)
121
{
122
        char *path = NULL;
123
        int len;
124
 
125
        len = strlen("/.intermezzo/") + strlen(fsetname)
126
                + 1 + strlen(name) + 1;
127
 
128
        PRESTO_ALLOC(path, len);
129
        if (path == NULL)
130
                return NULL;
131
 
132
        sprintf(path, "/.intermezzo/%s/%s", fsetname, name);
133
 
134
        return path;
135
}
136
 
137
char * izo_make_path(struct presto_file_set *fset, char *name)
138
{
139
        return _izo_make_path(fset->fset_name, name);
140
}
141
 
142
static struct file *_izo_fset_open(char *fsetname, char *name, int flags, int mode)
143
{
144
        char *path;
145
        struct file *f;
146
        int error;
147
        ENTRY;
148
 
149
        path = _izo_make_path(fsetname, name);
150
        if (path == NULL) {
151
                EXIT;
152
                return ERR_PTR(-ENOMEM);
153
        }
154
 
155
        CDEBUG(D_INODE, "opening file %s\n", path);
156
        f = filp_open(path, flags, mode);
157
        error = PTR_ERR(f);
158
        if (IS_ERR(f)) {
159
                CDEBUG(D_INODE, "Error %d\n", error);
160
        }
161
 
162
        PRESTO_FREE(path, strlen(path));
163
 
164
        EXIT;
165
        return f;
166
 
167
}
168
 
169
struct file *izo_fset_open(struct presto_file_set *fset, char *name, int flags, int mode)
170
{
171
        return _izo_fset_open(fset->fset_name, name, flags, mode);
172
}
173
 
174
 
175
 
176
/*
177
 *  note: this routine "pins" a dentry for a fileset root
178
 */
179
int presto_set_fsetroot(struct dentry *ioctl_dentry, char *fsetname,
180
                        unsigned int flags)
181
{
182
        struct presto_file_set *fset = NULL;
183
        struct presto_cache *cache;
184
        int error;
185
        struct file  *fset_root;
186
        struct dentry *dentry;
187
 
188
        ENTRY;
189
 
190
        fset_root = _izo_fset_open(fsetname, "ROOT",  O_RDONLY, 000);
191
        if (IS_ERR(fset_root)) {
192
                CERROR("Can't open %s/ROOT\n", fsetname);
193
                EXIT;
194
                error = PTR_ERR(fset_root);
195
                goto out;
196
        }
197
        dentry = dget(fset_root->f_dentry);
198
        filp_close(fset_root, NULL);
199
 
200
        dentry->d_inode->i_op = ioctl_dentry->d_inode->i_op;
201
        dentry->d_inode->i_fop = ioctl_dentry->d_inode->i_fop;
202
        dentry->d_op = ioctl_dentry->d_op;
203
        fset = presto_dentry2fset(dentry);
204
        if (fset && (fset->fset_dentry == dentry) ) {
205
                CERROR("Fsetroot already set (inode %ld)\n",
206
                       dentry->d_inode->i_ino);
207
                /* XXX: ignore because clear_fsetroot is broken  */
208
#if 0
209
                dput(dentry);
210
                EXIT;
211
                error = -EEXIST;
212
                goto out;
213
#endif
214
        }
215
 
216
        cache = presto_get_cache(dentry->d_inode);
217
        if (!cache) {
218
                CERROR("No cache found for inode %ld\n",
219
                       dentry->d_inode->i_ino);
220
                EXIT;
221
                error = -ENODEV;
222
                goto out_free;
223
        }
224
 
225
        PRESTO_ALLOC(fset, sizeof(*fset));
226
        if ( !fset ) {
227
                CERROR("No memory allocating fset for %s\n", fsetname);
228
                EXIT;
229
                error = -ENOMEM;
230
                goto out_free;
231
        }
232
        CDEBUG(D_INODE, "fset at %p\n", fset);
233
 
234
        CDEBUG(D_INODE, "InterMezzo: fsetroot: inode %ld, fileset name %s\n",
235
               dentry->d_inode->i_ino, fsetname);
236
 
237
        fset->fset_mnt = mntget(current->fs->pwdmnt);
238
        fset->fset_cache = cache;
239
        fset->fset_dentry = dentry;
240
        fset->fset_name = strdup(fsetname);
241
        fset->fset_chunkbits = CHUNK_BITS;
242
        fset->fset_flags = flags;
243
        fset->fset_file_maxio = FSET_DEFAULT_MAX_FILEIO;
244
        fset->fset_permit_lock = SPIN_LOCK_UNLOCKED;
245
        PRESTO_ALLOC(fset->fset_reint_buf, 64 * 1024);
246
        if (fset->fset_reint_buf == NULL) {
247
                EXIT;
248
                error = -ENOMEM;
249
                goto out_free;
250
        }
251
        init_waitqueue_head(&fset->fset_permit_queue);
252
 
253
        if (presto_d2d(dentry) == NULL) {
254
                dentry->d_fsdata = izo_alloc_ddata();
255
        }
256
        if (presto_d2d(dentry) == NULL) {
257
                CERROR("InterMezzo: %s: no memory\n", __FUNCTION__);
258
                EXIT;
259
                error = -ENOMEM;
260
                goto out_free;
261
        }
262
        presto_d2d(dentry)->dd_fset = fset;
263
        list_add(&fset->fset_list, &cache->cache_fset_list);
264
 
265
        error = izo_init_kml_file(fset, &fset->fset_kml);
266
        if ( error ) {
267
                EXIT;
268
                CDEBUG(D_JOURNAL, "Error init_kml %d\n", error);
269
                goto out_list_del;
270
        }
271
 
272
        error = izo_init_lml_file(fset, &fset->fset_lml);
273
        if ( error ) {
274
                int rc;
275
                EXIT;
276
                rc = izo_log_close(&fset->fset_kml);
277
                CDEBUG(D_JOURNAL, "Error init_lml %d, cleanup %d\n", error, rc);
278
                goto out_list_del;
279
        }
280
 
281
        /* init_last_rcvd_file could trigger a presto_file_write(), which
282
         * requires that the lml structure be initialized. -phil */
283
        error = izo_init_last_rcvd_file(fset, &fset->fset_rcvd);
284
        if ( error ) {
285
                int rc;
286
                EXIT;
287
                rc = izo_log_close(&fset->fset_kml);
288
                rc = izo_log_close(&fset->fset_lml);
289
                CDEBUG(D_JOURNAL, "Error init_lastrcvd %d, cleanup %d\n", error, rc);
290
                goto out_list_del;
291
        }
292
 
293
        CDEBUG(D_PIOCTL, "-------> fset at %p, dentry at %p, mtpt %p,"
294
               "fset %s, cache %p, presto_d2d(dentry)->dd_fset %p\n",
295
               fset, dentry, fset->fset_dentry, fset->fset_name, cache,
296
               presto_d2d(dentry)->dd_fset);
297
 
298
        EXIT;
299
        return 0;
300
 
301
 out_list_del:
302
        list_del(&fset->fset_list);
303
        presto_d2d(dentry)->dd_fset = NULL;
304
 out_free:
305
        if (fset) {
306
                mntput(fset->fset_mnt);
307
                if (fset->fset_reint_buf != NULL)
308
                        PRESTO_FREE(fset->fset_reint_buf, 64 * 1024);
309
                PRESTO_FREE(fset, sizeof(*fset));
310
        }
311
        dput(dentry);
312
 out:
313
        return error;
314
}
315
 
316
static int izo_cleanup_fset(struct presto_file_set *fset)
317
{
318
        int error;
319
        struct presto_cache *cache;
320
 
321
        ENTRY;
322
 
323
        CERROR("Cleaning up fset %s\n", fset->fset_name);
324
 
325
        error = izo_log_close(&fset->fset_kml);
326
        if (error)
327
                CERROR("InterMezzo: Closing kml for fset %s: %d\n",
328
                       fset->fset_name, error);
329
        error = izo_log_close(&fset->fset_lml);
330
        if (error)
331
                CERROR("InterMezzo: Closing lml for fset %s: %d\n",
332
                       fset->fset_name, error);
333
        error = izo_log_close(&fset->fset_rcvd);
334
        if (error)
335
                CERROR("InterMezzo: Closing last_rcvd for fset %s: %d\n",
336
                       fset->fset_name, error);
337
 
338
        cache = fset->fset_cache;
339
 
340
        list_del(&fset->fset_list);
341
 
342
        presto_d2d(fset->fset_dentry)->dd_fset = NULL;
343
        dput(fset->fset_dentry);
344
        mntput(fset->fset_mnt);
345
 
346
        PRESTO_FREE(fset->fset_name, strlen(fset->fset_name) + 1);
347
        PRESTO_FREE(fset->fset_reint_buf, 64 * 1024);
348
        PRESTO_FREE(fset, sizeof(*fset));
349
        EXIT;
350
        return error;
351
}
352
 
353
int izo_clear_fsetroot(struct dentry *dentry)
354
{
355
        struct presto_file_set *fset;
356
 
357
        ENTRY;
358
 
359
        fset = presto_dentry2fset(dentry);
360
        if (!fset) {
361
                EXIT;
362
                return -EINVAL;
363
        }
364
 
365
        izo_cleanup_fset(fset);
366
        EXIT;
367
        return 0;
368
}
369
 
370
int izo_clear_all_fsetroots(struct presto_cache *cache)
371
{
372
        struct presto_file_set *fset;
373
        struct list_head *tmp,*tmpnext;
374
        int error;
375
 
376
        error = 0;
377
        tmp = &cache->cache_fset_list;
378
        tmpnext = tmp->next;
379
        while ( tmpnext != &cache->cache_fset_list) {
380
                tmp = tmpnext;
381
                tmpnext = tmp->next;
382
                fset = list_entry(tmp, struct presto_file_set, fset_list);
383
 
384
                error = izo_cleanup_fset(fset);
385
                if (error)
386
                        break;
387
        }
388
        return error;
389
}
390
 
391
static struct vfsmount *izo_alloc_vfsmnt(void)
392
{
393
        struct vfsmount *mnt;
394
        PRESTO_ALLOC(mnt, sizeof(*mnt));
395
        if (mnt) {
396
                memset(mnt, 0, sizeof(struct vfsmount));
397
                atomic_set(&mnt->mnt_count,1);
398
                INIT_LIST_HEAD(&mnt->mnt_hash);
399
                INIT_LIST_HEAD(&mnt->mnt_child);
400
                INIT_LIST_HEAD(&mnt->mnt_mounts);
401
                INIT_LIST_HEAD(&mnt->mnt_list);
402
        }
403
        return mnt;
404
}
405
 
406
 
407
static void izo_setup_ctxt(struct dentry *root, struct vfsmount *mnt,
408
                           struct run_ctxt *save)
409
{
410
        struct run_ctxt new;
411
 
412
        mnt->mnt_root = root;
413
        mnt->mnt_sb = root->d_inode->i_sb;
414
        unlock_super(mnt->mnt_sb);
415
 
416
        new.rootmnt = mnt;
417
        new.root = root;
418
        new.pwdmnt = mnt;
419
        new.pwd = root;
420
        new.fsuid = 0;
421
        new.fsgid = 0;
422
        new.fs = get_fs();
423
        /* XXX where can we get the groups from? */
424
        new.ngroups = 0;
425
 
426
        push_ctxt(save, &new);
427
}
428
 
429
static void izo_cleanup_ctxt(struct vfsmount *mnt, struct run_ctxt *save)
430
{
431
        lock_super(mnt->mnt_sb);
432
        pop_ctxt(save);
433
}
434
 
435
static int izo_simple_mkdir(struct dentry *dir, char *name, int mode)
436
{
437
        struct dentry *dchild;
438
        int err;
439
        ENTRY;
440
 
441
        dchild = lookup_one_len(name, dir, strlen(name));
442
        if (IS_ERR(dchild)) {
443
                EXIT;
444
                return PTR_ERR(dchild);
445
        }
446
 
447
        if (dchild->d_inode) {
448
                dput(dchild);
449
                EXIT;
450
                return -EEXIST;
451
        }
452
 
453
        err = vfs_mkdir(dir->d_inode, dchild, mode);
454
        dput(dchild);
455
 
456
        EXIT;
457
        return err;
458
}
459
 
460
static int izo_simple_symlink(struct dentry *dir, char *name, char *tgt)
461
{
462
        struct dentry *dchild;
463
        int err;
464
        ENTRY;
465
 
466
        dchild = lookup_one_len(name, dir, strlen(name));
467
        if (IS_ERR(dchild)) {
468
                EXIT;
469
                return PTR_ERR(dchild);
470
        }
471
 
472
        if (dchild->d_inode) {
473
                dput(dchild);
474
                EXIT;
475
                return -EEXIST;
476
        }
477
 
478
        err = vfs_symlink(dir->d_inode, dchild, tgt);
479
        dput(dchild);
480
 
481
        EXIT;
482
        return err;
483
}
484
 
485
/*
486
 * run set_fsetroot in chroot environment
487
 */
488
int presto_set_fsetroot_from_ioc(struct dentry *root, char *fsetname,
489
                                 unsigned int flags)
490
{
491
        int rc;
492
        struct presto_cache *cache;
493
        struct vfsmount *mnt;
494
        struct run_ctxt save;
495
 
496
        if (root != root->d_inode->i_sb->s_root) {
497
                CERROR ("IOC_SET_FSET must be called on mount point\n");
498
                return -ENODEV;
499
        }
500
 
501
        cache = presto_get_cache(root->d_inode);
502
        mnt = cache->cache_vfsmount;
503
        if (!mnt) {
504
                EXIT;
505
                return -ENOMEM;
506
        }
507
 
508
        izo_setup_ctxt(root, mnt, &save);
509
        rc = presto_set_fsetroot(root, fsetname, flags);
510
        izo_cleanup_ctxt(mnt, &save);
511
        return rc;
512
}
513
 
514
/* XXX: this function should detect if fsetname is already in use for
515
   the cache under root
516
*/
517
int izo_prepare_fileset(struct dentry *root, char *fsetname)
518
{
519
        int err;
520
        struct dentry *dotizo = NULL, *fsetdir = NULL, *dotiopen = NULL;
521
        struct presto_cache *cache;
522
        struct vfsmount *mnt;
523
        struct run_ctxt save;
524
 
525
        cache = presto_get_cache(root->d_inode);
526
        mnt = cache->cache_vfsmount = izo_alloc_vfsmnt();
527
        if (!mnt) {
528
                EXIT;
529
                return -ENOMEM;
530
        }
531
 
532
        if (!fsetname)
533
                fsetname = "rootfset";
534
 
535
        izo_setup_ctxt(root, mnt, &save);
536
 
537
        err = izo_simple_mkdir(root, ".intermezzo", 0755);
538
        CDEBUG(D_CACHE, "mkdir on .intermezzo err %d\n", err);
539
 
540
        err = izo_simple_mkdir(root, "..iopen..", 0755);
541
        CDEBUG(D_CACHE, "mkdir on ..iopen.. err %d\n", err);
542
 
543
        dotiopen = lookup_one_len("..iopen..", root, strlen("..iopen.."));
544
        if (IS_ERR(dotiopen)) {
545
                EXIT;
546
                goto out;
547
        }
548
        dotiopen->d_inode->i_op = &presto_dir_iops;
549
        dput(dotiopen);
550
 
551
 
552
        dotizo = lookup_one_len(".intermezzo", root, strlen(".intermezzo"));
553
        if (IS_ERR(dotizo)) {
554
                EXIT;
555
                goto out;
556
        }
557
 
558
 
559
        err = izo_simple_mkdir(dotizo, fsetname, 0755);
560
        CDEBUG(D_CACHE, "mkdir err %d\n", err);
561
 
562
        /* XXX find the dentry of the root of the fileset (root for now) */
563
        fsetdir = lookup_one_len(fsetname, dotizo, strlen(fsetname));
564
        if (IS_ERR(fsetdir)) {
565
                EXIT;
566
                goto out;
567
        }
568
 
569
        err = izo_simple_symlink(fsetdir, "ROOT", "../..");
570
 
571
        /* XXX read flags from flags file */
572
        err =  presto_set_fsetroot(root, fsetname, 0);
573
        CDEBUG(D_CACHE, "set_fsetroot err %d\n", err);
574
 
575
 out:
576
        if (dotizo && !IS_ERR(dotizo))
577
                dput(dotizo);
578
        if (fsetdir && !IS_ERR(fsetdir))
579
                dput(fsetdir);
580
        izo_cleanup_ctxt(mnt, &save);
581
        return err;
582
}
583
 
584
int izo_set_fileid(struct file *dir, struct izo_ioctl_data *data)
585
{
586
        int rc = 0;
587
        struct presto_cache *cache;
588
        struct vfsmount *mnt;
589
        struct run_ctxt save;
590
        struct nameidata nd;
591
        struct dentry *dentry;
592
        struct presto_dentry_data *dd;
593
        struct dentry *root;
594
        char *buf = NULL;
595
 
596
        ENTRY;
597
 
598
 
599
        root = dir->f_dentry;
600
 
601
        /* actually, needs to be called on ROOT of fset, not mount point
602
        if (root != root->d_inode->i_sb->s_root) {
603
                CERROR ("IOC_SET_FSET must be called on mount point\n");
604
                return -ENODEV;
605
        }
606
        */
607
 
608
        cache = presto_get_cache(root->d_inode);
609
        mnt = cache->cache_vfsmount;
610
        if (!mnt) {
611
                EXIT;
612
                return -ENOMEM;
613
        }
614
 
615
        izo_setup_ctxt(root, mnt, &save);
616
 
617
        PRESTO_ALLOC(buf, data->ioc_plen1);
618
        if (!buf) {
619
                rc = -ENOMEM;
620
                EXIT;
621
                goto out;
622
        }
623
        if (copy_from_user(buf, data->ioc_pbuf1, data->ioc_plen1)) {
624
                rc =  -EFAULT;
625
                EXIT;
626
                goto out;
627
        }
628
 
629
        rc = presto_walk(buf, &nd);
630
        if (rc) {
631
                CERROR("Unable to open: %s\n", buf);
632
                EXIT;
633
                goto out;
634
        }
635
        dentry = nd.dentry;
636
        if (!dentry) {
637
                CERROR("no dentry!\n");
638
                rc =  -EINVAL;
639
                EXIT;
640
                goto out_close;
641
        }
642
        dd = presto_d2d(dentry);
643
        if (!dd) {
644
                CERROR("no dentry_data!\n");
645
                rc = -EINVAL;
646
                EXIT;
647
                goto out_close;
648
        }
649
 
650
        CDEBUG(D_FILE,"de:%p dd:%p\n", dentry, dd);
651
 
652
        if (dd->remote_ino != 0) {
653
                CERROR("remote_ino already set? %Lx:%Lx\n", dd->remote_ino,
654
                       dd->remote_generation);
655
                rc = 0;
656
                EXIT;
657
                goto out_close;
658
        }
659
 
660
 
661
        CDEBUG(D_FILE,"setting %p %p, %s to %Lx:%Lx\n", dentry, dd,
662
               buf, data->ioc_ino,
663
               data->ioc_generation);
664
        dd->remote_ino = data->ioc_ino;
665
        dd->remote_generation = data->ioc_generation;
666
 
667
        EXIT;
668
 out_close:
669
        path_release(&nd);
670
 out:
671
        if (buf)
672
                PRESTO_FREE(buf, data->ioc_plen1);
673
        izo_cleanup_ctxt(mnt, &save);
674
        return rc;
675
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.