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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *   Copyright (C) International Business Machines Corp., 2000-2003
3
 *   Portions Copyright (C) Christoph Hellwig, 2001-2002
4
 *
5
 *   This program is free software;  you can redistribute it and/or modify
6
 *   it under the terms of the GNU General Public License as published by
7
 *   the Free Software Foundation; either version 2 of the License, or
8
 *   (at your option) any later version.
9
 *
10
 *   This program is distributed in the hope that it will be useful,
11
 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13
 *   the GNU General Public License for more details.
14
 *
15
 *   You should have received a copy of the GNU General Public License
16
 *   along with this program;  if not, write to the Free Software
17
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
 */
19
 
20
#include <linux/config.h>
21
#include <linux/fs.h>
22
#include <linux/module.h>
23
#include <linux/blkdev.h>
24
#include <linux/completion.h>
25
#include <asm/uaccess.h>
26
#include "jfs_incore.h"
27
#include "jfs_filsys.h"
28
#include "jfs_metapage.h"
29
#include "jfs_superblock.h"
30
#include "jfs_dmap.h"
31
#include "jfs_imap.h"
32
#include "jfs_debug.h"
33
 
34
MODULE_DESCRIPTION("The Journaled Filesystem (JFS)");
35
MODULE_AUTHOR("Steve Best/Dave Kleikamp/Barry Arndt, IBM");
36
MODULE_LICENSE("GPL");
37
 
38
static struct super_operations jfs_super_operations;
39
static struct file_system_type jfs_fs_type;
40
 
41
int jfs_stop_threads;
42
static pid_t jfsIOthread;
43
static pid_t jfsCommitThread;
44
static pid_t jfsSyncThread;
45
DECLARE_COMPLETION(jfsIOwait);
46
 
47
#ifdef CONFIG_JFS_DEBUG
48
int jfsloglevel = JFS_LOGLEVEL_WARN;
49
MODULE_PARM(jfsloglevel, "i");
50
MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)");
51
#endif
52
 
53
/*
54
 * External declarations
55
 */
56
extern int jfs_mount(struct super_block *);
57
extern int jfs_mount_rw(struct super_block *, int);
58
extern int jfs_umount(struct super_block *);
59
extern int jfs_umount_rw(struct super_block *);
60
 
61
extern int jfsIOWait(void *);
62
extern int jfs_lazycommit(void *);
63
extern int jfs_sync(void *);
64
extern void jfs_clear_inode(struct inode *inode);
65
extern void jfs_read_inode(struct inode *inode);
66
extern void jfs_dirty_inode(struct inode *inode);
67
extern void jfs_delete_inode(struct inode *inode);
68
extern void jfs_write_inode(struct inode *inode, int wait);
69
extern int jfs_extendfs(struct super_block *, s64, int);
70
 
71
#ifdef PROC_FS_JFS              /* see jfs_debug.h */
72
extern void jfs_proc_init(void);
73
extern void jfs_proc_clean(void);
74
#endif
75
 
76
extern wait_queue_head_t jfs_IO_thread_wait;
77
extern wait_queue_head_t jfs_commit_thread_wait;
78
extern wait_queue_head_t jfs_sync_thread_wait;
79
 
80
static void jfs_handle_error(struct super_block *sb)
81
{
82
        struct jfs_sb_info *sbi = JFS_SBI(sb);
83
 
84
        if (sb->s_flags & MS_RDONLY)
85
                return;
86
 
87
        updateSuper(sb, FM_DIRTY);
88
 
89
        if (sbi->flag & JFS_ERR_PANIC)
90
                panic("JFS (device %s): panic forced after error\n",
91
                        bdevname(sb->s_dev));
92
        else if (sbi->flag & JFS_ERR_REMOUNT_RO) {
93
                jfs_err("ERROR: (device %s): remounting filesystem "
94
                        "as read-only\n",
95
                        bdevname(sb->s_dev));
96
                sb->s_flags |= MS_RDONLY;
97
        }
98
 
99
        /* nothing is done for continue beyond marking the superblock dirty */
100
}
101
 
102
void jfs_error(struct super_block *sb, const char * function, ...)
103
{
104
        static char error_buf[256];
105
        va_list args;
106
 
107
        va_start(args, function);
108
        vsprintf(error_buf, function, args);
109
        va_end(args);
110
 
111
        printk(KERN_ERR "ERROR: (device %s): %s\n", bdevname(sb->s_dev),
112
               error_buf);
113
 
114
        jfs_handle_error(sb);
115
}
116
 
117
static int jfs_statfs(struct super_block *sb, struct statfs *buf)
118
{
119
        struct jfs_sb_info *sbi = JFS_SBI(sb);
120
        s64 maxinodes;
121
        struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap;
122
 
123
        jfs_info("In jfs_statfs");
124
        buf->f_type = JFS_SUPER_MAGIC;
125
        buf->f_bsize = sbi->bsize;
126
        buf->f_blocks = sbi->bmap->db_mapsize;
127
        buf->f_bfree = sbi->bmap->db_nfree;
128
        buf->f_bavail = sbi->bmap->db_nfree;
129
        /*
130
         * If we really return the number of allocated & free inodes, some
131
         * applications will fail because they won't see enough free inodes.
132
         * We'll try to calculate some guess as to how may inodes we can
133
         * really allocate
134
         *
135
         * buf->f_files = atomic_read(&imap->im_numinos);
136
         * buf->f_ffree = atomic_read(&imap->im_numfree);
137
         */
138
        maxinodes = min((s64) atomic_read(&imap->im_numinos) +
139
                        ((sbi->bmap->db_nfree >> imap->im_l2nbperiext)
140
                         << L2INOSPEREXT), (s64) 0xffffffffLL);
141
        buf->f_files = maxinodes;
142
        buf->f_ffree = maxinodes - (atomic_read(&imap->im_numinos) -
143
                                    atomic_read(&imap->im_numfree));
144
 
145
        buf->f_namelen = JFS_NAME_MAX;
146
        return 0;
147
}
148
 
149
static void jfs_put_super(struct super_block *sb)
150
{
151
        struct jfs_sb_info *sbi = JFS_SBI(sb);
152
        int rc;
153
 
154
        jfs_info("In jfs_put_super");
155
        rc = jfs_umount(sb);
156
        if (rc)
157
                jfs_err("jfs_umount failed with return code %d", rc);
158
        unload_nls(sbi->nls_tab);
159
        sbi->nls_tab = NULL;
160
 
161
        kfree(sbi);
162
}
163
 
164
s64 jfs_get_volume_size(struct super_block *sb)
165
{
166
        uint blocks = 0;
167
        s64 bytes;
168
        kdev_t dev = sb->s_dev;
169
        int major = MAJOR(dev);
170
        int minor = MINOR(dev);
171
 
172
        if (blk_size[major]) {
173
                blocks = blk_size[major][minor];
174
                if (blocks) {
175
                        bytes = ((s64)blocks) << BLOCK_SIZE_BITS;
176
                        return bytes >> sb->s_blocksize_bits;
177
                }
178
        }
179
        return 0;
180
}
181
 
182
static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
183
                         int *flag)
184
{
185
        void *nls_map = NULL;
186
        char *this_char;
187
        char *value;
188
        struct jfs_sb_info *sbi = JFS_SBI(sb);
189
 
190
        *newLVSize = 0;
191
 
192
        if (!options)
193
                return 1;
194
        while ((this_char = strsep(&options, ",")) != NULL) {
195
                if (!*this_char)
196
                        continue;
197
                if ((value = strchr(this_char, '=')) != NULL)
198
                        *value++ = 0;
199
                if (!strcmp(this_char, "errors")) {
200
                        if (!value || !*value)
201
                                goto needs_arg;
202
                        if (!strcmp(value, "continue")) {
203
                                *flag &= ~JFS_ERR_REMOUNT_RO;
204
                                *flag &= ~JFS_ERR_PANIC;
205
                                *flag |= JFS_ERR_CONTINUE;
206
                        } else if (!strcmp(value, "remount-ro")) {
207
                                *flag &= ~JFS_ERR_CONTINUE;
208
                                *flag &= ~JFS_ERR_PANIC;
209
                                *flag |= JFS_ERR_REMOUNT_RO;
210
                        } else if (!strcmp(value, "panic")) {
211
                                *flag &= ~JFS_ERR_CONTINUE;
212
                                *flag &= ~JFS_ERR_REMOUNT_RO;
213
                                *flag |= JFS_ERR_PANIC;
214
                        } else {
215
                                printk(KERN_ERR "JFS: %s is an invalid error handler\n", value);
216
                                goto cleanup;
217
                        }
218
                } else if (!strcmp(this_char, "integrity")) {
219
                        *flag &= ~JFS_NOINTEGRITY;
220
                } else  if (!strcmp(this_char, "nointegrity")) {
221
                        *flag |= JFS_NOINTEGRITY;
222
                } else if (!strcmp(this_char, "iocharset")) {
223
                        if (!value || !*value)
224
                                goto needs_arg;
225
                        if (nls_map)    /* specified iocharset twice! */
226
                                unload_nls(nls_map);
227
                        nls_map = load_nls(value);
228
                        if (!nls_map) {
229
                                printk(KERN_ERR "JFS: charset not found\n");
230
                                goto cleanup;
231
                        }
232
                } else if (!strcmp(this_char, "resize")) {
233
                        if (!value || !*value) {
234
                                *newLVSize = jfs_get_volume_size(sb);
235
                                if (*newLVSize == 0)
236
                                        printk(KERN_ERR
237
                                         "JFS: Cannot determine volume size\n");
238
                        } else
239
                                *newLVSize = simple_strtoull(value, &value, 0);
240
 
241
                        /* Silently ignore the quota options */
242
                } else if (!strcmp(this_char, "grpquota")
243
                           || !strcmp(this_char, "noquota")
244
                           || !strcmp(this_char, "quota")
245
                           || !strcmp(this_char, "usrquota"))
246
                        /* Don't do anything ;-) */ ;
247
                else {
248
                        printk("jfs: Unrecognized mount option %s\n",
249
                               this_char);
250
                        goto cleanup;
251
                }
252
        }
253
        if (nls_map) {
254
                /* Discard old (if remount) */
255
                if (sbi->nls_tab)
256
                        unload_nls(sbi->nls_tab);
257
                sbi->nls_tab = nls_map;
258
        }
259
        return 1;
260
needs_arg:
261
        printk(KERN_ERR "JFS: %s needs an argument\n", this_char);
262
cleanup:
263
        if (nls_map)
264
                unload_nls(nls_map);
265
        return 0;
266
}
267
 
268
static int jfs_remount(struct super_block *sb, int *flags, char *data)
269
{
270
        s64 newLVSize = 0;
271
        int rc = 0;
272
        int flag = JFS_SBI(sb)->flag;
273
 
274
        if (!parse_options(data, sb, &newLVSize, &flag)) {
275
                return -EINVAL;
276
        }
277
        if (newLVSize) {
278
                if (sb->s_flags & MS_RDONLY) {
279
                        printk(KERN_ERR
280
                  "JFS: resize requires volume to be mounted read-write\n");
281
                        return -EROFS;
282
                }
283
                rc = jfs_extendfs(sb, newLVSize, 0);
284
                if (rc)
285
                        return rc;
286
        }
287
 
288
        if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
289
                JFS_SBI(sb)->flag = flag;
290
                return jfs_mount_rw(sb, 1);
291
        }
292
        if ((!(sb->s_flags & MS_RDONLY)) && (*flags & MS_RDONLY)) {
293
                rc = jfs_umount_rw(sb);
294
                JFS_SBI(sb)->flag = flag;
295
                return rc;
296
        }
297
        if ((JFS_SBI(sb)->flag & JFS_NOINTEGRITY) != (flag & JFS_NOINTEGRITY))
298
                if (!(sb->s_flags & MS_RDONLY)) {
299
                        rc = jfs_umount_rw(sb);
300
                        if (rc)
301
                                return rc;
302
                        JFS_SBI(sb)->flag = flag;
303
                        return jfs_mount_rw(sb, 1);
304
                }
305
        JFS_SBI(sb)->flag = flag;
306
 
307
        return 0;
308
}
309
 
310
static struct super_block *jfs_read_super(struct super_block *sb,
311
                                          void *data, int silent)
312
{
313
        struct jfs_sb_info *sbi;
314
        struct inode *inode;
315
        int rc;
316
        s64 newLVSize = 0;
317
        int flag;
318
 
319
        jfs_info("In jfs_read_super s_dev=0x%x s_flags=0x%lx", sb->s_dev,
320
                 sb->s_flags);
321
 
322
        sbi = kmalloc(sizeof (struct jfs_sb_info), GFP_KERNEL);
323
        if (!sbi)
324
                return NULL;
325
        memset(sbi, 0, sizeof (struct jfs_sb_info));
326
        sb->u.generic_sbp = sbi;
327
 
328
        /* initialize the mount flag and determine the default error handler */
329
        flag = JFS_ERR_REMOUNT_RO;
330
 
331
        if (!parse_options((char *) data, sb, &newLVSize, &flag)) {
332
                kfree(sbi);
333
                return NULL;
334
        }
335
        sbi->flag = flag;
336
 
337
        if (newLVSize) {
338
                printk(KERN_ERR "resize option for remount only\n");
339
                return NULL;
340
        }
341
 
342
        /*
343
         * Initialize blocksize to 4K.
344
         */
345
        sb_set_blocksize(sb, PSIZE);
346
 
347
        /*
348
         * Set method vectors.
349
         */
350
        sb->s_op = &jfs_super_operations;
351
 
352
        rc = jfs_mount(sb);
353
        if (rc) {
354
                if (!silent) {
355
                        jfs_err("jfs_mount failed w/return code = %d", rc);
356
                }
357
                goto out_kfree;
358
        }
359
        if (sb->s_flags & MS_RDONLY)
360
                sbi->log = 0;
361
        else {
362
                rc = jfs_mount_rw(sb, 0);
363
                if (rc) {
364
                        if (!silent) {
365
                                jfs_err("jfs_mount_rw failed, return code = %d",
366
                                        rc);
367
                        }
368
                        goto out_no_rw;
369
                }
370
        }
371
 
372
        sb->s_magic = JFS_SUPER_MAGIC;
373
 
374
        inode = iget(sb, ROOT_I);
375
        if (!inode || is_bad_inode(inode))
376
                goto out_no_root;
377
        sb->s_root = d_alloc_root(inode);
378
        if (!sb->s_root)
379
                goto out_no_root;
380
 
381
        if (!sbi->nls_tab)
382
                sbi->nls_tab = load_nls_default();
383
 
384
        /* logical blocks are represented by 40 bits in pxd_t, etc. */
385
        sb->s_maxbytes = ((u64) sb->s_blocksize) << 40;
386
#if BITS_PER_LONG == 32
387
        /*
388
         * Page cache is indexed by long.
389
         * I would use MAX_LFS_FILESIZE, but it's only half as big
390
         */
391
        sb->s_maxbytes = min(((u64) PAGE_CACHE_SIZE << 32) - 1, sb->s_maxbytes);
392
#endif
393
 
394
        return sb;
395
 
396
out_no_root:
397
        jfs_err("jfs_read_super: get root inode failed");
398
        if (inode)
399
                iput(inode);
400
 
401
out_no_rw:
402
        rc = jfs_umount(sb);
403
        if (rc) {
404
                jfs_err("jfs_umount failed with return code %d", rc);
405
        }
406
out_kfree:
407
        if (sbi->nls_tab)
408
                unload_nls(sbi->nls_tab);
409
        kfree(sbi);
410
        return NULL;
411
}
412
 
413
static void jfs_write_super_lockfs(struct super_block *sb)
414
{
415
        struct jfs_sb_info *sbi = JFS_SBI(sb);
416
        struct jfs_log *log = sbi->log;
417
 
418
        if (!(sb->s_flags & MS_RDONLY)) {
419
                txQuiesce(sb);
420
                lmLogShutdown(log);
421
                updateSuper(sb, FM_CLEAN);
422
        }
423
}
424
 
425
static void jfs_unlockfs(struct super_block *sb)
426
{
427
        struct jfs_sb_info *sbi = JFS_SBI(sb);
428
        struct jfs_log *log = sbi->log;
429
        int rc = 0;
430
 
431
        if (!(sb->s_flags & MS_RDONLY)) {
432
                updateSuper(sb, FM_MOUNT);
433
                if ((rc = lmLogInit(log)))
434
                        jfs_err("jfs_unlock failed with return code %d", rc);
435
                else
436
                        txResume(sb);
437
        }
438
}
439
 
440
 
441
static int jfs_sync_fs(struct super_block *sb)
442
{
443
        struct jfs_log *log = JFS_SBI(sb)->log;
444
 
445
        /* log == NULL indicates read-only mount */
446
        if (log)
447
                jfs_flush_journal(log, 1);
448
 
449
        return 0;
450
}
451
 
452
static struct super_operations jfs_super_operations = {
453
        .read_inode     = jfs_read_inode,
454
        .dirty_inode    = jfs_dirty_inode,
455
        .write_inode    = jfs_write_inode,
456
        .clear_inode    = jfs_clear_inode,
457
        .delete_inode   = jfs_delete_inode,
458
        .put_super      = jfs_put_super,
459
        .sync_fs        = jfs_sync_fs,
460
        .write_super_lockfs = jfs_write_super_lockfs,
461
        .unlockfs       = jfs_unlockfs,
462
        .statfs         = jfs_statfs,
463
        .remount_fs     = jfs_remount,
464
};
465
 
466
static struct file_system_type jfs_fs_type = {
467
        .owner          = THIS_MODULE,
468
        .name           = "jfs",
469
        .read_super     = jfs_read_super,
470
        .fs_flags       = FS_REQUIRES_DEV,
471
};
472
 
473
extern int metapage_init(void);
474
extern int txInit(void);
475
extern void txExit(void);
476
extern void metapage_exit(void);
477
 
478
static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
479
{
480
        struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
481
 
482
        if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
483
            SLAB_CTOR_CONSTRUCTOR) {
484
                memset(jfs_ip, 0, sizeof(struct jfs_inode_info));
485
                INIT_LIST_HEAD(&jfs_ip->anon_inode_list);
486
                init_rwsem(&jfs_ip->rdwrlock);
487
                init_MUTEX(&jfs_ip->commit_sem);
488
                jfs_ip->active_ag = -1;
489
        }
490
}
491
 
492
static int __init init_jfs_fs(void)
493
{
494
        int rc;
495
 
496
        jfs_inode_cachep =
497
            kmem_cache_create("jfs_ip", sizeof (struct jfs_inode_info), 0, 0,
498
                              init_once, NULL);
499
        if (jfs_inode_cachep == NULL)
500
                return -ENOMEM;
501
 
502
        /*
503
         * Metapage initialization
504
         */
505
        rc = metapage_init();
506
        if (rc) {
507
                jfs_err("metapage_init failed w/rc = %d", rc);
508
                goto free_slab;
509
        }
510
 
511
        /*
512
         * Transaction Manager initialization
513
         */
514
        rc = txInit();
515
        if (rc) {
516
                jfs_err("txInit failed w/rc = %d", rc);
517
                goto free_metapage;
518
        }
519
 
520
        /*
521
         * I/O completion thread (endio)
522
         */
523
        jfsIOthread = kernel_thread(jfsIOWait, 0,
524
                                    CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
525
        if (jfsIOthread < 0) {
526
                jfs_err("init_jfs_fs: fork failed w/rc = %d", jfsIOthread);
527
                goto end_txmngr;
528
        }
529
        wait_for_completion(&jfsIOwait);        /* Wait until thread starts */
530
 
531
        jfsCommitThread = kernel_thread(jfs_lazycommit, 0,
532
                                        CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
533
        if (jfsCommitThread < 0) {
534
                jfs_err("init_jfs_fs: fork failed w/rc = %d", jfsCommitThread);
535
                goto kill_iotask;
536
        }
537
        wait_for_completion(&jfsIOwait);        /* Wait until thread starts */
538
 
539
        jfsSyncThread = kernel_thread(jfs_sync, 0,
540
                                      CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
541
        if (jfsSyncThread < 0) {
542
                jfs_err("init_jfs_fs: fork failed w/rc = %d", jfsSyncThread);
543
                goto kill_committask;
544
        }
545
        wait_for_completion(&jfsIOwait);        /* Wait until thread starts */
546
 
547
#ifdef PROC_FS_JFS
548
        jfs_proc_init();
549
#endif
550
 
551
        return register_filesystem(&jfs_fs_type);
552
 
553
kill_committask:
554
        jfs_stop_threads = 1;
555
        wake_up(&jfs_commit_thread_wait);
556
        wait_for_completion(&jfsIOwait);        /* Wait for thread exit */
557
kill_iotask:
558
        jfs_stop_threads = 1;
559
        wake_up(&jfs_IO_thread_wait);
560
        wait_for_completion(&jfsIOwait);        /* Wait for thread exit */
561
end_txmngr:
562
        txExit();
563
free_metapage:
564
        metapage_exit();
565
free_slab:
566
        kmem_cache_destroy(jfs_inode_cachep);
567
        return rc;
568
}
569
 
570
static void __exit exit_jfs_fs(void)
571
{
572
        jfs_info("exit_jfs_fs called");
573
 
574
        jfs_stop_threads = 1;
575
        txExit();
576
        metapage_exit();
577
        wake_up(&jfs_IO_thread_wait);
578
        wait_for_completion(&jfsIOwait);        /* Wait for IO thread exit */
579
        wake_up(&jfs_commit_thread_wait);
580
        wait_for_completion(&jfsIOwait);        /* Wait for Commit thread exit */
581
        wake_up(&jfs_sync_thread_wait);
582
        wait_for_completion(&jfsIOwait);        /* Wait for Sync thread exit */
583
#ifdef PROC_FS_JFS
584
        jfs_proc_clean();
585
#endif
586
        unregister_filesystem(&jfs_fs_type);
587
        kmem_cache_destroy(jfs_inode_cachep);
588
}
589
 
590
EXPORT_NO_SYMBOLS;
591
 
592
module_init(init_jfs_fs)
593
module_exit(exit_jfs_fs)

powered by: WebSVN 2.1.0

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