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

📄 fs.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * JFFS2 -- Journalling Flash File System, Version 2. * * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse <dwmw2@infradead.org> * * For licensing information, see the file 'LICENCE' in this directory. * */#include <linux/capability.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/list.h>#include <linux/mtd/mtd.h>#include <linux/pagemap.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/vfs.h>#include <linux/crc32.h>#include "nodelist.h"static int jffs2_flash_setup(struct jffs2_sb_info *c);int jffs2_do_setattr (struct inode *inode, struct iattr *iattr){	struct jffs2_full_dnode *old_metadata, *new_metadata;	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);	struct jffs2_raw_inode *ri;	union jffs2_device_node dev;	unsigned char *mdata = NULL;	int mdatalen = 0;	unsigned int ivalid;	uint32_t alloclen;	int ret;	D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino));	/* Special cases - we don't want more than one data node	   for these types on the medium at any time. So setattr	   must read the original data associated with the node	   (i.e. the device numbers or the target name) and write	   it out again with the appropriate data attached */	if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {		/* For these, we don't actually need to read the old node */		mdatalen = jffs2_encode_dev(&dev, inode->i_rdev);		mdata = (char *)&dev;		D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));	} else if (S_ISLNK(inode->i_mode)) {		down(&f->sem);		mdatalen = f->metadata->size;		mdata = kmalloc(f->metadata->size, GFP_USER);		if (!mdata) {			up(&f->sem);			return -ENOMEM;		}		ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen);		if (ret) {			up(&f->sem);			kfree(mdata);			return ret;		}		up(&f->sem);		D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen));	}	ri = jffs2_alloc_raw_inode();	if (!ri) {		if (S_ISLNK(inode->i_mode))			kfree(mdata);		return -ENOMEM;	}	ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &alloclen,				  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);	if (ret) {		jffs2_free_raw_inode(ri);		if (S_ISLNK(inode->i_mode & S_IFMT))			 kfree(mdata);		return ret;	}	down(&f->sem);	ivalid = iattr->ia_valid;	ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);	ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);	ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen);	ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));	ri->ino = cpu_to_je32(inode->i_ino);	ri->version = cpu_to_je32(++f->highest_version);	ri->uid = cpu_to_je16((ivalid & ATTR_UID)?iattr->ia_uid:inode->i_uid);	ri->gid = cpu_to_je16((ivalid & ATTR_GID)?iattr->ia_gid:inode->i_gid);	if (ivalid & ATTR_MODE)		if (iattr->ia_mode & S_ISGID &&		    !in_group_p(je16_to_cpu(ri->gid)) && !capable(CAP_FSETID))			ri->mode = cpu_to_jemode(iattr->ia_mode & ~S_ISGID);		else			ri->mode = cpu_to_jemode(iattr->ia_mode);	else		ri->mode = cpu_to_jemode(inode->i_mode);	ri->isize = cpu_to_je32((ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size);	ri->atime = cpu_to_je32(I_SEC((ivalid & ATTR_ATIME)?iattr->ia_atime:inode->i_atime));	ri->mtime = cpu_to_je32(I_SEC((ivalid & ATTR_MTIME)?iattr->ia_mtime:inode->i_mtime));	ri->ctime = cpu_to_je32(I_SEC((ivalid & ATTR_CTIME)?iattr->ia_ctime:inode->i_ctime));	ri->offset = cpu_to_je32(0);	ri->csize = ri->dsize = cpu_to_je32(mdatalen);	ri->compr = JFFS2_COMPR_NONE;	if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {		/* It's an extension. Make it a hole node */		ri->compr = JFFS2_COMPR_ZERO;		ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size);		ri->offset = cpu_to_je32(inode->i_size);	}	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));	if (mdatalen)		ri->data_crc = cpu_to_je32(crc32(0, mdata, mdatalen));	else		ri->data_crc = cpu_to_je32(0);	new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, ALLOC_NORMAL);	if (S_ISLNK(inode->i_mode))		kfree(mdata);	if (IS_ERR(new_metadata)) {		jffs2_complete_reservation(c);		jffs2_free_raw_inode(ri);		up(&f->sem);		return PTR_ERR(new_metadata);	}	/* It worked. Update the inode */	inode->i_atime = ITIME(je32_to_cpu(ri->atime));	inode->i_ctime = ITIME(je32_to_cpu(ri->ctime));	inode->i_mtime = ITIME(je32_to_cpu(ri->mtime));	inode->i_mode = jemode_to_cpu(ri->mode);	inode->i_uid = je16_to_cpu(ri->uid);	inode->i_gid = je16_to_cpu(ri->gid);	old_metadata = f->metadata;	if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size)		jffs2_truncate_fragtree (c, &f->fragtree, iattr->ia_size);	if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {		jffs2_add_full_dnode_to_inode(c, f, new_metadata);		inode->i_size = iattr->ia_size;		f->metadata = NULL;	} else {		f->metadata = new_metadata;	}	if (old_metadata) {		jffs2_mark_node_obsolete(c, old_metadata->raw);		jffs2_free_full_dnode(old_metadata);	}	jffs2_free_raw_inode(ri);	up(&f->sem);	jffs2_complete_reservation(c);	/* We have to do the vmtruncate() without f->sem held, since	   some pages may be locked and waiting for it in readpage().	   We are protected from a simultaneous write() extending i_size	   back past iattr->ia_size, because do_truncate() holds the	   generic inode semaphore. */	if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size)		vmtruncate(inode, iattr->ia_size);	return 0;}int jffs2_setattr(struct dentry *dentry, struct iattr *iattr){	int rc;	rc = inode_change_ok(dentry->d_inode, iattr);	if (rc)		return rc;	rc = jffs2_do_setattr(dentry->d_inode, iattr);	if (!rc && (iattr->ia_valid & ATTR_MODE))		rc = jffs2_acl_chmod(dentry->d_inode);	return rc;}int jffs2_statfs(struct dentry *dentry, struct kstatfs *buf){	struct jffs2_sb_info *c = JFFS2_SB_INFO(dentry->d_sb);	unsigned long avail;	buf->f_type = JFFS2_SUPER_MAGIC;	buf->f_bsize = 1 << PAGE_SHIFT;	buf->f_blocks = c->flash_size >> PAGE_SHIFT;	buf->f_files = 0;	buf->f_ffree = 0;	buf->f_namelen = JFFS2_MAX_NAME_LEN;	spin_lock(&c->erase_completion_lock);	avail = c->dirty_size + c->free_size;	if (avail > c->sector_size * c->resv_blocks_write)		avail -= c->sector_size * c->resv_blocks_write;	else		avail = 0;	spin_unlock(&c->erase_completion_lock);	buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT;	return 0;}void jffs2_clear_inode (struct inode *inode){	/* We can forget about this inode for now - drop all	 *  the nodelists associated with it, etc.	 */	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);	D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode));	jffs2_do_clear_inode(c, f);}void jffs2_read_inode (struct inode *inode){	struct jffs2_inode_info *f;	struct jffs2_sb_info *c;	struct jffs2_raw_inode latest_node;	union jffs2_device_node jdev;	dev_t rdev = 0;	int ret;	D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino));	f = JFFS2_INODE_INFO(inode);	c = JFFS2_SB_INFO(inode->i_sb);	jffs2_init_inode_info(f);	down(&f->sem);	ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);	if (ret) {		make_bad_inode(inode);		up(&f->sem);		return;	}	inode->i_mode = jemode_to_cpu(latest_node.mode);	inode->i_uid = je16_to_cpu(latest_node.uid);	inode->i_gid = je16_to_cpu(latest_node.gid);	inode->i_size = je32_to_cpu(latest_node.isize);	inode->i_atime = ITIME(je32_to_cpu(latest_node.atime));	inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime));	inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime));	inode->i_nlink = f->inocache->nlink;	inode->i_blocks = (inode->i_size + 511) >> 9;	switch (inode->i_mode & S_IFMT) {	case S_IFLNK:		inode->i_op = &jffs2_symlink_inode_operations;		break;	case S_IFDIR:	{		struct jffs2_full_dirent *fd;		for (fd=f->dents; fd; fd = fd->next) {			if (fd->type == DT_DIR && fd->ino)				inc_nlink(inode);		}		/* and '..' */		inc_nlink(inode);		/* Root dir gets i_nlink 3 for some reason */		if (inode->i_ino == 1)			inc_nlink(inode);		inode->i_op = &jffs2_dir_inode_operations;		inode->i_fop = &jffs2_dir_operations;		break;	}	case S_IFREG:		inode->i_op = &jffs2_file_inode_operations;		inode->i_fop = &jffs2_file_operations;		inode->i_mapping->a_ops = &jffs2_file_address_operations;		inode->i_mapping->nrpages = 0;		break;	case S_IFBLK:	case S_IFCHR:		/* Read the device numbers from the media */		if (f->metadata->size != sizeof(jdev.old) &&		    f->metadata->size != sizeof(jdev.new)) {			printk(KERN_NOTICE "Device node has strange size %d\n", f->metadata->size);			up(&f->sem);			jffs2_do_clear_inode(c, f);			make_bad_inode(inode);			return;		}		D1(printk(KERN_DEBUG "Reading device numbers from flash\n"));		if (jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size) < 0) {			/* Eep */			printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino);			up(&f->sem);			jffs2_do_clear_inode(c, f);			make_bad_inode(inode);			return;		}		if (f->metadata->size == sizeof(jdev.old))			rdev = old_decode_dev(je16_to_cpu(jdev.old));		else			rdev = new_decode_dev(je32_to_cpu(jdev.new));	case S_IFSOCK:	case S_IFIFO:		inode->i_op = &jffs2_file_inode_operations;		init_special_inode(inode, inode->i_mode, rdev);		break;	default:		printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu\n", inode->i_mode, (unsigned long)inode->i_ino);	}	up(&f->sem);	D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));}void jffs2_dirty_inode(struct inode *inode){	struct iattr iattr;	if (!(inode->i_state & I_DIRTY_DATASYNC)) {		D2(printk(KERN_DEBUG "jffs2_dirty_inode() not calling setattr() for ino #%lu\n", inode->i_ino));		return;	}	D1(printk(KERN_DEBUG "jffs2_dirty_inode() calling setattr() for ino #%lu\n", inode->i_ino));	iattr.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_MTIME|ATTR_CTIME;	iattr.ia_mode = inode->i_mode;	iattr.ia_uid = inode->i_uid;	iattr.ia_gid = inode->i_gid;	iattr.ia_atime = inode->i_atime;	iattr.ia_mtime = inode->i_mtime;	iattr.ia_ctime = inode->i_ctime;

⌨️ 快捷键说明

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