^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * super.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 1999 Al Smith
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/exportfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/buffer_head.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/vfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "efs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/efs_vh.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/efs_fs_sb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static int efs_statfs(struct dentry *dentry, struct kstatfs *buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static int efs_fill_super(struct super_block *s, void *d, int silent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static struct dentry *efs_mount(struct file_system_type *fs_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int flags, const char *dev_name, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return mount_bdev(fs_type, flags, dev_name, data, efs_fill_super);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static void efs_kill_sb(struct super_block *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct efs_sb_info *sbi = SUPER_INFO(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) kill_block_super(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) kfree(sbi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static struct file_system_type efs_fs_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .name = "efs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .mount = efs_mount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .kill_sb = efs_kill_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .fs_flags = FS_REQUIRES_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) MODULE_ALIAS_FS("efs");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static struct pt_types sgi_pt_types[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {0x00, "SGI vh"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {0x01, "SGI trkrepl"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {0x02, "SGI secrepl"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {0x03, "SGI raw"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {0x04, "SGI bsd"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {SGI_SYSV, "SGI sysv"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {0x06, "SGI vol"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {SGI_EFS, "SGI efs"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {0x08, "SGI lv"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {0x09, "SGI rlv"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {0x0A, "SGI xfs"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {0x0B, "SGI xfslog"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {0x0C, "SGI xlv"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {0x82, "Linux swap"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {0x83, "Linux native"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {0, NULL}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static struct kmem_cache * efs_inode_cachep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static struct inode *efs_alloc_inode(struct super_block *sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct efs_inode_info *ei;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ei = kmem_cache_alloc(efs_inode_cachep, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (!ei)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return &ei->vfs_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static void efs_free_inode(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) kmem_cache_free(efs_inode_cachep, INODE_INFO(inode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static void init_once(void *foo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct efs_inode_info *ei = (struct efs_inode_info *) foo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) inode_init_once(&ei->vfs_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int __init init_inodecache(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) efs_inode_cachep = kmem_cache_create("efs_inode_cache",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) sizeof(struct efs_inode_info), 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) SLAB_ACCOUNT, init_once);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (efs_inode_cachep == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static void destroy_inodecache(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * Make sure all delayed rcu free inodes are flushed before we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * destroy cache.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) rcu_barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) kmem_cache_destroy(efs_inode_cachep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int efs_remount(struct super_block *sb, int *flags, char *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) sync_filesystem(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) *flags |= SB_RDONLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static const struct super_operations efs_superblock_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .alloc_inode = efs_alloc_inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .free_inode = efs_free_inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .statfs = efs_statfs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .remount_fs = efs_remount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static const struct export_operations efs_export_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .fh_to_dentry = efs_fh_to_dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .fh_to_parent = efs_fh_to_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .get_parent = efs_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static int __init init_efs_fs(void) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) pr_info(EFS_VERSION" - http://aeschi.ch.eu.org/efs/\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) err = init_inodecache();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) goto out1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) err = register_filesystem(&efs_fs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) destroy_inodecache();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) out1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static void __exit exit_efs_fs(void) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) unregister_filesystem(&efs_fs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) destroy_inodecache();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) module_init(init_efs_fs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) module_exit(exit_efs_fs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static efs_block_t efs_validate_vh(struct volume_header *vh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) __be32 cs, *ui;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int csum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) efs_block_t sblock = 0; /* shuts up gcc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct pt_types *pt_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) int pt_type, slice = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (be32_to_cpu(vh->vh_magic) != VHMAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * assume that we're dealing with a partition and allow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * read_super() to try and detect a valid superblock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * on the next block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ui = ((__be32 *) (vh + 1)) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) for(csum = 0; ui >= ((__be32 *) vh);) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) cs = *ui--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) csum += be32_to_cpu(cs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (csum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) pr_warn("SGI disklabel: checksum bad, label corrupted\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) pr_debug("bf: \"%16s\"\n", vh->vh_bootfile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) for(i = 0; i < NVDIR; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) char name[VDNAMESIZE+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) for(j = 0; j < VDNAMESIZE; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) name[j] = vh->vh_vd[i].vd_name[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) name[j] = (char) 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (name[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) pr_debug("vh: %8s block: 0x%08x size: 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) name, (int) be32_to_cpu(vh->vh_vd[i].vd_lbn),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) (int) be32_to_cpu(vh->vh_vd[i].vd_nbytes));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) for(i = 0; i < NPARTAB; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) pt_type = (int) be32_to_cpu(vh->vh_pt[i].pt_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) for(pt_entry = sgi_pt_types; pt_entry->pt_name; pt_entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (pt_type == pt_entry->pt_type) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (be32_to_cpu(vh->vh_pt[i].pt_nblks)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) pr_debug("pt %2d: start: %08d size: %08d type: 0x%02x (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) i, (int)be32_to_cpu(vh->vh_pt[i].pt_firstlbn),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) (int)be32_to_cpu(vh->vh_pt[i].pt_nblks),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) pt_type, (pt_entry->pt_name) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) pt_entry->pt_name : "unknown");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (IS_EFS(pt_type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) sblock = be32_to_cpu(vh->vh_pt[i].pt_firstlbn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) slice = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (slice == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) pr_notice("partition table contained no EFS partitions\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) pr_info("using slice %d (type %s, offset 0x%x)\n", slice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) (pt_entry->pt_name) ? pt_entry->pt_name : "unknown",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) sblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return sblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static int efs_validate_super(struct efs_sb_info *sb, struct efs_super *super) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (!IS_EFS_MAGIC(be32_to_cpu(super->fs_magic)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) sb->fs_magic = be32_to_cpu(super->fs_magic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) sb->total_blocks = be32_to_cpu(super->fs_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) sb->first_block = be32_to_cpu(super->fs_firstcg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) sb->group_size = be32_to_cpu(super->fs_cgfsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) sb->data_free = be32_to_cpu(super->fs_tfree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) sb->inode_free = be32_to_cpu(super->fs_tinode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) sb->inode_blocks = be16_to_cpu(super->fs_cgisize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) sb->total_groups = be16_to_cpu(super->fs_ncg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static int efs_fill_super(struct super_block *s, void *d, int silent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct efs_sb_info *sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) struct buffer_head *bh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct inode *root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) sb = kzalloc(sizeof(struct efs_sb_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (!sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) s->s_fs_info = sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) s->s_time_min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) s->s_time_max = U32_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) s->s_magic = EFS_SUPER_MAGIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (!sb_set_blocksize(s, EFS_BLOCKSIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) pr_err("device does not support %d byte blocks\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) EFS_BLOCKSIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* read the vh (volume header) block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) bh = sb_bread(s, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (!bh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) pr_err("cannot read volume header\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * if this returns zero then we didn't find any partition table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * this isn't (yet) an error - just assume for the moment that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * the device is valid and go on to search for a superblock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) sb->fs_start = efs_validate_vh((struct volume_header *) bh->b_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (sb->fs_start == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) bh = sb_bread(s, sb->fs_start + EFS_SUPER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (!bh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) pr_err("cannot read superblock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (efs_validate_super(sb, (struct efs_super *) bh->b_data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) pr_warn("invalid superblock at block %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) sb->fs_start + EFS_SUPER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (!sb_rdonly(s)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) pr_info("forcing read-only mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) s->s_flags |= SB_RDONLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) s->s_op = &efs_superblock_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) s->s_export_op = &efs_export_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) root = efs_iget(s, EFS_ROOTINODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (IS_ERR(root)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) pr_err("get root inode failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return PTR_ERR(root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) s->s_root = d_make_root(root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (!(s->s_root)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) pr_err("get root dentry failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static int efs_statfs(struct dentry *dentry, struct kstatfs *buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct super_block *sb = dentry->d_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) struct efs_sb_info *sbi = SUPER_INFO(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) buf->f_type = EFS_SUPER_MAGIC; /* efs magic number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) buf->f_bsize = EFS_BLOCKSIZE; /* blocksize */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) buf->f_blocks = sbi->total_groups * /* total data blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) (sbi->group_size - sbi->inode_blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) buf->f_bfree = sbi->data_free; /* free data blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) buf->f_bavail = sbi->data_free; /* free blocks for non-root */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) buf->f_files = sbi->total_groups * /* total inodes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) sbi->inode_blocks *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) (EFS_BLOCKSIZE / sizeof(struct efs_dinode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) buf->f_ffree = sbi->inode_free; /* free inodes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) buf->f_fsid = u64_to_fsid(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) buf->f_namelen = EFS_MAXNAMELEN; /* max filename length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)