linux/fs/omfs/inode.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Optimized MPEG FS - inode and super operations.
   4 * Copyright (C) 2006 Bob Copeland <me@bobcopeland.com>
   5 */
   6#include <linux/module.h>
   7#include <linux/sched.h>
   8#include <linux/slab.h>
   9#include <linux/fs.h>
  10#include <linux/vfs.h>
  11#include <linux/cred.h>
  12#include <linux/parser.h>
  13#include <linux/buffer_head.h>
  14#include <linux/vmalloc.h>
  15#include <linux/writeback.h>
  16#include <linux/seq_file.h>
  17#include <linux/crc-itu-t.h>
  18#include "omfs.h"
  19
  20MODULE_AUTHOR("Bob Copeland <me@bobcopeland.com>");
  21MODULE_DESCRIPTION("OMFS (ReplayTV/Karma) Filesystem for Linux");
  22MODULE_LICENSE("GPL");
  23
  24struct buffer_head *omfs_bread(struct super_block *sb, sector_t block)
  25{
  26        struct omfs_sb_info *sbi = OMFS_SB(sb);
  27        if (block >= sbi->s_num_blocks)
  28                return NULL;
  29
  30        return sb_bread(sb, clus_to_blk(sbi, block));
  31}
  32
  33struct inode *omfs_new_inode(struct inode *dir, umode_t mode)
  34{
  35        struct inode *inode;
  36        u64 new_block;
  37        int err;
  38        int len;
  39        struct omfs_sb_info *sbi = OMFS_SB(dir->i_sb);
  40
  41        inode = new_inode(dir->i_sb);
  42        if (!inode)
  43                return ERR_PTR(-ENOMEM);
  44
  45        err = omfs_allocate_range(dir->i_sb, sbi->s_mirrors, sbi->s_mirrors,
  46                        &new_block, &len);
  47        if (err)
  48                goto fail;
  49
  50        inode->i_ino = new_block;
  51        inode_init_owner(inode, NULL, mode);
  52        inode->i_mapping->a_ops = &omfs_aops;
  53
  54        inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
  55        switch (mode & S_IFMT) {
  56        case S_IFDIR:
  57                inode->i_op = &omfs_dir_inops;
  58                inode->i_fop = &omfs_dir_operations;
  59                inode->i_size = sbi->s_sys_blocksize;
  60                inc_nlink(inode);
  61                break;
  62        case S_IFREG:
  63                inode->i_op = &omfs_file_inops;
  64                inode->i_fop = &omfs_file_operations;
  65                inode->i_size = 0;
  66                break;
  67        }
  68
  69        insert_inode_hash(inode);
  70        mark_inode_dirty(inode);
  71        return inode;
  72fail:
  73        make_bad_inode(inode);
  74        iput(inode);
  75        return ERR_PTR(err);
  76}
  77
  78/*
  79 * Update the header checksums for a dirty inode based on its contents.
  80 * Caller is expected to hold the buffer head underlying oi and mark it
  81 * dirty.
  82 */
  83static void omfs_update_checksums(struct omfs_inode *oi)
  84{
  85        int xor, i, ofs = 0, count;
  86        u16 crc = 0;
  87        unsigned char *ptr = (unsigned char *) oi;
  88
  89        count = be32_to_cpu(oi->i_head.h_body_size);
  90        ofs = sizeof(struct omfs_header);
  91
  92        crc = crc_itu_t(crc, ptr + ofs, count);
  93        oi->i_head.h_crc = cpu_to_be16(crc);
  94
  95        xor = ptr[0];
  96        for (i = 1; i < OMFS_XOR_COUNT; i++)
  97                xor ^= ptr[i];
  98
  99        oi->i_head.h_check_xor = xor;
 100}
 101
 102static int __omfs_write_inode(struct inode *inode, int wait)
 103{
 104        struct omfs_inode *oi;
 105        struct omfs_sb_info *sbi = OMFS_SB(inode->i_sb);
 106        struct buffer_head *bh, *bh2;
 107        u64 ctime;
 108        int i;
 109        int ret = -EIO;
 110        int sync_failed = 0;
 111
 112        /* get current inode since we may have written sibling ptrs etc. */
 113        bh = omfs_bread(inode->i_sb, inode->i_ino);
 114        if (!bh)
 115                goto out;
 116
 117        oi = (struct omfs_inode *) bh->b_data;
 118
 119        oi->i_head.h_self = cpu_to_be64(inode->i_ino);
 120        if (S_ISDIR(inode->i_mode))
 121                oi->i_type = OMFS_DIR;
 122        else if (S_ISREG(inode->i_mode))
 123                oi->i_type = OMFS_FILE;
 124        else {
 125                printk(KERN_WARNING "omfs: unknown file type: %d\n",
 126                        inode->i_mode);
 127                goto out_brelse;
 128        }
 129
 130        oi->i_head.h_body_size = cpu_to_be32(sbi->s_sys_blocksize -
 131                sizeof(struct omfs_header));
 132        oi->i_head.h_version = 1;
 133        oi->i_head.h_type = OMFS_INODE_NORMAL;
 134        oi->i_head.h_magic = OMFS_IMAGIC;
 135        oi->i_size = cpu_to_be64(inode->i_size);
 136
 137        ctime = inode->i_ctime.tv_sec * 1000LL +
 138                ((inode->i_ctime.tv_nsec + 999)/1000);
 139        oi->i_ctime = cpu_to_be64(ctime);
 140
 141        omfs_update_checksums(oi);
 142
 143        mark_buffer_dirty(bh);
 144        if (wait) {
 145                sync_dirty_buffer(bh);
 146                if (buffer_req(bh) && !buffer_uptodate(bh))
 147                        sync_failed = 1;
 148        }
 149
 150        /* if mirroring writes, copy to next fsblock */
 151        for (i = 1; i < sbi->s_mirrors; i++) {
 152                bh2 = omfs_bread(inode->i_sb, inode->i_ino + i);
 153                if (!bh2)
 154                        goto out_brelse;
 155
 156                memcpy(bh2->b_data, bh->b_data, bh->b_size);
 157                mark_buffer_dirty(bh2);
 158                if (wait) {
 159                        sync_dirty_buffer(bh2);
 160                        if (buffer_req(bh2) && !buffer_uptodate(bh2))
 161                                sync_failed = 1;
 162                }
 163                brelse(bh2);
 164        }
 165        ret = (sync_failed) ? -EIO : 0;
 166out_brelse:
 167        brelse(bh);
 168out:
 169        return ret;
 170}
 171
 172static int omfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 173{
 174        return __omfs_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
 175}
 176
 177int omfs_sync_inode(struct inode *inode)
 178{
 179        return __omfs_write_inode(inode, 1);
 180}
 181
 182/*
 183 * called when an entry is deleted, need to clear the bits in the
 184 * bitmaps.
 185 */
 186static void omfs_evict_inode(struct inode *inode)
 187{
 188        truncate_inode_pages_final(&inode->i_data);
 189        clear_inode(inode);
 190
 191        if (inode->i_nlink)
 192                return;
 193
 194        if (S_ISREG(inode->i_mode)) {
 195                inode->i_size = 0;
 196                omfs_shrink_inode(inode);
 197        }
 198
 199        omfs_clear_range(inode->i_sb, inode->i_ino, 2);
 200}
 201
 202struct inode *omfs_iget(struct super_block *sb, ino_t ino)
 203{
 204        struct omfs_sb_info *sbi = OMFS_SB(sb);
 205        struct omfs_inode *oi;
 206        struct buffer_head *bh;
 207        u64 ctime;
 208        unsigned long nsecs;
 209        struct inode *inode;
 210
 211        inode = iget_locked(sb, ino);
 212        if (!inode)
 213                return ERR_PTR(-ENOMEM);
 214        if (!(inode->i_state & I_NEW))
 215                return inode;
 216
 217        bh = omfs_bread(inode->i_sb, ino);
 218        if (!bh)
 219                goto iget_failed;
 220
 221        oi = (struct omfs_inode *)bh->b_data;
 222
 223        /* check self */
 224        if (ino != be64_to_cpu(oi->i_head.h_self))
 225                goto fail_bh;
 226
 227        inode->i_uid = sbi->s_uid;
 228        inode->i_gid = sbi->s_gid;
 229
 230        ctime = be64_to_cpu(oi->i_ctime);
 231        nsecs = do_div(ctime, 1000) * 1000L;
 232
 233        inode->i_atime.tv_sec = ctime;
 234        inode->i_mtime.tv_sec = ctime;
 235        inode->i_ctime.tv_sec = ctime;
 236        inode->i_atime.tv_nsec = nsecs;
 237        inode->i_mtime.tv_nsec = nsecs;
 238        inode->i_ctime.tv_nsec = nsecs;
 239
 240        inode->i_mapping->a_ops = &omfs_aops;
 241
 242        switch (oi->i_type) {
 243        case OMFS_DIR:
 244                inode->i_mode = S_IFDIR | (S_IRWXUGO & ~sbi->s_dmask);
 245                inode->i_op = &omfs_dir_inops;
 246                inode->i_fop = &omfs_dir_operations;
 247                inode->i_size = sbi->s_sys_blocksize;
 248                inc_nlink(inode);
 249                break;
 250        case OMFS_FILE:
 251                inode->i_mode = S_IFREG | (S_IRWXUGO & ~sbi->s_fmask);
 252                inode->i_fop = &omfs_file_operations;
 253                inode->i_size = be64_to_cpu(oi->i_size);
 254                break;
 255        }
 256        brelse(bh);
 257        unlock_new_inode(inode);
 258        return inode;
 259fail_bh:
 260        brelse(bh);
 261iget_failed:
 262        iget_failed(inode);
 263        return ERR_PTR(-EIO);
 264}
 265
 266static void omfs_put_super(struct super_block *sb)
 267{
 268        struct omfs_sb_info *sbi = OMFS_SB(sb);
 269        kfree(sbi->s_imap);
 270        kfree(sbi);
 271        sb->s_fs_info = NULL;
 272}
 273
 274static int omfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 275{
 276        struct super_block *s = dentry->d_sb;
 277        struct omfs_sb_info *sbi = OMFS_SB(s);
 278        u64 id = huge_encode_dev(s->s_bdev->bd_dev);
 279
 280        buf->f_type = OMFS_MAGIC;
 281        buf->f_bsize = sbi->s_blocksize;
 282        buf->f_blocks = sbi->s_num_blocks;
 283        buf->f_files = sbi->s_num_blocks;
 284        buf->f_namelen = OMFS_NAMELEN;
 285        buf->f_fsid.val[0] = (u32)id;
 286        buf->f_fsid.val[1] = (u32)(id >> 32);
 287
 288        buf->f_bfree = buf->f_bavail = buf->f_ffree =
 289                omfs_count_free(s);
 290
 291        return 0;
 292}
 293
 294/*
 295 * Display the mount options in /proc/mounts.
 296 */
 297static int omfs_show_options(struct seq_file *m, struct dentry *root)
 298{
 299        struct omfs_sb_info *sbi = OMFS_SB(root->d_sb);
 300        umode_t cur_umask = current_umask();
 301
 302        if (!uid_eq(sbi->s_uid, current_uid()))
 303                seq_printf(m, ",uid=%u",
 304                           from_kuid_munged(&init_user_ns, sbi->s_uid));
 305        if (!gid_eq(sbi->s_gid, current_gid()))
 306                seq_printf(m, ",gid=%u",
 307                           from_kgid_munged(&init_user_ns, sbi->s_gid));
 308
 309        if (sbi->s_dmask == sbi->s_fmask) {
 310                if (sbi->s_fmask != cur_umask)
 311                        seq_printf(m, ",umask=%o", sbi->s_fmask);
 312        } else {
 313                if (sbi->s_dmask != cur_umask)
 314                        seq_printf(m, ",dmask=%o", sbi->s_dmask);
 315                if (sbi->s_fmask != cur_umask)
 316                        seq_printf(m, ",fmask=%o", sbi->s_fmask);
 317        }
 318
 319        return 0;
 320}
 321
 322static const struct super_operations omfs_sops = {
 323        .write_inode    = omfs_write_inode,
 324        .evict_inode    = omfs_evict_inode,
 325        .put_super      = omfs_put_super,
 326        .statfs         = omfs_statfs,
 327        .show_options   = omfs_show_options,
 328};
 329
 330/*
 331 * For Rio Karma, there is an on-disk free bitmap whose location is
 332 * stored in the root block.  For ReplayTV, there is no such free bitmap
 333 * so we have to walk the tree.  Both inodes and file data are allocated
 334 * from the same map.  This array can be big (300k) so we allocate
 335 * in units of the blocksize.
 336 */
 337static int omfs_get_imap(struct super_block *sb)
 338{
 339        unsigned int bitmap_size, array_size;
 340        int count;
 341        struct omfs_sb_info *sbi = OMFS_SB(sb);
 342        struct buffer_head *bh;
 343        unsigned long **ptr;
 344        sector_t block;
 345
 346        bitmap_size = DIV_ROUND_UP(sbi->s_num_blocks, 8);
 347        array_size = DIV_ROUND_UP(bitmap_size, sb->s_blocksize);
 348
 349        if (sbi->s_bitmap_ino == ~0ULL)
 350                goto out;
 351
 352        sbi->s_imap_size = array_size;
 353        sbi->s_imap = kcalloc(array_size, sizeof(unsigned long *), GFP_KERNEL);
 354        if (!sbi->s_imap)
 355                goto nomem;
 356
 357        block = clus_to_blk(sbi, sbi->s_bitmap_ino);
 358        if (block >= sbi->s_num_blocks)
 359                goto nomem;
 360
 361        ptr = sbi->s_imap;
 362        for (count = bitmap_size; count > 0; count -= sb->s_blocksize) {
 363                bh = sb_bread(sb, block++);
 364                if (!bh)
 365                        goto nomem_free;
 366                *ptr = kmalloc(sb->s_blocksize, GFP_KERNEL);
 367                if (!*ptr) {
 368                        brelse(bh);
 369                        goto nomem_free;
 370                }
 371                memcpy(*ptr, bh->b_data, sb->s_blocksize);
 372                if (count < sb->s_blocksize)
 373                        memset((void *)*ptr + count, 0xff,
 374                                sb->s_blocksize - count);
 375                brelse(bh);
 376                ptr++;
 377        }
 378out:
 379        return 0;
 380
 381nomem_free:
 382        for (count = 0; count < array_size; count++)
 383                kfree(sbi->s_imap[count]);
 384
 385        kfree(sbi->s_imap);
 386nomem:
 387        sbi->s_imap = NULL;
 388        sbi->s_imap_size = 0;
 389        return -ENOMEM;
 390}
 391
 392enum {
 393        Opt_uid, Opt_gid, Opt_umask, Opt_dmask, Opt_fmask, Opt_err
 394};
 395
 396static const match_table_t tokens = {
 397        {Opt_uid, "uid=%u"},
 398        {Opt_gid, "gid=%u"},
 399        {Opt_umask, "umask=%o"},
 400        {Opt_dmask, "dmask=%o"},
 401        {Opt_fmask, "fmask=%o"},
 402        {Opt_err, NULL},
 403};
 404
 405static int parse_options(char *options, struct omfs_sb_info *sbi)
 406{
 407        char *p;
 408        substring_t args[MAX_OPT_ARGS];
 409        int option;
 410
 411        if (!options)
 412                return 1;
 413
 414        while ((p = strsep(&options, ",")) != NULL) {
 415                int token;
 416                if (!*p)
 417                        continue;
 418
 419                token = match_token(p, tokens, args);
 420                switch (token) {
 421                case Opt_uid:
 422                        if (match_int(&args[0], &option))
 423                                return 0;
 424                        sbi->s_uid = make_kuid(current_user_ns(), option);
 425                        if (!uid_valid(sbi->s_uid))
 426                                return 0;
 427                        break;
 428                case Opt_gid:
 429                        if (match_int(&args[0], &option))
 430                                return 0;
 431                        sbi->s_gid = make_kgid(current_user_ns(), option);
 432                        if (!gid_valid(sbi->s_gid))
 433                                return 0;
 434                        break;
 435                case Opt_umask:
 436                        if (match_octal(&args[0], &option))
 437                                return 0;
 438                        sbi->s_fmask = sbi->s_dmask = option;
 439                        break;
 440                case Opt_dmask:
 441                        if (match_octal(&args[0], &option))
 442                                return 0;
 443                        sbi->s_dmask = option;
 444                        break;
 445                case Opt_fmask:
 446                        if (match_octal(&args[0], &option))
 447                                return 0;
 448                        sbi->s_fmask = option;
 449                        break;
 450                default:
 451                        return 0;
 452                }
 453        }
 454        return 1;
 455}
 456
 457static int omfs_fill_super(struct super_block *sb, void *data, int silent)
 458{
 459        struct buffer_head *bh, *bh2;
 460        struct omfs_super_block *omfs_sb;
 461        struct omfs_root_block *omfs_rb;
 462        struct omfs_sb_info *sbi;
 463        struct inode *root;
 464        int ret = -EINVAL;
 465
 466        sbi = kzalloc(sizeof(struct omfs_sb_info), GFP_KERNEL);
 467        if (!sbi)
 468                return -ENOMEM;
 469
 470        sb->s_fs_info = sbi;
 471
 472        sbi->s_uid = current_uid();
 473        sbi->s_gid = current_gid();
 474        sbi->s_dmask = sbi->s_fmask = current_umask();
 475
 476        if (!parse_options((char *) data, sbi))
 477                goto end;
 478
 479        sb->s_maxbytes = 0xffffffff;
 480
 481        sb_set_blocksize(sb, 0x200);
 482
 483        bh = sb_bread(sb, 0);
 484        if (!bh)
 485                goto end;
 486
 487        omfs_sb = (struct omfs_super_block *)bh->b_data;
 488
 489        if (omfs_sb->s_magic != cpu_to_be32(OMFS_MAGIC)) {
 490                if (!silent)
 491                        printk(KERN_ERR "omfs: Invalid superblock (%x)\n",
 492                                   omfs_sb->s_magic);
 493                goto out_brelse_bh;
 494        }
 495        sb->s_magic = OMFS_MAGIC;
 496
 497        sbi->s_num_blocks = be64_to_cpu(omfs_sb->s_num_blocks);
 498        sbi->s_blocksize = be32_to_cpu(omfs_sb->s_blocksize);
 499        sbi->s_mirrors = be32_to_cpu(omfs_sb->s_mirrors);
 500        sbi->s_root_ino = be64_to_cpu(omfs_sb->s_root_block);
 501        sbi->s_sys_blocksize = be32_to_cpu(omfs_sb->s_sys_blocksize);
 502        mutex_init(&sbi->s_bitmap_lock);
 503
 504        if (sbi->s_num_blocks > OMFS_MAX_BLOCKS) {
 505                printk(KERN_ERR "omfs: sysblock number (%llx) is out of range\n",
 506                       (unsigned long long)sbi->s_num_blocks);
 507                goto out_brelse_bh;
 508        }
 509
 510        if (sbi->s_sys_blocksize > PAGE_SIZE) {
 511                printk(KERN_ERR "omfs: sysblock size (%d) is out of range\n",
 512                        sbi->s_sys_blocksize);
 513                goto out_brelse_bh;
 514        }
 515
 516        if (sbi->s_blocksize < sbi->s_sys_blocksize ||
 517            sbi->s_blocksize > OMFS_MAX_BLOCK_SIZE) {
 518                printk(KERN_ERR "omfs: block size (%d) is out of range\n",
 519                        sbi->s_blocksize);
 520                goto out_brelse_bh;
 521        }
 522
 523        /*
 524         * Use sys_blocksize as the fs block since it is smaller than a
 525         * page while the fs blocksize can be larger.
 526         */
 527        sb_set_blocksize(sb, sbi->s_sys_blocksize);
 528
 529        /*
 530         * ...and the difference goes into a shift.  sys_blocksize is always
 531         * a power of two factor of blocksize.
 532         */
 533        sbi->s_block_shift = get_bitmask_order(sbi->s_blocksize) -
 534                get_bitmask_order(sbi->s_sys_blocksize);
 535
 536        bh2 = omfs_bread(sb, be64_to_cpu(omfs_sb->s_root_block));
 537        if (!bh2)
 538                goto out_brelse_bh;
 539
 540        omfs_rb = (struct omfs_root_block *)bh2->b_data;
 541
 542        sbi->s_bitmap_ino = be64_to_cpu(omfs_rb->r_bitmap);
 543        sbi->s_clustersize = be32_to_cpu(omfs_rb->r_clustersize);
 544
 545        if (sbi->s_num_blocks != be64_to_cpu(omfs_rb->r_num_blocks)) {
 546                printk(KERN_ERR "omfs: block count discrepancy between "
 547                        "super and root blocks (%llx, %llx)\n",
 548                        (unsigned long long)sbi->s_num_blocks,
 549                        (unsigned long long)be64_to_cpu(omfs_rb->r_num_blocks));
 550                goto out_brelse_bh2;
 551        }
 552
 553        if (sbi->s_bitmap_ino != ~0ULL &&
 554            sbi->s_bitmap_ino > sbi->s_num_blocks) {
 555                printk(KERN_ERR "omfs: free space bitmap location is corrupt "
 556                        "(%llx, total blocks %llx)\n",
 557                        (unsigned long long) sbi->s_bitmap_ino,
 558                        (unsigned long long) sbi->s_num_blocks);
 559                goto out_brelse_bh2;
 560        }
 561        if (sbi->s_clustersize < 1 ||
 562            sbi->s_clustersize > OMFS_MAX_CLUSTER_SIZE) {
 563                printk(KERN_ERR "omfs: cluster size out of range (%d)",
 564                        sbi->s_clustersize);
 565                goto out_brelse_bh2;
 566        }
 567
 568        ret = omfs_get_imap(sb);
 569        if (ret)
 570                goto out_brelse_bh2;
 571
 572        sb->s_op = &omfs_sops;
 573
 574        root = omfs_iget(sb, be64_to_cpu(omfs_rb->r_root_dir));
 575        if (IS_ERR(root)) {
 576                ret = PTR_ERR(root);
 577                goto out_brelse_bh2;
 578        }
 579
 580        sb->s_root = d_make_root(root);
 581        if (!sb->s_root) {
 582                ret = -ENOMEM;
 583                goto out_brelse_bh2;
 584        }
 585        printk(KERN_DEBUG "omfs: Mounted volume %s\n", omfs_rb->r_name);
 586
 587        ret = 0;
 588out_brelse_bh2:
 589        brelse(bh2);
 590out_brelse_bh:
 591        brelse(bh);
 592end:
 593        if (ret)
 594                kfree(sbi);
 595        return ret;
 596}
 597
 598static struct dentry *omfs_mount(struct file_system_type *fs_type,
 599                        int flags, const char *dev_name, void *data)
 600{
 601        return mount_bdev(fs_type, flags, dev_name, data, omfs_fill_super);
 602}
 603
 604static struct file_system_type omfs_fs_type = {
 605        .owner = THIS_MODULE,
 606        .name = "omfs",
 607        .mount = omfs_mount,
 608        .kill_sb = kill_block_super,
 609        .fs_flags = FS_REQUIRES_DEV,
 610};
 611MODULE_ALIAS_FS("omfs");
 612
 613static int __init init_omfs_fs(void)
 614{
 615        return register_filesystem(&omfs_fs_type);
 616}
 617
 618static void __exit exit_omfs_fs(void)
 619{
 620        unregister_filesystem(&omfs_fs_type);
 621}
 622
 623module_init(init_omfs_fs);
 624module_exit(exit_omfs_fs);
 625