⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 super.c

📁 嵌入式linux下基于SRAM的内存文件系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 + -