[PATCH] Minix V3 support
authorAndries Brouwer <aeb@cwi.nl>
Mon, 12 Feb 2007 08:52:49 +0000 (00:52 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 12 Feb 2007 17:48:31 +0000 (09:48 -0800)
This morning I needed to read a Minix V3 filesystem, but unfortunately my
2.6.19 did not support that, and neither did the downloaded 2.6.20rc4.

Fortunately, google told me that Daniel Aragones had already done the work,
patch found at http://www.terra.es/personal2/danarag/

Unfortunaly, looking at the patch was painful to my eyes, so I polished it
a bit before applying.  The resulting kernel boots, and reads the
filesystem it needed to read.

Signed-off-by: Daniel Aragones <danarag@gmail.com>
Signed-off-by: Andries Brouwer <aeb@cwi.nl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/minix/bitmap.c
fs/minix/dir.c
fs/minix/inode.c
fs/minix/itree_common.c
fs/minix/itree_v1.c
fs/minix/itree_v2.c
fs/minix/minix.h
include/linux/magic.h
include/linux/minix_fs.h

index df6b1075b5494dd380dbe374e0be88239e8b93e8..c4a554df7b7e63bb77c3678c9fb3b9eb8ba725c3 100644 (file)
@@ -26,14 +26,14 @@ static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, _
        for (i=0; i<numblocks-1; i++) {
                if (!(bh=map[i])) 
                        return(0);
-               for (j=0; j<BLOCK_SIZE; j++)
+               for (j=0; j<bh->b_size; j++)
                        sum += nibblemap[bh->b_data[j] & 0xf]
                                + nibblemap[(bh->b_data[j]>>4) & 0xf];
        }
 
        if (numblocks==0 || !(bh=map[numblocks-1]))
                return(0);
-       i = ((numbits-(numblocks-1)*BLOCK_SIZE*8)/16)*2;
+       i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2;
        for (j=0; j<i; j++) {
                sum += nibblemap[bh->b_data[j] & 0xf]
                        + nibblemap[(bh->b_data[j]>>4) & 0xf];
@@ -48,28 +48,29 @@ static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, _
        return(sum);
 }
 
-void minix_free_block(struct inode * inode, int block)
+void minix_free_block(struct inode *inode, unsigned long block)
 {
-       struct super_block * sb = inode->i_sb;
-       struct minix_sb_info * sbi = minix_sb(sb);
-       struct buffer_head * bh;
-       unsigned int bit,zone;
+       struct super_block *sb = inode->i_sb;
+       struct minix_sb_info *sbi = minix_sb(sb);
+       struct buffer_head *bh;
+       int k = sb->s_blocksize_bits + 3;
+       unsigned long bit, zone;
 
        if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) {
                printk("Trying to free block not in datazone\n");
                return;
        }
        zone = block - sbi->s_firstdatazone + 1;
-       bit = zone & 8191;
-       zone >>= 13;
+       bit = zone & ((1<<k) - 1);
+       zone >>= k;
        if (zone >= sbi->s_zmap_blocks) {
                printk("minix_free_block: nonexistent bitmap buffer\n");
                return;
        }
        bh = sbi->s_zmap[zone];
        lock_kernel();
-       if (!minix_test_and_clear_bit(bit,bh->b_data))
-               printk("free_block (%s:%d): bit already cleared\n",
+       if (!minix_test_and_clear_bit(bit, bh->b_data))
+               printk("minix_free_block (%s:%lu): bit already cleared\n",
                       sb->s_id, block);
        unlock_kernel();
        mark_buffer_dirty(bh);
@@ -79,6 +80,7 @@ void minix_free_block(struct inode * inode, int block)
 int minix_new_block(struct inode * inode)
 {
        struct minix_sb_info *sbi = minix_sb(inode->i_sb);
+       int bits_per_zone = 8 * inode->i_sb->s_blocksize;
        int i;
 
        for (i = 0; i < sbi->s_zmap_blocks; i++) {
@@ -86,11 +88,12 @@ int minix_new_block(struct inode * inode)
                int j;
 
                lock_kernel();
-               if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) {
-                       minix_set_bit(j,bh->b_data);
+               j = minix_find_first_zero_bit(bh->b_data, bits_per_zone);
+               if (j < bits_per_zone) {
+                       minix_set_bit(j, bh->b_data);
                        unlock_kernel();
                        mark_buffer_dirty(bh);
-                       j += i*8192 + sbi->s_firstdatazone-1;
+                       j += i * bits_per_zone + sbi->s_firstdatazone-1;
                        if (j < sbi->s_firstdatazone || j >= sbi->s_nzones)
                                break;
                        return j;
@@ -137,6 +140,7 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
        int block;
        struct minix_sb_info *sbi = minix_sb(sb);
        struct minix2_inode *p;
+       int minix2_inodes_per_block = sb->s_blocksize / sizeof(struct minix2_inode);
 
        *bh = NULL;
        if (!ino || ino > sbi->s_ninodes) {
@@ -146,14 +150,14 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
        }
        ino--;
        block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks +
-                ino / MINIX2_INODES_PER_BLOCK;
+                ino / minix2_inodes_per_block;
        *bh = sb_bread(sb, block);
        if (!*bh) {
                printk("Unable to read inode block\n");
                return NULL;
        }
        p = (void *)(*bh)->b_data;
-       return p + ino % MINIX2_INODES_PER_BLOCK;
+       return p + ino % minix2_inodes_per_block;
 }
 
 /* Clear the link count and mode of a deleted inode on disk. */
@@ -185,26 +189,30 @@ static void minix_clear_inode(struct inode *inode)
 
 void minix_free_inode(struct inode * inode)
 {
+       struct super_block *sb = inode->i_sb;
        struct minix_sb_info *sbi = minix_sb(inode->i_sb);
-       struct buffer_head * bh;
-       unsigned long ino;
+       struct buffer_head *bh;
+       int k = sb->s_blocksize_bits + 3;
+       unsigned long ino, bit;
 
        ino = inode->i_ino;
        if (ino < 1 || ino > sbi->s_ninodes) {
                printk("minix_free_inode: inode 0 or nonexistent inode\n");
                goto out;
        }
-       if ((ino >> 13) >= sbi->s_imap_blocks) {
+       bit = ino & ((1<<k) - 1);
+       ino >>= k;
+       if (ino >= sbi->s_imap_blocks) {
                printk("minix_free_inode: nonexistent imap in superblock\n");
                goto out;
        }
 
        minix_clear_inode(inode);       /* clear on-disk copy */
 
-       bh = sbi->s_imap[ino >> 13];
+       bh = sbi->s_imap[ino];
        lock_kernel();
-       if (!minix_test_and_clear_bit(ino & 8191, bh->b_data))
-               printk("minix_free_inode: bit %lu already cleared\n", ino);
+       if (!minix_test_and_clear_bit(bit, bh->b_data))
+               printk("minix_free_inode: bit %lu already cleared\n", bit);
        unlock_kernel();
        mark_buffer_dirty(bh);
  out:
@@ -217,35 +225,38 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
        struct minix_sb_info *sbi = minix_sb(sb);
        struct inode *inode = new_inode(sb);
        struct buffer_head * bh;
-       int i,j;
+       int bits_per_zone = 8 * sb->s_blocksize;
+       unsigned long j;
+       int i;
 
        if (!inode) {
                *error = -ENOMEM;
                return NULL;
        }
-       j = 8192;
+       j = bits_per_zone;
        bh = NULL;
        *error = -ENOSPC;
        lock_kernel();
        for (i = 0; i < sbi->s_imap_blocks; i++) {
                bh = sbi->s_imap[i];
-               if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
+               j = minix_find_first_zero_bit(bh->b_data, bits_per_zone);
+               if (j < bits_per_zone)
                        break;
        }
-       if (!bh || j >= 8192) {
+       if (!bh || j >= bits_per_zone) {
                unlock_kernel();
                iput(inode);
                return NULL;
        }
-       if (minix_test_and_set_bit(j,bh->b_data)) {     /* shouldn't happen */
-               printk("new_inode: bit already set\n");
+       if (minix_test_and_set_bit(j, bh->b_data)) {    /* shouldn't happen */
                unlock_kernel();
+               printk("minix_new_inode: bit already set\n");
                iput(inode);
                return NULL;
        }
        unlock_kernel();
        mark_buffer_dirty(bh);
-       j += i*8192;
+       j += i * bits_per_zone;
        if (!j || j > sbi->s_ninodes) {
                iput(inode);
                return NULL;
index ab782c4086f5b0c5833780f186634ace32f8439f..cb4cb571fddfc507f20a26b19b341efd8fdb2465 100644 (file)
@@ -4,6 +4,8 @@
  *  Copyright (C) 1991, 1992 Linus Torvalds
  *
  *  minix directory handling functions
+ *
+ *  Updated to filesystem version 3 by Daniel Aragones
  */
 
 #include "minix.h"
@@ -11,6 +13,7 @@
 #include <linux/smp_lock.h>
 
 typedef struct minix_dir_entry minix_dirent;
+typedef struct minix3_dir_entry minix3_dirent;
 
 static int minix_readdir(struct file *, void *, filldir_t);
 
@@ -89,6 +92,8 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
        unsigned long npages = dir_pages(inode);
        struct minix_sb_info *sbi = minix_sb(sb);
        unsigned chunk_size = sbi->s_dirsize;
+       char *name;
+       __u32 inumber;
 
        lock_kernel();
 
@@ -105,16 +110,24 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
                kaddr = (char *)page_address(page);
                p = kaddr+offset;
                limit = kaddr + minix_last_byte(inode, n) - chunk_size;
-               for ( ; p <= limit ; p = minix_next_entry(p, sbi)) {
-                       minix_dirent *de = (minix_dirent *)p;
-                       if (de->inode) {
+               for ( ; p <= limit; p = minix_next_entry(p, sbi)) {
+                       if (sbi->s_version == MINIX_V3) {
+                               minix3_dirent *de3 = (minix3_dirent *)p;
+                               name = de3->name;
+                               inumber = de3->inode;
+                       } else {
+                               minix_dirent *de = (minix_dirent *)p;
+                               name = de->name;
+                               inumber = de->inode;
+                       }
+                       if (inumber) {
                                int over;
-                               unsigned l = strnlen(de->name,sbi->s_namelen);
 
+                               unsigned l = strnlen(name, sbi->s_namelen);
                                offset = p - kaddr;
-                               over = filldir(dirent, de->name, l,
-                                               (n<<PAGE_CACHE_SHIFT) | offset,
-                                               de->inode, DT_UNKNOWN);
+                               over = filldir(dirent, name, l,
+                                       (n << PAGE_CACHE_SHIFT) | offset,
+                                       inumber, DT_UNKNOWN);
                                if (over) {
                                        dir_put_page(page);
                                        goto done;
@@ -156,23 +169,34 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page)
        unsigned long n;
        unsigned long npages = dir_pages(dir);
        struct page *page = NULL;
-       struct minix_dir_entry *de;
+       char *p;
 
+       char *namx;
+       __u32 inumber;
        *res_page = NULL;
 
        for (n = 0; n < npages; n++) {
-               char *kaddr;
+               char *kaddr, *limit;
+
                page = dir_get_page(dir, n);
                if (IS_ERR(page))
                        continue;
 
                kaddr = (char*)page_address(page);
-               de = (struct minix_dir_entry *) kaddr;
-               kaddr += minix_last_byte(dir, n) - sbi->s_dirsize;
-               for ( ; (char *) de <= kaddr ; de = minix_next_entry(de,sbi)) {
-                       if (!de->inode)
+               limit = kaddr + minix_last_byte(dir, n) - sbi->s_dirsize;
+               for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
+                       if (sbi->s_version == MINIX_V3) {
+                               minix3_dirent *de3 = (minix3_dirent *)p;
+                               namx = de3->name;
+                               inumber = de3->inode;
+                       } else {
+                               minix_dirent *de = (minix_dirent *)p;
+                               namx = de->name;
+                               inumber = de->inode;
+                       }
+                       if (!inumber)
                                continue;
-                       if (namecompare(namelen,sbi->s_namelen,name,de->name))
+                       if (namecompare(namelen, sbi->s_namelen, name, namx))
                                goto found;
                }
                dir_put_page(page);
@@ -181,7 +205,7 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page)
 
 found:
        *res_page = page;
-       return de;
+       return (minix_dirent *)p;
 }
 
 int minix_add_link(struct dentry *dentry, struct inode *inode)
@@ -192,12 +216,15 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
        struct super_block * sb = dir->i_sb;
        struct minix_sb_info * sbi = minix_sb(sb);
        struct page *page = NULL;
-       struct minix_dir_entry * de;
        unsigned long npages = dir_pages(dir);
        unsigned long n;
-       char *kaddr;
+       char *kaddr, *p;
+       minix_dirent *de;
+       minix3_dirent *de3;
        unsigned from, to;
        int err;
+       char *namx = NULL;
+       __u32 inumber;
 
        /*
         * We take care of directory expansion in the same loop
@@ -205,7 +232,7 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
         * to protect that region.
         */
        for (n = 0; n <= npages; n++) {
-               char *dir_end;
+               char *limit, *dir_end;
 
                page = dir_get_page(dir, n);
                err = PTR_ERR(page);
@@ -214,20 +241,30 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
                lock_page(page);
                kaddr = (char*)page_address(page);
                dir_end = kaddr + minix_last_byte(dir, n);
-               de = (minix_dirent *)kaddr;
-               kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize;
-               while ((char *)de <= kaddr) {
-                       if ((char *)de == dir_end) {
+               limit = kaddr + PAGE_CACHE_SIZE - sbi->s_dirsize;
+               for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
+                       de = (minix_dirent *)p;
+                       de3 = (minix3_dirent *)p;
+                       if (sbi->s_version == MINIX_V3) {
+                               namx = de3->name;
+                               inumber = de3->inode;
+                       } else {
+                               namx = de->name;
+                               inumber = de->inode;
+                       }
+                       if (p == dir_end) {
                                /* We hit i_size */
-                               de->inode = 0;
+                               if (sbi->s_version == MINIX_V3)
+                                       de3->inode = 0;
+                               else
+                                       de->inode = 0;
                                goto got_it;
                        }
-                       if (!de->inode)
+                       if (!inumber)
                                goto got_it;
                        err = -EEXIST;
-                       if (namecompare(namelen,sbi->s_namelen,name,de->name))
+                       if (namecompare(namelen, sbi->s_namelen, name, namx))
                                goto out_unlock;
-                       de = minix_next_entry(de, sbi);
                }
                unlock_page(page);
                dir_put_page(page);
@@ -236,14 +273,19 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
        return -EINVAL;
 
 got_it:
-       from = (char*)de - (char*)page_address(page);
+       from = p - (char*)page_address(page);
        to = from + sbi->s_dirsize;
        err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
        if (err)
                goto out_unlock;
-       memcpy (de->name, name, namelen);
-       memset (de->name + namelen, 0, sbi->s_dirsize - namelen - 2);
-       de->inode = inode->i_ino;
+       memcpy (namx, name, namelen);
+       if (sbi->s_version == MINIX_V3) {
+               memset (namx + namelen, 0, sbi->s_dirsize - namelen - 4);
+               de3->inode = inode->i_ino;
+       } else {
+               memset (namx + namelen, 0, sbi->s_dirsize - namelen - 2);
+               de->inode = inode->i_ino;
+       }
        err = dir_commit_chunk(page, from, to);
        dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
        mark_inode_dirty(dir);
@@ -283,8 +325,7 @@ int minix_make_empty(struct inode *inode, struct inode *dir)
 {
        struct address_space *mapping = inode->i_mapping;
        struct page *page = grab_cache_page(mapping, 0);
-       struct minix_sb_info * sbi = minix_sb(inode->i_sb);
-       struct minix_dir_entry * de;
+       struct minix_sb_info *sbi = minix_sb(inode->i_sb);
        char *kaddr;
        int err;
 
@@ -299,12 +340,23 @@ int minix_make_empty(struct inode *inode, struct inode *dir)
        kaddr = kmap_atomic(page, KM_USER0);
        memset(kaddr, 0, PAGE_CACHE_SIZE);
 
-       de = (struct minix_dir_entry *)kaddr;
-       de->inode = inode->i_ino;
-       strcpy(de->name,".");
-       de = minix_next_entry(de, sbi);
-       de->inode = dir->i_ino;
-       strcpy(de->name,"..");
+       if (sbi->s_version == MINIX_V3) {
+               minix3_dirent *de3 = (minix3_dirent *)kaddr;
+
+               de3->inode = inode->i_ino;
+               strcpy(de3->name, ".");
+               de3 = minix_next_entry(de3, sbi);
+               de3->inode = dir->i_ino;
+               strcpy(de3->name, "..");
+       } else {
+               minix_dirent *de = (minix_dirent *)kaddr;
+
+               de->inode = inode->i_ino;
+               strcpy(de->name, ".");
+               de = minix_next_entry(de, sbi);
+               de->inode = dir->i_ino;
+               strcpy(de->name, "..");
+       }
        kunmap_atomic(kaddr, KM_USER0);
 
        err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
@@ -321,33 +373,41 @@ int minix_empty_dir(struct inode * inode)
        struct page *page = NULL;
        unsigned long i, npages = dir_pages(inode);
        struct minix_sb_info *sbi = minix_sb(inode->i_sb);
+       char *name;
+       __u32 inumber;
 
        for (i = 0; i < npages; i++) {
-               char *kaddr;
-               minix_dirent * de;
-               page = dir_get_page(inode, i);
+               char *p, *kaddr, *limit;
 
+               page = dir_get_page(inode, i);
                if (IS_ERR(page))
                        continue;
 
                kaddr = (char *)page_address(page);
-               de = (minix_dirent *)kaddr;
-               kaddr += minix_last_byte(inode, i) - sbi->s_dirsize;
+               limit = kaddr + minix_last_byte(inode, i) - sbi->s_dirsize;
+               for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
+                       if (sbi->s_version == MINIX_V3) {
+                               minix3_dirent *de3 = (minix3_dirent *)p;
+                               name = de3->name;
+                               inumber = de3->inode;
+                       } else {
+                               minix_dirent *de = (minix_dirent *)p;
+                               name = de->name;
+                               inumber = de->inode;
+                       }
 
-               while ((char *)de <= kaddr) {
-                       if (de->inode != 0) {
+                       if (inumber != 0) {
                                /* check for . and .. */
-                               if (de->name[0] != '.')
+                               if (name[0] != '.')
                                        goto not_empty;
-                               if (!de->name[1]) {
-                                       if (de->inode != inode->i_ino)
+                               if (!name[1]) {
+                                       if (inumber != inode->i_ino)
                                                goto not_empty;
-                               } else if (de->name[1] != '.')
+                               } else if (name[1] != '.')
                                        goto not_empty;
-                               else if (de->name[2])
+                               else if (name[2])
                                        goto not_empty;
                        }
-                       de = minix_next_entry(de, sbi);
                }
                dir_put_page(page);
        }
index 629e09b38c5cf67b23a4fe1eee0190616f44ccb6..9ddfcc14828799d7adedb30d44bf0d0a9ae64da2 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++)
@@ -117,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))
@@ -140,7 +147,8 @@ 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;
 
@@ -192,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;
 
@@ -236,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))
@@ -278,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;
@@ -537,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;
 }
 
index 429baf8de105419c49308447d8978348892701b9..a731cabf1540e0d0f12bff4f88ea23d40e78dd7a 100644 (file)
@@ -23,7 +23,7 @@ static inline int verify_chain(Indirect *from, Indirect *to)
 
 static inline block_t *block_end(struct buffer_head *bh)
 {
-       return (block_t *)((char*)bh->b_data + BLOCK_SIZE);
+       return (block_t *)((char*)bh->b_data + bh->b_size);
 }
 
 static inline Indirect *get_branch(struct inode *inode,
@@ -85,7 +85,7 @@ static int alloc_branch(struct inode *inode,
                branch[n].key = cpu_to_block(nr);
                bh = sb_getblk(inode->i_sb, parent);
                lock_buffer(bh);
-               memset(bh->b_data, 0, BLOCK_SIZE);
+               memset(bh->b_data, 0, bh->b_size);
                branch[n].bh = bh;
                branch[n].p = (block_t*) bh->b_data + offsets[n];
                *branch[n].p = branch[n].key;
@@ -292,6 +292,7 @@ static void free_branches(struct inode *inode, block_t *p, block_t *q, int depth
 
 static inline void truncate (struct inode * inode)
 {
+       struct super_block *sb = inode->i_sb;
        block_t *idata = i_data(inode);
        int offsets[DEPTH];
        Indirect chain[DEPTH];
@@ -301,7 +302,7 @@ static inline void truncate (struct inode * inode)
        int first_whole;
        long iblock;
 
-       iblock = (inode->i_size + BLOCK_SIZE-1) >> 10;
+       iblock = (inode->i_size + sb->s_blocksize -1) >> sb->s_blocksize_bits;
        block_truncate_page(inode->i_mapping, inode->i_size, get_block);
 
        n = block_to_path(inode, iblock, offsets);
@@ -346,15 +347,16 @@ do_indirects:
        mark_inode_dirty(inode);
 }
 
-static inline unsigned nblocks(loff_t size)
+static inline unsigned nblocks(loff_t size, struct super_block *sb)
 {
+       int k = sb->s_blocksize_bits - 10;
        unsigned blocks, res, direct = DIRECT, i = DEPTH;
-       blocks = (size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
+       blocks = (size + sb->s_blocksize - 1) >> (BLOCK_SIZE_BITS + k);
        res = blocks;
        while (--i && blocks > direct) {
                blocks -= direct;
-               blocks += BLOCK_SIZE/sizeof(block_t) - 1;
-               blocks /= BLOCK_SIZE/sizeof(block_t);
+               blocks += sb->s_blocksize/sizeof(block_t) - 1;
+               blocks /= sb->s_blocksize/sizeof(block_t);
                res += blocks;
                direct = 1;
        }
index 656b1347a25bee35577d0d2cb73a190f9f3adac2..1a5f3bf0bcecde761fc78da91ea49a439ed44d99 100644 (file)
@@ -55,7 +55,7 @@ void V1_minix_truncate(struct inode * inode)
        truncate(inode);
 }
 
-unsigned V1_minix_blocks(loff_t size)
+unsigned V1_minix_blocks(loff_t size, struct super_block *sb)
 {
-       return nblocks(size);
+       return nblocks(size, sb);
 }
index 9adcdc754e0fc2da58b7496b472789d41a910445..ad8f0dec4ef46e2b3e6201dea67ddf6a0182ac94 100644 (file)
@@ -23,10 +23,11 @@ static inline block_t *i_data(struct inode *inode)
 static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
 {
        int n = 0;
+       struct super_block *sb = inode->i_sb;
 
        if (block < 0) {
                printk("minix_bmap: block<0\n");
-       } else if (block >= (minix_sb(inode->i_sb)->s_max_size/BLOCK_SIZE)) {
+       } else if (block >= (minix_sb(inode->i_sb)->s_max_size/sb->s_blocksize)) {
                printk("minix_bmap: block>big\n");
        } else if (block < 7) {
                offsets[n++] = block;
@@ -60,7 +61,7 @@ void V2_minix_truncate(struct inode * inode)
        truncate(inode);
 }
 
-unsigned V2_minix_blocks(loff_t size)
+unsigned V2_minix_blocks(loff_t size, struct super_block *sb)
 {
-       return nblocks(size);
+       return nblocks(size, sb);
 }
index c55b77cdcc8e2af21e447a168e5cbb4ad26c6d42..e016ee91d936e97472fce329ee82bba196e85610 100644 (file)
@@ -7,11 +7,10 @@
  * truncated. Else they will be disallowed (ENAMETOOLONG).
  */
 #define NO_TRUNCATE 1
-
 #define INODE_VERSION(inode)   minix_sb(inode->i_sb)->s_version
-
 #define MINIX_V1               0x0001          /* original minix fs */
 #define MINIX_V2               0x0002          /* minix V2 fs */
+#define MINIX_V3               0x0003          /* minix V3 fs */
 
 /*
  * minix fs inode data in memory
@@ -52,12 +51,10 @@ extern struct inode * minix_new_inode(const struct inode * dir, int * error);
 extern void minix_free_inode(struct inode * inode);
 extern unsigned long minix_count_free_inodes(struct minix_sb_info *sbi);
 extern int minix_new_block(struct inode * inode);
-extern void minix_free_block(struct inode * inode, int block);
+extern void minix_free_block(struct inode *inode, unsigned long block);
 extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi);
-
 extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 
-extern void V2_minix_truncate(struct inode *);
 extern void V1_minix_truncate(struct inode *);
 extern void V2_minix_truncate(struct inode *);
 extern void minix_truncate(struct inode *);
@@ -65,8 +62,8 @@ extern int minix_sync_inode(struct inode *);
 extern void minix_set_inode(struct inode *, dev_t);
 extern int V1_minix_get_block(struct inode *, long, struct buffer_head *, int);
 extern int V2_minix_get_block(struct inode *, long, struct buffer_head *, int);
-extern unsigned V1_minix_blocks(loff_t);
-extern unsigned V2_minix_blocks(loff_t);
+extern unsigned V1_minix_blocks(loff_t, struct super_block *);
+extern unsigned V2_minix_blocks(loff_t, struct super_block *);
 
 extern struct minix_dir_entry *minix_find_entry(struct dentry*, struct page**);
 extern int minix_add_link(struct dentry*, struct inode*);
@@ -76,7 +73,6 @@ extern int minix_empty_dir(struct inode*);
 extern void minix_set_link(struct minix_dir_entry*, struct page*, struct inode*);
 extern struct minix_dir_entry *minix_dotdot(struct inode*, struct page**);
 extern ino_t minix_inode_by_name(struct dentry*);
-
 extern int minix_sync_file(struct file *, struct dentry *, int);
 
 extern struct inode_operations minix_file_inode_operations;
index b78bbf42135ac4287e8be81efee7ce3ebcddb3a7..b32c8a97fcec51b3ea266b75a964df505d36f542 100644 (file)
@@ -18,6 +18,7 @@
 #define MINIX_SUPER_MAGIC2     0x138F          /* minix fs, 30 char names */
 #define MINIX2_SUPER_MAGIC     0x2468          /* minix V2 fs */
 #define MINIX2_SUPER_MAGIC2    0x2478          /* minix V2 fs, 30 char names */
+#define MINIX3_SUPER_MAGIC     0x4d5a          /* minix V3 fs */
 
 #define MSDOS_SUPER_MAGIC      0x4d44          /* MD */
 #define NCP_SUPER_MAGIC                0x564c          /* Guess, what 0x564c is :-) */
index 916e8f72c63d1b3f71a3d95f07649d874d205504..9850d513ff60e9b023273a9aa6a29f3b0baf2ed0 100644 (file)
@@ -25,7 +25,6 @@
 #define MINIX_ERROR_FS         0x0002          /* fs has errors. */
 
 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
-#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
 
 /*
  * This is the original minix inode layout on disk.
@@ -75,9 +74,33 @@ struct minix_super_block {
        __u32 s_zones;
 };
 
+/*
+ * V3 minix super-block data on disk
+ */
+struct minix3_super_block {
+       __u16 s_ninodes;
+       __u16 s_nzones;
+       __u16 s_pad0;
+       __u16 s_imap_blocks;
+       __u16 s_zmap_blocks;
+       __u16 s_firstdatazone;
+       __u16 s_log_zone_size;
+       __u16 s_pad1;
+       __u32 s_max_size;
+       __u32 s_zones;
+       __u16 s_magic;
+       __u16 s_pad2;
+       __u16 s_blocksize;
+       __u8  s_disk_version;
+};
+
 struct minix_dir_entry {
        __u16 inode;
        char name[0];
 };
 
+struct minix3_dir_entry {
+       __u32 inode;
+       char name[0];
+};
 #endif