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