109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/fs/minix/inode.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
61da177e4SLinus Torvalds *
7f762dd68SGertjan van Wingerde * Copyright (C) 1996 Gertjan van Wingerde
81da177e4SLinus Torvalds * Minix V2 fs support.
91da177e4SLinus Torvalds *
101da177e4SLinus Torvalds * Modified for 680x0 by Andreas Schwab
11939b00dfSAndries Brouwer * Updated to filesystem version 3 by Daniel Aragones
121da177e4SLinus Torvalds */
131da177e4SLinus Torvalds
141da177e4SLinus Torvalds #include <linux/module.h>
151da177e4SLinus Torvalds #include "minix.h"
161da177e4SLinus Torvalds #include <linux/buffer_head.h>
171da177e4SLinus Torvalds #include <linux/slab.h>
181da177e4SLinus Torvalds #include <linux/init.h>
191da177e4SLinus Torvalds #include <linux/highuid.h>
201da177e4SLinus Torvalds #include <linux/vfs.h>
21a9185b41SChristoph Hellwig #include <linux/writeback.h>
221da177e4SLinus Torvalds
23a9185b41SChristoph Hellwig static int minix_write_inode(struct inode *inode,
24a9185b41SChristoph Hellwig struct writeback_control *wbc);
25726c3342SDavid Howells static int minix_statfs(struct dentry *dentry, struct kstatfs *buf);
261da177e4SLinus Torvalds static int minix_remount (struct super_block * sb, int * flags, char * data);
271da177e4SLinus Torvalds
minix_evict_inode(struct inode * inode)285ccb4a78SAl Viro static void minix_evict_inode(struct inode *inode)
291da177e4SLinus Torvalds {
3091b0abe3SJohannes Weiner truncate_inode_pages_final(&inode->i_data);
315ccb4a78SAl Viro if (!inode->i_nlink) {
321da177e4SLinus Torvalds inode->i_size = 0;
331da177e4SLinus Torvalds minix_truncate(inode);
345ccb4a78SAl Viro }
355ccb4a78SAl Viro invalidate_inode_buffers(inode);
36dbd5768fSJan Kara clear_inode(inode);
375ccb4a78SAl Viro if (!inode->i_nlink)
381da177e4SLinus Torvalds minix_free_inode(inode);
391da177e4SLinus Torvalds }
401da177e4SLinus Torvalds
minix_put_super(struct super_block * sb)411da177e4SLinus Torvalds static void minix_put_super(struct super_block *sb)
421da177e4SLinus Torvalds {
431da177e4SLinus Torvalds int i;
441da177e4SLinus Torvalds struct minix_sb_info *sbi = minix_sb(sb);
451da177e4SLinus Torvalds
46bc98a42cSDavid Howells if (!sb_rdonly(sb)) {
47939b00dfSAndries Brouwer if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
481da177e4SLinus Torvalds sbi->s_ms->s_state = sbi->s_mount_state;
491da177e4SLinus Torvalds mark_buffer_dirty(sbi->s_sbh);
501da177e4SLinus Torvalds }
511da177e4SLinus Torvalds for (i = 0; i < sbi->s_imap_blocks; i++)
521da177e4SLinus Torvalds brelse(sbi->s_imap[i]);
531da177e4SLinus Torvalds for (i = 0; i < sbi->s_zmap_blocks; i++)
541da177e4SLinus Torvalds brelse(sbi->s_zmap[i]);
551da177e4SLinus Torvalds brelse (sbi->s_sbh);
561da177e4SLinus Torvalds kfree(sbi->s_imap);
571da177e4SLinus Torvalds sb->s_fs_info = NULL;
581da177e4SLinus Torvalds kfree(sbi);
591da177e4SLinus Torvalds }
601da177e4SLinus Torvalds
61e18b890bSChristoph Lameter static struct kmem_cache * minix_inode_cachep;
621da177e4SLinus Torvalds
minix_alloc_inode(struct super_block * sb)631da177e4SLinus Torvalds static struct inode *minix_alloc_inode(struct super_block *sb)
641da177e4SLinus Torvalds {
651da177e4SLinus Torvalds struct minix_inode_info *ei;
66fd60b288SMuchun Song ei = alloc_inode_sb(sb, minix_inode_cachep, GFP_KERNEL);
671da177e4SLinus Torvalds if (!ei)
681da177e4SLinus Torvalds return NULL;
691da177e4SLinus Torvalds return &ei->vfs_inode;
701da177e4SLinus Torvalds }
711da177e4SLinus Torvalds
minix_free_in_core_inode(struct inode * inode)72d67a398aSAl Viro static void minix_free_in_core_inode(struct inode *inode)
73fa0d7e3dSNick Piggin {
74fa0d7e3dSNick Piggin kmem_cache_free(minix_inode_cachep, minix_i(inode));
75fa0d7e3dSNick Piggin }
76fa0d7e3dSNick Piggin
init_once(void * foo)7751cc5068SAlexey Dobriyan static void init_once(void *foo)
781da177e4SLinus Torvalds {
791da177e4SLinus Torvalds struct minix_inode_info *ei = (struct minix_inode_info *) foo;
801da177e4SLinus Torvalds
811da177e4SLinus Torvalds inode_init_once(&ei->vfs_inode);
821da177e4SLinus Torvalds }
831da177e4SLinus Torvalds
init_inodecache(void)8484ee353dSFabian Frederick static int __init init_inodecache(void)
851da177e4SLinus Torvalds {
861da177e4SLinus Torvalds minix_inode_cachep = kmem_cache_create("minix_inode_cache",
871da177e4SLinus Torvalds sizeof(struct minix_inode_info),
88fffb60f9SPaul Jackson 0, (SLAB_RECLAIM_ACCOUNT|
895d097056SVladimir Davydov SLAB_MEM_SPREAD|SLAB_ACCOUNT),
9020c2df83SPaul Mundt init_once);
911da177e4SLinus Torvalds if (minix_inode_cachep == NULL)
921da177e4SLinus Torvalds return -ENOMEM;
931da177e4SLinus Torvalds return 0;
941da177e4SLinus Torvalds }
951da177e4SLinus Torvalds
destroy_inodecache(void)961da177e4SLinus Torvalds static void destroy_inodecache(void)
971da177e4SLinus Torvalds {
988c0a8537SKirill A. Shutemov /*
998c0a8537SKirill A. Shutemov * Make sure all delayed rcu free inodes are flushed before we
1008c0a8537SKirill A. Shutemov * destroy cache.
1018c0a8537SKirill A. Shutemov */
1028c0a8537SKirill A. Shutemov rcu_barrier();
1031a1d92c1SAlexey Dobriyan kmem_cache_destroy(minix_inode_cachep);
1041da177e4SLinus Torvalds }
1051da177e4SLinus Torvalds
106ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations minix_sops = {
1071da177e4SLinus Torvalds .alloc_inode = minix_alloc_inode,
108d67a398aSAl Viro .free_inode = minix_free_in_core_inode,
1091da177e4SLinus Torvalds .write_inode = minix_write_inode,
1105ccb4a78SAl Viro .evict_inode = minix_evict_inode,
1111da177e4SLinus Torvalds .put_super = minix_put_super,
1121da177e4SLinus Torvalds .statfs = minix_statfs,
1131da177e4SLinus Torvalds .remount_fs = minix_remount,
1141da177e4SLinus Torvalds };
1151da177e4SLinus Torvalds
minix_remount(struct super_block * sb,int * flags,char * data)1161da177e4SLinus Torvalds static int minix_remount (struct super_block * sb, int * flags, char * data)
1171da177e4SLinus Torvalds {
1181da177e4SLinus Torvalds struct minix_sb_info * sbi = minix_sb(sb);
1191da177e4SLinus Torvalds struct minix_super_block * ms;
1201da177e4SLinus Torvalds
12102b9984dSTheodore Ts'o sync_filesystem(sb);
1221da177e4SLinus Torvalds ms = sbi->s_ms;
1231751e8a6SLinus Torvalds if ((bool)(*flags & SB_RDONLY) == sb_rdonly(sb))
1241da177e4SLinus Torvalds return 0;
1251751e8a6SLinus Torvalds if (*flags & SB_RDONLY) {
1261da177e4SLinus Torvalds if (ms->s_state & MINIX_VALID_FS ||
1271da177e4SLinus Torvalds !(sbi->s_mount_state & MINIX_VALID_FS))
1281da177e4SLinus Torvalds return 0;
1291da177e4SLinus Torvalds /* Mounting a rw partition read-only. */
130939b00dfSAndries Brouwer if (sbi->s_version != MINIX_V3)
1311da177e4SLinus Torvalds ms->s_state = sbi->s_mount_state;
1321da177e4SLinus Torvalds mark_buffer_dirty(sbi->s_sbh);
1331da177e4SLinus Torvalds } else {
1341da177e4SLinus Torvalds /* Mount a partition which is read-only, read-write. */
135939b00dfSAndries Brouwer if (sbi->s_version != MINIX_V3) {
1361da177e4SLinus Torvalds sbi->s_mount_state = ms->s_state;
1371da177e4SLinus Torvalds ms->s_state &= ~MINIX_VALID_FS;
138939b00dfSAndries Brouwer } else {
139939b00dfSAndries Brouwer sbi->s_mount_state = MINIX_VALID_FS;
140939b00dfSAndries Brouwer }
1411da177e4SLinus Torvalds mark_buffer_dirty(sbi->s_sbh);
1421da177e4SLinus Torvalds
1431da177e4SLinus Torvalds if (!(sbi->s_mount_state & MINIX_VALID_FS))
1441da177e4SLinus Torvalds printk("MINIX-fs warning: remounting unchecked fs, "
14511b84487SDenis Vlasenko "running fsck is recommended\n");
1461da177e4SLinus Torvalds else if ((sbi->s_mount_state & MINIX_ERROR_FS))
1471da177e4SLinus Torvalds printk("MINIX-fs warning: remounting fs with errors, "
14811b84487SDenis Vlasenko "running fsck is recommended\n");
1491da177e4SLinus Torvalds }
1501da177e4SLinus Torvalds return 0;
1511da177e4SLinus Torvalds }
1521da177e4SLinus Torvalds
minix_check_superblock(struct super_block * sb)15332ac86efSEric Biggers static bool minix_check_superblock(struct super_block *sb)
154270ef410SEric Biggers {
15532ac86efSEric Biggers struct minix_sb_info *sbi = minix_sb(sb);
15632ac86efSEric Biggers
157270ef410SEric Biggers if (sbi->s_imap_blocks == 0 || sbi->s_zmap_blocks == 0)
158270ef410SEric Biggers return false;
159270ef410SEric Biggers
160270ef410SEric Biggers /*
161270ef410SEric Biggers * s_max_size must not exceed the block mapping limitation. This check
162270ef410SEric Biggers * is only needed for V1 filesystems, since V2/V3 support an extra level
163270ef410SEric Biggers * of indirect blocks which places the limit well above U32_MAX.
164270ef410SEric Biggers */
165270ef410SEric Biggers if (sbi->s_version == MINIX_V1 &&
16632ac86efSEric Biggers sb->s_maxbytes > (7 + 512 + 512*512) * BLOCK_SIZE)
167270ef410SEric Biggers return false;
168270ef410SEric Biggers
169270ef410SEric Biggers return true;
170270ef410SEric Biggers }
171270ef410SEric Biggers
minix_fill_super(struct super_block * s,void * data,int silent)1721da177e4SLinus Torvalds static int minix_fill_super(struct super_block *s, void *data, int silent)
1731da177e4SLinus Torvalds {
1741da177e4SLinus Torvalds struct buffer_head *bh;
1751da177e4SLinus Torvalds struct buffer_head **map;
1761da177e4SLinus Torvalds struct minix_super_block *ms;
177939b00dfSAndries Brouwer struct minix3_super_block *m3s = NULL;
178939b00dfSAndries Brouwer unsigned long i, block;
1791da177e4SLinus Torvalds struct inode *root_inode;
1801da177e4SLinus Torvalds struct minix_sb_info *sbi;
181a90a0880SDavid Howells int ret = -EINVAL;
1821da177e4SLinus Torvalds
183f8314dc6SPanagiotis Issaris sbi = kzalloc(sizeof(struct minix_sb_info), GFP_KERNEL);
1841da177e4SLinus Torvalds if (!sbi)
1851da177e4SLinus Torvalds return -ENOMEM;
1861da177e4SLinus Torvalds s->s_fs_info = sbi;
1871da177e4SLinus Torvalds
1882ecd05aeSAlexey Dobriyan BUILD_BUG_ON(32 != sizeof (struct minix_inode));
1892ecd05aeSAlexey Dobriyan BUILD_BUG_ON(64 != sizeof(struct minix2_inode));
1901da177e4SLinus Torvalds
1911da177e4SLinus Torvalds if (!sb_set_blocksize(s, BLOCK_SIZE))
1921da177e4SLinus Torvalds goto out_bad_hblock;
1931da177e4SLinus Torvalds
1941da177e4SLinus Torvalds if (!(bh = sb_bread(s, 1)))
1951da177e4SLinus Torvalds goto out_bad_sb;
1961da177e4SLinus Torvalds
1971da177e4SLinus Torvalds ms = (struct minix_super_block *) bh->b_data;
1981da177e4SLinus Torvalds sbi->s_ms = ms;
1991da177e4SLinus Torvalds sbi->s_sbh = bh;
2001da177e4SLinus Torvalds sbi->s_mount_state = ms->s_state;
2011da177e4SLinus Torvalds sbi->s_ninodes = ms->s_ninodes;
2021da177e4SLinus Torvalds sbi->s_nzones = ms->s_nzones;
2031da177e4SLinus Torvalds sbi->s_imap_blocks = ms->s_imap_blocks;
2041da177e4SLinus Torvalds sbi->s_zmap_blocks = ms->s_zmap_blocks;
2051da177e4SLinus Torvalds sbi->s_firstdatazone = ms->s_firstdatazone;
2061da177e4SLinus Torvalds sbi->s_log_zone_size = ms->s_log_zone_size;
20732ac86efSEric Biggers s->s_maxbytes = ms->s_max_size;
2081da177e4SLinus Torvalds s->s_magic = ms->s_magic;
2091da177e4SLinus Torvalds if (s->s_magic == MINIX_SUPER_MAGIC) {
2101da177e4SLinus Torvalds sbi->s_version = MINIX_V1;
2111da177e4SLinus Torvalds sbi->s_dirsize = 16;
2121da177e4SLinus Torvalds sbi->s_namelen = 14;
2138de52778SAl Viro s->s_max_links = MINIX_LINK_MAX;
2141da177e4SLinus Torvalds } else if (s->s_magic == MINIX_SUPER_MAGIC2) {
2151da177e4SLinus Torvalds sbi->s_version = MINIX_V1;
2161da177e4SLinus Torvalds sbi->s_dirsize = 32;
2171da177e4SLinus Torvalds sbi->s_namelen = 30;
2188de52778SAl Viro s->s_max_links = MINIX_LINK_MAX;
2191da177e4SLinus Torvalds } else if (s->s_magic == MINIX2_SUPER_MAGIC) {
2201da177e4SLinus Torvalds sbi->s_version = MINIX_V2;
2211da177e4SLinus Torvalds sbi->s_nzones = ms->s_zones;
2221da177e4SLinus Torvalds sbi->s_dirsize = 16;
2231da177e4SLinus Torvalds sbi->s_namelen = 14;
2248de52778SAl Viro s->s_max_links = MINIX2_LINK_MAX;
2251da177e4SLinus Torvalds } else if (s->s_magic == MINIX2_SUPER_MAGIC2) {
2261da177e4SLinus Torvalds sbi->s_version = MINIX_V2;
2271da177e4SLinus Torvalds sbi->s_nzones = ms->s_zones;
2281da177e4SLinus Torvalds sbi->s_dirsize = 32;
2291da177e4SLinus Torvalds sbi->s_namelen = 30;
2308de52778SAl Viro s->s_max_links = MINIX2_LINK_MAX;
231939b00dfSAndries Brouwer } else if ( *(__u16 *)(bh->b_data + 24) == MINIX3_SUPER_MAGIC) {
232939b00dfSAndries Brouwer m3s = (struct minix3_super_block *) bh->b_data;
233939b00dfSAndries Brouwer s->s_magic = m3s->s_magic;
234939b00dfSAndries Brouwer sbi->s_imap_blocks = m3s->s_imap_blocks;
235939b00dfSAndries Brouwer sbi->s_zmap_blocks = m3s->s_zmap_blocks;
236939b00dfSAndries Brouwer sbi->s_firstdatazone = m3s->s_firstdatazone;
237939b00dfSAndries Brouwer sbi->s_log_zone_size = m3s->s_log_zone_size;
23832ac86efSEric Biggers s->s_maxbytes = m3s->s_max_size;
239939b00dfSAndries Brouwer sbi->s_ninodes = m3s->s_ninodes;
240939b00dfSAndries Brouwer sbi->s_nzones = m3s->s_zones;
241939b00dfSAndries Brouwer sbi->s_dirsize = 64;
242939b00dfSAndries Brouwer sbi->s_namelen = 60;
243939b00dfSAndries Brouwer sbi->s_version = MINIX_V3;
244939b00dfSAndries Brouwer sbi->s_mount_state = MINIX_VALID_FS;
245939b00dfSAndries Brouwer sb_set_blocksize(s, m3s->s_blocksize);
2468de52778SAl Viro s->s_max_links = MINIX2_LINK_MAX;
2471da177e4SLinus Torvalds } else
2481da177e4SLinus Torvalds goto out_no_fs;
2491da177e4SLinus Torvalds
25032ac86efSEric Biggers if (!minix_check_superblock(s))
251270ef410SEric Biggers goto out_illegal_sb;
252270ef410SEric Biggers
2531da177e4SLinus Torvalds /*
2541da177e4SLinus Torvalds * Allocate the buffer map to keep the superblock small.
2551da177e4SLinus Torvalds */
2561da177e4SLinus Torvalds i = (sbi->s_imap_blocks + sbi->s_zmap_blocks) * sizeof(bh);
257f8314dc6SPanagiotis Issaris map = kzalloc(i, GFP_KERNEL);
2581da177e4SLinus Torvalds if (!map)
2591da177e4SLinus Torvalds goto out_no_map;
2601da177e4SLinus Torvalds sbi->s_imap = &map[0];
2611da177e4SLinus Torvalds sbi->s_zmap = &map[sbi->s_imap_blocks];
2621da177e4SLinus Torvalds
2631da177e4SLinus Torvalds block=2;
2641da177e4SLinus Torvalds for (i=0 ; i < sbi->s_imap_blocks ; i++) {
2651da177e4SLinus Torvalds if (!(sbi->s_imap[i]=sb_bread(s, block)))
2661da177e4SLinus Torvalds goto out_no_bitmap;
2671da177e4SLinus Torvalds block++;
2681da177e4SLinus Torvalds }
2691da177e4SLinus Torvalds for (i=0 ; i < sbi->s_zmap_blocks ; i++) {
2701da177e4SLinus Torvalds if (!(sbi->s_zmap[i]=sb_bread(s, block)))
2711da177e4SLinus Torvalds goto out_no_bitmap;
2721da177e4SLinus Torvalds block++;
2731da177e4SLinus Torvalds }
2741da177e4SLinus Torvalds
2751da177e4SLinus Torvalds minix_set_bit(0,sbi->s_imap[0]->b_data);
2761da177e4SLinus Torvalds minix_set_bit(0,sbi->s_zmap[0]->b_data);
2771da177e4SLinus Torvalds
278016e8d44SJosh Boyer /* Apparently minix can create filesystems that allocate more blocks for
279016e8d44SJosh Boyer * the bitmaps than needed. We simply ignore that, but verify it didn't
280016e8d44SJosh Boyer * create one with not enough blocks and bail out if so.
281016e8d44SJosh Boyer */
282016e8d44SJosh Boyer block = minix_blocks_needed(sbi->s_ninodes, s->s_blocksize);
283016e8d44SJosh Boyer if (sbi->s_imap_blocks < block) {
284016e8d44SJosh Boyer printk("MINIX-fs: file system does not have enough "
2856d6747f8SQi Yong "imap blocks allocated. Refusing to mount.\n");
286ca85c078SAl Viro goto out_no_bitmap;
287016e8d44SJosh Boyer }
288016e8d44SJosh Boyer
289016e8d44SJosh Boyer block = minix_blocks_needed(
2906d6747f8SQi Yong (sbi->s_nzones - sbi->s_firstdatazone + 1),
291016e8d44SJosh Boyer s->s_blocksize);
292016e8d44SJosh Boyer if (sbi->s_zmap_blocks < block) {
293016e8d44SJosh Boyer printk("MINIX-fs: file system does not have enough "
294016e8d44SJosh Boyer "zmap blocks allocated. Refusing to mount.\n");
295ca85c078SAl Viro goto out_no_bitmap;
296ca85c078SAl Viro }
297ca85c078SAl Viro
298ca85c078SAl Viro /* set up enough so that it can read an inode */
299ca85c078SAl Viro s->s_op = &minix_sops;
30022b13969SDeepa Dinamani s->s_time_min = 0;
30122b13969SDeepa Dinamani s->s_time_max = U32_MAX;
302ca85c078SAl Viro root_inode = minix_iget(s, MINIX_ROOT_INO);
303ca85c078SAl Viro if (IS_ERR(root_inode)) {
304ca85c078SAl Viro ret = PTR_ERR(root_inode);
305ca85c078SAl Viro goto out_no_root;
306016e8d44SJosh Boyer }
307016e8d44SJosh Boyer
308d6042eacSAl Viro ret = -ENOMEM;
309ca85c078SAl Viro s->s_root = d_make_root(root_inode);
310d6042eacSAl Viro if (!s->s_root)
311ca85c078SAl Viro goto out_no_root;
312d6042eacSAl Viro
313bc98a42cSDavid Howells if (!sb_rdonly(s)) {
314d6042eacSAl Viro if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
315d6042eacSAl Viro ms->s_state &= ~MINIX_VALID_FS;
316d6042eacSAl Viro mark_buffer_dirty(bh);
317d6042eacSAl Viro }
318d6042eacSAl Viro if (!(sbi->s_mount_state & MINIX_VALID_FS))
319d6042eacSAl Viro printk("MINIX-fs: mounting unchecked file system, "
320d6042eacSAl Viro "running fsck is recommended\n");
321d6042eacSAl Viro else if (sbi->s_mount_state & MINIX_ERROR_FS)
322d6042eacSAl Viro printk("MINIX-fs: mounting file system with errors, "
323d6042eacSAl Viro "running fsck is recommended\n");
324d6042eacSAl Viro
3251da177e4SLinus Torvalds return 0;
3261da177e4SLinus Torvalds
3271da177e4SLinus Torvalds out_no_root:
3281da177e4SLinus Torvalds if (!silent)
3291da177e4SLinus Torvalds printk("MINIX-fs: get root inode failed\n");
3301da177e4SLinus Torvalds goto out_freemap;
3311da177e4SLinus Torvalds
3321da177e4SLinus Torvalds out_no_bitmap:
3331da177e4SLinus Torvalds printk("MINIX-fs: bad superblock or unable to read bitmaps\n");
3341da177e4SLinus Torvalds out_freemap:
3351da177e4SLinus Torvalds for (i = 0; i < sbi->s_imap_blocks; i++)
3361da177e4SLinus Torvalds brelse(sbi->s_imap[i]);
3371da177e4SLinus Torvalds for (i = 0; i < sbi->s_zmap_blocks; i++)
3381da177e4SLinus Torvalds brelse(sbi->s_zmap[i]);
3391da177e4SLinus Torvalds kfree(sbi->s_imap);
3401da177e4SLinus Torvalds goto out_release;
3411da177e4SLinus Torvalds
3421da177e4SLinus Torvalds out_no_map:
343a90a0880SDavid Howells ret = -ENOMEM;
3441da177e4SLinus Torvalds if (!silent)
3451da177e4SLinus Torvalds printk("MINIX-fs: can't allocate map\n");
3461da177e4SLinus Torvalds goto out_release;
3471da177e4SLinus Torvalds
348f5fb09faSAndries Brouwer out_illegal_sb:
349f5fb09faSAndries Brouwer if (!silent)
350f5fb09faSAndries Brouwer printk("MINIX-fs: bad superblock\n");
351f5fb09faSAndries Brouwer goto out_release;
352f5fb09faSAndries Brouwer
3531da177e4SLinus Torvalds out_no_fs:
3541da177e4SLinus Torvalds if (!silent)
355939b00dfSAndries Brouwer printk("VFS: Can't find a Minix filesystem V1 | V2 | V3 "
356939b00dfSAndries Brouwer "on device %s.\n", s->s_id);
3571da177e4SLinus Torvalds out_release:
3581da177e4SLinus Torvalds brelse(bh);
3591da177e4SLinus Torvalds goto out;
3601da177e4SLinus Torvalds
3611da177e4SLinus Torvalds out_bad_hblock:
36211b84487SDenis Vlasenko printk("MINIX-fs: blocksize too small for device\n");
3631da177e4SLinus Torvalds goto out;
3641da177e4SLinus Torvalds
3651da177e4SLinus Torvalds out_bad_sb:
3661da177e4SLinus Torvalds printk("MINIX-fs: unable to read superblock\n");
3671da177e4SLinus Torvalds out:
3681da177e4SLinus Torvalds s->s_fs_info = NULL;
3691da177e4SLinus Torvalds kfree(sbi);
370a90a0880SDavid Howells return ret;
3711da177e4SLinus Torvalds }
3721da177e4SLinus Torvalds
minix_statfs(struct dentry * dentry,struct kstatfs * buf)373726c3342SDavid Howells static int minix_statfs(struct dentry *dentry, struct kstatfs *buf)
3741da177e4SLinus Torvalds {
375054475d2SColy Li struct super_block *sb = dentry->d_sb;
376054475d2SColy Li struct minix_sb_info *sbi = minix_sb(sb);
377054475d2SColy Li u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
378054475d2SColy Li buf->f_type = sb->s_magic;
379054475d2SColy Li buf->f_bsize = sb->s_blocksize;
3801da177e4SLinus Torvalds buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size;
381016e8d44SJosh Boyer buf->f_bfree = minix_count_free_blocks(sb);
3821da177e4SLinus Torvalds buf->f_bavail = buf->f_bfree;
3831da177e4SLinus Torvalds buf->f_files = sbi->s_ninodes;
384016e8d44SJosh Boyer buf->f_ffree = minix_count_free_inodes(sb);
3851da177e4SLinus Torvalds buf->f_namelen = sbi->s_namelen;
3866d1349c7SAl Viro buf->f_fsid = u64_to_fsid(id);
387054475d2SColy Li
3881da177e4SLinus Torvalds return 0;
3891da177e4SLinus Torvalds }
3901da177e4SLinus Torvalds
minix_get_block(struct inode * inode,sector_t block,struct buffer_head * bh_result,int create)3911da177e4SLinus Torvalds static int minix_get_block(struct inode *inode, sector_t block,
3921da177e4SLinus Torvalds struct buffer_head *bh_result, int create)
3931da177e4SLinus Torvalds {
3941da177e4SLinus Torvalds if (INODE_VERSION(inode) == MINIX_V1)
3951da177e4SLinus Torvalds return V1_minix_get_block(inode, block, bh_result, create);
3961da177e4SLinus Torvalds else
3971da177e4SLinus Torvalds return V2_minix_get_block(inode, block, bh_result, create);
3981da177e4SLinus Torvalds }
3991da177e4SLinus Torvalds
minix_writepage(struct page * page,struct writeback_control * wbc)4001da177e4SLinus Torvalds static int minix_writepage(struct page *page, struct writeback_control *wbc)
4011da177e4SLinus Torvalds {
4021da177e4SLinus Torvalds return block_write_full_page(page, minix_get_block, wbc);
4031da177e4SLinus Torvalds }
4044a66af9eSNick Piggin
minix_read_folio(struct file * file,struct folio * folio)4052c69e205SMatthew Wilcox (Oracle) static int minix_read_folio(struct file *file, struct folio *folio)
4061da177e4SLinus Torvalds {
4072c69e205SMatthew Wilcox (Oracle) return block_read_full_folio(folio, minix_get_block);
4081da177e4SLinus Torvalds }
4094a66af9eSNick Piggin
minix_prepare_chunk(struct page * page,loff_t pos,unsigned len)410f4e420dcSChristoph Hellwig int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len)
4111da177e4SLinus Torvalds {
4126e1db88dSChristoph Hellwig return __block_write_begin(page, pos, len, minix_get_block);
4131da177e4SLinus Torvalds }
4144a66af9eSNick Piggin
minix_write_failed(struct address_space * mapping,loff_t to)4157fc7cd00SMarco Stornelli static void minix_write_failed(struct address_space *mapping, loff_t to)
4167fc7cd00SMarco Stornelli {
4177fc7cd00SMarco Stornelli struct inode *inode = mapping->host;
4187fc7cd00SMarco Stornelli
4197fc7cd00SMarco Stornelli if (to > inode->i_size) {
4207caef267SKirill A. Shutemov truncate_pagecache(inode, inode->i_size);
4217fc7cd00SMarco Stornelli minix_truncate(inode);
4227fc7cd00SMarco Stornelli }
4237fc7cd00SMarco Stornelli }
4247fc7cd00SMarco Stornelli
minix_write_begin(struct file * file,struct address_space * mapping,loff_t pos,unsigned len,struct page ** pagep,void ** fsdata)4254a66af9eSNick Piggin static int minix_write_begin(struct file *file, struct address_space *mapping,
4269d6b0cd7SMatthew Wilcox (Oracle) loff_t pos, unsigned len,
4274a66af9eSNick Piggin struct page **pagep, void **fsdata)
4284a66af9eSNick Piggin {
429155130a4SChristoph Hellwig int ret;
430155130a4SChristoph Hellwig
431b3992d1eSMatthew Wilcox (Oracle) ret = block_write_begin(mapping, pos, len, pagep, minix_get_block);
4327fc7cd00SMarco Stornelli if (unlikely(ret))
4337fc7cd00SMarco Stornelli minix_write_failed(mapping, pos + len);
434155130a4SChristoph Hellwig
435155130a4SChristoph Hellwig return ret;
4364a66af9eSNick Piggin }
4374a66af9eSNick Piggin
minix_bmap(struct address_space * mapping,sector_t block)4381da177e4SLinus Torvalds static sector_t minix_bmap(struct address_space *mapping, sector_t block)
4391da177e4SLinus Torvalds {
4401da177e4SLinus Torvalds return generic_block_bmap(mapping,block,minix_get_block);
4411da177e4SLinus Torvalds }
4424a66af9eSNick Piggin
443f5e54d6eSChristoph Hellwig static const struct address_space_operations minix_aops = {
444e621900aSMatthew Wilcox (Oracle) .dirty_folio = block_dirty_folio,
4457ba13abbSMatthew Wilcox (Oracle) .invalidate_folio = block_invalidate_folio,
4462c69e205SMatthew Wilcox (Oracle) .read_folio = minix_read_folio,
4471da177e4SLinus Torvalds .writepage = minix_writepage,
4484a66af9eSNick Piggin .write_begin = minix_write_begin,
4494a66af9eSNick Piggin .write_end = generic_write_end,
4509ce3c0d2SQinghua Jin .bmap = minix_bmap,
4519ce3c0d2SQinghua Jin .direct_IO = noop_direct_IO
4521da177e4SLinus Torvalds };
4531da177e4SLinus Torvalds
45492e1d5beSArjan van de Ven static const struct inode_operations minix_symlink_inode_operations = {
4556b255391SAl Viro .get_link = page_get_link,
4561da177e4SLinus Torvalds .getattr = minix_getattr,
4571da177e4SLinus Torvalds };
4581da177e4SLinus Torvalds
minix_set_inode(struct inode * inode,dev_t rdev)4591da177e4SLinus Torvalds void minix_set_inode(struct inode *inode, dev_t rdev)
4601da177e4SLinus Torvalds {
4611da177e4SLinus Torvalds if (S_ISREG(inode->i_mode)) {
4621da177e4SLinus Torvalds inode->i_op = &minix_file_inode_operations;
4631da177e4SLinus Torvalds inode->i_fop = &minix_file_operations;
4641da177e4SLinus Torvalds inode->i_mapping->a_ops = &minix_aops;
4651da177e4SLinus Torvalds } else if (S_ISDIR(inode->i_mode)) {
4661da177e4SLinus Torvalds inode->i_op = &minix_dir_inode_operations;
4671da177e4SLinus Torvalds inode->i_fop = &minix_dir_operations;
4681da177e4SLinus Torvalds inode->i_mapping->a_ops = &minix_aops;
4691da177e4SLinus Torvalds } else if (S_ISLNK(inode->i_mode)) {
4701da177e4SLinus Torvalds inode->i_op = &minix_symlink_inode_operations;
47121fc61c7SAl Viro inode_nohighmem(inode);
4721da177e4SLinus Torvalds inode->i_mapping->a_ops = &minix_aops;
4731da177e4SLinus Torvalds } else
4741da177e4SLinus Torvalds init_special_inode(inode, inode->i_mode, rdev);
4751da177e4SLinus Torvalds }
4761da177e4SLinus Torvalds
4771da177e4SLinus Torvalds /*
4781da177e4SLinus Torvalds * The minix V1 function to read an inode.
4791da177e4SLinus Torvalds */
V1_minix_iget(struct inode * inode)480a90a0880SDavid Howells static struct inode *V1_minix_iget(struct inode *inode)
4811da177e4SLinus Torvalds {
4821da177e4SLinus Torvalds struct buffer_head * bh;
4831da177e4SLinus Torvalds struct minix_inode * raw_inode;
4841da177e4SLinus Torvalds struct minix_inode_info *minix_inode = minix_i(inode);
4851da177e4SLinus Torvalds int i;
4861da177e4SLinus Torvalds
4871da177e4SLinus Torvalds raw_inode = minix_V1_raw_inode(inode->i_sb, inode->i_ino, &bh);
4881da177e4SLinus Torvalds if (!raw_inode) {
489a90a0880SDavid Howells iget_failed(inode);
490a90a0880SDavid Howells return ERR_PTR(-EIO);
4911da177e4SLinus Torvalds }
492facb03ddSEric Biggers if (raw_inode->i_nlinks == 0) {
493facb03ddSEric Biggers printk("MINIX-fs: deleted inode referenced: %lu\n",
494facb03ddSEric Biggers inode->i_ino);
495facb03ddSEric Biggers brelse(bh);
496facb03ddSEric Biggers iget_failed(inode);
497facb03ddSEric Biggers return ERR_PTR(-ESTALE);
498facb03ddSEric Biggers }
4991da177e4SLinus Torvalds inode->i_mode = raw_inode->i_mode;
500f303bdc5SEric W. Biederman i_uid_write(inode, raw_inode->i_uid);
501f303bdc5SEric W. Biederman i_gid_write(inode, raw_inode->i_gid);
502bfe86848SMiklos Szeredi set_nlink(inode, raw_inode->i_nlinks);
5031da177e4SLinus Torvalds inode->i_size = raw_inode->i_size;
504f7f43858SJeff Layton inode->i_mtime = inode->i_atime = inode_set_ctime(inode, raw_inode->i_time, 0);
505ba52de12STheodore Ts'o inode->i_blocks = 0;
5061da177e4SLinus Torvalds for (i = 0; i < 9; i++)
5071da177e4SLinus Torvalds minix_inode->u.i1_data[i] = raw_inode->i_zone[i];
5081da177e4SLinus Torvalds minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0]));
5091da177e4SLinus Torvalds brelse(bh);
510a90a0880SDavid Howells unlock_new_inode(inode);
511a90a0880SDavid Howells return inode;
5121da177e4SLinus Torvalds }
5131da177e4SLinus Torvalds
5141da177e4SLinus Torvalds /*
5151da177e4SLinus Torvalds * The minix V2 function to read an inode.
5161da177e4SLinus Torvalds */
V2_minix_iget(struct inode * inode)517a90a0880SDavid Howells static struct inode *V2_minix_iget(struct inode *inode)
5181da177e4SLinus Torvalds {
5191da177e4SLinus Torvalds struct buffer_head * bh;
5201da177e4SLinus Torvalds struct minix2_inode * raw_inode;
5211da177e4SLinus Torvalds struct minix_inode_info *minix_inode = minix_i(inode);
5221da177e4SLinus Torvalds int i;
5231da177e4SLinus Torvalds
5241da177e4SLinus Torvalds raw_inode = minix_V2_raw_inode(inode->i_sb, inode->i_ino, &bh);
5251da177e4SLinus Torvalds if (!raw_inode) {
526a90a0880SDavid Howells iget_failed(inode);
527a90a0880SDavid Howells return ERR_PTR(-EIO);
5281da177e4SLinus Torvalds }
529facb03ddSEric Biggers if (raw_inode->i_nlinks == 0) {
530facb03ddSEric Biggers printk("MINIX-fs: deleted inode referenced: %lu\n",
531facb03ddSEric Biggers inode->i_ino);
532facb03ddSEric Biggers brelse(bh);
533facb03ddSEric Biggers iget_failed(inode);
534facb03ddSEric Biggers return ERR_PTR(-ESTALE);
535facb03ddSEric Biggers }
5361da177e4SLinus Torvalds inode->i_mode = raw_inode->i_mode;
537f303bdc5SEric W. Biederman i_uid_write(inode, raw_inode->i_uid);
538f303bdc5SEric W. Biederman i_gid_write(inode, raw_inode->i_gid);
539bfe86848SMiklos Szeredi set_nlink(inode, raw_inode->i_nlinks);
5401da177e4SLinus Torvalds inode->i_size = raw_inode->i_size;
5411da177e4SLinus Torvalds inode->i_mtime.tv_sec = raw_inode->i_mtime;
5421da177e4SLinus Torvalds inode->i_atime.tv_sec = raw_inode->i_atime;
543f7f43858SJeff Layton inode_set_ctime(inode, raw_inode->i_ctime, 0);
5441da177e4SLinus Torvalds inode->i_mtime.tv_nsec = 0;
5451da177e4SLinus Torvalds inode->i_atime.tv_nsec = 0;
546ba52de12STheodore Ts'o inode->i_blocks = 0;
5471da177e4SLinus Torvalds for (i = 0; i < 10; i++)
5481da177e4SLinus Torvalds minix_inode->u.i2_data[i] = raw_inode->i_zone[i];
5491da177e4SLinus Torvalds minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0]));
5501da177e4SLinus Torvalds brelse(bh);
551a90a0880SDavid Howells unlock_new_inode(inode);
552a90a0880SDavid Howells return inode;
5531da177e4SLinus Torvalds }
5541da177e4SLinus Torvalds
5551da177e4SLinus Torvalds /*
5561da177e4SLinus Torvalds * The global function to read an inode.
5571da177e4SLinus Torvalds */
minix_iget(struct super_block * sb,unsigned long ino)558a90a0880SDavid Howells struct inode *minix_iget(struct super_block *sb, unsigned long ino)
5591da177e4SLinus Torvalds {
560a90a0880SDavid Howells struct inode *inode;
561a90a0880SDavid Howells
562a90a0880SDavid Howells inode = iget_locked(sb, ino);
563a90a0880SDavid Howells if (!inode)
564a90a0880SDavid Howells return ERR_PTR(-ENOMEM);
565a90a0880SDavid Howells if (!(inode->i_state & I_NEW))
566a90a0880SDavid Howells return inode;
567a90a0880SDavid Howells
5681da177e4SLinus Torvalds if (INODE_VERSION(inode) == MINIX_V1)
569a90a0880SDavid Howells return V1_minix_iget(inode);
5701da177e4SLinus Torvalds else
571a90a0880SDavid Howells return V2_minix_iget(inode);
5721da177e4SLinus Torvalds }
5731da177e4SLinus Torvalds
5741da177e4SLinus Torvalds /*
5751da177e4SLinus Torvalds * The minix V1 function to synchronize an inode.
5761da177e4SLinus Torvalds */
V1_minix_update_inode(struct inode * inode)5771da177e4SLinus Torvalds static struct buffer_head * V1_minix_update_inode(struct inode * inode)
5781da177e4SLinus Torvalds {
5791da177e4SLinus Torvalds struct buffer_head * bh;
5801da177e4SLinus Torvalds struct minix_inode * raw_inode;
5811da177e4SLinus Torvalds struct minix_inode_info *minix_inode = minix_i(inode);
5821da177e4SLinus Torvalds int i;
5831da177e4SLinus Torvalds
5841da177e4SLinus Torvalds raw_inode = minix_V1_raw_inode(inode->i_sb, inode->i_ino, &bh);
5851da177e4SLinus Torvalds if (!raw_inode)
5861da177e4SLinus Torvalds return NULL;
5871da177e4SLinus Torvalds raw_inode->i_mode = inode->i_mode;
588f303bdc5SEric W. Biederman raw_inode->i_uid = fs_high2lowuid(i_uid_read(inode));
589f303bdc5SEric W. Biederman raw_inode->i_gid = fs_high2lowgid(i_gid_read(inode));
5901da177e4SLinus Torvalds raw_inode->i_nlinks = inode->i_nlink;
5911da177e4SLinus Torvalds raw_inode->i_size = inode->i_size;
5921da177e4SLinus Torvalds raw_inode->i_time = inode->i_mtime.tv_sec;
5931da177e4SLinus Torvalds if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
5941da177e4SLinus Torvalds raw_inode->i_zone[0] = old_encode_dev(inode->i_rdev);
5951da177e4SLinus Torvalds else for (i = 0; i < 9; i++)
5961da177e4SLinus Torvalds raw_inode->i_zone[i] = minix_inode->u.i1_data[i];
5971da177e4SLinus Torvalds mark_buffer_dirty(bh);
5981da177e4SLinus Torvalds return bh;
5991da177e4SLinus Torvalds }
6001da177e4SLinus Torvalds
6011da177e4SLinus Torvalds /*
6021da177e4SLinus Torvalds * The minix V2 function to synchronize an inode.
6031da177e4SLinus Torvalds */
V2_minix_update_inode(struct inode * inode)6041da177e4SLinus Torvalds static struct buffer_head * V2_minix_update_inode(struct inode * inode)
6051da177e4SLinus Torvalds {
6061da177e4SLinus Torvalds struct buffer_head * bh;
6071da177e4SLinus Torvalds struct minix2_inode * raw_inode;
6081da177e4SLinus Torvalds struct minix_inode_info *minix_inode = minix_i(inode);
6091da177e4SLinus Torvalds int i;
6101da177e4SLinus Torvalds
6111da177e4SLinus Torvalds raw_inode = minix_V2_raw_inode(inode->i_sb, inode->i_ino, &bh);
6121da177e4SLinus Torvalds if (!raw_inode)
6131da177e4SLinus Torvalds return NULL;
6141da177e4SLinus Torvalds raw_inode->i_mode = inode->i_mode;
615f303bdc5SEric W. Biederman raw_inode->i_uid = fs_high2lowuid(i_uid_read(inode));
616f303bdc5SEric W. Biederman raw_inode->i_gid = fs_high2lowgid(i_gid_read(inode));
6171da177e4SLinus Torvalds raw_inode->i_nlinks = inode->i_nlink;
6181da177e4SLinus Torvalds raw_inode->i_size = inode->i_size;
6191da177e4SLinus Torvalds raw_inode->i_mtime = inode->i_mtime.tv_sec;
6201da177e4SLinus Torvalds raw_inode->i_atime = inode->i_atime.tv_sec;
621f7f43858SJeff Layton raw_inode->i_ctime = inode_get_ctime(inode).tv_sec;
6221da177e4SLinus Torvalds if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
6231da177e4SLinus Torvalds raw_inode->i_zone[0] = old_encode_dev(inode->i_rdev);
6241da177e4SLinus Torvalds else for (i = 0; i < 10; i++)
6251da177e4SLinus Torvalds raw_inode->i_zone[i] = minix_inode->u.i2_data[i];
6261da177e4SLinus Torvalds mark_buffer_dirty(bh);
6271da177e4SLinus Torvalds return bh;
6281da177e4SLinus Torvalds }
6291da177e4SLinus Torvalds
minix_write_inode(struct inode * inode,struct writeback_control * wbc)630a9185b41SChristoph Hellwig static int minix_write_inode(struct inode *inode, struct writeback_control *wbc)
6311da177e4SLinus Torvalds {
6321da177e4SLinus Torvalds int err = 0;
6331da177e4SLinus Torvalds struct buffer_head *bh;
6341da177e4SLinus Torvalds
6350d7916d7SAl Viro if (INODE_VERSION(inode) == MINIX_V1)
6360d7916d7SAl Viro bh = V1_minix_update_inode(inode);
6370d7916d7SAl Viro else
6380d7916d7SAl Viro bh = V2_minix_update_inode(inode);
6390d7916d7SAl Viro if (!bh)
6400d7916d7SAl Viro return -EIO;
641a9185b41SChristoph Hellwig if (wbc->sync_mode == WB_SYNC_ALL && buffer_dirty(bh)) {
6421da177e4SLinus Torvalds sync_dirty_buffer(bh);
6430d7916d7SAl Viro if (buffer_req(bh) && !buffer_uptodate(bh)) {
6441da177e4SLinus Torvalds printk("IO error syncing minix inode [%s:%08lx]\n",
6451da177e4SLinus Torvalds inode->i_sb->s_id, inode->i_ino);
6460d7916d7SAl Viro err = -EIO;
6471da177e4SLinus Torvalds }
6481da177e4SLinus Torvalds }
6491da177e4SLinus Torvalds brelse (bh);
6501da177e4SLinus Torvalds return err;
6511da177e4SLinus Torvalds }
6521da177e4SLinus Torvalds
minix_getattr(struct mnt_idmap * idmap,const struct path * path,struct kstat * stat,u32 request_mask,unsigned int flags)653b74d24f7SChristian Brauner int minix_getattr(struct mnt_idmap *idmap, const struct path *path,
654549c7297SChristian Brauner struct kstat *stat, u32 request_mask, unsigned int flags)
6551da177e4SLinus Torvalds {
656a528d35eSDavid Howells struct super_block *sb = path->dentry->d_sb;
657a528d35eSDavid Howells struct inode *inode = d_inode(path->dentry);
658a528d35eSDavid Howells
659*0d72b928SJeff Layton generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
660a528d35eSDavid Howells if (INODE_VERSION(inode) == MINIX_V1)
661939b00dfSAndries Brouwer stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb);
6621da177e4SLinus Torvalds else
663939b00dfSAndries Brouwer stat->blocks = (sb->s_blocksize / 512) * V2_minix_blocks(stat->size, sb);
664939b00dfSAndries Brouwer stat->blksize = sb->s_blocksize;
6651da177e4SLinus Torvalds return 0;
6661da177e4SLinus Torvalds }
6671da177e4SLinus Torvalds
6681da177e4SLinus Torvalds /*
6691da177e4SLinus Torvalds * The function that is called for file truncation.
6701da177e4SLinus Torvalds */
minix_truncate(struct inode * inode)6711da177e4SLinus Torvalds void minix_truncate(struct inode * inode)
6721da177e4SLinus Torvalds {
6731da177e4SLinus Torvalds if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)))
6741da177e4SLinus Torvalds return;
6751da177e4SLinus Torvalds if (INODE_VERSION(inode) == MINIX_V1)
6761da177e4SLinus Torvalds V1_minix_truncate(inode);
6771da177e4SLinus Torvalds else
6781da177e4SLinus Torvalds V2_minix_truncate(inode);
6791da177e4SLinus Torvalds }
6801da177e4SLinus Torvalds
minix_mount(struct file_system_type * fs_type,int flags,const char * dev_name,void * data)681152a0836SAl Viro static struct dentry *minix_mount(struct file_system_type *fs_type,
682152a0836SAl Viro int flags, const char *dev_name, void *data)
6831da177e4SLinus Torvalds {
684152a0836SAl Viro return mount_bdev(fs_type, flags, dev_name, data, minix_fill_super);
6851da177e4SLinus Torvalds }
6861da177e4SLinus Torvalds
6871da177e4SLinus Torvalds static struct file_system_type minix_fs_type = {
6881da177e4SLinus Torvalds .owner = THIS_MODULE,
6891da177e4SLinus Torvalds .name = "minix",
690152a0836SAl Viro .mount = minix_mount,
6911da177e4SLinus Torvalds .kill_sb = kill_block_super,
6921da177e4SLinus Torvalds .fs_flags = FS_REQUIRES_DEV,
6931da177e4SLinus Torvalds };
6947f78e035SEric W. Biederman MODULE_ALIAS_FS("minix");
6951da177e4SLinus Torvalds
init_minix_fs(void)6961da177e4SLinus Torvalds static int __init init_minix_fs(void)
6971da177e4SLinus Torvalds {
6981da177e4SLinus Torvalds int err = init_inodecache();
6991da177e4SLinus Torvalds if (err)
7001da177e4SLinus Torvalds goto out1;
7011da177e4SLinus Torvalds err = register_filesystem(&minix_fs_type);
7021da177e4SLinus Torvalds if (err)
7031da177e4SLinus Torvalds goto out;
7041da177e4SLinus Torvalds return 0;
7051da177e4SLinus Torvalds out:
7061da177e4SLinus Torvalds destroy_inodecache();
7071da177e4SLinus Torvalds out1:
7081da177e4SLinus Torvalds return err;
7091da177e4SLinus Torvalds }
7101da177e4SLinus Torvalds
exit_minix_fs(void)7111da177e4SLinus Torvalds static void __exit exit_minix_fs(void)
7121da177e4SLinus Torvalds {
7131da177e4SLinus Torvalds unregister_filesystem(&minix_fs_type);
7141da177e4SLinus Torvalds destroy_inodecache();
7151da177e4SLinus Torvalds }
7161da177e4SLinus Torvalds
7171da177e4SLinus Torvalds module_init(init_minix_fs)
7181da177e4SLinus Torvalds module_exit(exit_minix_fs)
7191da177e4SLinus Torvalds MODULE_LICENSE("GPL");
7201da177e4SLinus Torvalds
721