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

📄 intrep.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
	while (!fm) {		/* Deadlocks suck. */		while(fmc->free_size < fmc->min_free_size + total_size + slack) {			jffs_fm_write_unlock(fmc);			if (!JFFS_ENOUGH_SPACE(c, total_size + slack))				return -ENOSPC;			jffs_fm_write_lock(fmc);		}		/* First try to allocate some flash memory.  */		err = jffs_fmalloc(fmc, total_size, node, &fm);				if (err == -ENOSPC) {			/* Just out of space. GC and try again */			if (fmc->dirty_size < fmc->sector_size) {				D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) "					 "failed, no dirty space to GC\n", fmc,					 total_size));				return err;			}						D1(printk(KERN_INFO "jffs_write_node(): Calling jffs_garbage_collect_now()\n"));			jffs_fm_write_unlock(fmc);			if ((err = jffs_garbage_collect_now(c))) {				D(printk("jffs_write_node(): jffs_garbage_collect_now() failed\n"));				return err;			}			jffs_fm_write_lock(fmc);			continue;		} 		if (err < 0) {			jffs_fm_write_unlock(fmc);			D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) "				 "failed!\n", fmc, total_size));			return err;		}		if (!fm->nodes) {			/* The jffs_fm struct that we got is not good enough.			   Make that space dirty and try again  */			if ((err = jffs_write_dummy_node(c, fm)) < 0) {				kfree(fm);				DJM(no_jffs_fm--);				jffs_fm_write_unlock(fmc);				D(printk("jffs_write_node(): "					 "jffs_write_dummy_node(): Failed!\n"));				return err;			}			fm = NULL;		}	} /* while(!fm) */	node->fm = fm;	ASSERT(if (fm->nodes == 0) {		printk(KERN_ERR "jffs_write_node(): fm->nodes == 0\n");	});	pos = node->fm->offset;	/* Increment the version number here. We can't let the caller	   set it beforehand, because we might have had to do GC on a node	   of this file - and we'd end up reusing version numbers.	*/	if (f) {		raw_inode->version = f->highest_version + 1;		D1(printk (KERN_NOTICE "jffs_write_node(): setting version of %s to %d\n", f->name, raw_inode->version));	}	/* Compute the checksum for the data and name chunks.  */	raw_inode->dchksum = jffs_checksum(data, raw_inode->dsize);	raw_inode->nchksum = jffs_checksum(name, raw_inode->nsize);	/* The checksum is calculated without the chksum and accurate	   fields so set them to zero first.  */	raw_inode->accurate = 0;	raw_inode->chksum = 0;	raw_inode->chksum = jffs_checksum(raw_inode,					  sizeof(struct jffs_raw_inode));	raw_inode->accurate = 0xff;	D3(printk("jffs_write_node(): About to write this raw inode to the "		  "flash at pos 0x%lx:\n", (long)pos));	D3(jffs_print_raw_inode(raw_inode));	/* Step 1: Write the raw jffs inode to the flash.  */	if ((err = flash_safe_write(fmc->mtd, pos,				    (u_char *)raw_inode,				    sizeof(struct jffs_raw_inode))) < 0) {		jffs_fmfree_partly(fmc, fm,				   total_name_size + total_data_size);		jffs_fm_write_unlock(fmc);		printk(KERN_ERR "JFFS: jffs_write_node: Failed to write "		       "raw_inode.\n");		return err;	}	pos += sizeof(struct jffs_raw_inode);	/* Step 2: Write the name, if there is any.  */	if (raw_inode->nsize) {		if ((err = flash_safe_write(fmc->mtd, pos,					    (u_char *)name,					    raw_inode->nsize)) < 0) {			jffs_fmfree_partly(fmc, fm, total_data_size);			jffs_fm_write_unlock(fmc);			printk(KERN_ERR "JFFS: jffs_write_node: Failed to "                              "write the name.\n");			return err;		}		pos += total_name_size;	}	/* Step 3: Append the actual data, if any.  */	if (raw_inode->dsize) {		if ((err = flash_safe_write(fmc->mtd, pos, data,					    raw_inode->dsize)) < 0) {			jffs_fmfree_partly(fmc, fm, 0);			jffs_fm_write_unlock(fmc);			printk(KERN_ERR "JFFS: jffs_write_node: Failed to "			       "write the data.\n");			return err;		}	}	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 = jffs_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 = 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;}/* 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;		kfree(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);	DJM(no_jffs_file--);	return 0;}/* 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 = (struct jffs_node *)					 kmalloc(sizeof(struct jffs_node),						 GFP_KERNEL))) {				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 = 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) {		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);			kfree(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 

⌨️ 快捷键说明

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