linux/fs/affs/super.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/affs/inode.c
   3 *
   4 *  (c) 1996  Hans-Joachim Widmaier - Rewritten
   5 *
   6 *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
   7 *
   8 *  (C) 1992  Eric Youngdale Modified for ISO 9660 filesystem.
   9 *
  10 *  (C) 1991  Linus Torvalds - minix filesystem
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/init.h>
  15#include <linux/statfs.h>
  16#include <linux/parser.h>
  17#include <linux/magic.h>
  18#include <linux/sched.h>
  19#include <linux/smp_lock.h>
  20#include "affs.h"
  21
  22extern struct timezone sys_tz;
  23
  24static int affs_statfs(struct dentry *dentry, struct kstatfs *buf);
  25static int affs_remount (struct super_block *sb, int *flags, char *data);
  26
  27static void
  28affs_commit_super(struct super_block *sb, int clean)
  29{
  30        struct affs_sb_info *sbi = AFFS_SB(sb);
  31        struct buffer_head *bh = sbi->s_root_bh;
  32        struct affs_root_tail *tail = AFFS_ROOT_TAIL(sb, bh);
  33
  34        tail->bm_flag = cpu_to_be32(clean);
  35        secs_to_datestamp(get_seconds(), &tail->disk_change);
  36        affs_fix_checksum(sb, bh);
  37        mark_buffer_dirty(bh);
  38}
  39
  40static void
  41affs_put_super(struct super_block *sb)
  42{
  43        struct affs_sb_info *sbi = AFFS_SB(sb);
  44        pr_debug("AFFS: put_super()\n");
  45
  46        lock_kernel();
  47
  48        if (!(sb->s_flags & MS_RDONLY))
  49                affs_commit_super(sb, 1);
  50
  51        kfree(sbi->s_prefix);
  52        affs_free_bitmap(sb);
  53        affs_brelse(sbi->s_root_bh);
  54        kfree(sbi);
  55        sb->s_fs_info = NULL;
  56
  57        unlock_kernel();
  58}
  59
  60static void
  61affs_write_super(struct super_block *sb)
  62{
  63        int clean = 2;
  64
  65        lock_super(sb);
  66        if (!(sb->s_flags & MS_RDONLY)) {
  67                //      if (sbi->s_bitmap[i].bm_bh) {
  68                //              if (buffer_dirty(sbi->s_bitmap[i].bm_bh)) {
  69                //                      clean = 0;
  70                affs_commit_super(sb, clean);
  71                sb->s_dirt = !clean;    /* redo until bitmap synced */
  72        } else
  73                sb->s_dirt = 0;
  74        unlock_super(sb);
  75
  76        pr_debug("AFFS: write_super() at %lu, clean=%d\n", get_seconds(), clean);
  77}
  78
  79static int
  80affs_sync_fs(struct super_block *sb, int wait)
  81{
  82        lock_super(sb);
  83        affs_commit_super(sb, 2);
  84        sb->s_dirt = 0;
  85        unlock_super(sb);
  86        return 0;
  87}
  88
  89static struct kmem_cache * affs_inode_cachep;
  90
  91static struct inode *affs_alloc_inode(struct super_block *sb)
  92{
  93        struct affs_inode_info *i;
  94
  95        i = kmem_cache_alloc(affs_inode_cachep, GFP_KERNEL);
  96        if (!i)
  97                return NULL;
  98
  99        i->vfs_inode.i_version = 1;
 100        i->i_lc = NULL;
 101        i->i_ext_bh = NULL;
 102        i->i_pa_cnt = 0;
 103
 104        return &i->vfs_inode;
 105}
 106
 107static void affs_destroy_inode(struct inode *inode)
 108{
 109        kmem_cache_free(affs_inode_cachep, AFFS_I(inode));
 110}
 111
 112static void init_once(void *foo)
 113{
 114        struct affs_inode_info *ei = (struct affs_inode_info *) foo;
 115
 116        init_MUTEX(&ei->i_link_lock);
 117        init_MUTEX(&ei->i_ext_lock);
 118        inode_init_once(&ei->vfs_inode);
 119}
 120
 121static int init_inodecache(void)
 122{
 123        affs_inode_cachep = kmem_cache_create("affs_inode_cache",
 124                                             sizeof(struct affs_inode_info),
 125                                             0, (SLAB_RECLAIM_ACCOUNT|
 126                                                SLAB_MEM_SPREAD),
 127                                             init_once);
 128        if (affs_inode_cachep == NULL)
 129                return -ENOMEM;
 130        return 0;
 131}
 132
 133static void destroy_inodecache(void)
 134{
 135        kmem_cache_destroy(affs_inode_cachep);
 136}
 137
 138static const struct super_operations affs_sops = {
 139        .alloc_inode    = affs_alloc_inode,
 140        .destroy_inode  = affs_destroy_inode,
 141        .write_inode    = affs_write_inode,
 142        .delete_inode   = affs_delete_inode,
 143        .clear_inode    = affs_clear_inode,
 144        .put_super      = affs_put_super,
 145        .write_super    = affs_write_super,
 146        .sync_fs        = affs_sync_fs,
 147        .statfs         = affs_statfs,
 148        .remount_fs     = affs_remount,
 149        .show_options   = generic_show_options,
 150};
 151
 152enum {
 153        Opt_bs, Opt_mode, Opt_mufs, Opt_prefix, Opt_protect,
 154        Opt_reserved, Opt_root, Opt_setgid, Opt_setuid,
 155        Opt_verbose, Opt_volume, Opt_ignore, Opt_err,
 156};
 157
 158static const match_table_t tokens = {
 159        {Opt_bs, "bs=%u"},
 160        {Opt_mode, "mode=%o"},
 161        {Opt_mufs, "mufs"},
 162        {Opt_prefix, "prefix=%s"},
 163        {Opt_protect, "protect"},
 164        {Opt_reserved, "reserved=%u"},
 165        {Opt_root, "root=%u"},
 166        {Opt_setgid, "setgid=%u"},
 167        {Opt_setuid, "setuid=%u"},
 168        {Opt_verbose, "verbose"},
 169        {Opt_volume, "volume=%s"},
 170        {Opt_ignore, "grpquota"},
 171        {Opt_ignore, "noquota"},
 172        {Opt_ignore, "quota"},
 173        {Opt_ignore, "usrquota"},
 174        {Opt_err, NULL},
 175};
 176
 177static int
 178parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s32 *root,
 179                int *blocksize, char **prefix, char *volume, unsigned long *mount_opts)
 180{
 181        char *p;
 182        substring_t args[MAX_OPT_ARGS];
 183
 184        /* Fill in defaults */
 185
 186        *uid        = current_uid();
 187        *gid        = current_gid();
 188        *reserved   = 2;
 189        *root       = -1;
 190        *blocksize  = -1;
 191        volume[0]   = ':';
 192        volume[1]   = 0;
 193        *mount_opts = 0;
 194        if (!options)
 195                return 1;
 196
 197        while ((p = strsep(&options, ",")) != NULL) {
 198                int token, n, option;
 199                if (!*p)
 200                        continue;
 201
 202                token = match_token(p, tokens, args);
 203                switch (token) {
 204                case Opt_bs:
 205                        if (match_int(&args[0], &n))
 206                                return -EINVAL;
 207                        if (n != 512 && n != 1024 && n != 2048
 208                            && n != 4096) {
 209                                printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n");
 210                                return 0;
 211                        }
 212                        *blocksize = n;
 213                        break;
 214                case Opt_mode:
 215                        if (match_octal(&args[0], &option))
 216                                return 1;
 217                        *mode = option & 0777;
 218                        *mount_opts |= SF_SETMODE;
 219                        break;
 220                case Opt_mufs:
 221                        *mount_opts |= SF_MUFS;
 222                        break;
 223                case Opt_prefix:
 224                        /* Free any previous prefix */
 225                        kfree(*prefix);
 226                        *prefix = match_strdup(&args[0]);
 227                        if (!*prefix)
 228                                return 0;
 229                        *mount_opts |= SF_PREFIX;
 230                        break;
 231                case Opt_protect:
 232                        *mount_opts |= SF_IMMUTABLE;
 233                        break;
 234                case Opt_reserved:
 235                        if (match_int(&args[0], reserved))
 236                                return 1;
 237                        break;
 238                case Opt_root:
 239                        if (match_int(&args[0], root))
 240                                return 1;
 241                        break;
 242                case Opt_setgid:
 243                        if (match_int(&args[0], &option))
 244                                return 1;
 245                        *gid = option;
 246                        *mount_opts |= SF_SETGID;
 247                        break;
 248                case Opt_setuid:
 249                        if (match_int(&args[0], &option))
 250                                return -EINVAL;
 251                        *uid = option;
 252                        *mount_opts |= SF_SETUID;
 253                        break;
 254                case Opt_verbose:
 255                        *mount_opts |= SF_VERBOSE;
 256                        break;
 257                case Opt_volume: {
 258                        char *vol = match_strdup(&args[0]);
 259                        if (!vol)
 260                                return 0;
 261                        strlcpy(volume, vol, 32);
 262                        kfree(vol);
 263                        break;
 264                }
 265                case Opt_ignore:
 266                        /* Silently ignore the quota options */
 267                        break;
 268                default:
 269                        printk("AFFS: Unrecognized mount option \"%s\" "
 270                                        "or missing value\n", p);
 271                        return 0;
 272                }
 273        }
 274        return 1;
 275}
 276
 277/* This function definitely needs to be split up. Some fine day I'll
 278 * hopefully have the guts to do so. Until then: sorry for the mess.
 279 */
 280
 281static int affs_fill_super(struct super_block *sb, void *data, int silent)
 282{
 283        struct affs_sb_info     *sbi;
 284        struct buffer_head      *root_bh = NULL;
 285        struct buffer_head      *boot_bh;
 286        struct inode            *root_inode = NULL;
 287        s32                      root_block;
 288        int                      size, blocksize;
 289        u32                      chksum;
 290        int                      num_bm;
 291        int                      i, j;
 292        s32                      key;
 293        uid_t                    uid;
 294        gid_t                    gid;
 295        int                      reserved;
 296        unsigned long            mount_flags;
 297        int                      tmp_flags;     /* fix remount prototype... */
 298        u8                       sig[4];
 299        int                      ret = -EINVAL;
 300
 301        save_mount_options(sb, data);
 302
 303        pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options");
 304
 305        sb->s_magic             = AFFS_SUPER_MAGIC;
 306        sb->s_op                = &affs_sops;
 307        sb->s_flags |= MS_NODIRATIME;
 308
 309        sbi = kzalloc(sizeof(struct affs_sb_info), GFP_KERNEL);
 310        if (!sbi)
 311                return -ENOMEM;
 312        sb->s_fs_info = sbi;
 313        mutex_init(&sbi->s_bmlock);
 314
 315        if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
 316                                &blocksize,&sbi->s_prefix,
 317                                sbi->s_volume, &mount_flags)) {
 318                printk(KERN_ERR "AFFS: Error parsing options\n");
 319                return -EINVAL;
 320        }
 321        /* N.B. after this point s_prefix must be released */
 322
 323        sbi->s_flags   = mount_flags;
 324        sbi->s_mode    = i;
 325        sbi->s_uid     = uid;
 326        sbi->s_gid     = gid;
 327        sbi->s_reserved= reserved;
 328
 329        /* Get the size of the device in 512-byte blocks.
 330         * If we later see that the partition uses bigger
 331         * blocks, we will have to change it.
 332         */
 333
 334        size = sb->s_bdev->bd_inode->i_size >> 9;
 335        pr_debug("AFFS: initial blocksize=%d, #blocks=%d\n", 512, size);
 336
 337        affs_set_blocksize(sb, PAGE_SIZE);
 338        /* Try to find root block. Its location depends on the block size. */
 339
 340        i = 512;
 341        j = 4096;
 342        if (blocksize > 0) {
 343                i = j = blocksize;
 344                size = size / (blocksize / 512);
 345        }
 346        for (blocksize = i, key = 0; blocksize <= j; blocksize <<= 1, size >>= 1) {
 347                sbi->s_root_block = root_block;
 348                if (root_block < 0)
 349                        sbi->s_root_block = (reserved + size - 1) / 2;
 350                pr_debug("AFFS: setting blocksize to %d\n", blocksize);
 351                affs_set_blocksize(sb, blocksize);
 352                sbi->s_partition_size = size;
 353
 354                /* The root block location that was calculated above is not
 355                 * correct if the partition size is an odd number of 512-
 356                 * byte blocks, which will be rounded down to a number of
 357                 * 1024-byte blocks, and if there were an even number of
 358                 * reserved blocks. Ideally, all partition checkers should
 359                 * report the real number of blocks of the real blocksize,
 360                 * but since this just cannot be done, we have to try to
 361                 * find the root block anyways. In the above case, it is one
 362                 * block behind the calculated one. So we check this one, too.
 363                 */
 364                for (num_bm = 0; num_bm < 2; num_bm++) {
 365                        pr_debug("AFFS: Dev %s, trying root=%u, bs=%d, "
 366                                "size=%d, reserved=%d\n",
 367                                sb->s_id,
 368                                sbi->s_root_block + num_bm,
 369                                blocksize, size, reserved);
 370                        root_bh = affs_bread(sb, sbi->s_root_block + num_bm);
 371                        if (!root_bh)
 372                                continue;
 373                        if (!affs_checksum_block(sb, root_bh) &&
 374                            be32_to_cpu(AFFS_ROOT_HEAD(root_bh)->ptype) == T_SHORT &&
 375                            be32_to_cpu(AFFS_ROOT_TAIL(sb, root_bh)->stype) == ST_ROOT) {
 376                                sbi->s_hashsize    = blocksize / 4 - 56;
 377                                sbi->s_root_block += num_bm;
 378                                key                        = 1;
 379                                goto got_root;
 380                        }
 381                        affs_brelse(root_bh);
 382                        root_bh = NULL;
 383                }
 384        }
 385        if (!silent)
 386                printk(KERN_ERR "AFFS: No valid root block on device %s\n",
 387                        sb->s_id);
 388        goto out_error;
 389
 390        /* N.B. after this point bh must be released */
 391got_root:
 392        root_block = sbi->s_root_block;
 393
 394        /* Find out which kind of FS we have */
 395        boot_bh = sb_bread(sb, 0);
 396        if (!boot_bh) {
 397                printk(KERN_ERR "AFFS: Cannot read boot block\n");
 398                goto out_error;
 399        }
 400        memcpy(sig, boot_bh->b_data, 4);
 401        brelse(boot_bh);
 402        chksum = be32_to_cpu(*(__be32 *)sig);
 403
 404        /* Dircache filesystems are compatible with non-dircache ones
 405         * when reading. As long as they aren't supported, writing is
 406         * not recommended.
 407         */
 408        if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS
 409             || chksum == MUFS_DCOFS) && !(sb->s_flags & MS_RDONLY)) {
 410                printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n",
 411                        sb->s_id);
 412                sb->s_flags |= MS_RDONLY;
 413        }
 414        switch (chksum) {
 415                case MUFS_FS:
 416                case MUFS_INTLFFS:
 417                case MUFS_DCFFS:
 418                        sbi->s_flags |= SF_MUFS;
 419                        /* fall thru */
 420                case FS_INTLFFS:
 421                case FS_DCFFS:
 422                        sbi->s_flags |= SF_INTL;
 423                        break;
 424                case MUFS_FFS:
 425                        sbi->s_flags |= SF_MUFS;
 426                        break;
 427                case FS_FFS:
 428                        break;
 429                case MUFS_OFS:
 430                        sbi->s_flags |= SF_MUFS;
 431                        /* fall thru */
 432                case FS_OFS:
 433                        sbi->s_flags |= SF_OFS;
 434                        sb->s_flags |= MS_NOEXEC;
 435                        break;
 436                case MUFS_DCOFS:
 437                case MUFS_INTLOFS:
 438                        sbi->s_flags |= SF_MUFS;
 439                case FS_DCOFS:
 440                case FS_INTLOFS:
 441                        sbi->s_flags |= SF_INTL | SF_OFS;
 442                        sb->s_flags |= MS_NOEXEC;
 443                        break;
 444                default:
 445                        printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n",
 446                                sb->s_id, chksum);
 447                        goto out_error;
 448        }
 449
 450        if (mount_flags & SF_VERBOSE) {
 451                u8 len = AFFS_ROOT_TAIL(sb, root_bh)->disk_name[0];
 452                printk(KERN_NOTICE "AFFS: Mounting volume \"%.*s\": Type=%.3s\\%c, Blocksize=%d\n",
 453                        len > 31 ? 31 : len,
 454                        AFFS_ROOT_TAIL(sb, root_bh)->disk_name + 1,
 455                        sig, sig[3] + '0', blocksize);
 456        }
 457
 458        sb->s_flags |= MS_NODEV | MS_NOSUID;
 459
 460        sbi->s_data_blksize = sb->s_blocksize;
 461        if (sbi->s_flags & SF_OFS)
 462                sbi->s_data_blksize -= 24;
 463
 464        /* Keep super block in cache */
 465        sbi->s_root_bh = root_bh;
 466        /* N.B. after this point s_root_bh must be released */
 467
 468        tmp_flags = sb->s_flags;
 469        if (affs_init_bitmap(sb, &tmp_flags))
 470                goto out_error;
 471        sb->s_flags = tmp_flags;
 472
 473        /* set up enough so that it can read an inode */
 474
 475        root_inode = affs_iget(sb, root_block);
 476        if (IS_ERR(root_inode)) {
 477                ret = PTR_ERR(root_inode);
 478                goto out_error_noinode;
 479        }
 480
 481        sb->s_root = d_alloc_root(root_inode);
 482        if (!sb->s_root) {
 483                printk(KERN_ERR "AFFS: Get root inode failed\n");
 484                goto out_error;
 485        }
 486        sb->s_root->d_op = &affs_dentry_operations;
 487
 488        pr_debug("AFFS: s_flags=%lX\n",sb->s_flags);
 489        return 0;
 490
 491        /*
 492         * Begin the cascaded cleanup ...
 493         */
 494out_error:
 495        if (root_inode)
 496                iput(root_inode);
 497out_error_noinode:
 498        kfree(sbi->s_bitmap);
 499        affs_brelse(root_bh);
 500        kfree(sbi->s_prefix);
 501        kfree(sbi);
 502        sb->s_fs_info = NULL;
 503        return ret;
 504}
 505
 506static int
 507affs_remount(struct super_block *sb, int *flags, char *data)
 508{
 509        struct affs_sb_info     *sbi = AFFS_SB(sb);
 510        int                      blocksize;
 511        uid_t                    uid;
 512        gid_t                    gid;
 513        int                      mode;
 514        int                      reserved;
 515        int                      root_block;
 516        unsigned long            mount_flags;
 517        int                      res = 0;
 518        char                    *new_opts = kstrdup(data, GFP_KERNEL);
 519
 520        pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data);
 521
 522        *flags |= MS_NODIRATIME;
 523
 524        if (!parse_options(data, &uid, &gid, &mode, &reserved, &root_block,
 525                           &blocksize, &sbi->s_prefix, sbi->s_volume,
 526                           &mount_flags)) {
 527                kfree(new_opts);
 528                return -EINVAL;
 529        }
 530        lock_kernel();
 531        replace_mount_options(sb, new_opts);
 532
 533        sbi->s_flags = mount_flags;
 534        sbi->s_mode  = mode;
 535        sbi->s_uid   = uid;
 536        sbi->s_gid   = gid;
 537
 538        if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
 539                unlock_kernel();
 540                return 0;
 541        }
 542        if (*flags & MS_RDONLY) {
 543                sb->s_dirt = 1;
 544                while (sb->s_dirt)
 545                        affs_write_super(sb);
 546                affs_free_bitmap(sb);
 547        } else
 548                res = affs_init_bitmap(sb, flags);
 549
 550        unlock_kernel();
 551        return res;
 552}
 553
 554static int
 555affs_statfs(struct dentry *dentry, struct kstatfs *buf)
 556{
 557        struct super_block *sb = dentry->d_sb;
 558        int              free;
 559        u64              id = huge_encode_dev(sb->s_bdev->bd_dev);
 560
 561        pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",AFFS_SB(sb)->s_partition_size,
 562             AFFS_SB(sb)->s_reserved);
 563
 564        free          = affs_count_free_blocks(sb);
 565        buf->f_type    = AFFS_SUPER_MAGIC;
 566        buf->f_bsize   = sb->s_blocksize;
 567        buf->f_blocks  = AFFS_SB(sb)->s_partition_size - AFFS_SB(sb)->s_reserved;
 568        buf->f_bfree   = free;
 569        buf->f_bavail  = free;
 570        buf->f_fsid.val[0] = (u32)id;
 571        buf->f_fsid.val[1] = (u32)(id >> 32);
 572        buf->f_namelen = 30;
 573        return 0;
 574}
 575
 576static int affs_get_sb(struct file_system_type *fs_type,
 577        int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 578{
 579        return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super,
 580                           mnt);
 581}
 582
 583static struct file_system_type affs_fs_type = {
 584        .owner          = THIS_MODULE,
 585        .name           = "affs",
 586        .get_sb         = affs_get_sb,
 587        .kill_sb        = kill_block_super,
 588        .fs_flags       = FS_REQUIRES_DEV,
 589};
 590
 591static int __init init_affs_fs(void)
 592{
 593        int err = init_inodecache();
 594        if (err)
 595                goto out1;
 596        err = register_filesystem(&affs_fs_type);
 597        if (err)
 598                goto out;
 599        return 0;
 600out:
 601        destroy_inodecache();
 602out1:
 603        return err;
 604}
 605
 606static void __exit exit_affs_fs(void)
 607{
 608        unregister_filesystem(&affs_fs_type);
 609        destroy_inodecache();
 610}
 611
 612MODULE_DESCRIPTION("Amiga filesystem support for Linux");
 613MODULE_LICENSE("GPL");
 614
 615module_init(init_affs_fs)
 616module_exit(exit_affs_fs)
 617