summaryrefslogtreecommitdiffstats
path: root/fs/minix
diff options
context:
space:
mode:
Diffstat (limited to 'fs/minix')
-rw-r--r--fs/minix/Makefile2
-rw-r--r--fs/minix/bitmap.c29
-rw-r--r--fs/minix/file.c14
-rw-r--r--fs/minix/fsync.c344
-rw-r--r--fs/minix/inode.c591
-rw-r--r--fs/minix/itree_common.c417
-rw-r--r--fs/minix/itree_v1.c63
-rw-r--r--fs/minix/itree_v2.c68
-rw-r--r--fs/minix/namei.c28
-rw-r--r--fs/minix/truncate.c420
10 files changed, 602 insertions, 1374 deletions
diff --git a/fs/minix/Makefile b/fs/minix/Makefile
index c3aee4fe3..13841d16a 100644
--- a/fs/minix/Makefile
+++ b/fs/minix/Makefile
@@ -8,7 +8,7 @@
# Note 2! The CFLAGS definitions are now in the main makefile.
O_TARGET := minix.o
-O_OBJS := bitmap.o truncate.o namei.o inode.o file.o dir.o fsync.o
+O_OBJS := bitmap.o itree_v1.o itree_v2.o namei.o inode.o file.o dir.o
M_OBJS := $(O_TARGET)
include $(TOPDIR)/Rules.make
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index fa2bd5f03..a268be2f1 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -83,9 +83,7 @@ void minix_free_block(struct inode * inode, int block)
if (!minix_test_and_clear_bit(bit,bh->b_data))
printk("free_block (%s:%d): bit already cleared\n",
kdevname(sb->s_dev), block);
- else
- DQUOT_FREE_BLOCK(sb, inode, 1);
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
return;
}
@@ -100,9 +98,6 @@ int minix_new_block(struct inode * inode)
return 0;
}
repeat:
- if(DQUOT_ALLOC_BLOCK(sb, inode, 1))
- return -EDQUOT;
-
j = 8192;
bh = NULL;
for (i = 0; i < sb->u.minix_sb.s_zmap_blocks; i++) {
@@ -114,10 +109,9 @@ repeat:
return 0;
if (minix_test_and_set_bit(j,bh->b_data)) {
printk("new_block: bit already set");
- DQUOT_FREE_BLOCK(sb, inode, 1);
goto repeat;
}
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
j += i*8192 + sb->u.minix_sb.s_firstdatazone-1;
if (j < sb->u.minix_sb.s_firstdatazone ||
j >= sb->u.minix_sb.s_nzones)
@@ -156,7 +150,7 @@ static struct buffer_head *V1_minix_clear_inode(struct inode *inode)
(ino - 1) % MINIX_INODES_PER_BLOCK);
raw_inode->i_nlinks = 0;
raw_inode->i_mode = 0;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
return bh;
}
@@ -184,7 +178,7 @@ static struct buffer_head *V2_minix_clear_inode(struct inode *inode)
(ino - 1) % MINIX2_INODES_PER_BLOCK);
raw_inode->i_nlinks = 0;
raw_inode->i_mode = 0;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
return bh;
}
@@ -215,15 +209,12 @@ void minix_free_inode(struct inode * inode)
return;
}
- DQUOT_FREE_INODE(inode->i_sb, inode);
- DQUOT_DROP(inode);
-
bh = inode->i_sb->u.minix_sb.s_imap[ino >> 13];
minix_clear_inode(inode);
clear_inode(inode);
if (!minix_test_and_clear_bit(ino & 8191, bh->b_data))
printk("free_inode: bit %lu already cleared.\n",ino);
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
}
struct inode * minix_new_inode(const struct inode * dir, int * error)
@@ -258,7 +249,7 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
unlock_super(sb);
return NULL;
}
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
j += i*8192;
if (!j || j > inode->i_sb->u.minix_sb.s_ninodes) {
iput(inode);
@@ -276,14 +267,6 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
mark_inode_dirty(inode);
unlock_super(sb);
- if(DQUOT_ALLOC_INODE(sb, inode)) {
- sb->dq_op->drop(inode);
- inode->i_nlink = 0;
- iput(inode);
- *error = -EDQUOT;
- return NULL;
- }
-
*error = 0;
return inode;
}
diff --git a/fs/minix/file.c b/fs/minix/file.c
index c0b5ad89f..63534d4bc 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -13,6 +13,8 @@
* We have mostly NULLs here: the current defaults are OK for
* the minix filesystem.
*/
+static int minix_sync_file(struct file *, struct dentry *, int);
+
struct file_operations minix_file_operations = {
read: generic_file_read,
write: generic_file_write,
@@ -23,3 +25,15 @@ struct file_operations minix_file_operations = {
struct inode_operations minix_file_inode_operations = {
truncate: minix_truncate,
};
+
+static int minix_sync_file(struct file * file,
+ struct dentry *dentry,
+ int datasync)
+{
+ struct inode *inode = dentry->d_inode;
+
+ if (INODE_VERSION(inode) == MINIX_V1)
+ return V1_minix_sync_file(inode);
+ else
+ return V2_minix_sync_file(inode);
+}
diff --git a/fs/minix/fsync.c b/fs/minix/fsync.c
deleted file mode 100644
index 96e1ffa86..000000000
--- a/fs/minix/fsync.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * linux/fs/minix/fsync.c
- *
- * Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk)
- * from
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * Copyright (C) 1996 Gertjan van Wingerde (gertjan@cs.vu.nl)
- * Minix V2 fs support
- *
- * minix fsync primitive
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/locks.h>
-#include <linux/smp_lock.h>
-
-#include <linux/fs.h>
-#include <linux/minix_fs.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#define blocksize BLOCK_SIZE
-
-/*
- * The functions for minix V1 fs file synchronization.
- */
-static int V1_sync_block (struct inode * inode, unsigned short * block, int wait)
-{
- struct buffer_head * bh;
- unsigned short tmp;
-
- if (!*block)
- return 0;
- tmp = *block;
- bh = get_hash_table(inode->i_dev, *block, blocksize);
- if (!bh)
- return 0;
- if (*block != tmp) {
- brelse (bh);
- return 1;
- }
- if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
- brelse(bh);
- return -1;
- }
- if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh))
- {
- brelse(bh);
- return 0;
- }
- ll_rw_block(WRITE, 1, &bh);
- atomic_dec(&bh->b_count);
- return 0;
-}
-
-static int V1_sync_iblock (struct inode * inode, unsigned short * iblock,
- struct buffer_head **bh, int wait)
-{
- int rc;
- unsigned short tmp;
-
- *bh = NULL;
- tmp = *iblock;
- if (!tmp)
- return 0;
- rc = V1_sync_block (inode, iblock, wait);
- if (rc)
- return rc;
- *bh = bread(inode->i_dev, tmp, blocksize);
- if (tmp != *iblock) {
- brelse(*bh);
- *bh = NULL;
- return 1;
- }
- if (!*bh)
- return -1;
- return 0;
-}
-
-static int V1_sync_direct(struct inode *inode, int wait)
-{
- int i;
- int rc, err = 0;
-
- for (i = 0; i < 7; i++) {
- rc = V1_sync_block (inode,
- (unsigned short *) inode->u.minix_i.u.i1_data + i, wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- return err;
-}
-
-static int V1_sync_indirect(struct inode *inode, unsigned short *iblock, int wait)
-{
- int i;
- struct buffer_head * ind_bh;
- int rc, err = 0;
-
- rc = V1_sync_iblock (inode, iblock, &ind_bh, wait);
- if (rc || !ind_bh)
- return rc;
-
- for (i = 0; i < 512; i++) {
- rc = V1_sync_block (inode,
- ((unsigned short *) ind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(ind_bh);
- return err;
-}
-
-static int V1_sync_dindirect(struct inode *inode, unsigned short *diblock,
- int wait)
-{
- int i;
- struct buffer_head * dind_bh;
- int rc, err = 0;
-
- rc = V1_sync_iblock (inode, diblock, &dind_bh, wait);
- if (rc || !dind_bh)
- return rc;
-
- for (i = 0; i < 512; i++) {
- rc = V1_sync_indirect (inode,
- ((unsigned short *) dind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(dind_bh);
- return err;
-}
-
-static int V1_minix_sync_file(struct inode * inode, struct file * file)
-{
- int wait, err = 0;
-
- lock_kernel();
- for (wait=0; wait<=1; wait++)
- {
- err |= V1_sync_direct(inode, wait);
- err |= V1_sync_indirect(inode, inode->u.minix_i.u.i1_data + 7, wait);
- err |= V1_sync_dindirect(inode, inode->u.minix_i.u.i1_data + 8, wait);
- }
- err |= minix_sync_inode (inode);
- unlock_kernel();
- return (err < 0) ? -EIO : 0;
-}
-
-/*
- * The functions for minix V2 fs file synchronization.
- */
-static int V2_sync_block (struct inode * inode, unsigned long * block, int wait)
-{
- struct buffer_head * bh;
- unsigned long tmp;
-
- if (!*block)
- return 0;
- tmp = *block;
- bh = get_hash_table(inode->i_dev, *block, blocksize);
- if (!bh)
- return 0;
- if (*block != tmp) {
- brelse (bh);
- return 1;
- }
- if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
- brelse(bh);
- return -1;
- }
- if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh))
- {
- brelse(bh);
- return 0;
- }
- ll_rw_block(WRITE, 1, &bh);
- atomic_dec(&bh->b_count);
- return 0;
-}
-
-static int V2_sync_iblock (struct inode * inode, unsigned long * iblock,
- struct buffer_head **bh, int wait)
-{
- int rc;
- unsigned long tmp;
-
- *bh = NULL;
- tmp = *iblock;
- if (!tmp)
- return 0;
- rc = V2_sync_block (inode, iblock, wait);
- if (rc)
- return rc;
- *bh = bread(inode->i_dev, tmp, blocksize);
- if (tmp != *iblock) {
- brelse(*bh);
- *bh = NULL;
- return 1;
- }
- if (!*bh)
- return -1;
- return 0;
-}
-
-static int V2_sync_direct(struct inode *inode, int wait)
-{
- int i;
- int rc, err = 0;
-
- for (i = 0; i < 7; i++) {
- rc = V2_sync_block (inode,
- (unsigned long *)inode->u.minix_i.u.i2_data + i, wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- return err;
-}
-
-static int V2_sync_indirect(struct inode *inode, unsigned long *iblock, int wait)
-{
- int i;
- struct buffer_head * ind_bh;
- int rc, err = 0;
-
- rc = V2_sync_iblock (inode, iblock, &ind_bh, wait);
- if (rc || !ind_bh)
- return rc;
-
- for (i = 0; i < 256; i++) {
- rc = V2_sync_block (inode,
- ((unsigned long *) ind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(ind_bh);
- return err;
-}
-
-static int V2_sync_dindirect(struct inode *inode, unsigned long *diblock,
- int wait)
-{
- int i;
- struct buffer_head * dind_bh;
- int rc, err = 0;
-
- rc = V2_sync_iblock (inode, diblock, &dind_bh, wait);
- if (rc || !dind_bh)
- return rc;
-
- for (i = 0; i < 256; i++) {
- rc = V2_sync_indirect (inode,
- ((unsigned long *) dind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(dind_bh);
- return err;
-}
-
-static int V2_sync_tindirect(struct inode *inode, unsigned long *tiblock,
- int wait)
-{
- int i;
- struct buffer_head * tind_bh;
- int rc, err = 0;
-
- rc = V2_sync_iblock (inode, tiblock, &tind_bh, wait);
- if (rc || !tind_bh)
- return rc;
-
- for (i = 0; i < 256; i++) {
- rc = V2_sync_dindirect (inode,
- ((unsigned long *) tind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(tind_bh);
- return err;
-}
-
-static int V2_minix_sync_file(struct inode * inode, struct file * file)
-{
- int wait, err = 0;
-
- lock_kernel();
- for (wait=0; wait<=1; wait++)
- {
- err |= V2_sync_direct(inode, wait);
- err |= V2_sync_indirect(inode,
- (unsigned long *) inode->u.minix_i.u.i2_data + 7, wait);
- err |= V2_sync_dindirect(inode,
- (unsigned long *) inode->u.minix_i.u.i2_data + 8, wait);
- err |= V2_sync_tindirect(inode,
- (unsigned long *) inode->u.minix_i.u.i2_data + 9, wait);
- }
- err |= minix_sync_inode (inode);
- unlock_kernel();
- return (err < 0) ? -EIO : 0;
-}
-
-/*
- * The function which is called for file synchronization. File may be
- * NULL
- */
-
-int minix_sync_file(struct file * file, struct dentry *dentry, int datasync)
-{
- struct inode *inode = dentry->d_inode;
-
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return -EINVAL;
-
- if (INODE_VERSION(inode) == MINIX_V1)
- return V1_minix_sync_file(inode, file);
- else
- return V2_minix_sync_file(inode, file);
-}
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index b49626923..38bb52cfd 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -45,7 +45,7 @@ static void minix_delete_inode(struct inode *inode)
static void minix_commit_super(struct super_block * sb)
{
- mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1);
+ mark_buffer_dirty(sb->u.minix_sb.s_sbh);
sb->s_dirt = 0;
}
@@ -70,7 +70,7 @@ static void minix_put_super(struct super_block *sb)
if (!(sb->s_flags & MS_RDONLY)) {
sb->u.minix_sb.s_ms->s_state = sb->u.minix_sb.s_mount_state;
- mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1);
+ mark_buffer_dirty(sb->u.minix_sb.s_sbh);
}
for (i = 0; i < sb->u.minix_sb.s_imap_blocks; i++)
brelse(sb->u.minix_sb.s_imap[i]);
@@ -105,7 +105,7 @@ static int minix_remount (struct super_block * sb, int * flags, char * data)
return 0;
/* Mounting a rw partition read-only. */
ms->s_state = sb->u.minix_sb.s_mount_state;
- mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1);
+ mark_buffer_dirty(sb->u.minix_sb.s_sbh);
sb->s_dirt = 1;
minix_commit_super(sb);
}
@@ -113,7 +113,7 @@ static int minix_remount (struct super_block * sb, int * flags, char * data)
/* Mount a partition which is read-only, read-write. */
sb->u.minix_sb.s_mount_state = ms->s_state;
ms->s_state &= ~MINIX_VALID_FS;
- mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1);
+ mark_buffer_dirty(sb->u.minix_sb.s_sbh);
sb->s_dirt = 1;
if (!(sb->u.minix_sb.s_mount_state & MINIX_VALID_FS))
@@ -279,7 +279,7 @@ static struct super_block *minix_read_super(struct super_block *s, void *data,
if (!(s->s_flags & MS_RDONLY)) {
ms->s_state &= ~MINIX_VALID_FS;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
s->s_dirt = 1;
}
if (!(s->u.minix_sb.s_mount_state & MINIX_VALID_FS))
@@ -348,573 +348,13 @@ static int minix_statfs(struct super_block *sb, struct statfs *buf)
return 0;
}
-/*
- * The minix V1 fs bmap functions.
- */
-#define V1_inode_bmap(inode,nr) (((unsigned short *)(inode)->u.minix_i.u.i1_data)[(nr)])
-
-static int V1_block_bmap(struct buffer_head * bh, int nr)
-{
- int tmp;
-
- if (!bh)
- return 0;
- tmp = ((unsigned short *) bh->b_data)[nr];
- brelse(bh);
- return tmp;
-}
-
-static int V1_minix_block_map(struct inode * inode, long block)
-{
- int i, ret;
-
- ret = 0;
- lock_kernel();
- if (block < 0) {
- printk("minix_bmap: block<0");
- goto out;
- }
- if (block >= (inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)) {
- printk("minix_bmap: block>big");
- goto out;
- }
- if (block < 7) {
- ret = V1_inode_bmap(inode,block);
- goto out;
- }
- block -= 7;
- if (block < 512) {
- i = V1_inode_bmap(inode,7);
- if (!i)
- goto out;
- ret = V1_block_bmap(bread(inode->i_dev, i,
- BLOCK_SIZE), block);
- goto out;
- }
- block -= 512;
- i = V1_inode_bmap(inode,8);
- if (!i)
- goto out;
- i = V1_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>9);
- if (!i)
- goto out;
- ret = V1_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
- block & 511);
-out:
- unlock_kernel();
- return ret;
-}
-
-/*
- * The minix V2 fs bmap functions.
- */
-#define V2_inode_bmap(inode,nr) (((unsigned int *)(inode)->u.minix_i.u.i2_data)[(nr)])
-static int V2_block_bmap(struct buffer_head * bh, int nr)
-{
- int tmp;
-
- if (!bh)
- return 0;
- tmp = ((unsigned int *) bh->b_data)[nr];
- brelse(bh);
- return tmp;
-}
-
-static int V2_minix_block_map(struct inode * inode, int block)
-{
- int i, ret;
-
- ret = 0;
- lock_kernel();
- if (block < 0) {
- printk("minix_bmap: block<0");
- goto out;
- }
- if (block >= (inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)) {
- printk("minix_bmap: block>big");
- goto out;
- }
- if (block < 7) {
- ret = V2_inode_bmap(inode,block);
- goto out;
- }
- block -= 7;
- if (block < 256) {
- i = V2_inode_bmap(inode, 7);
- if (!i)
- goto out;
- ret = V2_block_bmap(bread(inode->i_dev, i,
- BLOCK_SIZE), block);
- goto out;
- }
- block -= 256;
- if (block < (256 * 256)) {
- i = V2_inode_bmap(inode, 8);
- if (!i)
- goto out;
- i = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
- block >> 8);
- if (!i)
- goto out;
- ret = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
- block & 255);
- goto out;
- }
- block -= (256 * 256);
- i = V2_inode_bmap(inode, 9);
- if (!i)
- goto out;
- i = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
- block >> 16);
- if (!i)
- goto out;
- i = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
- (block >> 8) & 255);
- if (!i)
- goto out;
- ret = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
- block & 255);
-out:
- unlock_kernel();
- return ret;
-}
-
-/*
- * The minix V1 fs getblk functions.
- */
-static struct buffer_head * V1_inode_getblk(struct inode * inode, int nr,
- int new_block, int *err,
- int metadata, int *phys, int *new)
-{
- int tmp;
- unsigned short *p;
- struct buffer_head * result;
-
- p = inode->u.minix_i.u.i1_data + nr;
-repeat:
- tmp = *p;
- if (tmp) {
- if (metadata) {
- result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp == *p)
- return result;
- brelse(result);
- goto repeat;
- } else {
- *phys = tmp;
- return NULL;
- }
- }
-
- tmp = minix_new_block(inode);
- if (!tmp) {
- *err = -ENOSPC;
- return NULL;
- }
- if (metadata) {
- result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
- if (*p) {
- minix_free_block(inode, tmp);
- brelse(result);
- goto repeat;
- }
- memset(result->b_data, 0, BLOCK_SIZE);
- mark_buffer_uptodate(result, 1);
- mark_buffer_dirty(result, 1);
- } else {
- if (*p) {
- /*
- * Nobody is allowed to change block allocation
- * state from under us:
- */
- BUG();
- minix_free_block(inode, tmp);
- goto repeat;
- }
- *phys = tmp;
- result = NULL;
- *err = 0;
- *new = 1;
- }
- *p = tmp;
-
- inode->i_ctime = CURRENT_TIME;
- mark_inode_dirty(inode);
- return result;
-}
-
-static struct buffer_head * V1_block_getblk(struct inode * inode,
- struct buffer_head * bh, int nr, int new_block, int *err,
- int metadata, int *phys, int *new)
-{
- int tmp;
- unsigned short *p;
- struct buffer_head * result;
-
- result = NULL;
- if (!bh)
- goto out;
- if (!buffer_uptodate(bh)) {
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh))
- goto out;
- }
- p = nr + (unsigned short *) bh->b_data;
-repeat:
- tmp = *p;
- if (tmp) {
- if (metadata) {
- result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
- if (tmp == *p)
- goto out;
- brelse(result);
- goto repeat;
- } else {
- *phys = tmp;
- goto out;
- }
- }
-
- tmp = minix_new_block(inode);
- if (!tmp)
- goto out;
- if (metadata) {
- result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
- if (*p) {
- minix_free_block(inode, tmp);
- brelse(result);
- goto repeat;
- }
- memset(result->b_data, 0, BLOCK_SIZE);
- mark_buffer_uptodate(result, 1);
- mark_buffer_dirty(result, 1);
- } else {
- *phys = tmp;
- *new = 1;
- }
- if (*p) {
- minix_free_block(inode, tmp);
- brelse(result);
- goto repeat;
- }
-
- *p = tmp;
- mark_buffer_dirty(bh, 1);
- *err = 0;
-out:
- brelse(bh);
- return result;
-}
-
-static int V1_get_block(struct inode * inode, long block,
- struct buffer_head *bh_result, int create)
-{
- int ret, err, new, phys, ptr;
- struct buffer_head *bh;
-
- if (!create) {
- phys = V1_minix_block_map(inode, block);
- if (phys) {
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- }
- return 0;
- }
-
- err = -EIO;
- new = 0;
- ret = 0;
- bh = NULL;
-
- lock_kernel();
- if (block < 0)
- goto abort_negative;
- if (block >= inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)
- goto abort_too_big;
-
- err = 0;
- ptr = block;
- /*
- * ok, these macros clean the logic up a bit and make
- * it much more readable:
- */
-#define GET_INODE_DATABLOCK(x) \
- V1_inode_getblk(inode, x, block, &err, 0, &phys, &new)
-#define GET_INODE_PTR(x) \
- V1_inode_getblk(inode, x, block, &err, 1, NULL, NULL)
-#define GET_INDIRECT_DATABLOCK(x) \
- V1_block_getblk(inode, bh, x, block, &err, 0, &phys, &new)
-#define GET_INDIRECT_PTR(x) \
- V1_block_getblk(inode, bh, x, block, &err, 1, NULL, NULL)
-
- if (ptr < 7) {
- bh = GET_INODE_DATABLOCK(ptr);
- goto out;
- }
- ptr -= 7;
- if (ptr < 512) {
- bh = GET_INODE_PTR(7);
- goto get_indirect;
- }
- ptr -= 512;
- bh = GET_INODE_PTR(8);
- bh = GET_INDIRECT_PTR((ptr >> 9) & 511);
-get_indirect:
- bh = GET_INDIRECT_DATABLOCK(ptr & 511);
-
-#undef GET_INODE_DATABLOCK
-#undef GET_INODE_PTR
-#undef GET_INDIRECT_DATABLOCK
-#undef GET_INDIRECT_PTR
-
-out:
- if (err)
- goto abort;
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- if (new)
- bh_result->b_state |= (1UL << BH_New);
-abort:
- unlock_kernel();
- return err;
-
-abort_negative:
- printk("minix_getblk: block<0");
- goto abort;
-
-abort_too_big:
- printk("minix_getblk: block>big");
- goto abort;
-}
-
-/*
- * The minix V2 fs getblk functions.
- */
-static struct buffer_head * V2_inode_getblk(struct inode * inode, int nr,
- int new_block, int *err,
- int metadata, int *phys, int *new)
-{
- int tmp;
- unsigned int *p;
- struct buffer_head * result;
-
- p = (unsigned int *) inode->u.minix_i.u.i2_data + nr;
-repeat:
- tmp = *p;
- if (tmp) {
- if (metadata) {
- result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp == *p)
- return result;
- brelse(result);
- goto repeat;
- } else {
- *phys = tmp;
- return NULL;
- }
- }
-
- tmp = minix_new_block(inode);
- if (!tmp) {
- *err = -ENOSPC;
- return NULL;
- }
- if (metadata) {
- result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
- if (*p) {
- minix_free_block(inode, tmp);
- brelse(result);
- goto repeat;
- }
- memset(result->b_data, 0, BLOCK_SIZE);
- mark_buffer_uptodate(result, 1);
- mark_buffer_dirty(result, 1);
- } else {
- if (*p) {
- /*
- * Nobody is allowed to change block allocation
- * state from under us:
- */
- BUG();
- minix_free_block(inode, tmp);
- goto repeat;
- }
- *phys = tmp;
- result = NULL;
- *err = 0;
- *new = 1;
- }
- *p = tmp;
-
- inode->i_ctime = CURRENT_TIME;
- mark_inode_dirty(inode);
- return result;
-}
-
-static struct buffer_head * V2_block_getblk(struct inode * inode,
- struct buffer_head * bh, int nr, int new_block, int *err,
- int metadata, int *phys, int *new)
-{
- int tmp;
- unsigned int *p;
- struct buffer_head * result;
-
- result = NULL;
- if (!bh)
- goto out;
- if (!buffer_uptodate(bh)) {
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh))
- goto out;
- }
- p = nr + (unsigned int *) bh->b_data;
-repeat:
- tmp = *p;
- if (tmp) {
- if (metadata) {
- result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
- if (tmp == *p)
- goto out;
- brelse(result);
- goto repeat;
- } else {
- *phys = tmp;
- goto out;
- }
- }
-
- tmp = minix_new_block(inode);
- if (!tmp)
- goto out;
- if (metadata) {
- result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
- if (*p) {
- minix_free_block(inode, tmp);
- brelse(result);
- goto repeat;
- }
- memset(result->b_data, 0, BLOCK_SIZE);
- mark_buffer_uptodate(result, 1);
- mark_buffer_dirty(result, 1);
- } else {
- *phys = tmp;
- *new = 1;
- }
- if (*p) {
- minix_free_block(inode, tmp);
- brelse(result);
- goto repeat;
- }
-
- *p = tmp;
- mark_buffer_dirty(bh, 1);
- *err = 0;
-out:
- brelse(bh);
- return result;
-}
-
-static int V2_get_block(struct inode * inode, long block,
- struct buffer_head *bh_result, int create)
-{
- int ret, err, new, phys, ptr;
- struct buffer_head * bh;
-
- if (!create) {
- phys = V2_minix_block_map(inode, block);
- if (phys) {
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- }
- return 0;
- }
-
- err = -EIO;
- new = 0;
- ret = 0;
- bh = NULL;
-
- lock_kernel();
- if (block < 0)
- goto abort_negative;
- if (block >= inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)
- goto abort_too_big;
-
- err = 0;
- ptr = block;
- /*
- * ok, these macros clean the logic up a bit and make
- * it much more readable:
- */
-#define GET_INODE_DATABLOCK(x) \
- V2_inode_getblk(inode, x, block, &err, 0, &phys, &new)
-#define GET_INODE_PTR(x) \
- V2_inode_getblk(inode, x, block, &err, 1, NULL, NULL)
-#define GET_INDIRECT_DATABLOCK(x) \
- V2_block_getblk(inode, bh, x, block, &err, 0, &phys, &new)
-#define GET_INDIRECT_PTR(x) \
- V2_block_getblk(inode, bh, x, block, &err, 1, NULL, NULL)
-
- if (ptr < 7) {
- bh = GET_INODE_DATABLOCK(ptr);
- goto out;
- }
- ptr -= 7;
- if (ptr < 256) {
- bh = GET_INODE_PTR(7);
- goto get_indirect;
- }
- ptr -= 256;
- if (ptr < 256*256) {
- bh = GET_INODE_PTR(8);
- goto get_double;
- }
- ptr -= 256*256;
- bh = GET_INODE_PTR(9);
- bh = GET_INDIRECT_PTR((ptr >> 16) & 255);
-get_double:
- bh = GET_INDIRECT_PTR((ptr >> 8) & 255);
-get_indirect:
- bh = GET_INDIRECT_DATABLOCK(ptr & 255);
-
-#undef GET_INODE_DATABLOCK
-#undef GET_INODE_PTR
-#undef GET_INDIRECT_DATABLOCK
-#undef GET_INDIRECT_PTR
-
-out:
- if (err)
- goto abort;
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- if (new)
- bh_result->b_state |= (1UL << BH_New);
-abort:
- unlock_kernel();
- return err;
-
-abort_negative:
- printk("minix_getblk: block<0");
- goto abort;
-
-abort_too_big:
- printk("minix_getblk: block>big");
- goto abort;
-}
-
static int minix_get_block(struct inode *inode, long block,
struct buffer_head *bh_result, int create)
{
if (INODE_VERSION(inode) == MINIX_V1)
- return V1_get_block(inode, block, bh_result, create);
+ return V1_minix_get_block(inode, block, bh_result, create);
else
- return V2_get_block(inode, block, bh_result, create);
+ return V2_minix_get_block(inode, block, bh_result, create);
}
/*
@@ -934,7 +374,7 @@ struct buffer_head *minix_getblk(struct inode *inode, int block, int create)
if (buffer_new(&dummy)) {
memset(bh->b_data, 0, BLOCK_SIZE);
mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
}
return bh;
}
@@ -1130,7 +570,7 @@ static struct buffer_head * V1_minix_update_inode(struct inode * inode)
raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
else for (block = 0; block < 9; block++)
raw_inode->i_zone[block] = inode->u.minix_i.u.i1_data[block];
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
return bh;
}
@@ -1170,7 +610,7 @@ static struct buffer_head * V2_minix_update_inode(struct inode * inode)
raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
else for (block = 0; block < 10; block++)
raw_inode->i_zone[block] = inode->u.minix_i.u.i2_data[block];
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
return bh;
}
@@ -1216,6 +656,17 @@ int minix_sync_inode(struct inode * inode)
return err;
}
+/*
+ * The function that is called for file truncation.
+ */
+void minix_truncate(struct inode * inode)
+{
+ if (INODE_VERSION(inode) == MINIX_V1)
+ V1_minix_truncate(inode);
+ else
+ V2_minix_truncate(inode);
+}
+
static DECLARE_FSTYPE_DEV(minix_fs_type,"minix",minix_read_super);
static int __init init_minix_fs(void)
diff --git a/fs/minix/itree_common.c b/fs/minix/itree_common.c
new file mode 100644
index 000000000..0ad6b18c1
--- /dev/null
+++ b/fs/minix/itree_common.c
@@ -0,0 +1,417 @@
+/* Generic part */
+
+typedef struct {
+ block_t *p;
+ block_t key;
+ struct buffer_head *bh;
+} Indirect;
+
+static inline void add_chain(Indirect *p, struct buffer_head *bh, block_t *v)
+{
+ p->key = *(p->p = v);
+ p->bh = bh;
+}
+
+static inline int verify_chain(Indirect *from, Indirect *to)
+{
+ while (from <= to && from->key == *from->p)
+ from++;
+ return (from > to);
+}
+
+static inline block_t *block_end(struct buffer_head *bh)
+{
+ return (block_t *)((char*)bh->b_data + BLOCK_SIZE);
+}
+
+static inline Indirect *get_branch(struct inode *inode,
+ int depth,
+ int *offsets,
+ Indirect chain[DEPTH],
+ int *err)
+{
+ kdev_t dev = inode->i_dev;
+ Indirect *p = chain;
+ struct buffer_head *bh;
+
+ *err = 0;
+ /* i_data is not going away, no lock needed */
+ add_chain (chain, NULL, i_data(inode) + *offsets);
+ if (!p->key)
+ goto no_block;
+ while (--depth) {
+ bh = bread(dev, block_to_cpu(p->key), BLOCK_SIZE);
+ if (!bh)
+ goto failure;
+ /* Reader: pointers */
+ if (!verify_chain(chain, p))
+ goto changed;
+ add_chain(++p, bh, (block_t *)bh->b_data + *++offsets);
+ /* Reader: end */
+ if (!p->key)
+ goto no_block;
+ }
+ return NULL;
+
+changed:
+ *err = -EAGAIN;
+ goto no_block;
+failure:
+ *err = -EIO;
+no_block:
+ return p;
+}
+
+static int alloc_branch(struct inode *inode,
+ int num,
+ int *offsets,
+ Indirect *branch)
+{
+ int n = 0;
+ int i;
+ int parent = minix_new_block(inode);
+
+ branch[0].key = cpu_to_block(parent);
+ if (parent) for (n = 1; n < num; n++) {
+ struct buffer_head *bh;
+ /* Allocate the next block */
+ int nr = minix_new_block(inode);
+ if (!nr)
+ break;
+ branch[n].key = cpu_to_block(nr);
+ bh = getblk(inode->i_dev, parent, BLOCK_SIZE);
+ if (!buffer_uptodate(bh))
+ wait_on_buffer(bh);
+ memset(bh->b_data, 0, BLOCK_SIZE);
+ branch[n].bh = bh;
+ branch[n].p = (block_t*) bh->b_data + offsets[n];
+ *branch[n].p = branch[n].key;
+ mark_buffer_uptodate(bh, 1);
+ mark_buffer_dirty(bh);
+ parent = nr;
+ }
+ if (n == num)
+ return 0;
+
+ /* Allocation failed, free what we already allocated */
+ for (i = 1; i < n; i++)
+ bforget(branch[i].bh);
+ for (i = 0; i < n; i++)
+ minix_free_block(inode, block_to_cpu(branch[i].key));
+ return -ENOSPC;
+}
+
+static inline int splice_branch(struct inode *inode,
+ Indirect chain[DEPTH],
+ Indirect *where,
+ int num)
+{
+ int i;
+
+ /* Verify that place we are splicing to is still there and vacant */
+
+ /* Writer: pointers */
+ if (!verify_chain(chain, where-1) || *where->p)
+ /* Writer: end */
+ goto changed;
+
+ /* That's it */
+
+ *where->p = where->key;
+
+ /* Writer: end */
+
+ /* We are done with atomic stuff, now do the rest of housekeeping */
+
+ inode->i_ctime = CURRENT_TIME;
+
+ /* had we spliced it onto indirect block? */
+ if (where->bh)
+ mark_buffer_dirty(where->bh);
+
+ mark_inode_dirty(inode);
+ return 0;
+
+changed:
+ for (i = 1; i < num; i++)
+ bforget(where[i].bh);
+ for (i = 0; i < num; i++)
+ minix_free_block(inode, block_to_cpu(where[i].key));
+ return -EAGAIN;
+}
+
+static inline int get_block(struct inode * inode, long block,
+ struct buffer_head *bh_result, int create)
+{
+ int err = -EIO;
+ int offsets[DEPTH];
+ Indirect chain[DEPTH];
+ Indirect *partial;
+ int left;
+ int depth = block_to_path(inode, block, offsets);
+
+ if (depth == 0)
+ goto out;
+
+ lock_kernel();
+reread:
+ partial = get_branch(inode, depth, offsets, chain, &err);
+
+ /* Simplest case - block found, no allocation needed */
+ if (!partial) {
+got_it:
+ bh_result->b_dev = inode->i_dev;
+ bh_result->b_blocknr = block_to_cpu(chain[depth-1].key);
+ bh_result->b_state |= (1UL << BH_Mapped);
+ /* Clean up and exit */
+ partial = chain+depth-1; /* the whole chain */
+ goto cleanup;
+ }
+
+ /* Next simple case - plain lookup or failed read of indirect block */
+ if (!create || err == -EIO) {
+cleanup:
+ while (partial > chain) {
+ brelse(partial->bh);
+ partial--;
+ }
+ unlock_kernel();
+out:
+ return err;
+ }
+
+ /*
+ * Indirect block might be removed by truncate while we were
+ * reading it. Handling of that case (forget what we've got and
+ * reread) is taken out of the main path.
+ */
+ if (err == -EAGAIN)
+ goto changed;
+
+ left = (chain + depth) - partial;
+ err = alloc_branch(inode, left, offsets+(partial-chain), partial);
+ if (err)
+ goto cleanup;
+
+ if (splice_branch(inode, chain, partial, left) < 0)
+ goto changed;
+
+ bh_result->b_state |= (1UL << BH_New);
+ goto got_it;
+
+changed:
+ while (partial > chain) {
+ bforget(partial->bh);
+ partial--;
+ }
+ goto reread;
+}
+
+static inline int all_zeroes(block_t *p, block_t *q)
+{
+ while (p < q)
+ if (*p++)
+ return 0;
+ return 1;
+}
+
+static Indirect *find_shared(struct inode *inode,
+ int depth,
+ int offsets[DEPTH],
+ Indirect chain[DEPTH],
+ block_t *top)
+{
+ Indirect *partial, *p;
+ int k, err;
+
+ *top = 0;
+ for (k = depth; k > 1 && !offsets[k-1]; k--)
+ ;
+ partial = get_branch(inode, k, offsets, chain, &err);
+ /* Writer: pointers */
+ if (!partial)
+ partial = chain + k-1;
+ if (!partial->key && *partial->p)
+ /* Writer: end */
+ goto no_top;
+ for (p=partial;p>chain && all_zeroes((block_t*)p->bh->b_data,p->p);p--)
+ ;
+ if (p == chain + k - 1 && p > chain) {
+ p->p--;
+ } else {
+ *top = *p->p;
+ *p->p = 0;
+ }
+ /* Writer: end */
+
+ while(partial > p)
+ {
+ brelse(partial->bh);
+ partial--;
+ }
+no_top:
+ return partial;
+}
+
+static inline void free_data(struct inode *inode, block_t *p, block_t *q)
+{
+ unsigned long nr;
+
+ for ( ; p < q ; p++) {
+ nr = block_to_cpu(*p);
+ if (nr) {
+ *p = 0;
+ minix_free_block(inode, nr);
+ }
+ }
+}
+
+static void free_branches(struct inode *inode, block_t *p, block_t *q, int depth)
+{
+ struct buffer_head * bh;
+ unsigned long nr;
+
+ if (depth--) {
+ for ( ; p < q ; p++) {
+ nr = block_to_cpu(*p);
+ if (!nr)
+ continue;
+ *p = 0;
+ bh = bread (inode->i_dev, nr, BLOCK_SIZE);
+ if (!bh)
+ continue;
+ free_branches(inode, (block_t*)bh->b_data,
+ block_end(bh), depth);
+ bforget(bh);
+ minix_free_block(inode, nr);
+ mark_inode_dirty(inode);
+ }
+ } else
+ free_data(inode, p, q);
+}
+
+static inline void truncate (struct inode * inode)
+{
+ block_t *idata = i_data(inode);
+ int offsets[DEPTH];
+ Indirect chain[DEPTH];
+ Indirect *partial;
+ block_t nr = 0;
+ int n;
+ int first_whole;
+ long iblock;
+
+ iblock = (inode->i_size + BLOCK_SIZE-1) >> 10;
+ block_truncate_page(inode->i_mapping, inode->i_size, get_block);
+
+ n = block_to_path(inode, iblock, offsets);
+ if (!n)
+ return;
+
+ if (n == 1) {
+ free_data(inode, idata+offsets[0], idata + DIRECT);
+ first_whole = 0;
+ goto do_indirects;
+ }
+
+ first_whole = offsets[0] + 1 - DIRECT;
+ partial = find_shared(inode, n, offsets, chain, &nr);
+ if (nr) {
+ if (partial == chain)
+ mark_inode_dirty(inode);
+ else
+ mark_buffer_dirty(partial->bh);
+ free_branches(inode, &nr, &nr+1, (chain+n-1) - partial);
+ }
+ /* Clear the ends of indirect blocks on the shared branch */
+ while (partial > chain) {
+ free_branches(inode, partial->p + 1, block_end(partial->bh),
+ (chain+n-1) - partial);
+ mark_buffer_dirty(partial->bh);
+ brelse (partial->bh);
+ partial--;
+ }
+do_indirects:
+ /* Kill the remaining (whole) subtrees */
+ while (first_whole < DEPTH-1) {
+ nr = idata[DIRECT+first_whole];
+ if (nr) {
+ idata[DIRECT+first_whole] = 0;
+ mark_inode_dirty(inode);
+ free_branches(inode, &nr, &nr+1, first_whole+1);
+ }
+ first_whole++;
+ }
+ inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ mark_inode_dirty(inode);
+}
+
+static int sync_block (struct inode * inode, block_t block, int wait)
+{
+ struct buffer_head * bh;
+
+ if (!block)
+ return 0;
+ bh = get_hash_table(inode->i_dev, block_to_cpu(block), BLOCK_SIZE);
+ if (!bh)
+ return 0;
+ if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
+ brelse(bh);
+ return -1;
+ }
+ if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh))
+ {
+ brelse(bh);
+ return 0;
+ }
+ ll_rw_block(WRITE, 1, &bh);
+ atomic_dec(&bh->b_count);
+ return 0;
+}
+
+static int sync_indirect(struct inode *inode, block_t iblock, int depth,
+ int wait)
+{
+ struct buffer_head * ind_bh = NULL;
+ int rc, err = 0;
+
+ if (!iblock)
+ return 0;
+
+ rc = sync_block (inode, iblock, wait);
+ if (rc)
+ return rc;
+
+ ind_bh = bread(inode->i_dev, block_to_cpu(iblock), BLOCK_SIZE);
+ if (!ind_bh)
+ return -1;
+
+ if (--depth) {
+ block_t *p = (block_t*)ind_bh->b_data;
+ block_t *end = block_end(ind_bh);
+ while (p < end) {
+ rc = sync_indirect (inode, *p++, depth, wait);
+ if (rc > 0)
+ break;
+ if (rc)
+ err = rc;
+ }
+ }
+ brelse(ind_bh);
+ return err;
+}
+
+static inline int sync_file(struct inode * inode)
+{
+ int wait, err = 0, i;
+ block_t *idata = i_data(inode);
+
+ lock_kernel();
+ err = generic_buffer_fdatasync(inode, 0, ~0UL);
+ for (wait=0; wait<=1; wait++)
+ for (i=1; i<DEPTH; i++)
+ err |= sync_indirect(inode, idata[DIRECT+i-1], i, wait);
+ err |= minix_sync_inode (inode);
+ unlock_kernel();
+ return (err < 0) ? -EIO : 0;
+}
diff --git a/fs/minix/itree_v1.c b/fs/minix/itree_v1.c
new file mode 100644
index 000000000..47aee63e1
--- /dev/null
+++ b/fs/minix/itree_v1.c
@@ -0,0 +1,63 @@
+#include <linux/sched.h>
+#include <linux/locks.h>
+#include <linux/minix_fs.h>
+#include <linux/smp_lock.h>
+
+enum {DEPTH = 3, DIRECT = 7}; /* Only double indirect */
+
+typedef u16 block_t; /* 16 bit, host order */
+
+static inline unsigned long block_to_cpu(block_t n)
+{
+ return n;
+}
+
+static inline block_t cpu_to_block(unsigned long n)
+{
+ return n;
+}
+
+static inline block_t *i_data(struct inode *inode)
+{
+ return (block_t *)inode->u.minix_i.u.i1_data;
+}
+
+static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
+{
+ int n = 0;
+
+ if (block < 0) {
+ printk("minix_bmap: block<0");
+ } else if (block >= (inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)) {
+ printk("minix_bmap: block>big");
+ } else if (block < 7) {
+ offsets[n++] = block;
+ } else if ((block -= 7) < 512) {
+ offsets[n++] = 7;
+ offsets[n++] = block;
+ } else {
+ block -= 512;
+ offsets[n++] = 8;
+ offsets[n++] = block>>9;
+ offsets[n++] = block & 511;
+ }
+ return n;
+}
+
+#include "itree_common.c"
+
+int V1_minix_get_block(struct inode * inode, long block,
+ struct buffer_head *bh_result, int create)
+{
+ return get_block(inode, block, bh_result, create);
+}
+
+void V1_minix_truncate(struct inode * inode)
+{
+ truncate(inode);
+}
+
+int V1_minix_sync_file(struct inode * inode)
+{
+ return sync_file(inode);
+}
diff --git a/fs/minix/itree_v2.c b/fs/minix/itree_v2.c
new file mode 100644
index 000000000..333d5f785
--- /dev/null
+++ b/fs/minix/itree_v2.c
@@ -0,0 +1,68 @@
+#include <linux/sched.h>
+#include <linux/locks.h>
+#include <linux/minix_fs.h>
+#include <linux/smp_lock.h>
+
+enum {DIRECT = 7, DEPTH = 4}; /* Have triple indirect */
+
+typedef u32 block_t; /* 32 bit, host order */
+
+static inline unsigned long block_to_cpu(block_t n)
+{
+ return n;
+}
+
+static inline block_t cpu_to_block(unsigned long n)
+{
+ return n;
+}
+
+static inline block_t *i_data(struct inode *inode)
+{
+ return (block_t *)inode->u.minix_i.u.i2_data;
+}
+
+static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
+{
+ int n = 0;
+
+ if (block < 0) {
+ printk("minix_bmap: block<0");
+ } else if (block >= (inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)) {
+ printk("minix_bmap: block>big");
+ } else if (block < 7) {
+ offsets[n++] = block;
+ } else if ((block -= 7) < 256) {
+ offsets[n++] = 7;
+ offsets[n++] = block;
+ } else if ((block -= 256) < 256*256) {
+ offsets[n++] = 8;
+ offsets[n++] = block>>8;
+ offsets[n++] = block & 255;
+ } else {
+ block -= 256*256;
+ offsets[n++] = 9;
+ offsets[n++] = block>>16;
+ offsets[n++] = (block>>8) & 255;
+ offsets[n++] = block & 255;
+ }
+ return n;
+}
+
+#include "itree_common.c"
+
+int V2_minix_get_block(struct inode * inode, long block,
+ struct buffer_head *bh_result, int create)
+{
+ return get_block(inode, block, bh_result, create);
+}
+
+void V2_minix_truncate(struct inode * inode)
+{
+ truncate(inode);
+}
+
+int V2_minix_sync_file(struct inode * inode)
+{
+ return sync_file(inode);
+}
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index 0de210186..870656cb7 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -187,7 +187,7 @@ static int minix_add_entry(struct inode * dir,
for (i = 0; i < info->s_namelen ; i++)
de->name[i] = (i < namelen) ? name[i] : 0;
dir->i_version = ++event;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
*res_dir = de;
break;
}
@@ -228,7 +228,7 @@ static int minix_create(struct inode * dir, struct dentry *dentry, int mode)
return error;
}
de->inode = inode->i_ino;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
brelse(bh);
d_instantiate(dentry, inode);
return 0;
@@ -257,7 +257,7 @@ static int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int
return error;
}
de->inode = inode->i_ino;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
brelse(bh);
d_instantiate(dentry, inode);
return 0;
@@ -296,7 +296,7 @@ static int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
de->inode = dir->i_ino;
strcpy(de->name,"..");
inode->i_nlink = 2;
- mark_buffer_dirty(dir_block, 1);
+ mark_buffer_dirty(dir_block);
brelse(dir_block);
inode->i_mode = S_IFDIR | mode;
if (dir->i_mode & S_ISGID)
@@ -310,7 +310,7 @@ static int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
return error;
}
de->inode = inode->i_ino;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
dir->i_nlink++;
mark_inode_dirty(dir);
brelse(bh);
@@ -389,7 +389,6 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry)
if (!bh)
goto end_rmdir;
inode = dentry->d_inode;
- DQUOT_INIT(inode);
if (!empty_dir(inode)) {
retval = -ENOTEMPTY;
@@ -403,7 +402,7 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry)
printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
de->inode = 0;
dir->i_version = ++event;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
inode->i_nlink=0;
mark_inode_dirty(inode);
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
@@ -424,7 +423,6 @@ static int minix_unlink(struct inode * dir, struct dentry *dentry)
retval = -ENOENT;
inode = dentry->d_inode;
- DQUOT_INIT(inode);
bh = minix_find_entry(dir, dentry->d_name.name,
dentry->d_name.len, &de);
if (!bh || de->inode != inode->i_ino)
@@ -437,7 +435,7 @@ static int minix_unlink(struct inode * dir, struct dentry *dentry)
}
de->inode = 0;
dir->i_version = ++event;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
mark_inode_dirty(dir);
inode->i_nlink--;
@@ -482,7 +480,7 @@ static int minix_symlink(struct inode * dir, struct dentry *dentry,
goto fail;
de->inode = inode->i_ino;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
brelse(bh);
d_instantiate(dentry, inode);
out:
@@ -515,7 +513,7 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir,
return error;
}
de->inode = inode->i_ino;
- mark_buffer_dirty(bh, 1);
+ mark_buffer_dirty(bh);
brelse(bh);
inode->i_nlink++;
inode->i_ctime = CURRENT_TIME;
@@ -557,8 +555,6 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
if (!new_inode) {
brelse(new_bh);
new_bh = NULL;
- } else {
- DQUOT_INIT(new_inode);
}
}
if (S_ISDIR(old_inode->i_mode)) {
@@ -600,11 +596,11 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
new_inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(new_inode);
}
- mark_buffer_dirty(old_bh, 1);
- mark_buffer_dirty(new_bh, 1);
+ mark_buffer_dirty(old_bh);
+ mark_buffer_dirty(new_bh);
if (dir_bh) {
PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
- mark_buffer_dirty(dir_bh, 1);
+ mark_buffer_dirty(dir_bh);
old_dir->i_nlink--;
mark_inode_dirty(old_dir);
if (new_inode) {
diff --git a/fs/minix/truncate.c b/fs/minix/truncate.c
deleted file mode 100644
index 70b01dc20..000000000
--- a/fs/minix/truncate.c
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * linux/fs/truncate.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * Copyright (C) 1996 Gertjan van Wingerde (gertjan@cs.vu.nl)
- * Minix V2 fs support.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/minix_fs.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-#define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
-#define INDIRECT_BLOCK(offset) (DIRECT_BLOCK-offset)
-#define V1_DINDIRECT_BLOCK(offset) ((DIRECT_BLOCK-offset)>>9)
-#define V2_DINDIRECT_BLOCK(offset) ((DIRECT_BLOCK-offset)>>8)
-#define TINDIRECT_BLOCK(offset) ((DIRECT_BLOCK-(offset))>>8)
-
-/*
- * Truncate has the most races in the whole filesystem: coding it is
- * a pain in the a**, especially as I don't do any locking.
- *
- * The code may look a bit weird, but that's just because I've tried to
- * handle things like file-size changes in a somewhat graceful manner.
- * Anyway, truncating a file at the same time somebody else writes to it
- * is likely to result in pretty weird behaviour...
- *
- * The new code handles normal truncates (size = 0) as well as the more
- * general case (size = XXX). I hope.
- */
-
-#define DATA_BUFFER_USED(bh) \
- (atomic_read(&bh->b_count) > 1 || buffer_locked(bh))
-
-/*
- * The functions for minix V1 fs truncation.
- */
-static int V1_trunc_direct(struct inode * inode)
-{
- unsigned short * p;
- struct buffer_head * bh;
- int i, tmp;
- int retry = 0;
-
-repeat:
- for (i = DIRECT_BLOCK ; i < 7 ; i++) {
- p = i + inode->u.minix_i.u.i1_data;
- if (!(tmp = *p))
- continue;
- bh = get_hash_table(inode->i_dev,tmp,BLOCK_SIZE);
- if (i < DIRECT_BLOCK) {
- brelse(bh);
- goto repeat;
- }
- if ((bh && DATA_BUFFER_USED(bh)) || tmp != *p) {
- retry = 1;
- brelse(bh);
- continue;
- }
- *p = 0;
- mark_inode_dirty(inode);
- bforget(bh);
- minix_free_block(inode,tmp);
- }
- return retry;
-}
-
-static int V1_trunc_indirect(struct inode * inode, int offset, unsigned short * p)
-{
- struct buffer_head * bh;
- int i, tmp;
- struct buffer_head * ind_bh;
- unsigned short * ind;
- int retry = 0;
-
- tmp = *p;
- if (!tmp)
- return 0;
- ind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp != *p) {
- brelse(ind_bh);
- return 1;
- }
- if (!ind_bh) {
- *p = 0;
- return 0;
- }
-repeat:
- for (i = INDIRECT_BLOCK(offset) ; i < 512 ; i++) {
- if (i < 0)
- i = 0;
- if (i < INDIRECT_BLOCK(offset))
- goto repeat;
- ind = i+(unsigned short *) ind_bh->b_data;
- tmp = *ind;
- if (!tmp)
- continue;
- bh = get_hash_table(inode->i_dev,tmp,BLOCK_SIZE);
- if (i < INDIRECT_BLOCK(offset)) {
- brelse(bh);
- goto repeat;
- }
- if ((bh && DATA_BUFFER_USED(bh)) || tmp != *ind) {
- retry = 1;
- brelse(bh);
- continue;
- }
- *ind = 0;
- mark_buffer_dirty(ind_bh, 1);
- bforget(bh);
- minix_free_block(inode,tmp);
- }
- ind = (unsigned short *) ind_bh->b_data;
- for (i = 0; i < 512; i++)
- if (*(ind++))
- break;
- if (i >= 512) {
- if (atomic_read(&ind_bh->b_count) != 1)
- retry = 1;
- else {
- tmp = *p;
- *p = 0;
- minix_free_block(inode,tmp);
- }
- }
- brelse(ind_bh);
- return retry;
-}
-
-static int V1_trunc_dindirect(struct inode * inode, int offset, unsigned short *p)
-{
- int i, tmp;
- struct buffer_head * dind_bh;
- unsigned short * dind;
- int retry = 0;
-
- if (!(tmp = *p))
- return 0;
- dind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp != *p) {
- brelse(dind_bh);
- return 1;
- }
- if (!dind_bh) {
- *p = 0;
- return 0;
- }
-repeat:
- for (i = V1_DINDIRECT_BLOCK(offset) ; i < 512 ; i ++) {
- if (i < 0)
- i = 0;
- if (i < V1_DINDIRECT_BLOCK(offset))
- goto repeat;
- dind = i+(unsigned short *) dind_bh->b_data;
- retry |= V1_trunc_indirect(inode,offset+(i<<9),dind);
- mark_buffer_dirty(dind_bh, 1);
- }
- dind = (unsigned short *) dind_bh->b_data;
- for (i = 0; i < 512; i++)
- if (*(dind++))
- break;
- if (i >= 512) {
- if (atomic_read(&dind_bh->b_count) != 1)
- retry = 1;
- else {
- tmp = *p;
- *p = 0;
- mark_inode_dirty(inode);
- minix_free_block(inode,tmp);
- }
- }
- brelse(dind_bh);
- return retry;
-}
-
-static void V1_minix_truncate(struct inode * inode)
-{
- int retry;
-
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
- while (1) {
- retry = V1_trunc_direct(inode);
- retry |= V1_trunc_indirect(inode, 7, inode->u.minix_i.u.i1_data + 7);
- retry |= V1_trunc_dindirect(inode, 7+512, inode->u.minix_i.u.i1_data + 8);
- if (!retry)
- break;
- current->counter = 0;
- schedule();
- }
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- mark_inode_dirty(inode);
-}
-
-/*
- * The functions for minix V2 fs truncation.
- */
-static int V2_trunc_direct(struct inode * inode)
-{
- unsigned long * p;
- struct buffer_head * bh;
- int i, tmp;
- int retry = 0;
-
-repeat:
- for (i = DIRECT_BLOCK ; i < 7 ; i++) {
- p = (unsigned long *) inode->u.minix_i.u.i2_data + i;
- if (!(tmp = *p))
- continue;
- bh = get_hash_table(inode->i_dev,tmp,BLOCK_SIZE);
- if (i < DIRECT_BLOCK) {
- brelse(bh);
- goto repeat;
- }
- if ((bh && DATA_BUFFER_USED(bh)) || tmp != *p) {
- retry = 1;
- brelse(bh);
- continue;
- }
- *p = 0;
- mark_inode_dirty(inode);
- bforget(bh);
- minix_free_block(inode,tmp);
- }
- return retry;
-}
-
-static int V2_trunc_indirect(struct inode * inode, int offset, unsigned long * p)
-{
- struct buffer_head * bh;
- int i, tmp;
- struct buffer_head * ind_bh;
- unsigned long * ind;
- int retry = 0;
-
- tmp = *p;
- if (!tmp)
- return 0;
- ind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp != *p) {
- brelse(ind_bh);
- return 1;
- }
- if (!ind_bh) {
- *p = 0;
- return 0;
- }
-repeat:
- for (i = INDIRECT_BLOCK(offset) ; i < 256 ; i++) {
- if (i < 0)
- i = 0;
- if (i < INDIRECT_BLOCK(offset))
- goto repeat;
- ind = i+(unsigned long *) ind_bh->b_data;
- tmp = *ind;
- if (!tmp)
- continue;
- bh = get_hash_table(inode->i_dev,tmp,BLOCK_SIZE);
- if (i < INDIRECT_BLOCK(offset)) {
- brelse(bh);
- goto repeat;
- }
- if ((bh && DATA_BUFFER_USED(bh)) || tmp != *ind) {
- retry = 1;
- brelse(bh);
- continue;
- }
- *ind = 0;
- mark_buffer_dirty(ind_bh, 1);
- bforget(bh);
- minix_free_block(inode,tmp);
- }
- ind = (unsigned long *) ind_bh->b_data;
- for (i = 0; i < 256; i++)
- if (*(ind++))
- break;
- if (i >= 256) {
- if (atomic_read(&ind_bh->b_count) != 1)
- retry = 1;
- else {
- tmp = *p;
- *p = 0;
- minix_free_block(inode,tmp);
- }
- }
- brelse(ind_bh);
- return retry;
-}
-
-static int V2_trunc_dindirect(struct inode * inode, int offset, unsigned long *p)
-{
- int i, tmp;
- struct buffer_head * dind_bh;
- unsigned long * dind;
- int retry = 0;
-
- if (!(tmp = *p))
- return 0;
- dind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp != *p) {
- brelse(dind_bh);
- return 1;
- }
- if (!dind_bh) {
- *p = 0;
- return 0;
- }
-repeat:
- for (i = V2_DINDIRECT_BLOCK(offset) ; i < 256 ; i ++) {
- if (i < 0)
- i = 0;
- if (i < V2_DINDIRECT_BLOCK(offset))
- goto repeat;
- dind = i+(unsigned long *) dind_bh->b_data;
- retry |= V2_trunc_indirect(inode,offset+(i<<8),dind);
- mark_buffer_dirty(dind_bh, 1);
- }
- dind = (unsigned long *) dind_bh->b_data;
- for (i = 0; i < 256; i++)
- if (*(dind++))
- break;
- if (i >= 256) {
- if (atomic_read(&dind_bh->b_count) != 1)
- retry = 1;
- else {
- tmp = *p;
- *p = 0;
- mark_inode_dirty(inode);
- minix_free_block(inode,tmp);
- }
- }
- brelse(dind_bh);
- return retry;
-}
-
-static int V2_trunc_tindirect(struct inode * inode, int offset, unsigned long * p)
-{
- int i, tmp;
- struct buffer_head * tind_bh;
- unsigned long * tind;
- int retry = 0;
-
- if (!(tmp = *p))
- return 0;
- tind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp != *p) {
- brelse(tind_bh);
- return 1;
- }
- if (!tind_bh) {
- *p = 0;
- return 0;
- }
-repeat:
- for (i = TINDIRECT_BLOCK(offset) ; i < 256 ; i ++) {
- if (i < 0)
- i = 0;
- if (i < TINDIRECT_BLOCK(offset))
- goto repeat;
- tind = i+(unsigned long *) tind_bh->b_data;
- retry |= V2_trunc_dindirect(inode,offset+(i<<8),tind);
- mark_buffer_dirty(tind_bh, 1);
- }
- tind = (unsigned long *) tind_bh->b_data;
- for (i = 0; i < 256; i++)
- if (*(tind++))
- break;
- if (i >= 256) {
- if (atomic_read(&tind_bh->b_count) != 1)
- retry = 1;
- else {
- tmp = *p;
- *p = 0;
- mark_inode_dirty(inode);
- minix_free_block(inode,tmp);
- }
- }
- brelse(tind_bh);
- return retry;
-}
-
-static void V2_minix_truncate(struct inode * inode)
-{
- int retry;
-
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
- while (1) {
- retry = V2_trunc_direct(inode);
- retry |= V2_trunc_indirect(inode,7,
- (unsigned long *) inode->u.minix_i.u.i2_data + 7);
- retry |= V2_trunc_dindirect(inode, 7+256,
- (unsigned long *) inode->u.minix_i.u.i2_data + 8);
- retry |= V2_trunc_tindirect(inode, 7+256+256*256,
- (unsigned long *) inode->u.minix_i.u.i2_data + 9);
- if (!retry)
- break;
- run_task_queue(&tq_disk);
- current->policy |= SCHED_YIELD;
- schedule();
- }
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- mark_inode_dirty(inode);
-}
-
-/*
- * The function that is called for file truncation.
- */
-void minix_truncate(struct inode * inode)
-{
- if (INODE_VERSION(inode) == MINIX_V1)
- V1_minix_truncate(inode);
- else
- V2_minix_truncate(inode);
-}