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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [super.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/fs/super.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 *
6
 *  super.c contains code to handle: - mount structures
7
 *                                   - super-block tables
8
 *                                   - filesystem drivers list
9
 *                                   - mount system call
10
 *                                   - umount system call
11
 *                                   - ustat system call
12
 *
13
 * GK 2/5/95  -  Changed to support mounting the root fs via NFS
14
 *
15
 *  Added kerneld support: Jacques Gelinas and Bjorn Ekwall
16
 *  Added change_root: Werner Almesberger & Hans Lermen, Feb '96
17
 *  Added options to /proc/mounts:
18
 *    Torbjörn Lindh (torbjorn.lindh@gopta.se), April 14, 1996.
19
 *  Added devfs support: Richard Gooch <rgooch@atnf.csiro.au>, 13-JAN-1998
20
 *  Heavily rewritten for 'one fs - one tree' dcache architecture. AV, Mar 2000
21
 */
22
 
23
#include <linux/config.h>
24
#include <linux/slab.h>
25
#include <linux/locks.h>
26
#include <linux/smp_lock.h>
27
#include <linux/devfs_fs_kernel.h>
28
#include <linux/major.h>
29
#include <linux/acct.h>
30
#include <linux/quotaops.h>
31
 
32
#include <asm/uaccess.h>
33
 
34
#include <linux/kmod.h>
35
#define __NO_VERSION__
36
#include <linux/module.h>
37
 
38
LIST_HEAD(super_blocks);
39
spinlock_t sb_lock = SPIN_LOCK_UNLOCKED;
40
 
41
/*
42
 * Handling of filesystem drivers list.
43
 * Rules:
44
 *      Inclusion to/removals from/scanning of list are protected by spinlock.
45
 *      During the unload module must call unregister_filesystem().
46
 *      We can access the fields of list element if:
47
 *              1) spinlock is held or
48
 *              2) we hold the reference to the module.
49
 *      The latter can be guaranteed by call of try_inc_mod_count(); if it
50
 *      returned 0 we must skip the element, otherwise we got the reference.
51
 *      Once the reference is obtained we can drop the spinlock.
52
 */
53
 
54
static struct file_system_type *file_systems;
55
static rwlock_t file_systems_lock = RW_LOCK_UNLOCKED;
56
 
57
/* WARNING: This can be used only if we _already_ own a reference */
58
static void get_filesystem(struct file_system_type *fs)
59
{
60
        if (fs->owner)
61
                __MOD_INC_USE_COUNT(fs->owner);
62
}
63
 
64
static void put_filesystem(struct file_system_type *fs)
65
{
66
        if (fs->owner)
67
                __MOD_DEC_USE_COUNT(fs->owner);
68
}
69
 
70
static struct file_system_type **find_filesystem(const char *name)
71
{
72
        struct file_system_type **p;
73
        for (p=&file_systems; *p; p=&(*p)->next)
74
                if (strcmp((*p)->name,name) == 0)
75
                        break;
76
        return p;
77
}
78
 
79
/**
80
 *      register_filesystem - register a new filesystem
81
 *      @fs: the file system structure
82
 *
83
 *      Adds the file system passed to the list of file systems the kernel
84
 *      is aware of for mount and other syscalls. Returns 0 on success,
85
 *      or a negative errno code on an error.
86
 *
87
 *      The &struct file_system_type that is passed is linked into the kernel
88
 *      structures and must not be freed until the file system has been
89
 *      unregistered.
90
 */
91
 
92
int register_filesystem(struct file_system_type * fs)
93
{
94
        int res = 0;
95
        struct file_system_type ** p;
96
 
97
        if (!fs)
98
                return -EINVAL;
99
        if (fs->next)
100
                return -EBUSY;
101
        INIT_LIST_HEAD(&fs->fs_supers);
102
        write_lock(&file_systems_lock);
103
        p = find_filesystem(fs->name);
104
        if (*p)
105
                res = -EBUSY;
106
        else
107
                *p = fs;
108
        write_unlock(&file_systems_lock);
109
        return res;
110
}
111
 
112
/**
113
 *      unregister_filesystem - unregister a file system
114
 *      @fs: filesystem to unregister
115
 *
116
 *      Remove a file system that was previously successfully registered
117
 *      with the kernel. An error is returned if the file system is not found.
118
 *      Zero is returned on a success.
119
 *
120
 *      Once this function has returned the &struct file_system_type structure
121
 *      may be freed or reused.
122
 */
123
 
124
int unregister_filesystem(struct file_system_type * fs)
125
{
126
        struct file_system_type ** tmp;
127
 
128
        write_lock(&file_systems_lock);
129
        tmp = &file_systems;
130
        while (*tmp) {
131
                if (fs == *tmp) {
132
                        *tmp = fs->next;
133
                        fs->next = NULL;
134
                        write_unlock(&file_systems_lock);
135
                        return 0;
136
                }
137
                tmp = &(*tmp)->next;
138
        }
139
        write_unlock(&file_systems_lock);
140
        return -EINVAL;
141
}
142
 
143
static int fs_index(const char * __name)
144
{
145
        struct file_system_type * tmp;
146
        char * name;
147
        int err, index;
148
 
149
        name = getname(__name);
150
        err = PTR_ERR(name);
151
        if (IS_ERR(name))
152
                return err;
153
 
154
        err = -EINVAL;
155
        read_lock(&file_systems_lock);
156
        for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
157
                if (strcmp(tmp->name,name) == 0) {
158
                        err = index;
159
                        break;
160
                }
161
        }
162
        read_unlock(&file_systems_lock);
163
        putname(name);
164
        return err;
165
}
166
 
167
static int fs_name(unsigned int index, char * buf)
168
{
169
        struct file_system_type * tmp;
170
        int len, res;
171
 
172
        read_lock(&file_systems_lock);
173
        for (tmp = file_systems; tmp; tmp = tmp->next, index--)
174
                if (index <= 0 && try_inc_mod_count(tmp->owner))
175
                                break;
176
        read_unlock(&file_systems_lock);
177
        if (!tmp)
178
                return -EINVAL;
179
 
180
        /* OK, we got the reference, so we can safely block */
181
        len = strlen(tmp->name) + 1;
182
        res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
183
        put_filesystem(tmp);
184
        return res;
185
}
186
 
187
static int fs_maxindex(void)
188
{
189
        struct file_system_type * tmp;
190
        int index;
191
 
192
        read_lock(&file_systems_lock);
193
        for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
194
                ;
195
        read_unlock(&file_systems_lock);
196
        return index;
197
}
198
 
199
/*
200
 * Whee.. Weird sysv syscall.
201
 */
202
asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2)
203
{
204
        int retval = -EINVAL;
205
 
206
        switch (option) {
207
                case 1:
208
                        retval = fs_index((const char *) arg1);
209
                        break;
210
 
211
                case 2:
212
                        retval = fs_name(arg1, (char *) arg2);
213
                        break;
214
 
215
                case 3:
216
                        retval = fs_maxindex();
217
                        break;
218
        }
219
        return retval;
220
}
221
 
222
int get_filesystem_list(char * buf)
223
{
224
        int len = 0;
225
        struct file_system_type * tmp;
226
 
227
        read_lock(&file_systems_lock);
228
        tmp = file_systems;
229
        while (tmp && len < PAGE_SIZE - 80) {
230
                len += sprintf(buf+len, "%s\t%s\n",
231
                        (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
232
                        tmp->name);
233
                tmp = tmp->next;
234
        }
235
        read_unlock(&file_systems_lock);
236
        return len;
237
}
238
 
239
struct file_system_type *get_fs_type(const char *name)
240
{
241
        struct file_system_type *fs;
242
 
243
        read_lock(&file_systems_lock);
244
        fs = *(find_filesystem(name));
245
        if (fs && !try_inc_mod_count(fs->owner))
246
                fs = NULL;
247
        read_unlock(&file_systems_lock);
248
        if (!fs && (request_module(name) == 0)) {
249
                read_lock(&file_systems_lock);
250
                fs = *(find_filesystem(name));
251
                if (fs && !try_inc_mod_count(fs->owner))
252
                        fs = NULL;
253
                read_unlock(&file_systems_lock);
254
        }
255
        return fs;
256
}
257
 
258
/**
259
 *      alloc_super     -       create new superblock
260
 *
261
 *      Allocates and initializes a new &struct super_block.  alloc_super()
262
 *      returns a pointer new superblock or %NULL if allocation had failed.
263
 */
264
static struct super_block *alloc_super(void)
265
{
266
        static struct super_operations empty_sops = {};
267
        struct super_block *s = kmalloc(sizeof(struct super_block),  GFP_USER);
268
        if (s) {
269
                memset(s, 0, sizeof(struct super_block));
270
                INIT_LIST_HEAD(&s->s_dirty);
271
                INIT_LIST_HEAD(&s->s_locked_inodes);
272
                INIT_LIST_HEAD(&s->s_files);
273
                INIT_LIST_HEAD(&s->s_instances);
274
                init_rwsem(&s->s_umount);
275
                sema_init(&s->s_lock, 1);
276
                down_write(&s->s_umount);
277
                s->s_count = S_BIAS;
278
                atomic_set(&s->s_active, 1);
279
                sema_init(&s->s_vfs_rename_sem,1);
280
                sema_init(&s->s_nfsd_free_path_sem,1);
281
                sema_init(&s->s_dquot.dqio_sem, 1);
282
                sema_init(&s->s_dquot.dqoff_sem, 1);
283
                s->s_maxbytes = MAX_NON_LFS;
284
                s->s_op = &empty_sops;
285
                s->dq_op = sb_dquot_ops;
286
                s->s_qcop = sb_quotactl_ops;
287
        }
288
        return s;
289
}
290
 
291
/**
292
 *      destroy_super   -       frees a superblock
293
 *      @s: superblock to free
294
 *
295
 *      Frees a superblock.
296
 */
297
static inline void destroy_super(struct super_block *s)
298
{
299
        kfree(s);
300
}
301
 
302
/* Superblock refcounting  */
303
 
304
/**
305
 *      deactivate_super        -       turn an active reference into temporary
306
 *      @s: superblock to deactivate
307
 *
308
 *      Turns an active reference into temporary one.  Returns 0 if there are
309
 *      other active references, 1 if we had deactivated the last one.
310
 */
311
static inline int deactivate_super(struct super_block *s)
312
{
313
        if (!atomic_dec_and_lock(&s->s_active, &sb_lock))
314
                return 0;
315
        s->s_count -= S_BIAS-1;
316
        spin_unlock(&sb_lock);
317
        return 1;
318
}
319
 
320
/**
321
 *      put_super       -       drop a temporary reference to superblock
322
 *      @s: superblock in question
323
 *
324
 *      Drops a temporary reference, frees superblock if there's no
325
 *      references left.
326
 */
327
static inline void put_super(struct super_block *s)
328
{
329
        spin_lock(&sb_lock);
330
        if (!--s->s_count)
331
                destroy_super(s);
332
        spin_unlock(&sb_lock);
333
}
334
 
335
/**
336
 *      grab_super      - acquire an active reference
337
 *      @s      - reference we are trying to make active
338
 *
339
 *      Tries to acquire an active reference.  grab_super() is used when we
340
 *      had just found a superblock in super_blocks or fs_type->fs_supers
341
 *      and want to turn it into a full-blown active reference.  grab_super()
342
 *      is called with sb_lock held and drops it.  Returns 1 in case of
343
 *      success, 0 if we had failed (superblock contents was already dead or
344
 *      dying when grab_super() had been called).
345
 */
346
static int grab_super(struct super_block *s)
347
{
348
        s->s_count++;
349
        spin_unlock(&sb_lock);
350
        down_write(&s->s_umount);
351
        if (s->s_root) {
352
                spin_lock(&sb_lock);
353
                if (s->s_count > S_BIAS) {
354
                        atomic_inc(&s->s_active);
355
                        s->s_count--;
356
                        spin_unlock(&sb_lock);
357
                        return 1;
358
                }
359
                spin_unlock(&sb_lock);
360
        }
361
        up_write(&s->s_umount);
362
        put_super(s);
363
        return 0;
364
}
365
 
366
/**
367
 *      insert_super    -       put superblock on the lists
368
 *      @s:     superblock in question
369
 *      @type:  filesystem type it will belong to
370
 *
371
 *      Associates superblock with fs type and puts it on per-type and global
372
 *      superblocks' lists.  Should be called with sb_lock held; drops it.
373
 */
374
static void insert_super(struct super_block *s, struct file_system_type *type)
375
{
376
        s->s_type = type;
377
        list_add(&s->s_list, super_blocks.prev);
378
        list_add(&s->s_instances, &type->fs_supers);
379
        spin_unlock(&sb_lock);
380
        get_filesystem(type);
381
}
382
 
383
static void put_anon_dev(kdev_t dev);
384
 
385
/**
386
 *      remove_super    -       makes superblock unreachable
387
 *      @s:     superblock in question
388
 *
389
 *      Removes superblock from the lists, unlocks it, drop the reference
390
 *      and releases the hosting device.  @s should have no active
391
 *      references by that time and after remove_super() it's essentially
392
 *      in rundown mode - all remaining references are temporary, no new
393
 *      reference of any sort are going to appear and all holders of
394
 *      temporary ones will eventually drop them.  At that point superblock
395
 *      itself will be destroyed; all its contents is already gone.
396
 */
397
static void remove_super(struct super_block *s)
398
{
399
        kdev_t dev = s->s_dev;
400
        struct block_device *bdev = s->s_bdev;
401
        struct file_system_type *fs = s->s_type;
402
 
403
        spin_lock(&sb_lock);
404
        list_del(&s->s_list);
405
        list_del(&s->s_instances);
406
        spin_unlock(&sb_lock);
407
        up_write(&s->s_umount);
408
        put_super(s);
409
        put_filesystem(fs);
410
        if (bdev)
411
                blkdev_put(bdev, BDEV_FS);
412
        else
413
                put_anon_dev(dev);
414
}
415
 
416
struct vfsmount *alloc_vfsmnt(char *name);
417
void free_vfsmnt(struct vfsmount *mnt);
418
 
419
static inline struct super_block * find_super(kdev_t dev)
420
{
421
        struct list_head *p;
422
 
423
        list_for_each(p, &super_blocks) {
424
                struct super_block * s = sb_entry(p);
425
                if (s->s_dev == dev) {
426
                        s->s_count++;
427
                        return s;
428
                }
429
        }
430
        return NULL;
431
}
432
 
433
void drop_super(struct super_block *sb)
434
{
435
        up_read(&sb->s_umount);
436
        put_super(sb);
437
}
438
 
439
static inline void write_super(struct super_block *sb)
440
{
441
        lock_super(sb);
442
        if (sb->s_root && sb->s_dirt)
443
                if (sb->s_op && sb->s_op->write_super)
444
                        sb->s_op->write_super(sb);
445
        unlock_super(sb);
446
}
447
 
448
/*
449
 * Note: check the dirty flag before waiting, so we don't
450
 * hold up the sync while mounting a device. (The newly
451
 * mounted device won't need syncing.)
452
 */
453
void sync_supers(kdev_t dev, int wait)
454
{
455
        struct super_block * sb;
456
 
457
        if (dev) {
458
                sb = get_super(dev);
459
                if (sb) {
460
                        if (sb->s_dirt)
461
                                write_super(sb);
462
                        if (wait && sb->s_op && sb->s_op->sync_fs)
463
                                sb->s_op->sync_fs(sb);
464
                        drop_super(sb);
465
                }
466
                return;
467
        }
468
restart:
469
        spin_lock(&sb_lock);
470
        sb = sb_entry(super_blocks.next);
471
        while (sb != sb_entry(&super_blocks))
472
                if (sb->s_dirt) {
473
                        sb->s_count++;
474
                        spin_unlock(&sb_lock);
475
                        down_read(&sb->s_umount);
476
                        write_super(sb);
477
                        if (wait && sb->s_root && sb->s_op && sb->s_op->sync_fs)
478
                                sb->s_op->sync_fs(sb);
479
                        drop_super(sb);
480
                        goto restart;
481
                } else
482
                        sb = sb_entry(sb->s_list.next);
483
        spin_unlock(&sb_lock);
484
}
485
 
486
/**
487
 *      get_super       -       get the superblock of a device
488
 *      @dev: device to get the superblock for
489
 *
490
 *      Scans the superblock list and finds the superblock of the file system
491
 *      mounted on the device given. %NULL is returned if no match is found.
492
 */
493
 
494
struct super_block * get_super(kdev_t dev)
495
{
496
        struct super_block * s;
497
 
498
        if (!dev)
499
                return NULL;
500
restart:
501
        spin_lock(&sb_lock);
502
        s = find_super(dev);
503
        if (s) {
504
                spin_unlock(&sb_lock);
505
                down_read(&s->s_umount);
506
                if (s->s_root)
507
                        return s;
508
                drop_super(s);
509
                goto restart;
510
        }
511
        spin_unlock(&sb_lock);
512
        return NULL;
513
}
514
 
515
asmlinkage long sys_ustat(dev_t dev, struct ustat * ubuf)
516
{
517
        struct super_block *s;
518
        struct ustat tmp;
519
        struct statfs sbuf;
520
        int err = -EINVAL;
521
 
522
        s = get_super(to_kdev_t(dev));
523
        if (s == NULL)
524
                goto out;
525
        err = vfs_statfs(s, &sbuf);
526
        drop_super(s);
527
        if (err)
528
                goto out;
529
 
530
        memset(&tmp,0,sizeof(struct ustat));
531
        tmp.f_tfree = sbuf.f_bfree;
532
        tmp.f_tinode = sbuf.f_ffree;
533
 
534
        err = copy_to_user(ubuf,&tmp,sizeof(struct ustat)) ? -EFAULT : 0;
535
out:
536
        return err;
537
}
538
 
539
/**
540
 *      do_remount_sb   -       asks filesystem to change mount options.
541
 *      @sb:    superblock in question
542
 *      @flags: numeric part of options
543
 *      @data:  the rest of options
544
 *
545
 *      Alters the mount options of a mounted file system.
546
 */
547
int do_remount_sb(struct super_block *sb, int flags, void *data)
548
{
549
        int retval;
550
 
551
        if (!(flags & MS_RDONLY) && sb->s_dev && is_read_only(sb->s_dev))
552
                return -EACCES;
553
                /*flags |= MS_RDONLY;*/
554
        if (flags & MS_RDONLY)
555
                acct_auto_close(sb->s_dev);
556
        shrink_dcache_sb(sb);
557
        fsync_super(sb);
558
        /* If we are remounting RDONLY, make sure there are no rw files open */
559
        if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
560
                if (!fs_may_remount_ro(sb))
561
                        return -EBUSY;
562
        if (sb->s_op && sb->s_op->remount_fs) {
563
                lock_super(sb);
564
                retval = sb->s_op->remount_fs(sb, &flags, data);
565
                unlock_super(sb);
566
                if (retval)
567
                        return retval;
568
        }
569
        sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
570
        return 0;
571
}
572
 
573
/*
574
 * Unnamed block devices are dummy devices used by virtual
575
 * filesystems which don't use real block-devices.  -- jrs
576
 */
577
 
578
enum {Max_anon = 256};
579
static unsigned long unnamed_dev_in_use[Max_anon/(8*sizeof(unsigned long))];
580
static spinlock_t unnamed_dev_lock = SPIN_LOCK_UNLOCKED;/* protects the above */
581
 
582
/**
583
 *      put_anon_dev    -       release anonymous device number.
584
 *      @dev:   device in question
585
 */
586
static void put_anon_dev(kdev_t dev)
587
{
588
        spin_lock(&unnamed_dev_lock);
589
        clear_bit(MINOR(dev), unnamed_dev_in_use);
590
        spin_unlock(&unnamed_dev_lock);
591
}
592
 
593
/**
594
 *      get_anon_super  -       allocate a superblock for non-device fs
595
 *      @type:          filesystem type
596
 *      @compare:       check if existing superblock is what we want
597
 *      @data:          argument for @compare.
598
 *
599
 *      get_anon_super is a helper for non-blockdevice filesystems.
600
 *      It either finds and returns one of the superblocks of given type
601
 *      (if it can find one that would satisfy caller) or creates a new
602
 *      one.  In the either case we return an active reference to superblock
603
 *      with ->s_umount locked.  If superblock is new it gets a new
604
 *      anonymous device allocated for it and is inserted into lists -
605
 *      other initialization is left to caller.
606
 *
607
 *      Rather than duplicating all that logics every time when
608
 *      we want something that doesn't fit "nodev" and "single" we pull
609
 *      the relevant code into common helper and let get_sb_...() call
610
 *      it.
611
 *
612
 *      NB: get_sb_...() is going to become an fs type method, with
613
 *      current ->read_super() becoming a callback used by common instances.
614
 */
615
struct super_block *get_anon_super(struct file_system_type *type,
616
        int (*compare)(struct super_block *,void *), void *data)
617
{
618
        struct super_block *s = alloc_super();
619
        kdev_t dev;
620
        struct list_head *p;
621
 
622
        if (!s)
623
                return ERR_PTR(-ENOMEM);
624
 
625
retry:
626
        spin_lock(&sb_lock);
627
        if (compare) list_for_each(p, &type->fs_supers) {
628
                struct super_block *old;
629
                old = list_entry(p, struct super_block, s_instances);
630
                if (!compare(old, data))
631
                        continue;
632
                if (!grab_super(old))
633
                        goto retry;
634
                destroy_super(s);
635
                return old;
636
        }
637
 
638
        spin_lock(&unnamed_dev_lock);
639
        dev = find_first_zero_bit(unnamed_dev_in_use, Max_anon);
640
        if (dev == Max_anon) {
641
                spin_unlock(&unnamed_dev_lock);
642
                spin_unlock(&sb_lock);
643
                destroy_super(s);
644
                return ERR_PTR(-EMFILE);
645
        }
646
        set_bit(dev, unnamed_dev_in_use);
647
        spin_unlock(&unnamed_dev_lock);
648
 
649
        s->s_dev = dev;
650
        insert_super(s, type);
651
        return s;
652
}
653
 
654
static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
655
        int flags, char *dev_name, void * data)
656
{
657
        struct inode *inode;
658
        struct block_device *bdev;
659
        struct block_device_operations *bdops;
660
        devfs_handle_t de;
661
        struct super_block * s;
662
        struct nameidata nd;
663
        struct list_head *p;
664
        kdev_t dev;
665
        int error = 0;
666
        mode_t mode = FMODE_READ; /* we always need it ;-) */
667
 
668
        /* What device it is? */
669
        if (!dev_name || !*dev_name)
670
                return ERR_PTR(-EINVAL);
671
        error = path_lookup(dev_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
672
        if (error)
673
                return ERR_PTR(error);
674
        inode = nd.dentry->d_inode;
675
        error = -ENOTBLK;
676
        if (!S_ISBLK(inode->i_mode))
677
                goto out;
678
        error = -EACCES;
679
        if (nd.mnt->mnt_flags & MNT_NODEV)
680
                goto out;
681
        bd_acquire(inode);
682
        bdev = inode->i_bdev;
683
        de = devfs_get_handle_from_inode (inode);
684
        bdops = devfs_get_ops (de);         /*  Increments module use count  */
685
        if (bdops) bdev->bd_op = bdops;
686
        /* Done with lookups, semaphore down */
687
        dev = to_kdev_t(bdev->bd_dev);
688
        if (!(flags & MS_RDONLY))
689
                mode |= FMODE_WRITE;
690
        error = blkdev_get(bdev, mode, 0, BDEV_FS);
691
        devfs_put_ops (de);   /*  Decrement module use count now we're safe  */
692
        if (error)
693
                goto out;
694
        check_disk_change(dev);
695
        error = -EACCES;
696
        if (!(flags & MS_RDONLY) && is_read_only(dev))
697
                goto out1;
698
 
699
        error = -ENOMEM;
700
        s = alloc_super();
701
        if (!s)
702
                goto out1;
703
 
704
        error = -EBUSY;
705
restart:
706
        spin_lock(&sb_lock);
707
 
708
        list_for_each(p, &super_blocks) {
709
                struct super_block *old = sb_entry(p);
710
                if (old->s_dev != dev)
711
                        continue;
712
                if (old->s_type != fs_type ||
713
                    ((flags ^ old->s_flags) & MS_RDONLY)) {
714
                        spin_unlock(&sb_lock);
715
                        destroy_super(s);
716
                        goto out1;
717
                }
718
                if (!grab_super(old))
719
                        goto restart;
720
                destroy_super(s);
721
                blkdev_put(bdev, BDEV_FS);
722
                path_release(&nd);
723
                return old;
724
        }
725
        s->s_dev = dev;
726
        s->s_bdev = bdev;
727
        s->s_flags = flags;
728
        insert_super(s, fs_type);
729
        if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
730
                goto Einval;
731
        s->s_flags |= MS_ACTIVE;
732
        path_release(&nd);
733
        return s;
734
 
735
Einval:
736
        deactivate_super(s);
737
        remove_super(s);
738
        error = -EINVAL;
739
        goto out;
740
out1:
741
        blkdev_put(bdev, BDEV_FS);
742
out:
743
        path_release(&nd);
744
        return ERR_PTR(error);
745
}
746
 
747
static struct super_block *get_sb_nodev(struct file_system_type *fs_type,
748
        int flags, char *dev_name, void *data)
749
{
750
        struct super_block *s = get_anon_super(fs_type, NULL, NULL);
751
 
752
        if (IS_ERR(s))
753
                return s;
754
 
755
        s->s_flags = flags;
756
        if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) {
757
                deactivate_super(s);
758
                remove_super(s);
759
                return ERR_PTR(-EINVAL);
760
        }
761
        s->s_flags |= MS_ACTIVE;
762
        return s;
763
}
764
 
765
static int compare_single(struct super_block *s, void *p)
766
{
767
        return 1;
768
}
769
 
770
static struct super_block *get_sb_single(struct file_system_type *fs_type,
771
        int flags, char *dev_name, void *data)
772
{
773
        struct super_block *s = get_anon_super(fs_type, compare_single, NULL);
774
 
775
        if (IS_ERR(s))
776
                return s;
777
        if (!s->s_root) {
778
                s->s_flags = flags;
779
                if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) {
780
                        deactivate_super(s);
781
                        remove_super(s);
782
                        return ERR_PTR(-EINVAL);
783
                }
784
                s->s_flags |= MS_ACTIVE;
785
        }
786
        do_remount_sb(s, flags, data);
787
        return s;
788
}
789
 
790
struct vfsmount *
791
do_kern_mount(const char *fstype, int flags, char *name, void *data)
792
{
793
        struct file_system_type *type = get_fs_type(fstype);
794
        struct super_block *sb = ERR_PTR(-ENOMEM);
795
        struct vfsmount *mnt;
796
 
797
        if (!type)
798
                return ERR_PTR(-ENODEV);
799
 
800
        mnt = alloc_vfsmnt(name);
801
        if (!mnt)
802
                goto out;
803
        if (type->fs_flags & FS_REQUIRES_DEV)
804
                sb = get_sb_bdev(type, flags, name, data);
805
        else if (type->fs_flags & FS_SINGLE)
806
                sb = get_sb_single(type, flags, name, data);
807
        else
808
                sb = get_sb_nodev(type, flags, name, data);
809
        if (IS_ERR(sb))
810
                goto out_mnt;
811
        if (type->fs_flags & FS_NOMOUNT)
812
                sb->s_flags |= MS_NOUSER;
813
        mnt->mnt_sb = sb;
814
        mnt->mnt_root = dget(sb->s_root);
815
        mnt->mnt_mountpoint = sb->s_root;
816
        mnt->mnt_parent = mnt;
817
        up_write(&sb->s_umount);
818
        put_filesystem(type);
819
        return mnt;
820
out_mnt:
821
        free_vfsmnt(mnt);
822
out:
823
        put_filesystem(type);
824
        return (struct vfsmount *)sb;
825
}
826
 
827
void kill_super(struct super_block *sb)
828
{
829
        struct dentry *root = sb->s_root;
830
        struct file_system_type *fs = sb->s_type;
831
        struct super_operations *sop = sb->s_op;
832
 
833
        if (!deactivate_super(sb))
834
                return;
835
 
836
        down_write(&sb->s_umount);
837
        sb->s_root = NULL;
838
        /* Need to clean after the sucker */
839
        if (fs->fs_flags & FS_LITTER)
840
                d_genocide(root);
841
        shrink_dcache_parent(root);
842
        dput(root);
843
        fsync_super(sb);
844
        lock_super(sb);
845
        lock_kernel();
846
        sb->s_flags &= ~MS_ACTIVE;
847
        invalidate_inodes(sb);  /* bad name - it should be evict_inodes() */
848
        if (sop) {
849
                if (sop->write_super && sb->s_dirt)
850
                        sop->write_super(sb);
851
                if (sop->put_super)
852
                        sop->put_super(sb);
853
        }
854
 
855
        /* Forget any remaining inodes */
856
        if (invalidate_inodes(sb)) {
857
                printk(KERN_ERR "VFS: Busy inodes after unmount. "
858
                        "Self-destruct in 5 seconds.  Have a nice day...\n");
859
        }
860
 
861
        unlock_kernel();
862
        unlock_super(sb);
863
        remove_super(sb);
864
}
865
 
866
struct vfsmount *kern_mount(struct file_system_type *type)
867
{
868
        return do_kern_mount(type->name, 0, (char *)type->name, NULL);
869
}

powered by: WebSVN 2.1.0

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