19
19
#include <linux/init.h>
20
20
#include <linux/string.h>
21
21
#include <linux/blkdev.h>
22
+ #include <linux/mtd/mtd.h>
23
+ #include <linux/mtd/super.h>
22
24
#include <linux/slab.h>
23
25
#include <linux/vfs.h>
24
26
#include <linux/mutex.h>
@@ -36,6 +38,9 @@ struct cramfs_sb_info {
36
38
unsigned long blocks ;
37
39
unsigned long files ;
38
40
unsigned long flags ;
41
+ void * linear_virt_addr ;
42
+ resource_size_t linear_phys_addr ;
43
+ size_t mtd_point_size ;
39
44
};
40
45
41
46
static inline struct cramfs_sb_info * CRAMFS_SB (struct super_block * sb )
@@ -140,6 +145,9 @@ static struct inode *get_cramfs_inode(struct super_block *sb,
140
145
* BLKS_PER_BUF*PAGE_SIZE, so that the caller doesn't need to
141
146
* worry about end-of-buffer issues even when decompressing a full
142
147
* page cache.
148
+ *
149
+ * Note: This is all optimized away at compile time when
150
+ * CONFIG_CRAMFS_BLOCKDEV=n.
143
151
*/
144
152
#define READ_BUFFERS (2)
145
153
/* NEXT_BUFFER(): Loop over [0..(READ_BUFFERS-1)]. */
@@ -160,10 +168,10 @@ static struct super_block *buffer_dev[READ_BUFFERS];
160
168
static int next_buffer ;
161
169
162
170
/*
163
- * Returns a pointer to a buffer containing at least LEN bytes of
164
- * filesystem starting at byte offset OFFSET into the filesystem.
171
+ * Populate our block cache and return a pointer to it.
165
172
*/
166
- static void * cramfs_read (struct super_block * sb , unsigned int offset , unsigned int len )
173
+ static void * cramfs_blkdev_read (struct super_block * sb , unsigned int offset ,
174
+ unsigned int len )
167
175
{
168
176
struct address_space * mapping = sb -> s_bdev -> bd_inode -> i_mapping ;
169
177
struct page * pages [BLKS_PER_BUF ];
@@ -239,11 +247,49 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
239
247
return read_buffers [buffer ] + offset ;
240
248
}
241
249
250
+ /*
251
+ * Return a pointer to the linearly addressed cramfs image in memory.
252
+ */
253
+ static void * cramfs_direct_read (struct super_block * sb , unsigned int offset ,
254
+ unsigned int len )
255
+ {
256
+ struct cramfs_sb_info * sbi = CRAMFS_SB (sb );
257
+
258
+ if (!len )
259
+ return NULL ;
260
+ if (len > sbi -> size || offset > sbi -> size - len )
261
+ return page_address (ZERO_PAGE (0 ));
262
+ return sbi -> linear_virt_addr + offset ;
263
+ }
264
+
265
+ /*
266
+ * Returns a pointer to a buffer containing at least LEN bytes of
267
+ * filesystem starting at byte offset OFFSET into the filesystem.
268
+ */
269
+ static void * cramfs_read (struct super_block * sb , unsigned int offset ,
270
+ unsigned int len )
271
+ {
272
+ struct cramfs_sb_info * sbi = CRAMFS_SB (sb );
273
+
274
+ if (IS_ENABLED (CONFIG_CRAMFS_MTD ) && sbi -> linear_virt_addr )
275
+ return cramfs_direct_read (sb , offset , len );
276
+ else if (IS_ENABLED (CONFIG_CRAMFS_BLOCKDEV ))
277
+ return cramfs_blkdev_read (sb , offset , len );
278
+ else
279
+ return NULL ;
280
+ }
281
+
242
282
static void cramfs_kill_sb (struct super_block * sb )
243
283
{
244
284
struct cramfs_sb_info * sbi = CRAMFS_SB (sb );
245
285
246
- kill_block_super (sb );
286
+ if (IS_ENABLED (CCONFIG_CRAMFS_MTD ) && sb -> s_mtd ) {
287
+ if (sbi && sbi -> mtd_point_size )
288
+ mtd_unpoint (sb -> s_mtd , 0 , sbi -> mtd_point_size );
289
+ kill_mtd_super (sb );
290
+ } else if (IS_ENABLED (CONFIG_CRAMFS_BLOCKDEV ) && sb -> s_bdev ) {
291
+ kill_block_super (sb );
292
+ }
247
293
kfree (sbi );
248
294
}
249
295
@@ -254,45 +300,37 @@ static int cramfs_remount(struct super_block *sb, int *flags, char *data)
254
300
return 0 ;
255
301
}
256
302
257
- static int cramfs_fill_super (struct super_block * sb , void * data , int silent )
303
+ static int cramfs_read_super (struct super_block * sb ,
304
+ struct cramfs_super * super , int silent )
258
305
{
259
- int i ;
260
- struct cramfs_super super ;
306
+ struct cramfs_sb_info * sbi = CRAMFS_SB (sb );
261
307
unsigned long root_offset ;
262
- struct cramfs_sb_info * sbi ;
263
- struct inode * root ;
264
-
265
- sb -> s_flags |= MS_RDONLY ;
266
-
267
- sbi = kzalloc (sizeof (struct cramfs_sb_info ), GFP_KERNEL );
268
- if (!sbi )
269
- return - ENOMEM ;
270
- sb -> s_fs_info = sbi ;
271
308
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 ;
309
+ /* We don't know the real size yet */
310
+ sbi -> size = PAGE_SIZE ;
276
311
277
312
/* Read the first block and get the superblock from it */
278
- memcpy (& super , cramfs_read (sb , 0 , sizeof (super )), sizeof (super ));
313
+ mutex_lock (& read_mutex );
314
+ memcpy (super , cramfs_read (sb , 0 , sizeof (* super )), sizeof (* super ));
279
315
mutex_unlock (& read_mutex );
280
316
281
317
/* Do sanity checks on the superblock */
282
- if (super . magic != CRAMFS_MAGIC ) {
318
+ if (super -> magic != CRAMFS_MAGIC ) {
283
319
/* check for wrong endianness */
284
- if (super . magic == CRAMFS_MAGIC_WEND ) {
320
+ if (super -> magic == CRAMFS_MAGIC_WEND ) {
285
321
if (!silent )
286
322
pr_err ("wrong endianness\n" );
287
323
return - EINVAL ;
288
324
}
289
325
290
326
/* check at 512 byte offset */
291
327
mutex_lock (& read_mutex );
292
- memcpy (& super , cramfs_read (sb , 512 , sizeof (super )), sizeof (super ));
328
+ memcpy (super ,
329
+ cramfs_read (sb , 512 , sizeof (* super )),
330
+ sizeof (* super ));
293
331
mutex_unlock (& read_mutex );
294
- if (super . magic != CRAMFS_MAGIC ) {
295
- if (super . magic == CRAMFS_MAGIC_WEND && !silent )
332
+ if (super -> magic != CRAMFS_MAGIC ) {
333
+ if (super -> magic == CRAMFS_MAGIC_WEND && !silent )
296
334
pr_err ("wrong endianness\n" );
297
335
else if (!silent )
298
336
pr_err ("wrong magic\n" );
@@ -301,44 +339,53 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
301
339
}
302
340
303
341
/* get feature flags first */
304
- if (super . flags & ~CRAMFS_SUPPORTED_FLAGS ) {
342
+ if (super -> flags & ~CRAMFS_SUPPORTED_FLAGS ) {
305
343
pr_err ("unsupported filesystem features\n" );
306
344
return - EINVAL ;
307
345
}
308
346
309
347
/* Check that the root inode is in a sane state */
310
- if (!S_ISDIR (super . root .mode )) {
348
+ if (!S_ISDIR (super -> root .mode )) {
311
349
pr_err ("root is not a directory\n" );
312
350
return - EINVAL ;
313
351
}
314
352
/* correct strange, hard-coded permissions of mkcramfs */
315
- super . root .mode |= ( S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH ) ;
353
+ super -> root .mode |= 0555 ;
316
354
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 ;
355
+ root_offset = super -> root .offset << 2 ;
356
+ if (super -> flags & CRAMFS_FLAG_FSID_VERSION_2 ) {
357
+ sbi -> size = super -> size ;
358
+ sbi -> blocks = super -> fsid .blocks ;
359
+ sbi -> files = super -> fsid .files ;
322
360
} else {
323
361
sbi -> size = 1 <<28 ;
324
362
sbi -> blocks = 0 ;
325
363
sbi -> files = 0 ;
326
364
}
327
- sbi -> magic = super . magic ;
328
- sbi -> flags = super . flags ;
365
+ sbi -> magic = super -> magic ;
366
+ sbi -> flags = super -> flags ;
329
367
if (root_offset == 0 )
330
368
pr_info ("empty filesystem" );
331
- else if (!(super . flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET ) &&
369
+ else if (!(super -> flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET ) &&
332
370
((root_offset != sizeof (struct cramfs_super )) &&
333
371
(root_offset != 512 + sizeof (struct cramfs_super ))))
334
372
{
335
373
pr_err ("bad root offset %lu\n" , root_offset );
336
374
return - EINVAL ;
337
375
}
338
376
377
+ return 0 ;
378
+ }
379
+
380
+ static int cramfs_finalize_super (struct super_block * sb ,
381
+ struct cramfs_inode * cramfs_root )
382
+ {
383
+ struct inode * root ;
384
+
339
385
/* Set it all up.. */
386
+ sb -> s_flags |= MS_RDONLY ;
340
387
sb -> s_op = & cramfs_ops ;
341
- root = get_cramfs_inode (sb , & super . root , 0 );
388
+ root = get_cramfs_inode (sb , cramfs_root , 0 );
342
389
if (IS_ERR (root ))
343
390
return PTR_ERR (root );
344
391
sb -> s_root = d_make_root (root );
@@ -347,10 +394,79 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
347
394
return 0 ;
348
395
}
349
396
397
+ static int cramfs_blkdev_fill_super (struct super_block * sb , void * data ,
398
+ int silent )
399
+ {
400
+ struct cramfs_sb_info * sbi ;
401
+ struct cramfs_super super ;
402
+ int i , err ;
403
+
404
+ sbi = kzalloc (sizeof (struct cramfs_sb_info ), GFP_KERNEL );
405
+ if (!sbi )
406
+ return - ENOMEM ;
407
+ sb -> s_fs_info = sbi ;
408
+
409
+ /* Invalidate the read buffers on mount: think disk change.. */
410
+ for (i = 0 ; i < READ_BUFFERS ; i ++ )
411
+ buffer_blocknr [i ] = -1 ;
412
+
413
+ err = cramfs_read_super (sb , & super , silent );
414
+ if (err )
415
+ return err ;
416
+ return cramfs_finalize_super (sb , & super .root );
417
+ }
418
+
419
+ static int cramfs_mtd_fill_super (struct super_block * sb , void * data ,
420
+ int silent )
421
+ {
422
+ struct cramfs_sb_info * sbi ;
423
+ struct cramfs_super super ;
424
+ int err ;
425
+
426
+ sbi = kzalloc (sizeof (struct cramfs_sb_info ), GFP_KERNEL );
427
+ if (!sbi )
428
+ return - ENOMEM ;
429
+ sb -> s_fs_info = sbi ;
430
+
431
+ /* Map only one page for now. Will remap it when fs size is known. */
432
+ err = mtd_point (sb -> s_mtd , 0 , PAGE_SIZE , & sbi -> mtd_point_size ,
433
+ & sbi -> linear_virt_addr , & sbi -> linear_phys_addr );
434
+ if (err || sbi -> mtd_point_size != PAGE_SIZE ) {
435
+ pr_err ("unable to get direct memory access to mtd:%s\n" ,
436
+ sb -> s_mtd -> name );
437
+ return err ? : - ENODATA ;
438
+ }
439
+
440
+ pr_info ("checking physical address %pap for linear cramfs image\n" ,
441
+ & sbi -> linear_phys_addr );
442
+ err = cramfs_read_super (sb , & super , silent );
443
+ if (err )
444
+ return err ;
445
+
446
+ /* Remap the whole filesystem now */
447
+ pr_info ("linear cramfs image on mtd:%s appears to be %lu KB in size\n" ,
448
+ sb -> s_mtd -> name , sbi -> size /1024 );
449
+ mtd_unpoint (sb -> s_mtd , 0 , PAGE_SIZE );
450
+ err = mtd_point (sb -> s_mtd , 0 , sbi -> size , & sbi -> mtd_point_size ,
451
+ & sbi -> linear_virt_addr , & sbi -> linear_phys_addr );
452
+ if (err || sbi -> mtd_point_size != sbi -> size ) {
453
+ pr_err ("unable to get direct memory access to mtd:%s\n" ,
454
+ sb -> s_mtd -> name );
455
+ return err ? : - ENODATA ;
456
+ }
457
+
458
+ return cramfs_finalize_super (sb , & super .root );
459
+ }
460
+
350
461
static int cramfs_statfs (struct dentry * dentry , struct kstatfs * buf )
351
462
{
352
463
struct super_block * sb = dentry -> d_sb ;
353
- u64 id = huge_encode_dev (sb -> s_bdev -> bd_dev );
464
+ u64 id = 0 ;
465
+
466
+ if (sb -> s_bdev )
467
+ id = huge_encode_dev (sb -> s_bdev -> bd_dev );
468
+ else if (sb -> s_dev )
469
+ id = huge_encode_dev (sb -> s_dev );
354
470
355
471
buf -> f_type = CRAMFS_MAGIC ;
356
472
buf -> f_bsize = PAGE_SIZE ;
@@ -573,10 +689,22 @@ static const struct super_operations cramfs_ops = {
573
689
.statfs = cramfs_statfs ,
574
690
};
575
691
576
- static struct dentry * cramfs_mount (struct file_system_type * fs_type ,
577
- int flags , const char * dev_name , void * data )
692
+ static struct dentry * cramfs_mount (struct file_system_type * fs_type , int flags ,
693
+ const char * dev_name , void * data )
578
694
{
579
- return mount_bdev (fs_type , flags , dev_name , data , cramfs_fill_super );
695
+ struct dentry * ret = ERR_PTR (- ENOPROTOOPT );
696
+
697
+ if (IS_ENABLED (CONFIG_CRAMFS_MTD )) {
698
+ ret = mount_mtd (fs_type , flags , dev_name , data ,
699
+ cramfs_mtd_fill_super );
700
+ if (!IS_ERR (ret ))
701
+ return ret ;
702
+ }
703
+ if (IS_ENABLED (CONFIG_CRAMFS_BLOCKDEV )) {
704
+ ret = mount_bdev (fs_type , flags , dev_name , data ,
705
+ cramfs_blkdev_fill_super );
706
+ }
707
+ return ret ;
580
708
}
581
709
582
710
static struct file_system_type cramfs_fs_type = {
0 commit comments