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

📄 j_intrep.cpp

📁 JFFS的源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		if (f->name) {
			free(f->name);
			DJM(no_name--);
		}
		if (!(f->name = (char *) malloc(raw_inode->nsize + 1))) {
			D(printk("jffs_insert_node(): f->name == 0\n"));
			return -ENOMEM;
		}
		DJM(no_name++);
		memcpy(f->name, name, raw_inode->nsize);
		f->name[raw_inode->nsize] = '\0';
		f->nsize = raw_inode->nsize;
		D3(printk("jffs_insert_node(): Updated the name of "
			  "the file to \"%s\".\n", name));
	}

	if (!c->building_fs) {
		D3(printk("jffs_insert_node(): ---------------------------"
			  "------------------------------------------- 1\n"));
		if (insert_into_tree) {
			jffs_insert_file_into_tree(f);
		}
		if (f->deleted) {
			/* Mark all versions of the node as obsolete.  */
			jffs_possibly_delete_file(f);
		}
		else {
			if (node->data_size || node->removed_size) {
				jffs_update_file(f, node);
			}
			jffs_remove_redundant_nodes(f);
		}
#ifdef USE_GC
		if (!c->fmc->no_call_gc) {
			jffs_garbage_collect(c);
		}
#endif
		D3(printk("jffs_insert_node(): ---------------------------"
			  "------------------------------------------- 2\n"));
	}
	return 0;
} /* jffs_insert_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 int
jffs_get_node_data(struct jffs_file *f, struct jffs_node *node, 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 = jffs_min(avail, max_size);
	flash_safe_read(fmc->flash_part, (unsigned char *) pos,
			(unsigned char *)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.  */
int jffs_read_data(struct jffs_file *f, 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.  */

	D1(printk("jffs_read_data(): file = \"%s\", read_offset = %d, "
		  "size = %u\n",
		  (f->name ? f->name : ""), read_offset, size));

	if (read_offset >= f->size) {
		//!!!!!与FDK文件传送冲突
		//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 = jffs_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;
}

/* Find a file with its inode number.  */
struct jffs_file *
jffs_find_file(struct jffs_control *c, __u32 ino)
{
	struct jffs_file *f;
	int i = ino % c->hash_len;

	D3(printk("jffs_find_file(): ino: %u\n", ino));

	for (f = c->hash[i]; f && (ino != f->ino); f = f->hash_next);

	D3(if (f) {
		printk("jffs_find_file(): Found file with ino "
		       "%u. (name: \"%s\")\n",
		       ino, (f->name ? f->name : ""));
	}
	else {
		printk("jffs_find_file(): Couldn't find file "
			 "with ino %u.\n", ino);
	});

	return f;
}

/* Used for traversing all nodes in the hash table.  */
int
jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *))
{
	struct jffs_file *f;
	struct jffs_file *next_f;
	int pos;
	int r;
	int result = 0;

	for (pos = 0; pos < c->hash_len; pos++) {
		for (f = c->hash[pos]; f; f = next_f) {
			/* We need a reference to the next file in the
			   list because `func' might remove the current
			   file `f'.  */
			next_f = f->hash_next;
			if ((r = func(f)) < 0) {
				return r;
			}
			result += r;
		}
	}

	return result;
}

/* Build up a file's range list from scratch by going through the
   version list.  */
int jffs_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;
}
/* A new node (with data) has been added to the file and now the range
   list has to be modified.  */
static int
jffs_update_file(struct jffs_file *f, struct jffs_node *node)
{
	int err;

	D3(printk("jffs_update_file(): ino: %u, version: %u\n",
		  f->ino, node->version));

	if (node->data_size == 0) {
		if (node->removed_size == 0) {
			/* data_offset == X  */
			/* data_size == 0  */
			/* remove_size == 0  */
		}
		else {
			/* data_offset == X  */
			/* data_size == 0  */
			/* remove_size != 0  */
			if ((err = jffs_delete_data(f, node)) < 0) {
				return err;
			}
		}
	}
	else {
		/* data_offset == X  */
		/* data_size != 0  */
		/* remove_size == Y  */
		//如果是虚节点,先进行插入
		if(node->data_offset > f->size){
			if ((err = jffs_insert_virtual_data(f, node)) < 0) {
				return err;
			}
		}
		if ((err = jffs_delete_data(f, node)) < 0) {
			return err;
		}
		if ((err = jffs_insert_data(f, node)) < 0) {
			return err;
		}
	}
	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.   */
/*f表示被修改的文件, node传递删除数据的偏移和大小
只对RAM中的node进行修改, 不修改flash上的raw_inode, 除非已完全删除
在Flash上如何保存修改*/
static int jffs_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) return 0;

	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.  */
		//????? D(printf("jffs_delete_data(): there's no data to remove\n"));
		return 0;
	}

	if (n->data_offset > offset) {
		/* XXX: Not implemented yet.  */
		D(printf("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 = (struct jffs_node *)
					 malloc(sizeof(struct jffs_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;
			jffs_add_node(new_node);
			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 = jffs_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) {
		clearHW();
		if (n->data_size <= remove_size) {
			struct jffs_node *p = n;
			remove_size -= n->data_size;
			n = n->range_next;
		  //if(n->name_size == 0)//!!!有名称存在,不能删除
		  {	
			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);
			free(p);
			DJM(no_jffs_node--);
		  }/*if(n->name_size == 0)*/	
		}
		else { /*最后一个node*/
			n->data_size -= remove_size;
			n->fm_offset += remove_size;
			/*删除一段, offset应向前移动*/
			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;
	}

	f->size -= node->removed_size;
	D3(printk("jffs_delete_data(): f->size = %d\n", f->size));
	return 0;
} /* jffs_delete_data()  */

static int jffs_insert_virtual_data(struct jffs_file *f, struct jffs_node *node)
{
		/* 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 = (struct jffs_node *)
				     malloc(sizeof(struct jffs_node)))) {
			D(printk("jffs_insert_data(): virtual_node == 0\n"));
			return -ENOMEM;
		}

		//D(printk("jffs_insert_data: Inserting a virtual node.\n"));
		//D(printk("  node->data_offset = %u\n", node->data_offset));
		//D(printk("  f->size = %u, f->name = %s\n", f->size,f->name));

		virtual_node->ino = node->ino;
		virtual_node->version = node->version;
		virtual_node->removed_size = 0;
		virtual_node->fm_offset = 0;
		virtual_node->name_size = 0;
		virtual_node->fm = 0; /* This is a virtual data holder.  */
		virtual_node->version_prev = 0;
		virtual_node->version_next = 0;
		virtual_node->range_next = 0;

		/* Are there any data at all in the file yet?  */
		if (f->range_head) {
			virtual_node->data_offset
			= f->range_tail->data_offset
			  + f->range_tail->data_size;
			virtual_node->data_size
			= node->data_offset - virtual_node->data_offset;
			virtual_node->range_prev = f->range_tail;
			f->range_tail->range_next = virtual_node;
		}
		else {
			virtual_node->data_offset = 0;
			virtual_node->data_size = node->data_offset;
			virtual_node->range_prev = 0;
			f->range_head = virtual_node;
		}

		f->range_tail = virtual_node;
		f->size += virtual_node->data_size;

		/* Insert this virtual node in the version list as well.  */
		for (n = f->version_head; n ; n = n->version_next) {
			if (n->version == virtual_node->version) {
				virtual_node->version_prev = n->version_prev;
				n->version_prev = virtual_node;
				if (virtual_node->version_prev) {
					virtual_node->version_prev
					->version_next = virtual_node;
				}
				else {
					f->version_head = virtual_node;

⌨️ 快捷键说明

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