📄 001-squashfs.patch
字号:
+ ERROR("Failed to allocate meta_index\n");+ goto failed;+ }+ for(i = 0; i < SQUASHFS_META_NUMBER; i++) {+ msblk->meta_index[i].inode_number = 0;+ msblk->meta_index[i].locked = 0;+ }+ msblk->next_meta_index = 0;+ }++ for(i = SQUASHFS_META_NUMBER; i &&+ msblk->meta_index[msblk->next_meta_index].locked; i --)+ msblk->next_meta_index = (msblk->next_meta_index + 1) %+ SQUASHFS_META_NUMBER;++ if(i == 0) {+ TRACE("empty_meta_index: failed!\n");+ goto failed;+ }++ TRACE("empty_meta_index: returned meta entry %d, %p\n",+ msblk->next_meta_index,+ &msblk->meta_index[msblk->next_meta_index]);++ meta = &msblk->meta_index[msblk->next_meta_index];+ msblk->next_meta_index = (msblk->next_meta_index + 1) %+ SQUASHFS_META_NUMBER;++ meta->inode_number = inode->i_ino;+ meta->offset = offset;+ meta->skip = skip;+ meta->entries = 0;+ meta->locked = 1;++failed:+ up(&msblk->meta_index_mutex);+ return meta;+}+++void release_meta_index(struct inode *inode, struct meta_index *meta)+{+ meta->locked = 0;+}+++static int read_block_index(struct super_block *s, int blocks, char *block_list,+ long long *start_block, int *offset)+{+ struct squashfs_sb_info *msblk = s->s_fs_info;+ unsigned int *block_listp;+ int block = 0;++ if (msblk->swap) {+ char sblock_list[blocks << 2];++ if (!squashfs_get_cached_block(s, sblock_list, *start_block,+ *offset, blocks << 2, start_block, offset)) {+ ERROR("Unable to read block list [%llx:%x]\n",+ *start_block, *offset);+ goto failure;+ }+ SQUASHFS_SWAP_INTS(((unsigned int *)block_list),+ ((unsigned int *)sblock_list), blocks);+ } else+ if (!squashfs_get_cached_block(s, block_list, *start_block,+ *offset, blocks << 2, start_block, offset)) {+ ERROR("Unable to read block list [%llx:%x]\n",+ *start_block, *offset);+ goto failure;+ }++ for (block_listp = (unsigned int *) block_list; blocks;+ block_listp++, blocks --)+ block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);++ return block;++failure:+ return -1;+}+++#define SIZE 256++static inline int calculate_skip(int blocks) {+ int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);+ return skip >= 7 ? 7 : skip + 1;+}+++static int get_meta_index(struct inode *inode, int index,+ long long *index_block, int *index_offset,+ long long *data_block, char *block_list)+{+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;+ struct squashfs_super_block *sblk = &msblk->sblk;+ int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);+ int offset = 0;+ struct meta_index *meta;+ struct meta_entry *meta_entry;+ long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;+ int cur_offset = SQUASHFS_I(inode)->offset;+ long long cur_data_block = SQUASHFS_I(inode)->start_block;+ int i;++ index /= SQUASHFS_META_INDEXES * skip;++ while ( offset < index ) {+ meta = locate_meta_index(inode, index, offset + 1);++ if (meta == NULL) {+ if ((meta = empty_meta_index(inode, offset + 1,+ skip)) == NULL)+ goto all_done;+ } else {+ offset = index < meta->offset + meta->entries ? index :+ meta->offset + meta->entries - 1;+ meta_entry = &meta->meta_entry[offset - meta->offset];+ cur_index_block = meta_entry->index_block + sblk->inode_table_start;+ cur_offset = meta_entry->offset;+ cur_data_block = meta_entry->data_block;+ TRACE("get_meta_index: offset %d, meta->offset %d, "+ "meta->entries %d\n", offset, meta->offset,+ meta->entries);+ TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"+ " data_block 0x%llx\n", cur_index_block,+ cur_offset, cur_data_block);+ }++ for (i = meta->offset + meta->entries; i <= index &&+ i < meta->offset + SQUASHFS_META_ENTRIES; i++) {+ int blocks = skip * SQUASHFS_META_INDEXES;++ while (blocks) {+ int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :+ blocks;+ int res = read_block_index(inode->i_sb, block,+ block_list, &cur_index_block,+ &cur_offset);++ if (res == -1)+ goto failed;++ cur_data_block += res;+ blocks -= block;+ }++ meta_entry = &meta->meta_entry[i - meta->offset];+ meta_entry->index_block = cur_index_block - sblk->inode_table_start;+ meta_entry->offset = cur_offset;+ meta_entry->data_block = cur_data_block;+ meta->entries ++;+ offset ++;+ }++ TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",+ meta->offset, meta->entries);++ release_meta_index(inode, meta);+ }++all_done:+ *index_block = cur_index_block;+ *index_offset = cur_offset;+ *data_block = cur_data_block;++ return offset * SQUASHFS_META_INDEXES * skip;++failed:+ release_meta_index(inode, meta);+ return -1;+}+++static long long read_blocklist(struct inode *inode, int index,+ int readahead_blks, char *block_list,+ unsigned short **block_p, unsigned int *bsize)+{+ long long block_ptr;+ int offset;+ long long block;+ int res = get_meta_index(inode, index, &block_ptr, &offset, &block,+ block_list);++ TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"+ " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,+ block);++ if(res == -1)+ goto failure;++ index -= res;++ while ( index ) {+ int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;+ int res = read_block_index(inode->i_sb, blocks, block_list,+ &block_ptr, &offset);+ if (res == -1)+ goto failure;+ block += res;+ index -= blocks;+ }++ if (read_block_index(inode->i_sb, 1, block_list,+ &block_ptr, &offset) == -1)+ goto failure;+ *bsize = *((unsigned int *) block_list);++ return block;++failure:+ return 0;+}+++static int squashfs_readpage(struct file *file, struct page *page)+{+ struct inode *inode = page->mapping->host;+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;+ struct squashfs_super_block *sblk = &msblk->sblk;+ unsigned char block_list[SIZE];+ long long block;+ unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;+ int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);+ void *pageaddr;+ struct squashfs_fragment_cache *fragment = NULL;+ char *data_ptr = msblk->read_page;++ int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;+ int start_index = page->index & ~mask;+ int end_index = start_index | mask;++ TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",+ page->index,+ SQUASHFS_I(inode)->start_block);++ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>+ PAGE_CACHE_SHIFT))+ goto skip_read;++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK+ || index < (i_size_read(inode) >>+ sblk->block_log)) {+ if ((block = (msblk->read_blocklist)(inode, index, 1,+ block_list, NULL, &bsize)) == 0)+ goto skip_read;++ down(&msblk->read_page_mutex);++ if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,+ block, bsize, NULL))) {+ ERROR("Unable to read page, block %llx, size %x\n", block,+ bsize);+ up(&msblk->read_page_mutex);+ goto skip_read;+ }+ } else {+ if ((fragment = get_cached_fragment(inode->i_sb,+ SQUASHFS_I(inode)->+ u.s1.fragment_start_block,+ SQUASHFS_I(inode)->u.s1.fragment_size))+ == NULL) {+ ERROR("Unable to read page, block %llx, size %x\n",+ SQUASHFS_I(inode)->+ u.s1.fragment_start_block,+ (int) SQUASHFS_I(inode)->+ u.s1.fragment_size);+ goto skip_read;+ }+ bytes = SQUASHFS_I(inode)->u.s1.fragment_offset ++ (i_size_read(inode) & (sblk->block_size+ - 1));+ byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;+ data_ptr = fragment->data;+ }++ for (i = start_index; i <= end_index && byte_offset < bytes;+ i++, byte_offset += PAGE_CACHE_SIZE) {+ struct page *push_page;+ int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ?+ PAGE_CACHE_SIZE : bytes - byte_offset;++ TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",+ bytes, i, byte_offset, available_bytes);++ if (i == page->index) {+ pageaddr = kmap_atomic(page, KM_USER0);+ memcpy(pageaddr, data_ptr + byte_offset,+ available_bytes);+ memset(pageaddr + available_bytes, 0,+ PAGE_CACHE_SIZE - available_bytes);+ kunmap_atomic(pageaddr, KM_USER0);+ flush_dcache_page(page);+ SetPageUptodate(page);+ unlock_page(page);+ } else if ((push_page =+ grab_cache_page_nowait(page->mapping, i))) {+ pageaddr = kmap_atomic(push_page, KM_USER0);++ memcpy(pageaddr, data_ptr + byte_offset,+ available_bytes);+ memset(pageaddr + available_bytes, 0,+ PAGE_CACHE_SIZE - available_bytes);+ kunmap_atomic(pageaddr, KM_USER0);+ flush_dcache_page(push_page);+ SetPageUptodate(push_page);+ unlock_page(push_page);+ page_cache_release(push_page);+ }+ }++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK+ || index < (i_size_read(inode) >>+ sblk->block_log))+ up(&msblk->read_page_mutex);+ else+ release_cached_fragment(msblk, fragment);++ return 0;++skip_read:+ pageaddr = kmap_atomic(page, KM_USER0);+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);+ kunmap_atomic(pageaddr, KM_USER0);+ flush_dcache_page(page);+ SetPageUptodate(page);+ unlock_page(page);++ return 0;+}+++static int squashfs_readpage4K(struct file *file, struct page *page)+{+ struct inode *inode = page->mapping->host;+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;+ struct squashfs_super_block *sblk = &msblk->sblk;+ unsigned char block_list[SIZE];+ long long block;+ unsigned int bsize, bytes = 0;+ void *pageaddr;++ TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",+ page->index,+ SQUASHFS_I(inode)->start_block);++ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>+ PAGE_CACHE_SHIFT)) {+ pageaddr = kmap_atomic(page, KM_USER0);+ goto skip_read;+ }++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK+ || page->index < (i_size_read(inode) >>+ sblk->block_log)) {+ block = (msblk->read_blocklist)(inode, page->index, 1,+ block_list, NULL, &bsize);++ down(&msblk->read_page_mutex);+ bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,+ bsize, NULL);+ pageaddr = kmap_atomic(page, KM_USER0);+ if (bytes)+ memcpy(pageaddr, msblk->read_page, bytes);+ else+ ERROR("Unable to read page, block %llx, size %x\n",+ block, bsize);+ up(&msblk->read_page_mutex);+ } else {+ struct squashfs_fragment_cache *fragment =+ get_cached_fragment(inode->i_sb,+ SQUASHFS_I(inode)->+ u.s1.fragment_start_block,+ SQUASHFS_I(inode)-> u.s1.fragment_size);+ pageaddr = kmap_atomic(page, KM_USER0);+ if (fragment) {+ bytes = i_size_read(inode) & (sblk->block_size - 1);+ memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->+ u.s1.fragment_offset, bytes);+ release_cached_fragment(msblk, fragment);+ } else+ ERROR("Unable to read page, block %llx, size %x\n",+ SQUASHFS_I(inode)->+ u.s1.fragment_start_block, (int)+ SQUASHFS_I(inode)-> u.s1.fragment_size);+ }++skip_read:+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);+ kunmap_atomic(pageaddr, KM_USER0);+ flush_dcache_page(page);+ SetPageUptodate(page);+ unlock_page(page);++ return 0;+}+++static int get_dir_index_using_offset(struct super_block *s, long long+ *next_block, unsigned int *next_offset,+ long long index_start,+ unsigned int index_offset, int i_count,+ long long f_pos)+{+ struct squashfs_sb_info *msblk = s->s_fs_info;+ struct squashfs_super_block *sblk = &msblk->sblk;+ int i, length = 0;+ struct squashfs_dir_index index;++ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",+ i_count, (unsigned int) f_pos);++ f_pos =- 3;+ if (f_pos == 0)+ goto finish;++ for (i = 0; i < i_count; i++) {+ if (msblk->swap) {+ struct squashfs_dir_index sindex;+ squashfs_get_cached_block(s, (char *) &sindex,+ index_start, index_offset,+ sizeof(sindex), &index_start,+ &index_offset);+ SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);+ } else+ squashfs_get_cached_block(s, (char *) &index,+ index_start, index_offset,+ sizeof(index), &index_start,+ &index_offset);++ if (index.index > f_pos)+ break;++ squashfs_get_cached_block(s, NULL, index_start, index_offset,+ index.size + 1, &index_start,+ &index_offset);++ length = index.index;+ *next_block = index.start_block + sblk->directory_table_start;+ }++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;++finish:+ return length + 3;+}+++static int get_dir_index_using_name(struct super_block *s, long long+ *next_block, unsigned int *next_offset,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -