The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/jfs/super.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *   Copyright (c) International Business Machines Corp., 2000-2002
    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 int jfs_statfs(struct super_block *sb, struct statfs *buf)
   81 {
   82         struct jfs_sb_info *sbi = JFS_SBI(sb);
   83         s64 maxinodes;
   84         struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap;
   85 
   86         jfs_info("In jfs_statfs");
   87         buf->f_type = JFS_SUPER_MAGIC;
   88         buf->f_bsize = sbi->bsize;
   89         buf->f_blocks = sbi->bmap->db_mapsize;
   90         buf->f_bfree = sbi->bmap->db_nfree;
   91         buf->f_bavail = sbi->bmap->db_nfree;
   92         /*
   93          * If we really return the number of allocated & free inodes, some
   94          * applications will fail because they won't see enough free inodes.
   95          * We'll try to calculate some guess as to how may inodes we can
   96          * really allocate
   97          *
   98          * buf->f_files = atomic_read(&imap->im_numinos);
   99          * buf->f_ffree = atomic_read(&imap->im_numfree);
  100          */
  101         maxinodes = min((s64) atomic_read(&imap->im_numinos) +
  102                         ((sbi->bmap->db_nfree >> imap->im_l2nbperiext)
  103                          << L2INOSPEREXT), (s64) 0xffffffffLL);
  104         buf->f_files = maxinodes;
  105         buf->f_ffree = maxinodes - (atomic_read(&imap->im_numinos) -
  106                                     atomic_read(&imap->im_numfree));
  107 
  108         buf->f_namelen = JFS_NAME_MAX;
  109         return 0;
  110 }
  111 
  112 static void jfs_put_super(struct super_block *sb)
  113 {
  114         struct jfs_sb_info *sbi = JFS_SBI(sb);
  115         int rc;
  116 
  117         jfs_info("In jfs_put_super");
  118         rc = jfs_umount(sb);
  119         if (rc)
  120                 jfs_err("jfs_umount failed with return code %d", rc);
  121         unload_nls(sbi->nls_tab);
  122         sbi->nls_tab = NULL;
  123 
  124         kfree(sbi);
  125 }
  126 
  127 s64 jfs_get_volume_size(struct super_block *sb)
  128 {
  129         uint blocks = 0;
  130         s64 bytes;
  131         kdev_t dev = sb->s_dev;
  132         int major = MAJOR(dev);
  133         int minor = MINOR(dev);
  134 
  135         if (blk_size[major]) {
  136                 blocks = blk_size[major][minor];
  137                 if (blocks) {
  138                         bytes = ((s64)blocks) << BLOCK_SIZE_BITS;
  139                         return bytes >> sb->s_blocksize_bits;
  140                 }
  141         }
  142         return 0;
  143 }
  144 
  145 static int parse_options(char *options, struct super_block *sb, s64 *newLVSize)
  146 {
  147         void *nls_map = NULL;
  148         char *this_char;
  149         char *value;
  150         struct jfs_sb_info *sbi = JFS_SBI(sb);
  151 
  152         *newLVSize = 0;
  153 
  154         if (!options)
  155                 return 1;
  156         while ((this_char = strsep(&options, ",")) != NULL) {
  157                 if (!*this_char)
  158                         continue;
  159                 if ((value = strchr(this_char, '=')) != NULL)
  160                         *value++ = 0;
  161                 if (!strcmp(this_char, "iocharset")) {
  162                         if (!value || !*value)
  163                                 goto needs_arg;
  164                         if (nls_map)    /* specified iocharset twice! */
  165                                 unload_nls(nls_map);
  166                         nls_map = load_nls(value);
  167                         if (!nls_map) {
  168                                 printk(KERN_ERR "JFS: charset not found\n");
  169                                 goto cleanup;
  170                         }
  171                 } else if (!strcmp(this_char, "resize")) {
  172                         if (!value || !*value) {
  173                                 *newLVSize = jfs_get_volume_size(sb);
  174                                 if (*newLVSize == 0)
  175                                         printk(KERN_ERR
  176                                          "JFS: Cannot determine volume size\n");
  177                         } else
  178                                 *newLVSize = simple_strtoull(value, &value, 0);
  179 
  180                         /* Silently ignore the quota options */
  181                 } else if (!strcmp(this_char, "grpquota")
  182                            || !strcmp(this_char, "noquota")
  183                            || !strcmp(this_char, "quota")
  184                            || !strcmp(this_char, "usrquota"))
  185                         /* Don't do anything ;-) */ ;
  186                 else {
  187                         printk("jfs: Unrecognized mount option %s\n",
  188                                this_char);
  189                         goto cleanup;
  190                 }
  191         }
  192         if (nls_map) {
  193                 /* Discard old (if remount) */
  194                 if (sbi->nls_tab)
  195                         unload_nls(sbi->nls_tab);
  196                 sbi->nls_tab = nls_map;
  197         }
  198         return 1;
  199 needs_arg:
  200         printk(KERN_ERR "JFS: %s needs an argument\n", this_char);
  201 cleanup:
  202         if (nls_map)
  203                 unload_nls(nls_map);
  204         return 0;
  205 }
  206 
  207 int jfs_remount(struct super_block *sb, int *flags, char *data)
  208 {
  209         s64 newLVSize = 0;
  210         int rc = 0;
  211 
  212         if (!parse_options(data, sb, &newLVSize)) {
  213                 return -EINVAL;
  214         }
  215         if (newLVSize) {
  216                 if (sb->s_flags & MS_RDONLY) {
  217                         printk(KERN_ERR
  218                   "JFS: resize requires volume to be mounted read-write\n");
  219                         return -EROFS;
  220                 }
  221                 rc = jfs_extendfs(sb, newLVSize, 0);
  222                 if (rc)
  223                         return rc;
  224         }
  225 
  226         if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY))
  227                 return jfs_mount_rw(sb, 1);
  228         else if ((!(sb->s_flags & MS_RDONLY)) && (*flags & MS_RDONLY))
  229                 return jfs_umount_rw(sb);
  230 
  231         return 0;
  232 }
  233 
  234 static struct super_block *jfs_read_super(struct super_block *sb,
  235                                           void *data, int silent)
  236 {
  237         struct jfs_sb_info *sbi;
  238         struct inode *inode;
  239         int rc;
  240         s64 newLVSize = 0;
  241 
  242         jfs_info("In jfs_read_super s_dev=0x%x s_flags=0x%lx", sb->s_dev,
  243                  sb->s_flags);
  244 
  245         sbi = kmalloc(sizeof (struct jfs_sb_info), GFP_KERNEL);
  246         if (!sbi)
  247                 return NULL;
  248         memset(sbi, 0, sizeof (struct jfs_sb_info));
  249         sb->u.generic_sbp = sbi;
  250 
  251         if (!parse_options((char *) data, sb, &newLVSize)) {
  252                 kfree(sbi);
  253                 return NULL;
  254         }
  255 
  256         if (newLVSize) {
  257                 printk(KERN_ERR "resize option for remount only\n");
  258                 return NULL;
  259         }
  260 
  261         /*
  262          * Initialize blocksize to 4K.
  263          */
  264         sb_set_blocksize(sb, PSIZE);
  265 
  266         /*
  267          * Set method vectors.
  268          */
  269         sb->s_op = &jfs_super_operations;
  270 
  271         rc = jfs_mount(sb);
  272         if (rc) {
  273                 if (!silent) {
  274                         jfs_err("jfs_mount failed w/return code = %d", rc);
  275                 }
  276                 goto out_kfree;
  277         }
  278         if (sb->s_flags & MS_RDONLY)
  279                 sbi->log = 0;
  280         else {
  281                 rc = jfs_mount_rw(sb, 0);
  282                 if (rc) {
  283                         if (!silent) {
  284                                 jfs_err("jfs_mount_rw failed, return code = %d",
  285                                         rc);
  286                         }
  287                         goto out_no_rw;
  288                 }
  289         }
  290 
  291         sb->s_magic = JFS_SUPER_MAGIC;
  292 
  293         inode = iget(sb, ROOT_I);
  294         if (!inode || is_bad_inode(inode))
  295                 goto out_no_root;
  296         sb->s_root = d_alloc_root(inode);
  297         if (!sb->s_root)
  298                 goto out_no_root;
  299 
  300         if (!sbi->nls_tab)
  301                 sbi->nls_tab = load_nls_default();
  302 
  303         /* logical blocks are represented by 40 bits in pxd_t, etc. */
  304         sb->s_maxbytes = ((u64) sb->s_blocksize) << 40;
  305 #if BITS_PER_LONG == 32
  306         /*
  307          * Page cache is indexed by long.
  308          * I would use MAX_LFS_FILESIZE, but it's only half as big
  309          */
  310         sb->s_maxbytes = min(((u64) PAGE_CACHE_SIZE << 32) - 1, sb->s_maxbytes);
  311 #endif
  312 
  313         return sb;
  314 
  315 out_no_root:
  316         jfs_err("jfs_read_super: get root inode failed");
  317         if (inode)
  318                 iput(inode);
  319 
  320 out_no_rw:
  321         rc = jfs_umount(sb);
  322         if (rc) {
  323                 jfs_err("jfs_umount failed with return code %d", rc);
  324         }
  325 out_kfree:
  326         if (sbi->nls_tab)
  327                 unload_nls(sbi->nls_tab);
  328         kfree(sbi);
  329         return NULL;
  330 }
  331 
  332 static void jfs_write_super_lockfs(struct super_block *sb)
  333 {
  334         struct jfs_sb_info *sbi = JFS_SBI(sb);
  335         struct jfs_log *log = sbi->log;
  336 
  337         if (!(sb->s_flags & MS_RDONLY)) {
  338                 txQuiesce(sb);
  339                 lmLogShutdown(log);
  340                 updateSuper(sb, FM_CLEAN);
  341         }
  342 }
  343 
  344 static void jfs_unlockfs(struct super_block *sb)
  345 {
  346         struct jfs_sb_info *sbi = JFS_SBI(sb);
  347         struct jfs_log *log = sbi->log;
  348         int rc = 0;
  349 
  350         if (!(sb->s_flags & MS_RDONLY)) {
  351                 updateSuper(sb, FM_MOUNT);
  352                 if ((rc = lmLogInit(log)))
  353                         jfs_err("jfs_unlock failed with return code %d", rc);
  354                 else
  355                         txResume(sb);
  356         }
  357 }
  358 
  359 
  360 static int jfs_sync_fs(struct super_block *sb)
  361 {
  362         struct jfs_log *log = JFS_SBI(sb)->log;
  363 
  364         /* log == NULL indicates read-only mount */
  365         if (log)
  366                 jfs_flush_journal(log, 1);
  367 
  368         return 0;
  369 }
  370 
  371 static struct super_operations jfs_super_operations = {
  372         .read_inode     = jfs_read_inode,
  373         .dirty_inode    = jfs_dirty_inode,
  374         .write_inode    = jfs_write_inode,
  375         .clear_inode    = jfs_clear_inode,
  376         .delete_inode   = jfs_delete_inode,
  377         .put_super      = jfs_put_super,
  378         .sync_fs        = jfs_sync_fs,
  379         .write_super_lockfs = jfs_write_super_lockfs,
  380         .unlockfs       = jfs_unlockfs,
  381         .statfs         = jfs_statfs,
  382         .remount_fs     = jfs_remount,
  383 };
  384 
  385 static struct file_system_type jfs_fs_type = {
  386         .owner          = THIS_MODULE,
  387         .name           = "jfs",
  388         .read_super     = jfs_read_super,
  389         .fs_flags       = FS_REQUIRES_DEV,
  390 };
  391 
  392 extern int metapage_init(void);
  393 extern int txInit(void);
  394 extern void txExit(void);
  395 extern void metapage_exit(void);
  396 
  397 static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
  398 {
  399         struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
  400 
  401         if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
  402             SLAB_CTOR_CONSTRUCTOR) {
  403                 INIT_LIST_HEAD(&jfs_ip->anon_inode_list);
  404                 init_rwsem(&jfs_ip->rdwrlock);
  405                 init_MUTEX(&jfs_ip->commit_sem);
  406                 jfs_ip->atlhead = 0;
  407                 jfs_ip->active_ag = -1;
  408         }
  409 }
  410 
  411 static int __init init_jfs_fs(void)
  412 {
  413         int rc;
  414 
  415         jfs_inode_cachep =
  416             kmem_cache_create("jfs_ip", sizeof (struct jfs_inode_info), 0, 0,
  417                               init_once, NULL);
  418         if (jfs_inode_cachep == NULL)
  419                 return -ENOMEM;
  420 
  421         /*
  422          * Metapage initialization
  423          */
  424         rc = metapage_init();
  425         if (rc) {
  426                 jfs_err("metapage_init failed w/rc = %d", rc);
  427                 goto free_slab;
  428         }
  429 
  430         /*
  431          * Transaction Manager initialization
  432          */
  433         rc = txInit();
  434         if (rc) {
  435                 jfs_err("txInit failed w/rc = %d", rc);
  436                 goto free_metapage;
  437         }
  438 
  439         /*
  440          * I/O completion thread (endio)
  441          */
  442         jfsIOthread = kernel_thread(jfsIOWait, 0,
  443                                     CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
  444         if (jfsIOthread < 0) {
  445                 jfs_err("init_jfs_fs: fork failed w/rc = %d", jfsIOthread);
  446                 goto end_txmngr;
  447         }
  448         wait_for_completion(&jfsIOwait);        /* Wait until thread starts */
  449 
  450         jfsCommitThread = kernel_thread(jfs_lazycommit, 0,
  451                                         CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
  452         if (jfsCommitThread < 0) {
  453                 jfs_err("init_jfs_fs: fork failed w/rc = %d", jfsCommitThread);
  454                 goto kill_iotask;
  455         }
  456         wait_for_completion(&jfsIOwait);        /* Wait until thread starts */
  457 
  458         jfsSyncThread = kernel_thread(jfs_sync, 0,
  459                                       CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
  460         if (jfsSyncThread < 0) {
  461                 jfs_err("init_jfs_fs: fork failed w/rc = %d", jfsSyncThread);
  462                 goto kill_committask;
  463         }
  464         wait_for_completion(&jfsIOwait);        /* Wait until thread starts */
  465 
  466 #ifdef PROC_FS_JFS
  467         jfs_proc_init();
  468 #endif
  469 
  470         return register_filesystem(&jfs_fs_type);
  471 
  472 kill_committask:
  473         jfs_stop_threads = 1;
  474         wake_up(&jfs_commit_thread_wait);
  475         wait_for_completion(&jfsIOwait);        /* Wait for thread exit */
  476 kill_iotask:
  477         jfs_stop_threads = 1;
  478         wake_up(&jfs_IO_thread_wait);
  479         wait_for_completion(&jfsIOwait);        /* Wait for thread exit */
  480 end_txmngr:
  481         txExit();
  482 free_metapage:
  483         metapage_exit();
  484 free_slab:
  485         kmem_cache_destroy(jfs_inode_cachep);
  486         return -rc;
  487 }
  488 
  489 static void __exit exit_jfs_fs(void)
  490 {
  491         jfs_info("exit_jfs_fs called");
  492 
  493         jfs_stop_threads = 1;
  494         txExit();
  495         metapage_exit();
  496         wake_up(&jfs_IO_thread_wait);
  497         wait_for_completion(&jfsIOwait);        /* Wait for IO thread exit */
  498         wake_up(&jfs_commit_thread_wait);
  499         wait_for_completion(&jfsIOwait);        /* Wait for Commit thread exit */
  500         wake_up(&jfs_sync_thread_wait);
  501         wait_for_completion(&jfsIOwait);        /* Wait for Sync thread exit */
  502 #ifdef PROC_FS_JFS
  503         jfs_proc_clean();
  504 #endif
  505         unregister_filesystem(&jfs_fs_type);
  506         kmem_cache_destroy(jfs_inode_cachep);
  507 }
  508 
  509 EXPORT_NO_SYMBOLS;
  510 
  511 module_init(init_jfs_fs)
  512 module_exit(exit_jfs_fs)

Cache object: 014e2198f4b0824ecb24b9d09bb15de4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.