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

📄 inode.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/fs/affs/inode.c * *  (c) 1996  Hans-Joachim Widmaier - Rewritten * *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem. *  *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem. * *  (C) 1991  Linus Torvalds - minix filesystem */#include <linux/module.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/malloc.h>#include <linux/stat.h>#include <linux/sched.h>#include <linux/affs_fs.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/string.h>#include <linux/locks.h>#include <linux/errno.h>#include <linux/genhd.h>#include <linux/amigaffs.h>#include <linux/major.h>#include <linux/blkdev.h>#include <asm/system.h>#include <asm/segment.h>extern int *blk_size[];extern struct timezone sys_tz;#define MIN(a,b) (((a)<(b))?(a):(b))voidaffs_put_super(struct super_block *sb){	int	 i;	pr_debug("affs_put_super()\n");	lock_super(sb);	for (i = 0; i < sb->u.affs_sb.s_bm_count; i++)		affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh);	if (!(sb->s_flags & MS_RDONLY)) {		ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = htonl(1);		secs_to_datestamp(CURRENT_TIME,				  &ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered);		affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5);		mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1);	}	if (sb->u.affs_sb.s_flags & SF_PREFIX)		kfree(sb->u.affs_sb.s_prefix);	kfree(sb->u.affs_sb.s_bitmap);	affs_brelse(sb->u.affs_sb.s_root_bh);	/* I'm not happy with this. It would be better to save the previous	 * value of this devices blksize_size[][] in the super block and	 * restore it here, but with the affs superblock being quite large	 * already ...	 */	set_blocksize(sb->s_dev,BLOCK_SIZE);	sb->s_dev = 0;	unlock_super(sb);	MOD_DEC_USE_COUNT;	return;}static voidaffs_write_super(struct super_block *sb){	int	 i, clean = 2;	if (!(sb->s_flags & MS_RDONLY)) {		lock_super(sb);		for (i = 0, clean = 1; i < sb->u.affs_sb.s_bm_count; i++) {			if (sb->u.affs_sb.s_bitmap[i].bm_bh) {				if (buffer_dirty(sb->u.affs_sb.s_bitmap[i].bm_bh)) {					clean = 0;					break;				}			}		}		unlock_super(sb);		ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = htonl(clean);		secs_to_datestamp(CURRENT_TIME,				  &ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered);		affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5);		mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1);		sb->s_dirt = !clean;	/* redo until bitmap synced */	} else		sb->s_dirt = 0;	pr_debug("AFFS: write_super() at %d, clean=%d\n",CURRENT_TIME,clean);}static struct super_operations affs_sops = { 	affs_read_inode,	affs_notify_change,	affs_write_inode,	affs_put_inode,		affs_put_super,	affs_write_super,	affs_statfs,	NULL			/* remount */};intaffs_parent_ino(struct inode *dir){	int root_ino = (dir->i_sb->u.affs_sb.s_root_block);	if (!S_ISDIR (dir->i_mode)) {		printk ("affs_parent_ino: argument is not a directory\n");		return root_ino;	}	if (dir->i_ino == root_ino)		return root_ino;	return dir->u.affs_i.i_parent;}static intparse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, int *root,		int *blocksize, char **prefix, char *volume, unsigned long *mount_opts){	char	*this_char, *value;	int	 f;	/* Fill in defaults */	*uid        = 0;	*gid        = 0;	*reserved   = 2;	*root       = -1;	*blocksize  = -1;	*prefix     = "/";	volume[0]   = ':';	volume[1]   = 0;	*mount_opts = 0;	if (!options)		return 1;	for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {		f = 0;		if ((value = strchr(this_char,'=')) != NULL)			*value++ = 0;		if (!strcmp(this_char,"protect")) {			if (value) {				printk("AFFS: option protect does not take an argument\n");				return 0;			}			*mount_opts |= SF_IMMUTABLE;		}		else if (!strcmp(this_char,"verbose")) {			if (value) {				printk("AFFS: option verbose does not take an argument\n");				return 0;			}			*mount_opts |= SF_VERBOSE;		}		else if ((f = !strcmp(this_char,"uid")) || !strcmp(this_char,"setuid")) {			if (!value)				*uid = current->uid;			else if (!*value) {				printk("AFFS: argument for uid option missing\n");				return 0;			} else {				*uid = simple_strtoul(value,&value,0);				if (*value)					return 0;				if (!f)					*mount_opts |= SF_SETUID;			}		}		else if ((f = !strcmp(this_char,"gid")) || !strcmp(this_char,"setgid")) {			if (!value)				*gid = current->gid;			else if (!*value) {				printk("AFFS: argument for gid option missing\n");				return 0;			} else {				*gid = simple_strtoul(value,&value,0);				if (*value)					return 0;				if (!f)					*mount_opts |= SF_SETGID;			}		}		else if (!strcmp(this_char,"prefix")) {			if (!value) {				printk("AFFS: The prefix option requires an argument\n");				return 0;			}			*prefix = kmalloc(strlen(value) + 1,GFP_KERNEL);			if (!*prefix)				return 0;			strcpy(*prefix,value);			*mount_opts |= SF_PREFIX;		}		else if (!strcmp(this_char,"volume")) {			if (!value) {				printk("AFFS: The volume option requires an argument\n");				return 0;			}			if (strlen(value) > 30)				value[30] = 0;			strcpy(volume,value);		}		else if (!strcmp(this_char,"mode")) {			if (!value || !*value) {				printk("AFFS: The mode option requires an argument\n");				return 0;			}			*mode = simple_strtoul(value,&value,8) & 0777;			if (*value)				return 0;			*mount_opts |= SF_SETMODE;		}		else if (!strcmp(this_char,"reserved")) {			if (!value || !*value) {				printk("AFFS: The reserved option requires an argument\n");				return 0;			}			*reserved = simple_strtoul(value,&value,0);			if (*value)				return 0;		}		else if (!strcmp(this_char,"root")) {			if (!value || !*value) {				printk("AFFS: The root option requires an argument\n");				return 0;			}			*root = simple_strtoul(value,&value,0);			if (*value)				return 0;		}		else if (!strcmp(this_char,"bs")) {			if (!value || !*value) {				printk("AFFS: The bs option requires an argument\n");				return 0;			}			*blocksize = simple_strtoul(value,&value,0);			if (*value)				return 0;			if (*blocksize != 512 && *blocksize != 1024 && *blocksize != 2048			    && *blocksize != 4096) {				printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed).\n");				return 0;			}		}		/* Silently ignore the quota options */		else if (!strcmp (this_char, "grpquota")			 || !strcmp (this_char, "noquota")			 || !strcmp (this_char, "quota")			 || !strcmp (this_char, "usrquota"))			;		else {			printk("AFFS: Unrecognized mount option %s\n", this_char);			return 0;		}	}	return 1;}/* This function definitely needs to be split up. Some fine day I'll * hopefully have the guts to do so. Until then: sorry for the mess. */struct super_block *affs_read_super(struct super_block *s,void *data, int silent){	struct buffer_head	*bh = NULL;	struct buffer_head	*bb;	kdev_t			 dev = s->s_dev;	int			 root_block;	int			 size;	__u32			 chksum;	__u32			*bm;	int			 ptype, stype;	int			 mapidx;	int			 num_bm;	int			 i, j;	int			 key;	int			 blocksize;	uid_t			 uid;	gid_t			 gid;	int			 reserved;	int			 az_no;	unsigned long		 mount_flags;	unsigned long		 offset;	pr_debug("affs_read_super(%s)\n",data ? (const char *)data : "no options");	MOD_INC_USE_COUNT;	if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,	    &blocksize,&s->u.affs_sb.s_prefix,s->u.affs_sb.s_volume,&mount_flags)) {		s->s_dev = 0;		printk("AFFS: error parsing options.\n");		MOD_DEC_USE_COUNT;		return NULL;	}	lock_super(s);	/* Get the size of the device in 512-byte blocks.	 * If we later see that the partition uses bigger	 * blocks, we will have to change it.	 */	size = blksize_size[MAJOR(dev)][MINOR(dev)];	size = (size ? size : BLOCK_SIZE) / 512 * blk_size[MAJOR(dev)][MINOR(dev)];	s->u.affs_sb.s_bitmap  = NULL;	s->u.affs_sb.s_root_bh = NULL;	s->u.affs_sb.s_flags   = mount_flags;	s->u.affs_sb.s_mode    = i;	s->u.affs_sb.s_uid     = uid;	s->u.affs_sb.s_gid     = gid;	if (size == 0) {		s->s_dev = 0;		unlock_super(s);		printk("affs_read_super: could not determine device size\n");		goto out;	}	s->u.affs_sb.s_partition_size = size;	s->u.affs_sb.s_reserved       = reserved;	/* Try to find root block. Its location may depend on the block size. */	s->u.affs_sb.s_hashsize = 0;	if (blocksize > 0) {		chksum = blocksize;		num_bm = blocksize;	} else {		chksum = 512;		num_bm = 4096;	}	for (blocksize = chksum; blocksize <= num_bm; blocksize <<= 1, size >>= 1) {		if (root_block < 0)			s->u.affs_sb.s_root_block = (reserved + size - 1) / 2;		else			s->u.affs_sb.s_root_block = root_block;		pr_debug("Trying bs=%d bytes, root at %d, size=%d blocks (%d reserved)\n",			 blocksize,s->u.affs_sb.s_root_block,size,reserved);		set_blocksize(dev,blocksize);		bh = affs_bread(dev,s->u.affs_sb.s_root_block,blocksize);		if (!bh) {			printk("AFFS: unable to read root block\n");			goto out;		}		if (!affs_checksum_block(blocksize,bh->b_data,&ptype,&stype) &&		    ptype == T_SHORT && stype == ST_ROOT) {			s->s_blocksize          = blocksize;			s->u.affs_sb.s_hashsize = blocksize / 4 - 56;			break;		}		affs_brelse(bh);		bh = NULL;	}	if (!s->u.affs_sb.s_hashsize) {		affs_brelse(bh);		if (!silent)			printk("AFFS: Can't find a valid root block on device %s\n",kdevname(dev));		goto out;	}	root_block = s->u.affs_sb.s_root_block;	s->u.affs_sb.s_partition_size   = size;	s->s_blocksize_bits             = blocksize == 512 ? 9 :					  blocksize == 1024 ? 10 :					  blocksize == 2048 ? 11 : 12;	/* Find out which kind of FS we have */	bb = affs_bread(dev,0,s->s_blocksize);	if (bb) {		chksum = htonl(*(__u32 *)bb->b_data);		/* Dircache filesystems are compatible with non-dircache ones		 * when reading. As long as they aren't supported, writing is		 * not recommended.		 */		if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS		     || chksum == MUFS_DCOFS) && !(s->s_flags & MS_RDONLY)) {			printk("AFFS: Dircache FS - mounting %s read only.\n",kdevname(dev));			s->s_flags |= MS_RDONLY;		}		switch (chksum) {			case MUFS_FS:			case MUFS_INTLFFS:				s->u.affs_sb.s_flags |= SF_MUFS;				/* fall thru */			case FS_INTLFFS:				s->u.affs_sb.s_flags |= SF_INTL;				break;			case MUFS_DCFFS:			case MUFS_FFS:				s->u.affs_sb.s_flags |= SF_MUFS;				break;			case FS_DCFFS:			case FS_FFS:				break;			case MUFS_OFS:				s->u.affs_sb.s_flags |= SF_MUFS;				/* fall thru */			case FS_OFS:				s->u.affs_sb.s_flags |= SF_OFS;				break;			case MUFS_DCOFS:			case MUFS_INTLOFS:				s->u.affs_sb.s_flags |= SF_MUFS;			case FS_DCOFS:			case FS_INTLOFS:				s->u.affs_sb.s_flags |= SF_INTL | SF_OFS;				break;			default:				printk("AFFS: Unknown filesystem on device %s: %08X\n",				       kdevname(dev),chksum);				affs_brelse(bb);				goto out;		}		affs_brelse(bb);	} else {		printk("AFFS: Can't get boot block.\n");		goto out;	}	if (mount_flags & SF_VERBOSE) {		chksum = ntohl(chksum);		printk("AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n",		       GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0],		       &GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1],		       (char *)&chksum,((char *)&chksum)[3] + '0',blocksize);	}	s->s_magic  = AFFS_SUPER_MAGIC;	s->s_flags |= MS_NODEV | MS_NOSUID;	/* Keep super block in cache */	if (!(s->u.affs_sb.s_root_bh = affs_bread(dev,root_block,s->s_blocksize))) {		printk("AFFS: Can't read root block a second time\n");		goto out;	}	/* Allocate space for bitmaps, zones and others */	size   = s->u.affs_sb.s_partition_size - reserved;	num_bm = (size + s->s_blocksize * 8 - 32 - 1) / (s->s_blocksize * 8 - 32);	az_no  = (size + AFFS_ZONE_SIZE - 1) / (AFFS_ZONE_SIZE - 32);	ptype  = num_bm * sizeof(struct affs_bm_info) + 		 az_no * sizeof(struct affs_alloc_zone) +		 MAX_ZONES * sizeof(struct affs_zone);	pr_debug("num_bm=%d, az_no=%d, sum=%d\n",num_bm,az_no,ptype);	if (!(s->u.affs_sb.s_bitmap = kmalloc(ptype,GFP_KERNEL))) {		printk("AFFS: Not enough memory.\n");		goto out;	}	memset(s->u.affs_sb.s_bitmap,0,ptype);	s->u.affs_sb.s_zones   = (struct affs_zone *)&s->u.affs_sb.s_bitmap[num_bm];	s->u.affs_sb.s_alloc   = (struct affs_alloc_zone *)&s->u.affs_sb.s_zones[MAX_ZONES];	s->u.affs_sb.s_num_az  = az_no;	mapidx = 0;	if (ROOT_END_S(bh->b_data,s)->bm_flag == 0) {		if (!(s->s_flags & MS_RDONLY)) {			printk("AFFS: Bitmap invalid - mounting %s read only.\n",kdevname(dev));			s->s_flags |= MS_RDONLY;		}		affs_brelse(bh);		bh = NULL;		goto nobitmap;	}	/* The following section is ugly, I know. Especially because of the	 * reuse of some variables that are not named properly.	 */	key    = root_block;	ptype  = s->s_blocksize / 4 - 49;	stype  = ptype + 25;	offset = s->u.affs_sb.s_reserved;	az_no  = 0;	while (bh) {		bm = (__u32 *)bh->b_data;		for (i = ptype; i < stype && bm[i]; i++, mapidx++) {			if (mapidx >= num_bm) {				printk("AFFS: Not enough bitmap space!?\n");				goto out;			}			bb = affs_bread(s->s_dev,htonl(bm[i]),s->s_blocksize);			if (bb) {				if (affs_checksum_block(s->s_blocksize,bb->b_data,NULL,NULL) &&				    !(s->s_flags & MS_RDONLY)) {					printk("AFFS: Bitmap (%d,key=%lu) invalid - "

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -