diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-10-05 01:18:40 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-10-05 01:18:40 +0000 |
commit | 012bb3e61e5eced6c610f9e036372bf0c8def2d1 (patch) | |
tree | 87efc733f9b164e8c85c0336f92c8fb7eff6d183 /fs/minix | |
parent | 625a1589d3d6464b5d90b8a0918789e3afffd220 (diff) |
Merge with Linux 2.4.0-test9. Please check DECstation, I had a number
of rejects to fixup while integrating Linus patches. I also found
that this kernel will only boot SMP on Origin; the UP kernel freeze
soon after bootup with SCSI timeout messages. I commit this anyway
since I found that the last CVS versions had the same problem.
Diffstat (limited to 'fs/minix')
-rw-r--r-- | fs/minix/Makefile | 2 | ||||
-rw-r--r-- | fs/minix/bitmap.c | 29 | ||||
-rw-r--r-- | fs/minix/file.c | 14 | ||||
-rw-r--r-- | fs/minix/fsync.c | 344 | ||||
-rw-r--r-- | fs/minix/inode.c | 591 | ||||
-rw-r--r-- | fs/minix/itree_common.c | 417 | ||||
-rw-r--r-- | fs/minix/itree_v1.c | 63 | ||||
-rw-r--r-- | fs/minix/itree_v2.c | 68 | ||||
-rw-r--r-- | fs/minix/namei.c | 28 | ||||
-rw-r--r-- | fs/minix/truncate.c | 420 |
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); -} |