History

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

Linus Torvalds committed 8 years ago

Commit cbda1b22 parents ca5b857 8d595986 files · +584 −69Browse files

Unified · Split

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