001-squashfs.patch

来自「Linux Home Server 是专门为家庭和SOHO/SMB 设计的高性价」· PATCH 代码 · 共 2,252 行 · 第 1/5 页

PATCH
2,252
字号
+			up(&msblk->block_cache_mutex);+			continue;+		}++		if ((bytes = msblk->block_cache[i].length - offset) >= length) {+			if (buffer)+				memcpy(buffer, msblk->block_cache[i].data ++						offset, length);+			if (msblk->block_cache[i].length - offset == length) {+				*next_block = msblk->block_cache[i].next_index;+				*next_offset = 0;+			} else {+				*next_block = block;+				*next_offset = offset + length;+			}+			up(&msblk->block_cache_mutex);+			goto finish;+		} else {+			if (buffer) {+				memcpy(buffer, msblk->block_cache[i].data ++						offset, bytes);+				buffer += bytes;+			}+			block = msblk->block_cache[i].next_index;+			up(&msblk->block_cache_mutex);+			length -= bytes;+			offset = 0;+		}+	}++finish:+	return return_length;+out:+	return 0;+}+++static int get_fragment_location(struct super_block *s, unsigned int fragment,+				long long *fragment_start_block,+				unsigned int *fragment_size)+{+	struct squashfs_sb_info *msblk = s->s_fs_info;+	long long start_block =+		msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];+	int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);+	struct squashfs_fragment_entry fragment_entry;++	if (msblk->swap) {+		struct squashfs_fragment_entry sfragment_entry;++		if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,+					start_block, offset,+					sizeof(sfragment_entry), &start_block,+					&offset))+			goto out;+		SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);+	} else+		if (!squashfs_get_cached_block(s, (char *) &fragment_entry,+					start_block, offset,+					sizeof(fragment_entry), &start_block,+					&offset))+			goto out;++	*fragment_start_block = fragment_entry.start_block;+	*fragment_size = fragment_entry.size;++	return 1;++out:+	return 0;+}+++SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct+					squashfs_fragment_cache *fragment)+{+	down(&msblk->fragment_mutex);+	fragment->locked --;+	wake_up(&msblk->fragment_wait_queue);+	up(&msblk->fragment_mutex);+}+++SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block+					*s, long long start_block,+					int length)+{+	int i, n;+	struct squashfs_sb_info *msblk = s->s_fs_info;++	while ( 1 ) {+		down(&msblk->fragment_mutex);++		for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&+				msblk->fragment[i].block != start_block; i++);++		if (i == SQUASHFS_CACHED_FRAGMENTS) {+			for (i = msblk->next_fragment, n =+				SQUASHFS_CACHED_FRAGMENTS; n &&+				msblk->fragment[i].locked; n--, i = (i + 1) %+				SQUASHFS_CACHED_FRAGMENTS);++			if (n == 0) {+				wait_queue_t wait;++				init_waitqueue_entry(&wait, current);+				add_wait_queue(&msblk->fragment_wait_queue,+									&wait);+				set_current_state(TASK_UNINTERRUPTIBLE);+				up(&msblk->fragment_mutex);+				schedule();+				set_current_state(TASK_RUNNING);+				remove_wait_queue(&msblk->fragment_wait_queue,+									&wait);+				continue;+			}+			msblk->next_fragment = (msblk->next_fragment + 1) %+				SQUASHFS_CACHED_FRAGMENTS;++			if (msblk->fragment[i].data == NULL)+				if (!(msblk->fragment[i].data = SQUASHFS_ALLOC+						(SQUASHFS_FILE_MAX_SIZE))) {+					ERROR("Failed to allocate fragment "+							"cache block\n");+					up(&msblk->fragment_mutex);+					goto out;+				}++			msblk->fragment[i].block = SQUASHFS_INVALID_BLK;+			msblk->fragment[i].locked = 1;+			up(&msblk->fragment_mutex);++			if (!(msblk->fragment[i].length = squashfs_read_data(s,+						msblk->fragment[i].data,+						start_block, length, NULL))) {+				ERROR("Unable to read fragment cache block "+							"[%llx]\n", start_block);+				msblk->fragment[i].locked = 0;+				goto out;+			}++			msblk->fragment[i].block = start_block;+			TRACE("New fragment %d, start block %lld, locked %d\n",+						i, msblk->fragment[i].block,+						msblk->fragment[i].locked);+			break;+		}++		msblk->fragment[i].locked++;+		up(&msblk->fragment_mutex);+		TRACE("Got fragment %d, start block %lld, locked %d\n", i,+						msblk->fragment[i].block,+						msblk->fragment[i].locked);+		break;+	}++	return &msblk->fragment[i];++out:+	return NULL;+}+++static struct inode *squashfs_new_inode(struct super_block *s,+		struct squashfs_base_inode_header *inodeb)+{+	struct squashfs_sb_info *msblk = s->s_fs_info;+	struct inode *i = new_inode(s);++	if (i) {+		i->i_ino = inodeb->inode_number;+		i->i_mtime.tv_sec = inodeb->mtime;+		i->i_atime.tv_sec = inodeb->mtime;+		i->i_ctime.tv_sec = inodeb->mtime;+		i->i_uid = msblk->uid[inodeb->uid];+		i->i_mode = inodeb->mode;+		i->i_size = 0;+		if (inodeb->guid == SQUASHFS_GUIDS)+			i->i_gid = i->i_uid;+		else+			i->i_gid = msblk->guid[inodeb->guid];+	}++	return i;+}+++static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode)+{+	struct inode *i;+	struct squashfs_sb_info *msblk = s->s_fs_info;+	struct squashfs_super_block *sblk = &msblk->sblk;+	long long block = SQUASHFS_INODE_BLK(inode) ++		sblk->inode_table_start;+	unsigned int offset = SQUASHFS_INODE_OFFSET(inode);+	long long next_block;+	unsigned int next_offset;+	union squashfs_inode_header id, sid;+	struct squashfs_base_inode_header *inodeb = &id.base,+					  *sinodeb = &sid.base;++	TRACE("Entered squashfs_iget\n");++	if (msblk->swap) {+		if (!squashfs_get_cached_block(s, (char *) sinodeb, block,+					offset, sizeof(*sinodeb), &next_block,+					&next_offset))+			goto failed_read;+		SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,+					sizeof(*sinodeb));+	} else+		if (!squashfs_get_cached_block(s, (char *) inodeb, block,+					offset, sizeof(*inodeb), &next_block,+					&next_offset))+			goto failed_read;++	switch(inodeb->inode_type) {+		case SQUASHFS_FILE_TYPE: {+			unsigned int frag_size;+			long long frag_blk;+			struct squashfs_reg_inode_header *inodep = &id.reg;+			struct squashfs_reg_inode_header *sinodep = &sid.reg;++			if (msblk->swap) {+				if (!squashfs_get_cached_block(s, (char *)+						sinodep, block, offset,+						sizeof(*sinodep), &next_block,+						&next_offset))+					goto failed_read;+				SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);+			} else+				if (!squashfs_get_cached_block(s, (char *)+						inodep, block, offset,+						sizeof(*inodep), &next_block,+						&next_offset))+					goto failed_read;++			frag_blk = SQUASHFS_INVALID_BLK;+			if (inodep->fragment != SQUASHFS_INVALID_FRAG &&+					!get_fragment_location(s,+					inodep->fragment, &frag_blk, &frag_size))+				goto failed_read;++			if((i = squashfs_new_inode(s, inodeb)) == NULL)+				goto failed_read1;++			i->i_nlink = 1;+			i->i_size = inodep->file_size;+			i->i_fop = &generic_ro_fops;+			i->i_mode |= S_IFREG;+			i->i_blocks = ((i->i_size - 1) >> 9) + 1;+			SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;+			SQUASHFS_I(i)->u.s1.fragment_size = frag_size;+			SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;+			SQUASHFS_I(i)->start_block = inodep->start_block;+			SQUASHFS_I(i)->u.s1.block_list_start = next_block;+			SQUASHFS_I(i)->offset = next_offset;+			if (sblk->block_size > 4096)+				i->i_data.a_ops = &squashfs_aops;+			else+				i->i_data.a_ops = &squashfs_aops_4K;++			TRACE("File inode %x:%x, start_block %llx, "+					"block_list_start %llx, offset %x\n",+					SQUASHFS_INODE_BLK(inode), offset,+					inodep->start_block, next_block,+					next_offset);+			break;+		}+		case SQUASHFS_LREG_TYPE: {+			unsigned int frag_size;+			long long frag_blk;+			struct squashfs_lreg_inode_header *inodep = &id.lreg;+			struct squashfs_lreg_inode_header *sinodep = &sid.lreg;++			if (msblk->swap) {+				if (!squashfs_get_cached_block(s, (char *)+						sinodep, block, offset,+						sizeof(*sinodep), &next_block,+						&next_offset))+					goto failed_read;+				SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);+			} else+				if (!squashfs_get_cached_block(s, (char *)+						inodep, block, offset,+						sizeof(*inodep), &next_block,+						&next_offset))+					goto failed_read;++			frag_blk = SQUASHFS_INVALID_BLK;+			if (inodep->fragment != SQUASHFS_INVALID_FRAG &&+					!get_fragment_location(s,+					inodep->fragment, &frag_blk, &frag_size))+				goto failed_read;++			if((i = squashfs_new_inode(s, inodeb)) == NULL)+				goto failed_read1;++			i->i_nlink = inodep->nlink;+			i->i_size = inodep->file_size;+			i->i_fop = &generic_ro_fops;+			i->i_mode |= S_IFREG;+			i->i_blocks = ((i->i_size - 1) >> 9) + 1;+			SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;+			SQUASHFS_I(i)->u.s1.fragment_size = frag_size;+			SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;+			SQUASHFS_I(i)->start_block = inodep->start_block;+			SQUASHFS_I(i)->u.s1.block_list_start = next_block;+			SQUASHFS_I(i)->offset = next_offset;+			if (sblk->block_size > 4096)+				i->i_data.a_ops = &squashfs_aops;+			else+				i->i_data.a_ops = &squashfs_aops_4K;++			TRACE("File inode %x:%x, start_block %llx, "+					"block_list_start %llx, offset %x\n",+					SQUASHFS_INODE_BLK(inode), offset,+					inodep->start_block, next_block,+					next_offset);+			break;+		}+		case SQUASHFS_DIR_TYPE: {+			struct squashfs_dir_inode_header *inodep = &id.dir;+			struct squashfs_dir_inode_header *sinodep = &sid.dir;++			if (msblk->swap) {+				if (!squashfs_get_cached_block(s, (char *)+						sinodep, block, offset,+						sizeof(*sinodep), &next_block,+						&next_offset))+					goto failed_read;+				SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);+			} else+				if (!squashfs_get_cached_block(s, (char *)+						inodep, block, offset,+						sizeof(*inodep), &next_block,+						&next_offset))+					goto failed_read;++			if((i = squashfs_new_inode(s, inodeb)) == NULL)+				goto failed_read1;++			i->i_nlink = inodep->nlink;+			i->i_size = inodep->file_size;+			i->i_op = &squashfs_dir_inode_ops;+			i->i_fop = &squashfs_dir_ops;+			i->i_mode |= S_IFDIR;+			SQUASHFS_I(i)->start_block = inodep->start_block;+			SQUASHFS_I(i)->offset = inodep->offset;+			SQUASHFS_I(i)->u.s2.directory_index_count = 0;+			SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;++			TRACE("Directory inode %x:%x, start_block %x, offset "+					"%x\n", SQUASHFS_INODE_BLK(inode),+					offset, inodep->start_block,+					inodep->offset);+			break;+		}+		case SQUASHFS_LDIR_TYPE: {+			struct squashfs_ldir_inode_header *inodep = &id.ldir;+			struct squashfs_ldir_inode_header *sinodep = &sid.ldir;++			if (msblk->swap) {+				if (!squashfs_get_cached_block(s, (char *)+						sinodep, block, offset,+						sizeof(*sinodep), &next_block,+						&next_offset))+					goto failed_read;+				SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,+						sinodep);+			} else+				if (!squashfs_get_cached_block(s, (char *)+						inodep, block, offset,+						sizeof(*inodep), &next_block,+						&next_offset))+					goto failed_read;++			if((i = squashfs_new_inode(s, inodeb)) == NULL)+				goto failed_read1;++			i->i_nlink = inodep->nlink;+			i->i_size = inodep->file_size;+			i->i_op = &squashfs_dir_inode_ops;+			i->i_fop = &squashfs_dir_ops;+			i->i_mode |= S_IFDIR;+			SQUASHFS_I(i)->start_block = inodep->start_block;+			SQUASHFS_I(i)->offset = inodep->offset;+			SQUASHFS_I(i)->u.s2.directory_index_start = next_block;+			SQUASHFS_I(i)->u.s2.directory_index_offset =+								next_offset;+			SQUASHFS_I(i)->u.s2.directory_index_count =+								inodep->i_count;+			SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;++			TRACE("Long directory inode %x:%x, start_block %x, "+					"offset %x\n",+					SQUASHFS_INODE_BLK(inode), offset,+					inodep->start_block, inodep->offset);+			break;+		}+		case SQUASHFS_SYMLINK_TYPE: {+			struct squashfs_symlink_inode_header *inodep =+								&id.symlink;+			struct squashfs_symlink_inode_header *sinodep =+								&sid.symlink;++			if (msblk->swap) {+				if (!squashfs_get_cached_block(s, (char *)+						sinodep, block, offset,+						sizeof(*sinodep), &next_block,+						&next_offset))+					goto failed_read;+				SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,+								sinodep);+			} else+				if (!squashfs_get_cached_block(s, (char *)+						inodep, block, offset,+						sizeof(*inodep), &next_block,+						&next_offset))+					goto failed_read;++			if((i = squashfs_new_inode(s, inodeb)) == NULL)+				goto failed_read1;++			i->i_nlink = inodep->nlink;+			i->i_size = inodep->symlink_size;+			i->i_op = &page_symlink_inode_operations;+			i->i_data.a_ops = &squashfs_symlink_aops;+			i->i_mode |= S_IFLNK;+			SQUASHFS_I(i)->start_block = next_block;+			SQUASHFS_I(i)->offset = next_offset;++			TRACE("Symbolic link inode %x:%x, start_block %llx, "+					"offset %x\n",+					SQUASHFS_INODE_BLK(inode), offset,+					next_block, next_offset);+			break;+		 }+		 case SQUASHFS_BLKDEV_TYPE:+		 case SQUASHFS_CHRDEV_TYPE: {+			struct squashfs_dev_inode_header *inodep = &id.dev;+			struct squashfs_dev_inode_header *sinodep = &sid.dev;++			if (msblk->swap) {+				if (!squashfs_get_cached_block(s, (char *)+						sinodep, block, offset,+						sizeof(*sinodep), &next_block,+						&next_offset))+					goto failed_read;+				SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);+			} else

⌨️ 快捷键说明

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