📄 super.c
字号:
/* * FILE NAME fs/pramfs/super.c * * BRIEF DESCRIPTION * * Super block operations. * * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com> * * Copyright 2003 Sony Corporation * Copyright 2003 Matsushita Electric Industrial Co., Ltd. * 2003-2004 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */#include <linux/module.h>#include <linux/string.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/blkdev.h>#include <linux/parser.h>#include <linux/vfs.h>#include <linux/pram_fs.h>#include <asm/uaccess.h>#include <asm/io.h>#ifdef CONFIG_PRAMFS_VNVRAM#include <linux/vnvram.h>#include <linux/mtd/mtd.h>#endifMODULE_AUTHOR("Steve Longerbeam, stevel@mvista.com");MODULE_DESCRIPTION("Protected/Persistent RAM Filesystem");MODULE_LICENSE("GPL");static struct super_operations pram_sops;#ifndef MODULEextern struct list_head super_blocks;struct super_block * find_pramfs_super(void){ struct list_head *p; list_for_each(p, &super_blocks) { struct super_block * s = sb_entry(p); if (s->s_magic == PRAM_SUPER_MAGIC) return s; } return NULL;}EXPORT_SYMBOL(find_pramfs_super);#endifstatic void pram_set_blocksize(struct super_block * sb, unsigned long size){ int bits, min_bits, max_bits; min_bits = ilog2(PRAM_MIN_BLOCK_SIZE); max_bits = ilog2(PRAM_MAX_BLOCK_SIZE); bits = ilog2(size); if (bits < min_bits) bits = min_bits; if (bits > max_bits) bits = max_bits; sb->s_blocksize_bits = bits; sb->s_blocksize = (1<<bits);}static inline void * pram_ioremap(struct pram_sb_info *sbi, unsigned long phys_addr, size_t size){ void * retval;#ifdef CONFIG_PRAMFS_VNVRAM /* if use vnvram, no need ioremap at all */ if (sbi->vnvram) retval = sbi->vnvram->virt_addr; else#endif retval = (void *)ioremap(phys_addr, size);#ifndef CONFIG_PRAMFS_NOWP if (retval) { spin_lock(&init_mm.page_table_lock); pram_writeable(retval, size, 0); spin_unlock(&init_mm.page_table_lock); }#endif return retval;}static inline void pram_iounmap(struct pram_sb_info *sbi, void *virt_addr){#ifdef CONFIG_PRAMFS_VNVRAM /* if use vnvram, no need ioremap at all */ if (sbi->vnvram) return;#endif iounmap((void __iomem *)virt_addr);}static inline intinit_super(struct super_block * sb, void * data, unsigned long maxsize, struct pram_sb_info * sbi, struct pram_super_block ** superp, struct pram_inode ** root_ip){ char *p; unsigned long blocksize; struct pram_super_block * super; struct pram_inode * root_i; int retval = -EINVAL; unsigned long bpi, num_inodes, bitmap_size; unsigned long num_blocks; pram_off_t bitmap_start;#ifdef CONFIG_PRAMFS_VNVRAM struct vnvram_info *vnvram = sbi->vnvram; if (vnvram && maxsize > vnvram->size) { pram_err("size 0x%lx too large, vnvram only 0x%x", maxsize, vnvram->size); goto out; }#endif /* CONFIG_PRAMFS_VNVRAM */ sbi->virt_addr = pram_ioremap(sbi, sbi->phys_addr, maxsize); if (!sbi->virt_addr) { pram_err("ioremap of the pramfs image failed\n"); goto out; } if ((p = strstr((char *)data, "bs="))) blocksize = simple_strtoul(p + 3, NULL, 0);#ifdef CONFIG_PRAMFS_VNVRAM /* if use vnvram, blocksize is chunk size default */ else if (vnvram) blocksize = vnvram->chunk_size;#endif else blocksize = PRAM_DEF_BLOCK_SIZE; pram_set_blocksize(sb, blocksize); blocksize = sb->s_blocksize; /* maxsize should be page aligned and block aligned */ if (maxsize & (PAGE_SIZE-1) || maxsize & (blocksize - 1)) { pram_err("size 0x%lx isn't aligned to" " a page or block boundary\n", maxsize); goto out; } if ((p = strstr((char *)data, "N="))) { num_inodes = simple_strtoul(p + 2, NULL, 0); } else { if ((p = strstr((char *)data, "bpi="))) bpi = simple_strtoul(p + 4, NULL, 0); else { /* default is that 5% of the filesystem is devoted to the inode table */ bpi = 20 * PRAM_INODE_SIZE; } num_inodes = maxsize / bpi; } /* up num_inodes such that the end of the inode table (and start of bitmap) is on a block boundary */ bitmap_start = PRAM_SB_SIZE + (num_inodes<<PRAM_INODE_BITS); if (bitmap_start & (blocksize - 1)) bitmap_start = (bitmap_start + blocksize) & ~(blocksize-1); num_inodes = (bitmap_start - PRAM_SB_SIZE) >> PRAM_INODE_BITS; /* ckeck size */ { unsigned long failsafe_blocks = pram_get_failsafe_blocks_count(sb) << sb->s_blocksize_bits; if (maxsize < (bitmap_start + failsafe_blocks)) { pram_err("size too small, at least 0x%lx\n", bitmap_start + failsafe_blocks + sb->s_blocksize); goto out; } } num_blocks = (maxsize - bitmap_start) >> sb->s_blocksize_bits; num_blocks -= pram_get_failsafe_blocks_count(sb); /* calc the data blocks in-use bitmap size in bytes */ if (num_blocks & 7) bitmap_size = ((num_blocks + 8) & ~7) >> 3; else bitmap_size = num_blocks >> 3; /* round it up to the nearest blocksize boundary */ if (bitmap_size & (blocksize - 1)) bitmap_size = (bitmap_size + blocksize) & ~(blocksize-1); pram_info("blocksize %lu, num inodes %lu, num blocks %lu\n", blocksize, num_inodes, num_blocks); pram_dbg("bitmap start 0x%08lx, bitmap size %lu\n", (unsigned long)bitmap_start, bitmap_size); pram_dbg("max name length %d\n", PRAM_NAME_LEN);#ifdef CONFIG_PRAMFS_FAILSAFE pram_dbg("num failsafe blocks %lu\n", pram_get_failsafe_blocks_count(sb));#endif super = pram_get_super(sb); pram_lock_range(sb, super, PRAM_SB_SIZE); /* no use lock_super! */ memset(super, 0, PRAM_SB_SIZE); super->s_size = maxsize; super->s_blocksize = blocksize; super->s_inodes_count = num_inodes; pram_set_free_inodes_count(sb, num_inodes - 1); pram_set_free_inode_hint(sb, 1); super->s_blocks_count = num_blocks; super->s_bitmap_blocks = bitmap_size >> sb->s_blocksize_bits; pram_set_free_blocks_count(sb, num_blocks - super->s_bitmap_blocks); super->s_bitmap_start = bitmap_start; pram_unlock_range(sb, super, PRAM_SB_SIZE); /* clear out inode table */ { unsigned long i = PRAM_SB_SIZE; while (i < bitmap_start) { void *inode = (u8 *)super + i; pram_lock_range(sb, inode, PRAM_INODE_SIZE); memset(inode, 0, PRAM_INODE_SIZE); pram_unlock_range(sb, inode, PRAM_INODE_SIZE); i += PRAM_INODE_SIZE; } } root_i = pram_get_inode(sb, PRAM_ROOT_INO); pram_lock_range(sb, root_i, PRAM_INODE_SIZE); /* no use lock_inode! */ root_i->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR; root_i->i_links_count = 2; root_i->i_d.d_parent = PRAM_ROOT_INO; pram_sync_inode(root_i); pram_unlock_range(sb, root_i, PRAM_INODE_SIZE); pram_lock_range(sb, pram_get_bitmap(sb), bitmap_size); pram_init_bitmap(sb); pram_unlock_range(sb, pram_get_bitmap(sb), bitmap_size); /* set magic in the end, make sure every thing is fine */ pram_lock_range(sb, super, PRAM_SB_SIZE); /* no use lock_super! */ super->s_magic = PRAM_SUPER_MAGIC; pram_sync_super(super); pram_unlock_range(sb, super, PRAM_SB_SIZE); *superp = super; *root_ip = root_i; retval = 0;out: return retval;}#ifdef CONFIG_PRAMFS_FAILSAFEstatic void inline pram_do_powerfail_restore(struct super_block * sb, struct pram_super_block * super){ __u32 count, i; pram_powerfail_restore(sb); pram_fsck(sb); /* update fbi's free_inode*, free_block* data */ for (count = 0, i = 1; i < super->s_inodes_count; i++) { ino_t ino = PRAM_ROOT_INO + (i << PRAM_INODE_BITS); struct pram_inode * pi = pram_get_inode(sb, ino); if (pram_inode_is_free(pi)) count++; } pram_set_free_inodes_count(sb, count); pram_set_free_inode_hint(sb, 1); count = bitmap_weight(pram_get_bitmap(sb), super->s_blocks_count); count = super->s_blocks_count - count; pram_set_free_blocks_count(sb, count); pram_info("free inodes %d free blocks %d\n", pram_get_free_inodes_count(sb), pram_get_free_blocks_count(sb));}#elsestatic void inline pram_do_powerfail_restore(struct super_block * sb, struct pram_super_block * super) {}#endifstatic inline intfill_super(struct super_block * sb, void * data, struct pram_sb_info * sbi, struct pram_super_block ** superp, struct pram_inode ** root_ip){ int retval = -EINVAL; struct pram_super_block * super; struct pram_inode * root_i; pram_off_t root_offset; unsigned long maxsize, blocksize; pram_info("checking physical address 0x%lx for pramfs image\n", sbi->phys_addr); /* Map only one page for now. Will remap it when fs size is known. */ sbi->virt_addr = pram_ioremap(sbi, sbi->phys_addr, PAGE_SIZE); if (!sbi->virt_addr) { pram_err("ioremap of the pramfs image failed\n"); goto out; } super = pram_get_super(sb); /* Do sanity checks on the superblock */ if (super->s_magic != PRAM_SUPER_MAGIC) { pram_err("wrong magic\n"); goto out; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -