|
Lines 173-186
out:
Link Here
|
| 173 |
|
173 |
|
| 174 |
SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, |
174 |
SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, |
| 175 |
long long index, unsigned int length, |
175 |
long long index, unsigned int length, |
| 176 |
long long *next_index) |
176 |
long long *next_index, int srclength) |
| 177 |
{ |
177 |
{ |
| 178 |
struct squashfs_sb_info *msblk = s->s_fs_info; |
178 |
struct squashfs_sb_info *msblk = s->s_fs_info; |
|
|
179 |
struct squashfs_super_block *sblk = &msblk->sblk; |
| 179 |
struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >> |
180 |
struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >> |
| 180 |
msblk->devblksize_log2) + 2]; |
181 |
msblk->devblksize_log2) + 2]; |
| 181 |
unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); |
182 |
unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); |
| 182 |
unsigned int cur_index = index >> msblk->devblksize_log2; |
183 |
unsigned int cur_index = index >> msblk->devblksize_log2; |
| 183 |
int bytes, avail_bytes, b = 0, k; |
184 |
int bytes, avail_bytes, b = 0, k = 0; |
| 184 |
char *c_buffer; |
185 |
char *c_buffer; |
| 185 |
unsigned int compressed; |
186 |
unsigned int compressed; |
| 186 |
unsigned int c_byte = length; |
187 |
unsigned int c_byte = length; |
|
Lines 191-198
SQSH_EXTERN unsigned int squashfs_read_d
Link Here
|
| 191 |
c_buffer = compressed ? msblk->read_data : buffer; |
192 |
c_buffer = compressed ? msblk->read_data : buffer; |
| 192 |
c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); |
193 |
c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); |
| 193 |
|
194 |
|
| 194 |
TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed |
195 |
TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, compressed |
| 195 |
? "" : "un", (unsigned int) c_byte); |
196 |
? "" : "un", (unsigned int) c_byte, srclength); |
|
|
197 |
|
| 198 |
if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) |
| 199 |
goto read_failure; |
| 196 |
|
200 |
|
| 197 |
if (!(bh[0] = sb_getblk(s, cur_index))) |
201 |
if (!(bh[0] = sb_getblk(s, cur_index))) |
| 198 |
goto block_release; |
202 |
goto block_release; |
|
Lines 204-209
SQSH_EXTERN unsigned int squashfs_read_d
Link Here
|
| 204 |
} |
208 |
} |
| 205 |
ll_rw_block(READ, b, bh); |
209 |
ll_rw_block(READ, b, bh); |
| 206 |
} else { |
210 |
} else { |
|
|
211 |
if (index < 0 || (index + 2) > sblk->bytes_used) |
| 212 |
goto read_failure; |
| 213 |
|
| 207 |
if (!(bh[0] = get_block_length(s, &cur_index, &offset, |
214 |
if (!(bh[0] = get_block_length(s, &cur_index, &offset, |
| 208 |
&c_byte))) |
215 |
&c_byte))) |
| 209 |
goto read_failure; |
216 |
goto read_failure; |
|
Lines 216-221
SQSH_EXTERN unsigned int squashfs_read_d
Link Here
|
| 216 |
TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed |
223 |
TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed |
| 217 |
? "" : "un", (unsigned int) c_byte); |
224 |
? "" : "un", (unsigned int) c_byte); |
| 218 |
|
225 |
|
|
|
226 |
if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) |
| 227 |
goto read_failure; |
| 228 |
|
| 219 |
for (b = 1; bytes < c_byte; b++) { |
229 |
for (b = 1; bytes < c_byte; b++) { |
| 220 |
if (!(bh[b] = sb_getblk(s, ++cur_index))) |
230 |
if (!(bh[b] = sb_getblk(s, ++cur_index))) |
| 221 |
goto block_release; |
231 |
goto block_release; |
|
Lines 227-233
SQSH_EXTERN unsigned int squashfs_read_d
Link Here
|
| 227 |
if (compressed) |
237 |
if (compressed) |
| 228 |
down(&msblk->read_data_mutex); |
238 |
down(&msblk->read_data_mutex); |
| 229 |
|
239 |
|
| 230 |
for (bytes = 0, k = 0; k < b; k++) { |
240 |
for (bytes = 0; k < b; k++) { |
| 231 |
avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ? |
241 |
avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ? |
| 232 |
msblk->devblksize - offset : |
242 |
msblk->devblksize - offset : |
| 233 |
c_byte - bytes; |
243 |
c_byte - bytes; |
|
Lines 249-255
SQSH_EXTERN unsigned int squashfs_read_d
Link Here
|
| 249 |
msblk->stream.next_in = c_buffer; |
259 |
msblk->stream.next_in = c_buffer; |
| 250 |
msblk->stream.avail_in = c_byte; |
260 |
msblk->stream.avail_in = c_byte; |
| 251 |
msblk->stream.next_out = buffer; |
261 |
msblk->stream.next_out = buffer; |
| 252 |
msblk->stream.avail_out = msblk->read_size; |
262 |
msblk->stream.avail_out = srclength; |
| 253 |
|
263 |
|
| 254 |
if (((zlib_err = zlib_inflateInit(&msblk->stream)) != Z_OK) || |
264 |
if (((zlib_err = zlib_inflateInit(&msblk->stream)) != Z_OK) || |
| 255 |
((zlib_err = zlib_inflate(&msblk->stream, Z_FINISH)) |
265 |
((zlib_err = zlib_inflate(&msblk->stream, Z_FINISH)) |
|
Lines 271-278
SQSH_EXTERN unsigned int squashfs_read_d
Link Here
|
| 271 |
return bytes; |
281 |
return bytes; |
| 272 |
|
282 |
|
| 273 |
block_release: |
283 |
block_release: |
| 274 |
while (--b >= 0) |
284 |
for (; k < b; k++) |
| 275 |
brelse(bh[b]); |
285 |
brelse(bh[k]); |
| 276 |
|
286 |
|
| 277 |
read_failure: |
287 |
read_failure: |
| 278 |
ERROR("sb_bread failed reading block 0x%x\n", cur_index); |
288 |
ERROR("sb_bread failed reading block 0x%x\n", cur_index); |
|
Lines 336-349
SQSH_EXTERN int squashfs_get_cached_bloc
Link Here
|
| 336 |
msblk->block_cache[i].block = SQUASHFS_USED_BLK; |
346 |
msblk->block_cache[i].block = SQUASHFS_USED_BLK; |
| 337 |
up(&msblk->block_cache_mutex); |
347 |
up(&msblk->block_cache_mutex); |
| 338 |
|
348 |
|
| 339 |
if (!(msblk->block_cache[i].length = |
349 |
msblk->block_cache[i].length = squashfs_read_data(s, |
| 340 |
squashfs_read_data(s, |
350 |
msblk->block_cache[i].data, block, 0, &next_index, |
| 341 |
msblk->block_cache[i].data, |
351 |
SQUASHFS_METADATA_SIZE); |
| 342 |
block, 0, &next_index))) { |
352 |
|
| 343 |
ERROR("Unable to read cache block [%llx:%x]\n", |
353 |
if (msblk->block_cache[i].length == 0) { |
| 344 |
block, offset); |
354 |
ERROR("Unable to read cache block [%llx:%x]\n", |
| 345 |
goto out; |
355 |
block, offset); |
| 346 |
} |
356 |
down(&msblk->block_cache_mutex); |
|
|
357 |
msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; |
| 358 |
kfree(msblk->block_cache[i].data); |
| 359 |
wake_up(&msblk->waitq); |
| 360 |
up(&msblk->block_cache_mutex); |
| 361 |
goto out; |
| 362 |
} |
| 347 |
|
363 |
|
| 348 |
down(&msblk->block_cache_mutex); |
364 |
down(&msblk->block_cache_mutex); |
| 349 |
wake_up(&msblk->waitq); |
365 |
wake_up(&msblk->waitq); |
|
Lines 357-363
SQSH_EXTERN int squashfs_get_cached_bloc
Link Here
|
| 357 |
continue; |
373 |
continue; |
| 358 |
} |
374 |
} |
| 359 |
|
375 |
|
| 360 |
if ((bytes = msblk->block_cache[i].length - offset) >= length) { |
376 |
bytes = msblk->block_cache[i].length - offset; |
|
|
377 |
|
| 378 |
if (bytes < 1) |
| 379 |
goto out; |
| 380 |
else if (bytes >= length) { |
| 361 |
if (buffer) |
381 |
if (buffer) |
| 362 |
memcpy(buffer, msblk->block_cache[i].data + |
382 |
memcpy(buffer, msblk->block_cache[i].data + |
| 363 |
offset, length); |
383 |
offset, length); |
|
Lines 442-447
SQSH_EXTERN struct squashfs_fragment_cac
Link Here
|
| 442 |
{ |
462 |
{ |
| 443 |
int i, n; |
463 |
int i, n; |
| 444 |
struct squashfs_sb_info *msblk = s->s_fs_info; |
464 |
struct squashfs_sb_info *msblk = s->s_fs_info; |
|
|
465 |
struct squashfs_super_block *sblk = &msblk->sblk; |
| 445 |
|
466 |
|
| 446 |
while ( 1 ) { |
467 |
while ( 1 ) { |
| 447 |
down(&msblk->fragment_mutex); |
468 |
down(&msblk->fragment_mutex); |
|
Lines 487-493
SQSH_EXTERN struct squashfs_fragment_cac
Link Here
|
| 487 |
|
508 |
|
| 488 |
if (!(msblk->fragment[i].length = squashfs_read_data(s, |
509 |
if (!(msblk->fragment[i].length = squashfs_read_data(s, |
| 489 |
msblk->fragment[i].data, |
510 |
msblk->fragment[i].data, |
| 490 |
start_block, length, NULL))) { |
511 |
start_block, length, NULL, |
|
|
512 |
sblk->block_size))) { |
| 491 |
ERROR("Unable to read fragment cache block " |
513 |
ERROR("Unable to read fragment cache block " |
| 492 |
"[%llx]\n", start_block); |
514 |
"[%llx]\n", start_block); |
| 493 |
msblk->fragment[i].locked = 0; |
515 |
msblk->fragment[i].locked = 0; |
|
Lines 876-881
static int read_fragment_index_table(str
Link Here
|
| 876 |
{ |
898 |
{ |
| 877 |
struct squashfs_sb_info *msblk = s->s_fs_info; |
899 |
struct squashfs_sb_info *msblk = s->s_fs_info; |
| 878 |
struct squashfs_super_block *sblk = &msblk->sblk; |
900 |
struct squashfs_super_block *sblk = &msblk->sblk; |
|
|
901 |
unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); |
| 902 |
|
| 903 |
if (length == 0) |
| 904 |
return 1; |
| 879 |
|
905 |
|
| 880 |
/* Allocate fragment index table */ |
906 |
/* Allocate fragment index table */ |
| 881 |
if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES |
907 |
if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES |
|
Lines 884-896
static int read_fragment_index_table(str
Link Here
|
| 884 |
return 0; |
910 |
return 0; |
| 885 |
} |
911 |
} |
| 886 |
|
912 |
|
| 887 |
if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) && |
913 |
if (!squashfs_read_data(s, (char *) msblk->fragment_index, |
| 888 |
!squashfs_read_data(s, (char *) |
914 |
sblk->fragment_table_start, length | |
| 889 |
msblk->fragment_index, |
915 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { |
| 890 |
sblk->fragment_table_start, |
|
|
| 891 |
SQUASHFS_FRAGMENT_INDEX_BYTES |
| 892 |
(sblk->fragments) | |
| 893 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { |
| 894 |
ERROR("unable to read fragment index table\n"); |
916 |
ERROR("unable to read fragment index table\n"); |
| 895 |
return 0; |
917 |
return 0; |
| 896 |
} |
918 |
} |
|
Lines 982-990
static int squashfs_fill_super(struct su
Link Here
|
| 982 |
init_waitqueue_head(&msblk->waitq); |
1004 |
init_waitqueue_head(&msblk->waitq); |
| 983 |
init_waitqueue_head(&msblk->fragment_wait_queue); |
1005 |
init_waitqueue_head(&msblk->fragment_wait_queue); |
| 984 |
|
1006 |
|
|
|
1007 |
sblk->bytes_used = sizeof(struct squashfs_super_block); |
| 985 |
if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, |
1008 |
if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, |
| 986 |
sizeof(struct squashfs_super_block) | |
1009 |
sizeof(struct squashfs_super_block) | |
| 987 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { |
1010 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, |
|
|
1011 |
sizeof(struct squashfs_super_block))) { |
| 988 |
SERROR("unable to read superblock\n"); |
1012 |
SERROR("unable to read superblock\n"); |
| 989 |
goto failed_mount; |
1013 |
goto failed_mount; |
| 990 |
} |
1014 |
} |
|
Lines 1012-1017
static int squashfs_fill_super(struct su
Link Here
|
| 1012 |
if(!supported_squashfs_filesystem(msblk, silent)) |
1036 |
if(!supported_squashfs_filesystem(msblk, silent)) |
| 1013 |
goto failed_mount; |
1037 |
goto failed_mount; |
| 1014 |
|
1038 |
|
|
|
1039 |
/* Check the filesystem does not extend beyond the end of the |
| 1040 |
block device */ |
| 1041 |
if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) |
| 1042 |
goto failed_mount; |
| 1043 |
|
| 1044 |
/* Check the root inode for sanity */ |
| 1045 |
if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) |
| 1046 |
goto failed_mount; |
| 1047 |
|
| 1015 |
TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); |
1048 |
TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); |
| 1016 |
TRACE("Inodes are %scompressed\n", |
1049 |
TRACE("Inodes are %scompressed\n", |
| 1017 |
SQUASHFS_UNCOMPRESSED_INODES |
1050 |
SQUASHFS_UNCOMPRESSED_INODES |
|
Lines 1081-1087
static int squashfs_fill_super(struct su
Link Here
|
| 1081 |
if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, |
1114 |
if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, |
| 1082 |
((sblk->no_uids + sblk->no_guids) * |
1115 |
((sblk->no_uids + sblk->no_guids) * |
| 1083 |
sizeof(unsigned int)) | |
1116 |
sizeof(unsigned int)) | |
| 1084 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { |
1117 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, |
|
|
1118 |
(sblk->no_uids + sblk->no_guids) * |
| 1119 |
sizeof(unsigned int))) { |
| 1085 |
ERROR("unable to read uid/gid table\n"); |
1120 |
ERROR("unable to read uid/gid table\n"); |
| 1086 |
goto failed_mount; |
1121 |
goto failed_mount; |
| 1087 |
} |
1122 |
} |
|
Lines 1092-1098
static int squashfs_fill_super(struct su
Link Here
|
| 1092 |
if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, |
1127 |
if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, |
| 1093 |
((sblk->no_uids + sblk->no_guids) * |
1128 |
((sblk->no_uids + sblk->no_guids) * |
| 1094 |
sizeof(unsigned int)) | |
1129 |
sizeof(unsigned int)) | |
| 1095 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { |
1130 |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, |
|
|
1131 |
(sblk->no_uids + sblk->no_guids) * |
| 1132 |
sizeof(unsigned int))) { |
| 1096 |
ERROR("unable to read uid/gid table\n"); |
1133 |
ERROR("unable to read uid/gid table\n"); |
| 1097 |
goto failed_mount; |
1134 |
goto failed_mount; |
| 1098 |
} |
1135 |
} |
|
Lines 1518-1524
static int squashfs_readpage(struct file
Link Here
|
| 1518 |
down(&msblk->read_page_mutex); |
1555 |
down(&msblk->read_page_mutex); |
| 1519 |
|
1556 |
|
| 1520 |
if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page, |
1557 |
if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page, |
| 1521 |
block, bsize, NULL))) { |
1558 |
block, bsize, NULL, |
|
|
1559 |
msblk->read_size))) { |
| 1522 |
ERROR("Unable to read page, block %llx, size %x\n", block, |
1560 |
ERROR("Unable to read page, block %llx, size %x\n", block, |
| 1523 |
bsize); |
1561 |
bsize); |
| 1524 |
up(&msblk->read_page_mutex); |
1562 |
up(&msblk->read_page_mutex); |
|
Lines 1618-1632
static int squashfs_readpage4K(struct fi
Link Here
|
| 1618 |
|
1656 |
|
| 1619 |
if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> |
1657 |
if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> |
| 1620 |
PAGE_CACHE_SHIFT)) { |
1658 |
PAGE_CACHE_SHIFT)) { |
| 1621 |
pageaddr = kmap_atomic(page, KM_USER0); |
|
|
| 1622 |
block_list = NULL; |
1659 |
block_list = NULL; |
| 1623 |
goto skip_read; |
1660 |
goto skip_read; |
| 1624 |
} |
1661 |
} |
| 1625 |
|
1662 |
|
| 1626 |
if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) { |
1663 |
if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) { |
| 1627 |
ERROR("Failed to allocate block_list\n"); |
1664 |
ERROR("Failed to allocate block_list\n"); |
| 1628 |
pageaddr = kmap_atomic(page, KM_USER0); |
|
|
| 1629 |
block_list = NULL; |
| 1630 |
goto skip_read; |
1665 |
goto skip_read; |
| 1631 |
} |
1666 |
} |
| 1632 |
|
1667 |
|
|
Lines 1638-1648
static int squashfs_readpage4K(struct fi
Link Here
|
| 1638 |
|
1673 |
|
| 1639 |
down(&msblk->read_page_mutex); |
1674 |
down(&msblk->read_page_mutex); |
| 1640 |
bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, |
1675 |
bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, |
| 1641 |
bsize, NULL); |
1676 |
bsize, NULL, msblk->read_size); |
| 1642 |
pageaddr = kmap_atomic(page, KM_USER0); |
1677 |
if (bytes) { |
| 1643 |
if (bytes) |
1678 |
pageaddr = kmap_atomic(page, KM_USER0); |
| 1644 |
memcpy(pageaddr, msblk->read_page, bytes); |
1679 |
memcpy(pageaddr, msblk->read_page, bytes); |
| 1645 |
else |
1680 |
kunmap_atomic(pageaddr, KM_USER0); |
|
|
1681 |
} else |
| 1646 |
ERROR("Unable to read page, block %llx, size %x\n", |
1682 |
ERROR("Unable to read page, block %llx, size %x\n", |
| 1647 |
block, bsize); |
1683 |
block, bsize); |
| 1648 |
up(&msblk->read_page_mutex); |
1684 |
up(&msblk->read_page_mutex); |
|
Lines 1652-1662
static int squashfs_readpage4K(struct fi
Link Here
|
| 1652 |
SQUASHFS_I(inode)-> |
1688 |
SQUASHFS_I(inode)-> |
| 1653 |
u.s1.fragment_start_block, |
1689 |
u.s1.fragment_start_block, |
| 1654 |
SQUASHFS_I(inode)-> u.s1.fragment_size); |
1690 |
SQUASHFS_I(inode)-> u.s1.fragment_size); |
| 1655 |
pageaddr = kmap_atomic(page, KM_USER0); |
|
|
| 1656 |
if (fragment) { |
1691 |
if (fragment) { |
| 1657 |
bytes = i_size_read(inode) & (sblk->block_size - 1); |
1692 |
bytes = i_size_read(inode) & (sblk->block_size - 1); |
|
|
1693 |
pageaddr = kmap_atomic(page, KM_USER0); |
| 1658 |
memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)-> |
1694 |
memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)-> |
| 1659 |
u.s1.fragment_offset, bytes); |
1695 |
u.s1.fragment_offset, bytes); |
|
|
1696 |
kunmap_atomic(pageaddr, KM_USER0); |
| 1660 |
release_cached_fragment(msblk, fragment); |
1697 |
release_cached_fragment(msblk, fragment); |
| 1661 |
} else |
1698 |
} else |
| 1662 |
ERROR("Unable to read page, block %llx, size %x\n", |
1699 |
ERROR("Unable to read page, block %llx, size %x\n", |
|
Lines 1666-1671
static int squashfs_readpage4K(struct fi
Link Here
|
| 1666 |
} |
1703 |
} |
| 1667 |
|
1704 |
|
| 1668 |
skip_read: |
1705 |
skip_read: |
|
|
1706 |
pageaddr = kmap_atomic(page, KM_USER0); |
| 1669 |
memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); |
1707 |
memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); |
| 1670 |
kunmap_atomic(pageaddr, KM_USER0); |
1708 |
kunmap_atomic(pageaddr, KM_USER0); |
| 1671 |
flush_dcache_page(page); |
1709 |
flush_dcache_page(page); |