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 + -
显示快捷键?