Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'work.cramfs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull cramfs updates from Al Viro:
"Nicolas Pitre's cramfs work"

* 'work.cramfs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
cramfs: rehabilitate it
cramfs: add mmap support
cramfs: implement uncompressed and arbitrary data block positioning
cramfs: direct memory access support

+586 -71
+42
Documentation/filesystems/cramfs.txt
··· 45 45 mind the filesystem becoming unreadable to future kernels. 46 46 47 47 48 + Memory Mapped cramfs image 49 + -------------------------- 50 + 51 + The CRAMFS_MTD Kconfig option adds support for loading data directly from 52 + a physical linear memory range (usually non volatile memory like Flash) 53 + instead of going through the block device layer. This saves some memory 54 + since no intermediate buffering is necessary to hold the data before 55 + decompressing. 56 + 57 + And when data blocks are kept uncompressed and properly aligned, they will 58 + automatically be mapped directly into user space whenever possible providing 59 + eXecute-In-Place (XIP) from ROM of read-only segments. Data segments mapped 60 + read-write (hence they have to be copied to RAM) may still be compressed in 61 + the cramfs image in the same file along with non compressed read-only 62 + segments. Both MMU and no-MMU systems are supported. This is particularly 63 + handy for tiny embedded systems with very tight memory constraints. 64 + 65 + The location of the cramfs image in memory is system dependent. You must 66 + know the proper physical address where the cramfs image is located and 67 + configure an MTD device for it. Also, that MTD device must be supported 68 + by a map driver that implements the "point" method. Examples of such 69 + MTD drivers are cfi_cmdset_0001 (Intel/Sharp CFI flash) or physmap 70 + (Flash device in physical memory map). MTD partitions based on such devices 71 + are fine too. Then that device should be specified with the "mtd:" prefix 72 + as the mount device argument. For example, to mount the MTD device named 73 + "fs_partition" on the /mnt directory: 74 + 75 + $ mount -t cramfs mtd:fs_partition /mnt 76 + 77 + To boot a kernel with this as root filesystem, suffice to specify 78 + something like "root=mtd:fs_partition" on the kernel command line. 79 + 80 + 81 + Tools 82 + ----- 83 + 84 + A version of mkcramfs that can take advantage of the latest capabilities 85 + described above can be found here: 86 + 87 + https://github.com/npitre/cramfs-tools 88 + 89 + 48 90 For /usr/share/magic 49 91 -------------------- 50 92
+2 -2
MAINTAINERS
··· 3720 3720 F: include/linux/cpuidle.h 3721 3721 3722 3722 CRAMFS FILESYSTEM 3723 - W: http://sourceforge.net/projects/cramfs/ 3724 - S: Orphan / Obsolete 3723 + M: Nicolas Pitre <nico@linaro.org> 3724 + S: Maintained 3725 3725 F: Documentation/filesystems/cramfs.txt 3726 3726 F: fs/cramfs/ 3727 3727
+35 -4
fs/cramfs/Kconfig
··· 1 1 config CRAMFS 2 - tristate "Compressed ROM file system support (cramfs) (OBSOLETE)" 3 - depends on BLOCK 2 + tristate "Compressed ROM file system support (cramfs)" 4 3 select ZLIB_INFLATE 5 4 help 6 5 Saying Y here includes support for CramFs (Compressed ROM File ··· 15 16 cramfs. Note that the root file system (the one containing the 16 17 directory /) cannot be compiled as a module. 17 18 18 - This filesystem is obsoleted by SquashFS, which is much better 19 - in terms of performance and features. 19 + This filesystem is limited in capabilities and performance on 20 + purpose to remain small and low on RAM usage. It is most suitable 21 + for small embedded systems. If you have ample RAM to spare, you may 22 + consider a more capable compressed filesystem such as SquashFS 23 + which is much better in terms of performance and features. 24 + 25 + If unsure, say N. 26 + 27 + config CRAMFS_BLOCKDEV 28 + bool "Support CramFs image over a regular block device" if EXPERT 29 + depends on CRAMFS && BLOCK 30 + default y 31 + help 32 + This option allows the CramFs driver to load data from a regular 33 + block device such a disk partition or a ramdisk. 34 + 35 + config CRAMFS_MTD 36 + bool "Support CramFs image directly mapped in physical memory" 37 + depends on CRAMFS && MTD 38 + default y if !CRAMFS_BLOCKDEV 39 + help 40 + This option allows the CramFs driver to load data directly from 41 + a linear adressed memory range (usually non volatile memory 42 + like flash) instead of going through the block device layer. 43 + This saves some memory since no intermediate buffering is 44 + necessary. 45 + 46 + The location of the CramFs image is determined by a 47 + MTD device capable of direct memory mapping e.g. from 48 + the 'physmap' map driver or a resulting MTD partition. 49 + For example, this would mount the cramfs image stored in 50 + the MTD partition named "xip_fs" on the /mnt mountpoint: 51 + 52 + mount -t cramfs mtd:xip_fs /mnt 20 53 21 54 If unsure, say N.
+30 -1
fs/cramfs/README
··· 49 49 <block> immediately follows the last <block_pointer> for the file. 50 50 <block_pointer>s are each 32 bits long. 51 51 52 + When the CRAMFS_FLAG_EXT_BLOCK_POINTERS capability bit is set, each 53 + <block_pointer>'s top bits may contain special flags as follows: 54 + 55 + CRAMFS_BLK_FLAG_UNCOMPRESSED (bit 31): 56 + The block data is not compressed and should be copied verbatim. 57 + 58 + CRAMFS_BLK_FLAG_DIRECT_PTR (bit 30): 59 + The <block_pointer> stores the actual block start offset and not 60 + its end, shifted right by 2 bits. The block must therefore be 61 + aligned to a 4-byte boundary. The block size is either blksize 62 + if CRAMFS_BLK_FLAG_UNCOMPRESSED is also specified, otherwise 63 + the compressed data length is included in the first 2 bytes of 64 + the block data. This is used to allow discontiguous data layout 65 + and specific data block alignments e.g. for XIP applications. 66 + 67 + 52 68 The order of <file_data>'s is a depth-first descent of the directory 53 69 tree, i.e. the same order as `find -size +0 \( -type f -o -type l \) 54 70 -print'. 55 71 56 72 57 73 <block>: The i'th <block> is the output of zlib's compress function 58 - applied to the i'th blksize-sized chunk of the input data. 74 + applied to the i'th blksize-sized chunk of the input data if the 75 + corresponding CRAMFS_BLK_FLAG_UNCOMPRESSED <block_ptr> bit is not set, 76 + otherwise it is the input data directly. 59 77 (For the last <block> of the file, the input may of course be smaller.) 60 78 Each <block> may be a different size. (See <block_pointer> above.) 79 + 61 80 <block>s are merely byte-aligned, not generally u32-aligned. 81 + 82 + When CRAMFS_BLK_FLAG_DIRECT_PTR is specified then the corresponding 83 + <block> may be located anywhere and not necessarily contiguous with 84 + the previous/next blocks. In that case it is minimally u32-aligned. 85 + If CRAMFS_BLK_FLAG_UNCOMPRESSED is also specified then the size is always 86 + blksize except for the last block which is limited by the file length. 87 + If CRAMFS_BLK_FLAG_DIRECT_PTR is set and CRAMFS_BLK_FLAG_UNCOMPRESSED 88 + is not set then the first 2 bytes of the block contains the size of the 89 + remaining block data as this cannot be determined from the placement of 90 + logically adjacent blocks. 62 91 63 92 64 93 Holes
+452 -63
fs/cramfs/inode.c
··· 15 15 16 16 #include <linux/module.h> 17 17 #include <linux/fs.h> 18 + #include <linux/file.h> 18 19 #include <linux/pagemap.h> 20 + #include <linux/pfn_t.h> 21 + #include <linux/ramfs.h> 19 22 #include <linux/init.h> 20 23 #include <linux/string.h> 21 24 #include <linux/blkdev.h> 25 + #include <linux/mtd/mtd.h> 26 + #include <linux/mtd/super.h> 22 27 #include <linux/slab.h> 23 28 #include <linux/vfs.h> 24 29 #include <linux/mutex.h> ··· 41 36 unsigned long blocks; 42 37 unsigned long files; 43 38 unsigned long flags; 39 + void *linear_virt_addr; 40 + resource_size_t linear_phys_addr; 41 + size_t mtd_point_size; 44 42 }; 45 43 46 44 static inline struct cramfs_sb_info *CRAMFS_SB(struct super_block *sb) ··· 54 46 static const struct super_operations cramfs_ops; 55 47 static const struct inode_operations cramfs_dir_inode_operations; 56 48 static const struct file_operations cramfs_directory_operations; 49 + static const struct file_operations cramfs_physmem_fops; 57 50 static const struct address_space_operations cramfs_aops; 58 51 59 52 static DEFINE_MUTEX(read_mutex); ··· 102 93 case S_IFREG: 103 94 inode->i_fop = &generic_ro_fops; 104 95 inode->i_data.a_ops = &cramfs_aops; 96 + if (IS_ENABLED(CONFIG_CRAMFS_MTD) && 97 + CRAMFS_SB(sb)->flags & CRAMFS_FLAG_EXT_BLOCK_POINTERS && 98 + CRAMFS_SB(sb)->linear_phys_addr) 99 + inode->i_fop = &cramfs_physmem_fops; 105 100 break; 106 101 case S_IFDIR: 107 102 inode->i_op = &cramfs_dir_inode_operations; ··· 153 140 * BLKS_PER_BUF*PAGE_SIZE, so that the caller doesn't need to 154 141 * worry about end-of-buffer issues even when decompressing a full 155 142 * page cache. 143 + * 144 + * Note: This is all optimized away at compile time when 145 + * CONFIG_CRAMFS_BLOCKDEV=n. 156 146 */ 157 147 #define READ_BUFFERS (2) 158 148 /* NEXT_BUFFER(): Loop over [0..(READ_BUFFERS-1)]. */ ··· 176 160 static int next_buffer; 177 161 178 162 /* 179 - * Returns a pointer to a buffer containing at least LEN bytes of 180 - * filesystem starting at byte offset OFFSET into the filesystem. 163 + * Populate our block cache and return a pointer to it. 181 164 */ 182 - static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len) 165 + static void *cramfs_blkdev_read(struct super_block *sb, unsigned int offset, 166 + unsigned int len) 183 167 { 184 168 struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping; 185 169 struct page *pages[BLKS_PER_BUF]; ··· 255 239 return read_buffers[buffer] + offset; 256 240 } 257 241 242 + /* 243 + * Return a pointer to the linearly addressed cramfs image in memory. 244 + */ 245 + static void *cramfs_direct_read(struct super_block *sb, unsigned int offset, 246 + unsigned int len) 247 + { 248 + struct cramfs_sb_info *sbi = CRAMFS_SB(sb); 249 + 250 + if (!len) 251 + return NULL; 252 + if (len > sbi->size || offset > sbi->size - len) 253 + return page_address(ZERO_PAGE(0)); 254 + return sbi->linear_virt_addr + offset; 255 + } 256 + 257 + /* 258 + * Returns a pointer to a buffer containing at least LEN bytes of 259 + * filesystem starting at byte offset OFFSET into the filesystem. 260 + */ 261 + static void *cramfs_read(struct super_block *sb, unsigned int offset, 262 + unsigned int len) 263 + { 264 + struct cramfs_sb_info *sbi = CRAMFS_SB(sb); 265 + 266 + if (IS_ENABLED(CONFIG_CRAMFS_MTD) && sbi->linear_virt_addr) 267 + return cramfs_direct_read(sb, offset, len); 268 + else if (IS_ENABLED(CONFIG_CRAMFS_BLOCKDEV)) 269 + return cramfs_blkdev_read(sb, offset, len); 270 + else 271 + return NULL; 272 + } 273 + 274 + /* 275 + * For a mapping to be possible, we need a range of uncompressed and 276 + * contiguous blocks. Return the offset for the first block and number of 277 + * valid blocks for which that is true, or zero otherwise. 278 + */ 279 + static u32 cramfs_get_block_range(struct inode *inode, u32 pgoff, u32 *pages) 280 + { 281 + struct cramfs_sb_info *sbi = CRAMFS_SB(inode->i_sb); 282 + int i; 283 + u32 *blockptrs, first_block_addr; 284 + 285 + /* 286 + * We can dereference memory directly here as this code may be 287 + * reached only when there is a direct filesystem image mapping 288 + * available in memory. 289 + */ 290 + blockptrs = (u32 *)(sbi->linear_virt_addr + OFFSET(inode) + pgoff * 4); 291 + first_block_addr = blockptrs[0] & ~CRAMFS_BLK_FLAGS; 292 + i = 0; 293 + do { 294 + u32 block_off = i * (PAGE_SIZE >> CRAMFS_BLK_DIRECT_PTR_SHIFT); 295 + u32 expect = (first_block_addr + block_off) | 296 + CRAMFS_BLK_FLAG_DIRECT_PTR | 297 + CRAMFS_BLK_FLAG_UNCOMPRESSED; 298 + if (blockptrs[i] != expect) { 299 + pr_debug("range: block %d/%d got %#x expects %#x\n", 300 + pgoff+i, pgoff + *pages - 1, 301 + blockptrs[i], expect); 302 + if (i == 0) 303 + return 0; 304 + break; 305 + } 306 + } while (++i < *pages); 307 + 308 + *pages = i; 309 + return first_block_addr << CRAMFS_BLK_DIRECT_PTR_SHIFT; 310 + } 311 + 312 + #ifdef CONFIG_MMU 313 + 314 + /* 315 + * Return true if the last page of a file in the filesystem image contains 316 + * some other data that doesn't belong to that file. It is assumed that the 317 + * last block is CRAMFS_BLK_FLAG_DIRECT_PTR | CRAMFS_BLK_FLAG_UNCOMPRESSED 318 + * (verified by cramfs_get_block_range() and directly accessible in memory. 319 + */ 320 + static bool cramfs_last_page_is_shared(struct inode *inode) 321 + { 322 + struct cramfs_sb_info *sbi = CRAMFS_SB(inode->i_sb); 323 + u32 partial, last_page, blockaddr, *blockptrs; 324 + char *tail_data; 325 + 326 + partial = offset_in_page(inode->i_size); 327 + if (!partial) 328 + return false; 329 + last_page = inode->i_size >> PAGE_SHIFT; 330 + blockptrs = (u32 *)(sbi->linear_virt_addr + OFFSET(inode)); 331 + blockaddr = blockptrs[last_page] & ~CRAMFS_BLK_FLAGS; 332 + blockaddr <<= CRAMFS_BLK_DIRECT_PTR_SHIFT; 333 + tail_data = sbi->linear_virt_addr + blockaddr + partial; 334 + return memchr_inv(tail_data, 0, PAGE_SIZE - partial) ? true : false; 335 + } 336 + 337 + static int cramfs_physmem_mmap(struct file *file, struct vm_area_struct *vma) 338 + { 339 + struct inode *inode = file_inode(file); 340 + struct cramfs_sb_info *sbi = CRAMFS_SB(inode->i_sb); 341 + unsigned int pages, max_pages, offset; 342 + unsigned long address, pgoff = vma->vm_pgoff; 343 + char *bailout_reason; 344 + int ret; 345 + 346 + ret = generic_file_readonly_mmap(file, vma); 347 + if (ret) 348 + return ret; 349 + 350 + /* 351 + * Now try to pre-populate ptes for this vma with a direct 352 + * mapping avoiding memory allocation when possible. 353 + */ 354 + 355 + /* Could COW work here? */ 356 + bailout_reason = "vma is writable"; 357 + if (vma->vm_flags & VM_WRITE) 358 + goto bailout; 359 + 360 + max_pages = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT; 361 + bailout_reason = "beyond file limit"; 362 + if (pgoff >= max_pages) 363 + goto bailout; 364 + pages = min(vma_pages(vma), max_pages - pgoff); 365 + 366 + offset = cramfs_get_block_range(inode, pgoff, &pages); 367 + bailout_reason = "unsuitable block layout"; 368 + if (!offset) 369 + goto bailout; 370 + address = sbi->linear_phys_addr + offset; 371 + bailout_reason = "data is not page aligned"; 372 + if (!PAGE_ALIGNED(address)) 373 + goto bailout; 374 + 375 + /* Don't map the last page if it contains some other data */ 376 + if (pgoff + pages == max_pages && cramfs_last_page_is_shared(inode)) { 377 + pr_debug("mmap: %s: last page is shared\n", 378 + file_dentry(file)->d_name.name); 379 + pages--; 380 + } 381 + 382 + if (!pages) { 383 + bailout_reason = "no suitable block remaining"; 384 + goto bailout; 385 + } 386 + 387 + if (pages == vma_pages(vma)) { 388 + /* 389 + * The entire vma is mappable. remap_pfn_range() will 390 + * make it distinguishable from a non-direct mapping 391 + * in /proc/<pid>/maps by substituting the file offset 392 + * with the actual physical address. 393 + */ 394 + ret = remap_pfn_range(vma, vma->vm_start, address >> PAGE_SHIFT, 395 + pages * PAGE_SIZE, vma->vm_page_prot); 396 + } else { 397 + /* 398 + * Let's create a mixed map if we can't map it all. 399 + * The normal paging machinery will take care of the 400 + * unpopulated ptes via cramfs_readpage(). 401 + */ 402 + int i; 403 + vma->vm_flags |= VM_MIXEDMAP; 404 + for (i = 0; i < pages && !ret; i++) { 405 + unsigned long off = i * PAGE_SIZE; 406 + pfn_t pfn = phys_to_pfn_t(address + off, PFN_DEV); 407 + ret = vm_insert_mixed(vma, vma->vm_start + off, pfn); 408 + } 409 + } 410 + 411 + if (!ret) 412 + pr_debug("mapped %s[%lu] at 0x%08lx (%u/%lu pages) " 413 + "to vma 0x%08lx, page_prot 0x%llx\n", 414 + file_dentry(file)->d_name.name, pgoff, 415 + address, pages, vma_pages(vma), vma->vm_start, 416 + (unsigned long long)pgprot_val(vma->vm_page_prot)); 417 + return ret; 418 + 419 + bailout: 420 + pr_debug("%s[%lu]: direct mmap impossible: %s\n", 421 + file_dentry(file)->d_name.name, pgoff, bailout_reason); 422 + /* Didn't manage any direct map, but normal paging is still possible */ 423 + return 0; 424 + } 425 + 426 + #else /* CONFIG_MMU */ 427 + 428 + static int cramfs_physmem_mmap(struct file *file, struct vm_area_struct *vma) 429 + { 430 + return vma->vm_flags & (VM_SHARED | VM_MAYSHARE) ? 0 : -ENOSYS; 431 + } 432 + 433 + static unsigned long cramfs_physmem_get_unmapped_area(struct file *file, 434 + unsigned long addr, unsigned long len, 435 + unsigned long pgoff, unsigned long flags) 436 + { 437 + struct inode *inode = file_inode(file); 438 + struct super_block *sb = inode->i_sb; 439 + struct cramfs_sb_info *sbi = CRAMFS_SB(sb); 440 + unsigned int pages, block_pages, max_pages, offset; 441 + 442 + pages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; 443 + max_pages = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT; 444 + if (pgoff >= max_pages || pages > max_pages - pgoff) 445 + return -EINVAL; 446 + block_pages = pages; 447 + offset = cramfs_get_block_range(inode, pgoff, &block_pages); 448 + if (!offset || block_pages != pages) 449 + return -ENOSYS; 450 + addr = sbi->linear_phys_addr + offset; 451 + pr_debug("get_unmapped for %s ofs %#lx siz %lu at 0x%08lx\n", 452 + file_dentry(file)->d_name.name, pgoff*PAGE_SIZE, len, addr); 453 + return addr; 454 + } 455 + 456 + static unsigned int cramfs_physmem_mmap_capabilities(struct file *file) 457 + { 458 + return NOMMU_MAP_COPY | NOMMU_MAP_DIRECT | 459 + NOMMU_MAP_READ | NOMMU_MAP_EXEC; 460 + } 461 + 462 + #endif /* CONFIG_MMU */ 463 + 464 + static const struct file_operations cramfs_physmem_fops = { 465 + .llseek = generic_file_llseek, 466 + .read_iter = generic_file_read_iter, 467 + .splice_read = generic_file_splice_read, 468 + .mmap = cramfs_physmem_mmap, 469 + #ifndef CONFIG_MMU 470 + .get_unmapped_area = cramfs_physmem_get_unmapped_area, 471 + .mmap_capabilities = cramfs_physmem_mmap_capabilities, 472 + #endif 473 + }; 474 + 258 475 static void cramfs_kill_sb(struct super_block *sb) 259 476 { 260 477 struct cramfs_sb_info *sbi = CRAMFS_SB(sb); 261 478 262 - kill_block_super(sb); 479 + if (IS_ENABLED(CCONFIG_CRAMFS_MTD) && sb->s_mtd) { 480 + if (sbi && sbi->mtd_point_size) 481 + mtd_unpoint(sb->s_mtd, 0, sbi->mtd_point_size); 482 + kill_mtd_super(sb); 483 + } else if (IS_ENABLED(CONFIG_CRAMFS_BLOCKDEV) && sb->s_bdev) { 484 + kill_block_super(sb); 485 + } 263 486 kfree(sbi); 264 487 } 265 488 ··· 509 254 return 0; 510 255 } 511 256 512 - static int cramfs_fill_super(struct super_block *sb, void *data, int silent) 257 + static int cramfs_read_super(struct super_block *sb, 258 + struct cramfs_super *super, int silent) 513 259 { 514 - int i; 515 - struct cramfs_super super; 260 + struct cramfs_sb_info *sbi = CRAMFS_SB(sb); 516 261 unsigned long root_offset; 517 - struct cramfs_sb_info *sbi; 518 - struct inode *root; 519 262 520 - sb->s_flags |= MS_RDONLY; 521 - 522 - sbi = kzalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL); 523 - if (!sbi) 524 - return -ENOMEM; 525 - sb->s_fs_info = sbi; 526 - 527 - /* Invalidate the read buffers on mount: think disk change.. */ 528 - mutex_lock(&read_mutex); 529 - for (i = 0; i < READ_BUFFERS; i++) 530 - buffer_blocknr[i] = -1; 263 + /* We don't know the real size yet */ 264 + sbi->size = PAGE_SIZE; 531 265 532 266 /* Read the first block and get the superblock from it */ 533 - memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super)); 267 + mutex_lock(&read_mutex); 268 + memcpy(super, cramfs_read(sb, 0, sizeof(*super)), sizeof(*super)); 534 269 mutex_unlock(&read_mutex); 535 270 536 271 /* Do sanity checks on the superblock */ 537 - if (super.magic != CRAMFS_MAGIC) { 272 + if (super->magic != CRAMFS_MAGIC) { 538 273 /* check for wrong endianness */ 539 - if (super.magic == CRAMFS_MAGIC_WEND) { 274 + if (super->magic == CRAMFS_MAGIC_WEND) { 540 275 if (!silent) 541 276 pr_err("wrong endianness\n"); 542 277 return -EINVAL; ··· 534 289 535 290 /* check at 512 byte offset */ 536 291 mutex_lock(&read_mutex); 537 - memcpy(&super, cramfs_read(sb, 512, sizeof(super)), sizeof(super)); 292 + memcpy(super, 293 + cramfs_read(sb, 512, sizeof(*super)), 294 + sizeof(*super)); 538 295 mutex_unlock(&read_mutex); 539 - if (super.magic != CRAMFS_MAGIC) { 540 - if (super.magic == CRAMFS_MAGIC_WEND && !silent) 296 + if (super->magic != CRAMFS_MAGIC) { 297 + if (super->magic == CRAMFS_MAGIC_WEND && !silent) 541 298 pr_err("wrong endianness\n"); 542 299 else if (!silent) 543 300 pr_err("wrong magic\n"); ··· 548 301 } 549 302 550 303 /* get feature flags first */ 551 - if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) { 304 + if (super->flags & ~CRAMFS_SUPPORTED_FLAGS) { 552 305 pr_err("unsupported filesystem features\n"); 553 306 return -EINVAL; 554 307 } 555 308 556 309 /* Check that the root inode is in a sane state */ 557 - if (!S_ISDIR(super.root.mode)) { 310 + if (!S_ISDIR(super->root.mode)) { 558 311 pr_err("root is not a directory\n"); 559 312 return -EINVAL; 560 313 } 561 314 /* correct strange, hard-coded permissions of mkcramfs */ 562 - super.root.mode |= (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); 315 + super->root.mode |= 0555; 563 316 564 - root_offset = super.root.offset << 2; 565 - if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) { 566 - sbi->size = super.size; 567 - sbi->blocks = super.fsid.blocks; 568 - sbi->files = super.fsid.files; 317 + root_offset = super->root.offset << 2; 318 + if (super->flags & CRAMFS_FLAG_FSID_VERSION_2) { 319 + sbi->size = super->size; 320 + sbi->blocks = super->fsid.blocks; 321 + sbi->files = super->fsid.files; 569 322 } else { 570 323 sbi->size = 1<<28; 571 324 sbi->blocks = 0; 572 325 sbi->files = 0; 573 326 } 574 - sbi->magic = super.magic; 575 - sbi->flags = super.flags; 327 + sbi->magic = super->magic; 328 + sbi->flags = super->flags; 576 329 if (root_offset == 0) 577 330 pr_info("empty filesystem"); 578 - else if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && 331 + else if (!(super->flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && 579 332 ((root_offset != sizeof(struct cramfs_super)) && 580 333 (root_offset != 512 + sizeof(struct cramfs_super)))) 581 334 { ··· 583 336 return -EINVAL; 584 337 } 585 338 339 + return 0; 340 + } 341 + 342 + static int cramfs_finalize_super(struct super_block *sb, 343 + struct cramfs_inode *cramfs_root) 344 + { 345 + struct inode *root; 346 + 586 347 /* Set it all up.. */ 348 + sb->s_flags |= MS_RDONLY; 587 349 sb->s_op = &cramfs_ops; 588 - root = get_cramfs_inode(sb, &super.root, 0); 350 + root = get_cramfs_inode(sb, cramfs_root, 0); 589 351 if (IS_ERR(root)) 590 352 return PTR_ERR(root); 591 353 sb->s_root = d_make_root(root); ··· 603 347 return 0; 604 348 } 605 349 350 + static int cramfs_blkdev_fill_super(struct super_block *sb, void *data, 351 + int silent) 352 + { 353 + struct cramfs_sb_info *sbi; 354 + struct cramfs_super super; 355 + int i, err; 356 + 357 + sbi = kzalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL); 358 + if (!sbi) 359 + return -ENOMEM; 360 + sb->s_fs_info = sbi; 361 + 362 + /* Invalidate the read buffers on mount: think disk change.. */ 363 + for (i = 0; i < READ_BUFFERS; i++) 364 + buffer_blocknr[i] = -1; 365 + 366 + err = cramfs_read_super(sb, &super, silent); 367 + if (err) 368 + return err; 369 + return cramfs_finalize_super(sb, &super.root); 370 + } 371 + 372 + static int cramfs_mtd_fill_super(struct super_block *sb, void *data, 373 + int silent) 374 + { 375 + struct cramfs_sb_info *sbi; 376 + struct cramfs_super super; 377 + int err; 378 + 379 + sbi = kzalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL); 380 + if (!sbi) 381 + return -ENOMEM; 382 + sb->s_fs_info = sbi; 383 + 384 + /* Map only one page for now. Will remap it when fs size is known. */ 385 + err = mtd_point(sb->s_mtd, 0, PAGE_SIZE, &sbi->mtd_point_size, 386 + &sbi->linear_virt_addr, &sbi->linear_phys_addr); 387 + if (err || sbi->mtd_point_size != PAGE_SIZE) { 388 + pr_err("unable to get direct memory access to mtd:%s\n", 389 + sb->s_mtd->name); 390 + return err ? : -ENODATA; 391 + } 392 + 393 + pr_info("checking physical address %pap for linear cramfs image\n", 394 + &sbi->linear_phys_addr); 395 + err = cramfs_read_super(sb, &super, silent); 396 + if (err) 397 + return err; 398 + 399 + /* Remap the whole filesystem now */ 400 + pr_info("linear cramfs image on mtd:%s appears to be %lu KB in size\n", 401 + sb->s_mtd->name, sbi->size/1024); 402 + mtd_unpoint(sb->s_mtd, 0, PAGE_SIZE); 403 + err = mtd_point(sb->s_mtd, 0, sbi->size, &sbi->mtd_point_size, 404 + &sbi->linear_virt_addr, &sbi->linear_phys_addr); 405 + if (err || sbi->mtd_point_size != sbi->size) { 406 + pr_err("unable to get direct memory access to mtd:%s\n", 407 + sb->s_mtd->name); 408 + return err ? : -ENODATA; 409 + } 410 + 411 + return cramfs_finalize_super(sb, &super.root); 412 + } 413 + 606 414 static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf) 607 415 { 608 416 struct super_block *sb = dentry->d_sb; 609 - u64 id = huge_encode_dev(sb->s_bdev->bd_dev); 417 + u64 id = 0; 418 + 419 + if (sb->s_bdev) 420 + id = huge_encode_dev(sb->s_bdev->bd_dev); 421 + else if (sb->s_dev) 422 + id = huge_encode_dev(sb->s_dev); 610 423 611 424 buf->f_type = CRAMFS_MAGIC; 612 425 buf->f_bsize = PAGE_SIZE; ··· 827 502 828 503 if (page->index < maxblock) { 829 504 struct super_block *sb = inode->i_sb; 830 - u32 blkptr_offset = OFFSET(inode) + page->index*4; 831 - u32 start_offset, compr_len; 505 + u32 blkptr_offset = OFFSET(inode) + page->index * 4; 506 + u32 block_ptr, block_start, block_len; 507 + bool uncompressed, direct; 832 508 833 - start_offset = OFFSET(inode) + maxblock*4; 834 509 mutex_lock(&read_mutex); 835 - if (page->index) 836 - start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, 837 - 4); 838 - compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - 839 - start_offset); 840 - mutex_unlock(&read_mutex); 510 + block_ptr = *(u32 *) cramfs_read(sb, blkptr_offset, 4); 511 + uncompressed = (block_ptr & CRAMFS_BLK_FLAG_UNCOMPRESSED); 512 + direct = (block_ptr & CRAMFS_BLK_FLAG_DIRECT_PTR); 513 + block_ptr &= ~CRAMFS_BLK_FLAGS; 841 514 842 - if (compr_len == 0) 843 - ; /* hole */ 844 - else if (unlikely(compr_len > (PAGE_SIZE << 1))) { 845 - pr_err("bad compressed blocksize %u\n", 846 - compr_len); 847 - goto err; 515 + if (direct) { 516 + /* 517 + * The block pointer is an absolute start pointer, 518 + * shifted by 2 bits. The size is included in the 519 + * first 2 bytes of the data block when compressed, 520 + * or PAGE_SIZE otherwise. 521 + */ 522 + block_start = block_ptr << CRAMFS_BLK_DIRECT_PTR_SHIFT; 523 + if (uncompressed) { 524 + block_len = PAGE_SIZE; 525 + /* if last block: cap to file length */ 526 + if (page->index == maxblock - 1) 527 + block_len = 528 + offset_in_page(inode->i_size); 529 + } else { 530 + block_len = *(u16 *) 531 + cramfs_read(sb, block_start, 2); 532 + block_start += 2; 533 + } 848 534 } else { 849 - mutex_lock(&read_mutex); 535 + /* 536 + * The block pointer indicates one past the end of 537 + * the current block (start of next block). If this 538 + * is the first block then it starts where the block 539 + * pointer table ends, otherwise its start comes 540 + * from the previous block's pointer. 541 + */ 542 + block_start = OFFSET(inode) + maxblock * 4; 543 + if (page->index) 544 + block_start = *(u32 *) 545 + cramfs_read(sb, blkptr_offset - 4, 4); 546 + /* Beware... previous ptr might be a direct ptr */ 547 + if (unlikely(block_start & CRAMFS_BLK_FLAG_DIRECT_PTR)) { 548 + /* See comments on earlier code. */ 549 + u32 prev_start = block_start; 550 + block_start = prev_start & ~CRAMFS_BLK_FLAGS; 551 + block_start <<= CRAMFS_BLK_DIRECT_PTR_SHIFT; 552 + if (prev_start & CRAMFS_BLK_FLAG_UNCOMPRESSED) { 553 + block_start += PAGE_SIZE; 554 + } else { 555 + block_len = *(u16 *) 556 + cramfs_read(sb, block_start, 2); 557 + block_start += 2 + block_len; 558 + } 559 + } 560 + block_start &= ~CRAMFS_BLK_FLAGS; 561 + block_len = block_ptr - block_start; 562 + } 563 + 564 + if (block_len == 0) 565 + ; /* hole */ 566 + else if (unlikely(block_len > 2*PAGE_SIZE || 567 + (uncompressed && block_len > PAGE_SIZE))) { 568 + mutex_unlock(&read_mutex); 569 + pr_err("bad data blocksize %u\n", block_len); 570 + goto err; 571 + } else if (uncompressed) { 572 + memcpy(pgdata, 573 + cramfs_read(sb, block_start, block_len), 574 + block_len); 575 + bytes_filled = block_len; 576 + } else { 850 577 bytes_filled = cramfs_uncompress_block(pgdata, 851 578 PAGE_SIZE, 852 - cramfs_read(sb, start_offset, compr_len), 853 - compr_len); 854 - mutex_unlock(&read_mutex); 855 - if (unlikely(bytes_filled < 0)) 856 - goto err; 579 + cramfs_read(sb, block_start, block_len), 580 + block_len); 857 581 } 582 + mutex_unlock(&read_mutex); 583 + if (unlikely(bytes_filled < 0)) 584 + goto err; 858 585 } 859 586 860 587 memset(pgdata + bytes_filled, 0, PAGE_SIZE - bytes_filled); ··· 950 573 .statfs = cramfs_statfs, 951 574 }; 952 575 953 - static struct dentry *cramfs_mount(struct file_system_type *fs_type, 954 - int flags, const char *dev_name, void *data) 576 + static struct dentry *cramfs_mount(struct file_system_type *fs_type, int flags, 577 + const char *dev_name, void *data) 955 578 { 956 - return mount_bdev(fs_type, flags, dev_name, data, cramfs_fill_super); 579 + struct dentry *ret = ERR_PTR(-ENOPROTOOPT); 580 + 581 + if (IS_ENABLED(CONFIG_CRAMFS_MTD)) { 582 + ret = mount_mtd(fs_type, flags, dev_name, data, 583 + cramfs_mtd_fill_super); 584 + if (!IS_ERR(ret)) 585 + return ret; 586 + } 587 + if (IS_ENABLED(CONFIG_CRAMFS_BLOCKDEV)) { 588 + ret = mount_bdev(fs_type, flags, dev_name, data, 589 + cramfs_blkdev_fill_super); 590 + } 591 + return ret; 957 592 } 958 593 959 594 static struct file_system_type cramfs_fs_type = {
+25 -1
include/uapi/linux/cramfs_fs.h
··· 74 74 #define CRAMFS_FLAG_HOLES 0x00000100 /* support for holes */ 75 75 #define CRAMFS_FLAG_WRONG_SIGNATURE 0x00000200 /* reserved */ 76 76 #define CRAMFS_FLAG_SHIFTED_ROOT_OFFSET 0x00000400 /* shifted root fs */ 77 + #define CRAMFS_FLAG_EXT_BLOCK_POINTERS 0x00000800 /* block pointer extensions */ 77 78 78 79 /* 79 80 * Valid values in super.flags. Currently we refuse to mount ··· 84 83 #define CRAMFS_SUPPORTED_FLAGS ( 0x000000ff \ 85 84 | CRAMFS_FLAG_HOLES \ 86 85 | CRAMFS_FLAG_WRONG_SIGNATURE \ 87 - | CRAMFS_FLAG_SHIFTED_ROOT_OFFSET ) 86 + | CRAMFS_FLAG_SHIFTED_ROOT_OFFSET \ 87 + | CRAMFS_FLAG_EXT_BLOCK_POINTERS ) 88 88 89 + /* 90 + * Block pointer flags 91 + * 92 + * The maximum block offset that needs to be represented is roughly: 93 + * 94 + * (1 << CRAMFS_OFFSET_WIDTH) * 4 + 95 + * (1 << CRAMFS_SIZE_WIDTH) / PAGE_SIZE * (4 + PAGE_SIZE) 96 + * = 0x11004000 97 + * 98 + * That leaves room for 3 flag bits in the block pointer table. 99 + */ 100 + #define CRAMFS_BLK_FLAG_UNCOMPRESSED (1 << 31) 101 + #define CRAMFS_BLK_FLAG_DIRECT_PTR (1 << 30) 102 + 103 + #define CRAMFS_BLK_FLAGS ( CRAMFS_BLK_FLAG_UNCOMPRESSED \ 104 + | CRAMFS_BLK_FLAG_DIRECT_PTR ) 105 + 106 + /* 107 + * Direct blocks are at least 4-byte aligned. 108 + * Pointers to direct blocks are shifted down by 2 bits. 109 + */ 110 + #define CRAMFS_BLK_DIRECT_PTR_SHIFT 2 89 111 90 112 #endif /* _UAPI__CRAMFS_H */