~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/romfs/super.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* Block- or MTD-based romfs
  2  *
  3  * Copyright © 2007 Red Hat, Inc. All Rights Reserved.
  4  * Written by David Howells (dhowells@redhat.com)
  5  *
  6  * Derived from: ROMFS file system, Linux implementation
  7  *
  8  * Copyright © 1997-1999  Janos Farkas <chexum@shadow.banki.hu>
  9  *
 10  * Using parts of the minix filesystem
 11  * Copyright © 1991, 1992  Linus Torvalds
 12  *
 13  * and parts of the affs filesystem additionally
 14  * Copyright © 1993  Ray Burr
 15  * Copyright © 1996  Hans-Joachim Widmaier
 16  *
 17  * Changes
 18  *                                      Changed for 2.1.19 modules
 19  *      Jan 1997                        Initial release
 20  *      Jun 1997                        2.1.43+ changes
 21  *                                      Proper page locking in read_folio
 22  *                                      Changed to work with 2.1.45+ fs
 23  *      Jul 1997                        Fixed follow_link
 24  *                      2.1.47
 25  *                                      lookup shouldn't return -ENOENT
 26  *                                      from Horst von Brand:
 27  *                                        fail on wrong checksum
 28  *                                        double unlock_super was possible
 29  *                                        correct namelen for statfs
 30  *                                      spotted by Bill Hawes:
 31  *                                        readlink shouldn't iput()
 32  *      Jun 1998        2.1.106         from Avery Pennarun: glibc scandir()
 33  *                                        exposed a problem in readdir
 34  *                      2.1.107         code-freeze spellchecker run
 35  *      Aug 1998                        2.1.118+ VFS changes
 36  *      Sep 1998        2.1.122         another VFS change (follow_link)
 37  *      Apr 1999        2.2.7           no more EBADF checking in
 38  *                                        lookup/readdir, use ERR_PTR
 39  *      Jun 1999        2.3.6           d_alloc_root use changed
 40  *                      2.3.9           clean up usage of ENOENT/negative
 41  *                                        dentries in lookup
 42  *                                      clean up page flags setting
 43  *                                        (error, uptodate, locking) in
 44  *                                        in read_folio
 45  *                                      use init_special_inode for
 46  *                                        fifos/sockets (and streamline) in
 47  *                                        read_inode, fix _ops table order
 48  *      Aug 1999        2.3.16          __initfunc() => __init change
 49  *      Oct 1999        2.3.24          page->owner hack obsoleted
 50  *      Nov 1999        2.3.27          2.3.25+ page->offset => index change
 51  *
 52  *
 53  * This program is free software; you can redistribute it and/or
 54  * modify it under the terms of the GNU General Public Licence
 55  * as published by the Free Software Foundation; either version
 56  * 2 of the Licence, or (at your option) any later version.
 57  */
 58 
 59 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 60 
 61 #include <linux/module.h>
 62 #include <linux/string.h>
 63 #include <linux/fs.h>
 64 #include <linux/time.h>
 65 #include <linux/slab.h>
 66 #include <linux/init.h>
 67 #include <linux/blkdev.h>
 68 #include <linux/fs_context.h>
 69 #include <linux/mount.h>
 70 #include <linux/namei.h>
 71 #include <linux/statfs.h>
 72 #include <linux/mtd/super.h>
 73 #include <linux/ctype.h>
 74 #include <linux/highmem.h>
 75 #include <linux/pagemap.h>
 76 #include <linux/uaccess.h>
 77 #include <linux/major.h>
 78 #include "internal.h"
 79 
 80 static struct kmem_cache *romfs_inode_cachep;
 81 
 82 static const umode_t romfs_modemap[8] = {
 83         0,                      /* hard link */
 84         S_IFDIR  | 0644,        /* directory */
 85         S_IFREG  | 0644,        /* regular file */
 86         S_IFLNK  | 0777,        /* symlink */
 87         S_IFBLK  | 0600,        /* blockdev */
 88         S_IFCHR  | 0600,        /* chardev */
 89         S_IFSOCK | 0644,        /* socket */
 90         S_IFIFO  | 0644         /* FIFO */
 91 };
 92 
 93 static const unsigned char romfs_dtype_table[] = {
 94         DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_SOCK, DT_FIFO
 95 };
 96 
 97 static struct inode *romfs_iget(struct super_block *sb, unsigned long pos);
 98 
 99 /*
100  * read a page worth of data from the image
101  */
102 static int romfs_read_folio(struct file *file, struct folio *folio)
103 {
104         struct inode *inode = folio->mapping->host;
105         loff_t offset, size;
106         unsigned long fillsize, pos;
107         void *buf;
108         int ret;
109 
110         buf = kmap_local_folio(folio, 0);
111 
112         offset = folio_pos(folio);
113         size = i_size_read(inode);
114         fillsize = 0;
115         ret = 0;
116         if (offset < size) {
117                 size -= offset;
118                 fillsize = size > PAGE_SIZE ? PAGE_SIZE : size;
119 
120                 pos = ROMFS_I(inode)->i_dataoffset + offset;
121 
122                 ret = romfs_dev_read(inode->i_sb, pos, buf, fillsize);
123                 if (ret < 0) {
124                         fillsize = 0;
125                         ret = -EIO;
126                 }
127         }
128 
129         buf = folio_zero_tail(folio, fillsize, buf + fillsize);
130         kunmap_local(buf);
131         folio_end_read(folio, ret == 0);
132         return ret;
133 }
134 
135 static const struct address_space_operations romfs_aops = {
136         .read_folio     = romfs_read_folio
137 };
138 
139 /*
140  * read the entries from a directory
141  */
142 static int romfs_readdir(struct file *file, struct dir_context *ctx)
143 {
144         struct inode *i = file_inode(file);
145         struct romfs_inode ri;
146         unsigned long offset, maxoff;
147         int j, ino, nextfh;
148         char fsname[ROMFS_MAXFN];       /* XXX dynamic? */
149         int ret;
150 
151         maxoff = romfs_maxsize(i->i_sb);
152 
153         offset = ctx->pos;
154         if (!offset) {
155                 offset = i->i_ino & ROMFH_MASK;
156                 ret = romfs_dev_read(i->i_sb, offset, &ri, ROMFH_SIZE);
157                 if (ret < 0)
158                         goto out;
159                 offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
160         }
161 
162         /* Not really failsafe, but we are read-only... */
163         for (;;) {
164                 if (!offset || offset >= maxoff) {
165                         offset = maxoff;
166                         ctx->pos = offset;
167                         goto out;
168                 }
169                 ctx->pos = offset;
170 
171                 /* Fetch inode info */
172                 ret = romfs_dev_read(i->i_sb, offset, &ri, ROMFH_SIZE);
173                 if (ret < 0)
174                         goto out;
175 
176                 j = romfs_dev_strnlen(i->i_sb, offset + ROMFH_SIZE,
177                                       sizeof(fsname) - 1);
178                 if (j < 0)
179                         goto out;
180 
181                 ret = romfs_dev_read(i->i_sb, offset + ROMFH_SIZE, fsname, j);
182                 if (ret < 0)
183                         goto out;
184                 fsname[j] = '\0';
185 
186                 ino = offset;
187                 nextfh = be32_to_cpu(ri.next);
188                 if ((nextfh & ROMFH_TYPE) == ROMFH_HRD)
189                         ino = be32_to_cpu(ri.spec);
190                 if (!dir_emit(ctx, fsname, j, ino,
191                             romfs_dtype_table[nextfh & ROMFH_TYPE]))
192                         goto out;
193 
194                 offset = nextfh & ROMFH_MASK;
195         }
196 out:
197         return 0;
198 }
199 
200 /*
201  * look up an entry in a directory
202  */
203 static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry,
204                                    unsigned int flags)
205 {
206         unsigned long offset, maxoff;
207         struct inode *inode = NULL;
208         struct romfs_inode ri;
209         const char *name;               /* got from dentry */
210         int len, ret;
211 
212         offset = dir->i_ino & ROMFH_MASK;
213         ret = romfs_dev_read(dir->i_sb, offset, &ri, ROMFH_SIZE);
214         if (ret < 0)
215                 goto error;
216 
217         /* search all the file entries in the list starting from the one
218          * pointed to by the directory's special data */
219         maxoff = romfs_maxsize(dir->i_sb);
220         offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
221 
222         name = dentry->d_name.name;
223         len = dentry->d_name.len;
224 
225         for (;;) {
226                 if (!offset || offset >= maxoff)
227                         break;
228 
229                 ret = romfs_dev_read(dir->i_sb, offset, &ri, sizeof(ri));
230                 if (ret < 0)
231                         goto error;
232 
233                 /* try to match the first 16 bytes of name */
234                 ret = romfs_dev_strcmp(dir->i_sb, offset + ROMFH_SIZE, name,
235                                        len);
236                 if (ret < 0)
237                         goto error;
238                 if (ret == 1) {
239                         /* Hard link handling */
240                         if ((be32_to_cpu(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
241                                 offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
242                         inode = romfs_iget(dir->i_sb, offset);
243                         break;
244                 }
245 
246                 /* next entry */
247                 offset = be32_to_cpu(ri.next) & ROMFH_MASK;
248         }
249 
250         return d_splice_alias(inode, dentry);
251 error:
252         return ERR_PTR(ret);
253 }
254 
255 static const struct file_operations romfs_dir_operations = {
256         .read           = generic_read_dir,
257         .iterate_shared = romfs_readdir,
258         .llseek         = generic_file_llseek,
259 };
260 
261 static const struct inode_operations romfs_dir_inode_operations = {
262         .lookup         = romfs_lookup,
263 };
264 
265 /*
266  * get a romfs inode based on its position in the image (which doubles as the
267  * inode number)
268  */
269 static struct inode *romfs_iget(struct super_block *sb, unsigned long pos)
270 {
271         struct romfs_inode_info *inode;
272         struct romfs_inode ri;
273         struct inode *i;
274         unsigned long nlen;
275         unsigned nextfh;
276         int ret;
277         umode_t mode;
278 
279         /* we might have to traverse a chain of "hard link" file entries to get
280          * to the actual file */
281         for (;;) {
282                 ret = romfs_dev_read(sb, pos, &ri, sizeof(ri));
283                 if (ret < 0)
284                         goto error;
285 
286                 /* XXX: do romfs_checksum here too (with name) */
287 
288                 nextfh = be32_to_cpu(ri.next);
289                 if ((nextfh & ROMFH_TYPE) != ROMFH_HRD)
290                         break;
291 
292                 pos = be32_to_cpu(ri.spec) & ROMFH_MASK;
293         }
294 
295         /* determine the length of the filename */
296         nlen = romfs_dev_strnlen(sb, pos + ROMFH_SIZE, ROMFS_MAXFN);
297         if (IS_ERR_VALUE(nlen))
298                 goto eio;
299 
300         /* get an inode for this image position */
301         i = iget_locked(sb, pos);
302         if (!i)
303                 return ERR_PTR(-ENOMEM);
304 
305         if (!(i->i_state & I_NEW))
306                 return i;
307 
308         /* precalculate the data offset */
309         inode = ROMFS_I(i);
310         inode->i_metasize = (ROMFH_SIZE + nlen + 1 + ROMFH_PAD) & ROMFH_MASK;
311         inode->i_dataoffset = pos + inode->i_metasize;
312 
313         set_nlink(i, 1);                /* Hard to decide.. */
314         i->i_size = be32_to_cpu(ri.size);
315         inode_set_mtime_to_ts(i,
316                               inode_set_atime_to_ts(i, inode_set_ctime(i, 0, 0)));
317 
318         /* set up mode and ops */
319         mode = romfs_modemap[nextfh & ROMFH_TYPE];
320 
321         switch (nextfh & ROMFH_TYPE) {
322         case ROMFH_DIR:
323                 i->i_size = ROMFS_I(i)->i_metasize;
324                 i->i_op = &romfs_dir_inode_operations;
325                 i->i_fop = &romfs_dir_operations;
326                 if (nextfh & ROMFH_EXEC)
327                         mode |= S_IXUGO;
328                 break;
329         case ROMFH_REG:
330                 i->i_fop = &romfs_ro_fops;
331                 i->i_data.a_ops = &romfs_aops;
332                 if (nextfh & ROMFH_EXEC)
333                         mode |= S_IXUGO;
334                 break;
335         case ROMFH_SYM:
336                 i->i_op = &page_symlink_inode_operations;
337                 inode_nohighmem(i);
338                 i->i_data.a_ops = &romfs_aops;
339                 mode |= S_IRWXUGO;
340                 break;
341         default:
342                 /* depending on MBZ for sock/fifos */
343                 nextfh = be32_to_cpu(ri.spec);
344                 init_special_inode(i, mode, MKDEV(nextfh >> 16,
345                                                   nextfh & 0xffff));
346                 break;
347         }
348 
349         i->i_mode = mode;
350         i->i_blocks = (i->i_size + 511) >> 9;
351 
352         unlock_new_inode(i);
353         return i;
354 
355 eio:
356         ret = -EIO;
357 error:
358         pr_err("read error for inode 0x%lx\n", pos);
359         return ERR_PTR(ret);
360 }
361 
362 /*
363  * allocate a new inode
364  */
365 static struct inode *romfs_alloc_inode(struct super_block *sb)
366 {
367         struct romfs_inode_info *inode;
368 
369         inode = alloc_inode_sb(sb, romfs_inode_cachep, GFP_KERNEL);
370         return inode ? &inode->vfs_inode : NULL;
371 }
372 
373 /*
374  * return a spent inode to the slab cache
375  */
376 static void romfs_free_inode(struct inode *inode)
377 {
378         kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode));
379 }
380 
381 /*
382  * get filesystem statistics
383  */
384 static int romfs_statfs(struct dentry *dentry, struct kstatfs *buf)
385 {
386         struct super_block *sb = dentry->d_sb;
387         u64 id = 0;
388 
389         /* When calling huge_encode_dev(),
390          * use sb->s_bdev->bd_dev when,
391          *   - CONFIG_ROMFS_ON_BLOCK defined
392          * use sb->s_dev when,
393          *   - CONFIG_ROMFS_ON_BLOCK undefined and
394          *   - CONFIG_ROMFS_ON_MTD defined
395          * leave id as 0 when,
396          *   - CONFIG_ROMFS_ON_BLOCK undefined and
397          *   - CONFIG_ROMFS_ON_MTD undefined
398          */
399         if (sb->s_bdev)
400                 id = huge_encode_dev(sb->s_bdev->bd_dev);
401         else if (sb->s_dev)
402                 id = huge_encode_dev(sb->s_dev);
403 
404         buf->f_type = ROMFS_MAGIC;
405         buf->f_namelen = ROMFS_MAXFN;
406         buf->f_bsize = ROMBSIZE;
407         buf->f_bfree = buf->f_bavail = buf->f_ffree;
408         buf->f_blocks =
409                 (romfs_maxsize(dentry->d_sb) + ROMBSIZE - 1) >> ROMBSBITS;
410         buf->f_fsid = u64_to_fsid(id);
411         return 0;
412 }
413 
414 /*
415  * remounting must involve read-only
416  */
417 static int romfs_reconfigure(struct fs_context *fc)
418 {
419         sync_filesystem(fc->root->d_sb);
420         fc->sb_flags |= SB_RDONLY;
421         return 0;
422 }
423 
424 static const struct super_operations romfs_super_ops = {
425         .alloc_inode    = romfs_alloc_inode,
426         .free_inode     = romfs_free_inode,
427         .statfs         = romfs_statfs,
428 };
429 
430 /*
431  * checksum check on part of a romfs filesystem
432  */
433 static __u32 romfs_checksum(const void *data, int size)
434 {
435         const __be32 *ptr = data;
436         __u32 sum;
437 
438         sum = 0;
439         size >>= 2;
440         while (size > 0) {
441                 sum += be32_to_cpu(*ptr++);
442                 size--;
443         }
444         return sum;
445 }
446 
447 /*
448  * fill in the superblock
449  */
450 static int romfs_fill_super(struct super_block *sb, struct fs_context *fc)
451 {
452         struct romfs_super_block *rsb;
453         struct inode *root;
454         unsigned long pos, img_size;
455         const char *storage;
456         size_t len;
457         int ret;
458 
459 #ifdef CONFIG_BLOCK
460         if (!sb->s_mtd) {
461                 sb_set_blocksize(sb, ROMBSIZE);
462         } else {
463                 sb->s_blocksize = ROMBSIZE;
464                 sb->s_blocksize_bits = blksize_bits(ROMBSIZE);
465         }
466 #endif
467 
468         sb->s_maxbytes = 0xFFFFFFFF;
469         sb->s_magic = ROMFS_MAGIC;
470         sb->s_flags |= SB_RDONLY | SB_NOATIME;
471         sb->s_time_min = 0;
472         sb->s_time_max = 0;
473         sb->s_op = &romfs_super_ops;
474 
475 #ifdef CONFIG_ROMFS_ON_MTD
476         /* Use same dev ID from the underlying mtdblock device */
477         if (sb->s_mtd)
478                 sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, sb->s_mtd->index);
479 #endif
480         /* read the image superblock and check it */
481         rsb = kmalloc(512, GFP_KERNEL);
482         if (!rsb)
483                 return -ENOMEM;
484 
485         sb->s_fs_info = (void *) 512;
486         ret = romfs_dev_read(sb, 0, rsb, 512);
487         if (ret < 0)
488                 goto error_rsb;
489 
490         img_size = be32_to_cpu(rsb->size);
491 
492         if (sb->s_mtd && img_size > sb->s_mtd->size)
493                 goto error_rsb_inval;
494 
495         sb->s_fs_info = (void *) img_size;
496 
497         if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1 ||
498             img_size < ROMFH_SIZE) {
499                 if (!(fc->sb_flags & SB_SILENT))
500                         errorf(fc, "VFS: Can't find a romfs filesystem on dev %s.\n",
501                                sb->s_id);
502                 goto error_rsb_inval;
503         }
504 
505         if (romfs_checksum(rsb, min_t(size_t, img_size, 512))) {
506                 pr_err("bad initial checksum on dev %s.\n", sb->s_id);
507                 goto error_rsb_inval;
508         }
509 
510         storage = sb->s_mtd ? "MTD" : "the block layer";
511 
512         len = strnlen(rsb->name, ROMFS_MAXFN);
513         if (!(fc->sb_flags & SB_SILENT))
514                 pr_notice("Mounting image '%*.*s' through %s\n",
515                           (unsigned) len, (unsigned) len, rsb->name, storage);
516 
517         kfree(rsb);
518         rsb = NULL;
519 
520         /* find the root directory */
521         pos = (ROMFH_SIZE + len + 1 + ROMFH_PAD) & ROMFH_MASK;
522 
523         root = romfs_iget(sb, pos);
524         if (IS_ERR(root))
525                 return PTR_ERR(root);
526 
527         sb->s_root = d_make_root(root);
528         if (!sb->s_root)
529                 return -ENOMEM;
530 
531         return 0;
532 
533 error_rsb_inval:
534         ret = -EINVAL;
535 error_rsb:
536         kfree(rsb);
537         return ret;
538 }
539 
540 /*
541  * get a superblock for mounting
542  */
543 static int romfs_get_tree(struct fs_context *fc)
544 {
545         int ret = -EINVAL;
546 
547 #ifdef CONFIG_ROMFS_ON_MTD
548         ret = get_tree_mtd(fc, romfs_fill_super);
549 #endif
550 #ifdef CONFIG_ROMFS_ON_BLOCK
551         if (ret == -EINVAL)
552                 ret = get_tree_bdev(fc, romfs_fill_super);
553 #endif
554         return ret;
555 }
556 
557 static const struct fs_context_operations romfs_context_ops = {
558         .get_tree       = romfs_get_tree,
559         .reconfigure    = romfs_reconfigure,
560 };
561 
562 /*
563  * Set up the filesystem mount context.
564  */
565 static int romfs_init_fs_context(struct fs_context *fc)
566 {
567         fc->ops = &romfs_context_ops;
568         return 0;
569 }
570 
571 /*
572  * destroy a romfs superblock in the appropriate manner
573  */
574 static void romfs_kill_sb(struct super_block *sb)
575 {
576         generic_shutdown_super(sb);
577 
578 #ifdef CONFIG_ROMFS_ON_MTD
579         if (sb->s_mtd) {
580                 put_mtd_device(sb->s_mtd);
581                 sb->s_mtd = NULL;
582         }
583 #endif
584 #ifdef CONFIG_ROMFS_ON_BLOCK
585         if (sb->s_bdev) {
586                 sync_blockdev(sb->s_bdev);
587                 bdev_fput(sb->s_bdev_file);
588         }
589 #endif
590 }
591 
592 static struct file_system_type romfs_fs_type = {
593         .owner          = THIS_MODULE,
594         .name           = "romfs",
595         .init_fs_context = romfs_init_fs_context,
596         .kill_sb        = romfs_kill_sb,
597         .fs_flags       = FS_REQUIRES_DEV,
598 };
599 MODULE_ALIAS_FS("romfs");
600 
601 /*
602  * inode storage initialiser
603  */
604 static void romfs_i_init_once(void *_inode)
605 {
606         struct romfs_inode_info *inode = _inode;
607 
608         inode_init_once(&inode->vfs_inode);
609 }
610 
611 /*
612  * romfs module initialisation
613  */
614 static int __init init_romfs_fs(void)
615 {
616         int ret;
617 
618         pr_info("ROMFS MTD (C) 2007 Red Hat, Inc.\n");
619 
620         romfs_inode_cachep =
621                 kmem_cache_create("romfs_i",
622                                   sizeof(struct romfs_inode_info), 0,
623                                   SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT,
624                                   romfs_i_init_once);
625 
626         if (!romfs_inode_cachep) {
627                 pr_err("Failed to initialise inode cache\n");
628                 return -ENOMEM;
629         }
630         ret = register_filesystem(&romfs_fs_type);
631         if (ret) {
632                 pr_err("Failed to register filesystem\n");
633                 goto error_register;
634         }
635         return 0;
636 
637 error_register:
638         kmem_cache_destroy(romfs_inode_cachep);
639         return ret;
640 }
641 
642 /*
643  * romfs module removal
644  */
645 static void __exit exit_romfs_fs(void)
646 {
647         unregister_filesystem(&romfs_fs_type);
648         /*
649          * Make sure all delayed rcu free inodes are flushed before we
650          * destroy cache.
651          */
652         rcu_barrier();
653         kmem_cache_destroy(romfs_inode_cachep);
654 }
655 
656 module_init(init_romfs_fs);
657 module_exit(exit_romfs_fs);
658 
659 MODULE_DESCRIPTION("Direct-MTD Capable RomFS");
660 MODULE_AUTHOR("Red Hat, Inc.");
661 MODULE_LICENSE("GPL"); /* Actually dual-licensed, but it doesn't matter for */
662 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php