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

📄 intrep.c

📁 mtd最新cvs jffs文件系统分析
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Get data and size if there is any */	if (raw_inode->dsize) {		node_iovec[iovec_cnt].iov_base = (void *) data;		node_iovec[iovec_cnt].iov_len = (size_t) raw_inode->dsize;		iovec_cnt++;		/* No need to pad this because we're not actually putting		   anything after it.		*/	}	if ((err = flash_safe_writev(fmc->mtd, node_iovec, iovec_cnt,				    pos) < 0)) {		jffs_fmfree_partly(fmc, fm, 0);		jffs_fm_write_unlock(fmc);		printk(KERN_ERR "JFFS: jffs_write_node: Failed to write, "		       "requested %i, wrote %i\n", total_size, err);		goto retry;	}	if (raw_inode->deleted)		f->deleted = 1;	jffs_fm_write_unlock(fmc);	D3(printk("jffs_write_node(): Leaving...\n"));	return raw_inode->dsize;} /* jffs_write_node()  *//* Read data from the node and write it to the buffer.  'node_offset'   is how much we have read from this particular node before and which   shouldn't be read again.  'max_size' is how much space there is in   the buffer.  */static intjffs_get_node_data(struct jffs_file *f, struct jffs_node *node, 		   unsigned char *buf,__u32 node_offset, __u32 max_size,		   kdev_t dev){	struct jffs_fmcontrol *fmc = f->c->fmc;	__u32 pos = node->fm->offset + node->fm_offset + node_offset;	__u32 avail = node->data_size - node_offset;	__u32 r;	D2(printk("  jffs_get_node_data(): file: \"%s\", ino: %u, "		  "version: %u, node_offset: %u\n",		  f->name, node->ino, node->version, node_offset));	r = min(avail, max_size);	D3(printk(KERN_NOTICE "jffs_get_node_data\n"));	flash_safe_read(fmc->mtd, pos, buf, r);	D3(printk("  jffs_get_node_data(): Read %u byte%s.\n",		  r, (r == 1 ? "" : "s")));	return r;}/* Read data from the file's nodes.  Write the data to the buffer   'buf'.  'read_offset' tells how much data we should skip.  */intjffs_read_data(struct jffs_file *f, unsigned char *buf, __u32 read_offset,	       __u32 size){	struct jffs_node *node;	__u32 read_data = 0; /* Total amount of read data.  */	__u32 node_offset = 0;	__u32 pos = 0; /* Number of bytes traversed.  */	D2(printk("jffs_read_data(): file = \"%s\", read_offset = %d, "		  "size = %u\n",		  (f->name ? f->name : ""), read_offset, size));	if (read_offset >= f->size) {		D(printk("  f->size: %d\n", f->size));		return 0;	}	/* First find the node to read data from.  */	node = f->range_head;	while (pos <= read_offset) {		node_offset = read_offset - pos;		if (node_offset >= node->data_size) {			pos += node->data_size;			node = node->range_next;		}		else {			break;		}	}	/* "Cats are living proof that not everything in nature	   has to be useful."	   - Garrison Keilor ('97)  */	/* Fill the buffer.  */	while (node && (read_data < size)) {		int r;		if (!node->fm) {			/* This node does not refer to real data.  */			r = min(size - read_data,				     node->data_size - node_offset);			memset(&buf[read_data], 0, r);		}		else if ((r = jffs_get_node_data(f, node, &buf[read_data],						 node_offset,						 size - read_data,						 f->c->sb->s_dev)) < 0) {			return r;		}		read_data += r;		node_offset = 0;		node = node->range_next;	}	D3(printk("  jffs_read_data(): Read %u bytes.\n", read_data));	return read_data;}/* Used for traversing all nodes in the hash table.  */intjffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *)){	int pos;	int r;	int result = 0;	for (pos = 0; pos < c->hash_len; pos++) {		struct list_head *p, *next;		for (p = c->hash[pos].next; p != &c->hash[pos]; p = next) {			/* We need a reference to the next file in the			   list because `func' might remove the current			   file `f'.  */			next = p->next;			r = func(list_entry(p, struct jffs_file, hash));			if (r < 0)				return r;			result += r;		}	}	return result;}/* Free all nodes associated with a file.  */intjffs_free_node_list(struct jffs_file *f){	struct jffs_node *node;	struct jffs_node *p;	D3(printk("jffs_free_node_list(): f #%u, \"%s\"\n",		  f->ino, (f->name ? f->name : "")));	node = f->version_head;	while (node) {		p = node;		node = node->version_next;		jffs_free_node(p);		DJM(no_jffs_node--);	}	return 0;}/* Free a file and its name.  */intjffs_free_file(struct jffs_file *f){	D3(printk("jffs_free_file: f #%u, \"%s\"\n",		  f->ino, (f->name ? f->name : "")));	if (f->name) {		kfree(f->name);		DJM(no_name--);	}	kfree(f);	no_jffs_file--;	return 0;}longjffs_get_file_count(void){	return no_jffs_file;}/* See if a file is deleted. If so, mark that file's nodes as obsolete.  */intjffs_possibly_delete_file(struct jffs_file *f){	struct jffs_node *n;	D3(printk("jffs_possibly_delete_file(): ino: %u\n",		  f->ino));	ASSERT(if (!f) {		printk(KERN_ERR "jffs_possibly_delete_file(): f == NULL\n");		return -1;	});	if (f->deleted) {		/* First try to remove all older versions.  Commence with		   the oldest node.  */		for (n = f->version_head; n; n = n->version_next) {			if (!n->fm) {				continue;			}			if (jffs_fmfree(f->c->fmc, n->fm, n) < 0) {				break;			}		}		/* Unlink the file from the filesystem.  */		if (!f->c->building_fs) {			jffs_unlink_file_from_tree(f);		}		jffs_unlink_file_from_hash(f);		jffs_free_node_list(f);		jffs_free_file(f);	}	return 0;}/* Used in conjunction with jffs_foreach_file() to count the number   of files in the file system.  */intjffs_file_count(struct jffs_file *f){	return 1;}/* Build up a file's range list from scratch by going through the   version list.  */intjffs_build_file(struct jffs_file *f){	struct jffs_node *n;	D3(printk("jffs_build_file(): ino: %u, name: \"%s\"\n",		  f->ino, (f->name ? f->name : "")));	for (n = f->version_head; n; n = n->version_next) {		jffs_update_file(f, n);	}	return 0;}/* Remove an amount of data from a file. If this amount of data is   zero, that could mean that a node should be split in two parts.   We remove or change the appropriate nodes in the lists.   Starting offset of area to be removed is node->data_offset,   and the length of the area is in node->removed_size.   */static intjffs_delete_data(struct jffs_file *f, struct jffs_node *node){	struct jffs_node *n;	__u32 offset = node->data_offset;	__u32 remove_size = node->removed_size;	D3(printk("jffs_delete_data(): offset = %u, remove_size = %u\n",		  offset, remove_size));	if (remove_size == 0	    && f->range_tail	    && f->range_tail->data_offset + f->range_tail->data_size	       == offset) {		/* A simple append; nothing to remove or no node to split.  */		return 0;	}	/* Find the node where we should begin the removal.  */	for (n = f->range_head; n; n = n->range_next) {		if (n->data_offset + n->data_size > offset) {			break;		}	}	if (!n) {		/* If there's no data in the file there's no data to		   remove either.  */		return 0;	}	if (n->data_offset > offset) {		/* XXX: Not implemented yet.  */		printk(KERN_WARNING "JFFS: An unexpected situation "		       "occurred in jffs_delete_data.\n");	}	else if (n->data_offset < offset) {		/* See if the node has to be split into two parts.  */		if (n->data_offset + n->data_size > offset + remove_size) {			/* Do the split.  */			struct jffs_node *new_node;			D3(printk("jffs_delete_data(): Split node with "				  "version number %u.\n", n->version));			if (!(new_node = jffs_alloc_node())) {				D(printk("jffs_delete_data(): -ENOMEM\n"));				return -ENOMEM;			}			DJM(no_jffs_node++);			new_node->ino = n->ino;			new_node->version = n->version;			new_node->data_offset = offset;			new_node->data_size = n->data_size - (remove_size + (offset - n->data_offset));			new_node->fm_offset = n->fm_offset + (remove_size + (offset - n->data_offset));			new_node->name_size = n->name_size;			new_node->fm = n->fm;			new_node->version_prev = n;			new_node->version_next = n->version_next;			if (new_node->version_next) {				new_node->version_next->version_prev				= new_node;			}			else {				f->version_tail = new_node;			}			n->version_next = new_node;			new_node->range_prev = n;			new_node->range_next = n->range_next;			if (new_node->range_next) {				new_node->range_next->range_prev = new_node;			}			else {				f->range_tail = new_node;			}			/* A very interesting can of worms.  */			n->range_next = new_node;			n->data_size = offset - n->data_offset;			if (new_node->fm)				jffs_add_node(new_node);			else {				D1(printk(KERN_WARNING "jffs_delete_data(): Splitting an empty node (file hold).\n!"));				D1(printk(KERN_WARNING "FIXME: Did dwmw2 do the right thing here?\n"));			}			n = new_node->range_next;			remove_size = 0;		}		else {			/* No.  No need to split the node.  Just remove			   the end of the node.  */			int r = min(n->data_offset + n->data_size					 - offset, remove_size);			n->data_size -= r;			remove_size -= r;			n = n->range_next;		}	}	/* Remove as many nodes as necessary.  */	while (n && remove_size) {		if (n->data_size <= remove_size) {			struct jffs_node *p = n;			remove_size -= n->data_size;			n = n->range_next;			D3(printk("jffs_delete_data(): Removing node: "				  "ino: %u, version: %u%s\n",				  p->ino, p->version,				  (p->fm ? "" : " (virtual)")));			if (p->fm) {				jffs_fmfree(f->c->fmc, p->fm, p);			}			jffs_unlink_node_from_range_list(f, p);			jffs_unlink_node_from_version_list(f, p);			jffs_free_node(p);			DJM(no_jffs_node--);		}		else {			n->data_size -= remove_size;			n->fm_offset += remove_size;			n->data_offset -= (node->removed_size - remove_size);			n = n->range_next;			break;		}	}	/* Adjust the following nodes' information about offsets etc.  */	while (n && node->removed_size) {		n->data_offset -= node->removed_size;		n = n->range_next;	}	if (node->removed_size > (f->size - node->data_offset)) {		/* It's possible that the removed_size is in fact		 * greater than the amount of data we actually thought		 * were present in the first place - some of the nodes 		 * which this node originally obsoleted may already have		 * been deleted from the flash by subsequent garbage 		 * collection.		 *		 * If this is the case, don't let f->size go negative.		 * Bad things would happen :)		 */		f->size = node->data_offset;	} else {		f->size -= node->removed_size;	}	D3(printk("jffs_delete_data(): f->size = %d\n", f->size));	return 0;} /* jffs_delete_data()  *//* Insert some data into a file.  Prior to the call to this function,   jffs_delete_data should be called.  */static intjffs_insert_data(struct jffs_file *f, struct jffs_node *node){	D3(printk("jffs_insert_data(): node->data_offset = %u, "		  "node->data_size = %u, f->size = %u\n",		  node->data_offset, node->data_size, f->size));	/* Find the position where we should insert data.  */	retry:	if (node->data_offset == f->size) {		/* A simple append.  This is the most common operation.  */		node->range_next = 0;		node->range_prev = f->range_tail;		if (node->range_prev) {			node->range_prev->range_next = node;		}		f->range_tail = node;		f->size += node->data_size;		if (!f->range_head) {			f->range_head = node;		}	}	else if (node->data_offset < f->size) {		/* Trying to insert data into the middle of the file.  This		   means no problem because jffs_delete_data() has already		   prepared the range list for us.  */		struct jffs_node *n;		/* Find the correct place for the insertion and then insert		   the node.  */		for (n = f->range_head; n; n = n->range_next) {			D2(printk("Cool stuff's happening!\n"));			if (n->data_offset == node->data_offset) {				node->range_prev = n->range_prev;				if (node->range_prev) {					node->range_prev->range_next = node;				}				else {					f->range_head = node;				}				node->range_next = n;				n->range_prev = node;				break;			}			ASSERT(else if (n->data_offset + n->data_size >					node->data_offset) {				printk(KERN_ERR "jffs_insert_data(): "				       "Couldn't find a place to insert "				       "the data!\n");				return -1;			});		}		/* Adjust later nodes' offsets etc.  */		n = node->range_next;		while (n) {			n->data_offset += node->data_size;			n = n->range_next;		}		f->size += node->data_size;	}	else if (node->data_offset > f->size) {		/* Okay.  This is tricky.  This means that we want to insert		   data at a place that is beyond the limits of the file as		   it is constructed right now.  This is actually a common		   event that for instance could occur during the mounting		   of the file system if a large file have been truncated,		   rewritten and then only partially garbage collected.  */		struct jffs_node *n;		/* We need a place holder for the data that is missing in		   front of this insertion.  This "virtual node" will not		   be associated with any space on the flash device.  */		struct jffs_node *virtual_node;		if (!(virtual_node = jffs_alloc_node())) {			re

⌨️ 快捷键说明

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