Merge branch 'master' into for_paulus
[linux-drm-fsl-dcu.git] / fs / minix / inode.c
index 330ff9fc7cf065eb0b41871be0ee9a542a6a92e3..92e383af3709c89dc14531a05856684ff809d9cf 100644 (file)
@@ -7,6 +7,7 @@
  *     Minix V2 fs support.
  *
  *  Modified for 680x0 by Andreas Schwab
+ *  Updated to filesystem version 3 by Daniel Aragones
  */
 
 #include <linux/module.h>
@@ -36,7 +37,8 @@ static void minix_put_super(struct super_block *sb)
        struct minix_sb_info *sbi = minix_sb(sb);
 
        if (!(sb->s_flags & MS_RDONLY)) {
-               sbi->s_ms->s_state = sbi->s_mount_state;
+               if (sbi->s_version != MINIX_V3)  /* s_state is now out from V3 sb */
+                       sbi->s_ms->s_state = sbi->s_mount_state;
                mark_buffer_dirty(sbi->s_sbh);
        }
        for (i = 0; i < sbi->s_imap_blocks; i++)
@@ -51,12 +53,12 @@ static void minix_put_super(struct super_block *sb)
        return;
 }
 
-static kmem_cache_t * minix_inode_cachep;
+static struct kmem_cache * minix_inode_cachep;
 
 static struct inode *minix_alloc_inode(struct super_block *sb)
 {
        struct minix_inode_info *ei;
-       ei = (struct minix_inode_info *)kmem_cache_alloc(minix_inode_cachep, SLAB_KERNEL);
+       ei = (struct minix_inode_info *)kmem_cache_alloc(minix_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -67,7 +69,7 @@ static void minix_destroy_inode(struct inode *inode)
        kmem_cache_free(minix_inode_cachep, minix_i(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
        struct minix_inode_info *ei = (struct minix_inode_info *) foo;
 
@@ -90,11 +92,10 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(minix_inode_cachep))
-               printk(KERN_INFO "minix_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(minix_inode_cachep);
 }
 
-static struct super_operations minix_sops = {
+static const struct super_operations minix_sops = {
        .alloc_inode    = minix_alloc_inode,
        .destroy_inode  = minix_destroy_inode,
        .read_inode     = minix_read_inode,
@@ -118,12 +119,17 @@ static int minix_remount (struct super_block * sb, int * flags, char * data)
                    !(sbi->s_mount_state & MINIX_VALID_FS))
                        return 0;
                /* Mounting a rw partition read-only. */
-               ms->s_state = sbi->s_mount_state;
+               if (sbi->s_version != MINIX_V3)
+                       ms->s_state = sbi->s_mount_state;
                mark_buffer_dirty(sbi->s_sbh);
        } else {
                /* Mount a partition which is read-only, read-write. */
-               sbi->s_mount_state = ms->s_state;
-               ms->s_state &= ~MINIX_VALID_FS;
+               if (sbi->s_version != MINIX_V3) {
+                       sbi->s_mount_state = ms->s_state;
+                       ms->s_state &= ~MINIX_VALID_FS;
+               } else {
+                       sbi->s_mount_state = MINIX_VALID_FS;
+               }
                mark_buffer_dirty(sbi->s_sbh);
 
                if (!(sbi->s_mount_state & MINIX_VALID_FS))
@@ -141,22 +147,18 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
        struct buffer_head *bh;
        struct buffer_head **map;
        struct minix_super_block *ms;
-       int i, block;
+       struct minix3_super_block *m3s = NULL;
+       unsigned long i, block;
        struct inode *root_inode;
        struct minix_sb_info *sbi;
 
-       sbi = kmalloc(sizeof(struct minix_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct minix_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        s->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct minix_sb_info));
 
-       /* N.B. These should be compile-time tests.
-          Unfortunately that is impossible. */
-       if (32 != sizeof (struct minix_inode))
-               panic("bad V1 i-node size");
-       if (64 != sizeof(struct minix2_inode))
-               panic("bad V2 i-node size");
+       BUILD_BUG_ON(32 != sizeof (struct minix_inode));
+       BUILD_BUG_ON(64 != sizeof(struct minix2_inode));
 
        if (!sb_set_blocksize(s, BLOCK_SIZE))
                goto out_bad_hblock;
@@ -198,6 +200,22 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
                sbi->s_dirsize = 32;
                sbi->s_namelen = 30;
                sbi->s_link_max = MINIX2_LINK_MAX;
+       } else if ( *(__u16 *)(bh->b_data + 24) == MINIX3_SUPER_MAGIC) {
+               m3s = (struct minix3_super_block *) bh->b_data;
+               s->s_magic = m3s->s_magic;
+               sbi->s_imap_blocks = m3s->s_imap_blocks;
+               sbi->s_zmap_blocks = m3s->s_zmap_blocks;
+               sbi->s_firstdatazone = m3s->s_firstdatazone;
+               sbi->s_log_zone_size = m3s->s_log_zone_size;
+               sbi->s_max_size = m3s->s_max_size;
+               sbi->s_ninodes = m3s->s_ninodes;
+               sbi->s_nzones = m3s->s_zones;
+               sbi->s_dirsize = 64;
+               sbi->s_namelen = 60;
+               sbi->s_version = MINIX_V3;
+               sbi->s_link_max = MINIX2_LINK_MAX;
+               sbi->s_mount_state = MINIX_VALID_FS;
+               sb_set_blocksize(s, m3s->s_blocksize);
        } else
                goto out_no_fs;
 
@@ -207,10 +225,9 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
        if (sbi->s_imap_blocks == 0 || sbi->s_zmap_blocks == 0)
                goto out_illegal_sb;
        i = (sbi->s_imap_blocks + sbi->s_zmap_blocks) * sizeof(bh);
-       map = kmalloc(i, GFP_KERNEL);
+       map = kzalloc(i, GFP_KERNEL);
        if (!map)
                goto out_no_map;
-       memset(map, 0, i);
        sbi->s_imap = &map[0];
        sbi->s_zmap = &map[sbi->s_imap_blocks];
 
@@ -243,7 +260,8 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
                s->s_root->d_op = &minix_dentry_operations;
 
        if (!(s->s_flags & MS_RDONLY)) {
-               ms->s_state &= ~MINIX_VALID_FS;
+               if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
+                       ms->s_state &= ~MINIX_VALID_FS;
                mark_buffer_dirty(bh);
        }
        if (!(sbi->s_mount_state & MINIX_VALID_FS))
@@ -285,8 +303,8 @@ out_illegal_sb:
 
 out_no_fs:
        if (!silent)
-               printk("VFS: Can't find a Minix or Minix V2 filesystem "
-                       "on device %s\n", s->s_id);
+               printk("VFS: Can't find a Minix filesystem V1 | V2 | V3 "
+                      "on device %s.\n", s->s_id);
 out_release:
        brelse(bh);
        goto out;
@@ -351,7 +369,7 @@ static const struct address_space_operations minix_aops = {
        .bmap = minix_bmap
 };
 
-static struct inode_operations minix_symlink_inode_operations = {
+static const struct inode_operations minix_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .follow_link    = page_follow_link_light,
        .put_link       = page_put_link,
@@ -399,7 +417,7 @@ static void V1_minix_read_inode(struct inode * inode)
        inode->i_mtime.tv_nsec = 0;
        inode->i_atime.tv_nsec = 0;
        inode->i_ctime.tv_nsec = 0;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
        for (i = 0; i < 9; i++)
                minix_inode->u.i1_data[i] = raw_inode->i_zone[i];
        minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0]));
@@ -432,7 +450,7 @@ static void V2_minix_read_inode(struct inode * inode)
        inode->i_mtime.tv_nsec = 0;
        inode->i_atime.tv_nsec = 0;
        inode->i_ctime.tv_nsec = 0;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
        for (i = 0; i < 10; i++)
                minix_inode->u.i2_data[i] = raw_inode->i_zone[i];
        minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0]));
@@ -544,12 +562,14 @@ int minix_sync_inode(struct inode * inode)
 
 int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
+       struct inode *dir = dentry->d_parent->d_inode;
+       struct super_block *sb = dir->i_sb;
        generic_fillattr(dentry->d_inode, stat);
        if (INODE_VERSION(dentry->d_inode) == MINIX_V1)
-               stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size);
+               stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb);
        else
-               stat->blocks = (BLOCK_SIZE / 512) * V2_minix_blocks(stat->size);
-       stat->blksize = BLOCK_SIZE;
+               stat->blocks = (sb->s_blocksize / 512) * V2_minix_blocks(stat->size, sb);
+       stat->blksize = sb->s_blocksize;
        return 0;
 }