summaryrefslogtreecommitdiffstats
path: root/fs/minix
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-07-05 23:09:37 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-07-05 23:09:37 +0000
commitaba344fdfed81b2c03d6114c54cfd73a486aa10b (patch)
treed032d8430bf1234c3ecc6f6330d6de6e887e5963 /fs/minix
parent40c138bfc6d37dbff5339f84575db1e3cec6e34e (diff)
Merge with Linux 2.3.9.
Diffstat (limited to 'fs/minix')
-rw-r--r--fs/minix/dir.c7
-rw-r--r--fs/minix/file.c53
-rw-r--r--fs/minix/fsync.c4
-rw-r--r--fs/minix/inode.c567
-rw-r--r--fs/minix/symlink.c7
-rw-r--r--fs/minix/truncate.c12
6 files changed, 391 insertions, 259 deletions
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index 187925903..a44d5d69d 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -52,11 +52,14 @@ struct inode_operations minix_dir_inode_operations = {
minix_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* bmap */
+ NULL, /* flushpage */
NULL, /* truncate */
- NULL /* permission */
+ NULL, /* permission */
+ NULL, /* smap */
+ NULL /* revalidate */
};
static int minix_readdir(struct file * filp,
diff --git a/fs/minix/file.c b/fs/minix/file.c
index d6b7ecb17..14d478bde 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -27,50 +27,14 @@
#include <linux/fs.h>
#include <linux/minix_fs.h>
-static int minix_writepage(struct file *file, struct page *page)
-{
- struct dentry *dentry = file->f_dentry;
- struct inode *inode = dentry->d_inode;
- unsigned long block;
- int *p, nr[PAGE_SIZE/BLOCK_SIZE];
- int i, err, created;
- struct buffer_head *bh;
-
- i = PAGE_SIZE / BLOCK_SIZE;
- block = page->offset / BLOCK_SIZE;
- p = nr;
- bh = page->buffers;
- do {
- if (bh && bh->b_blocknr)
- *p = bh->b_blocknr;
- else
- *p = minix_getblk_block(inode, block, 1, &err, &created);
- if (!*p)
- return -EIO;
- i--;
- block++;
- p++;
- if (bh)
- bh = bh->b_this_page;
- } while(i > 0);
-
- /* IO start */
- brw_page(WRITE, page, inode->i_dev, nr, BLOCK_SIZE, 1);
- return 0;
-}
-
-static long minix_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char *buf)
-{
- return block_write_one_page(file, page, offset, bytes, buf, minix_getblk_block);
-}
-
/*
* Write to a file (through the page cache).
*/
static ssize_t
minix_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
- return generic_file_write(file, buf, count, ppos, minix_write_one_page);
+ return generic_file_write(file, buf, count,
+ ppos, block_write_partial_page);
}
/*
@@ -88,7 +52,10 @@ static struct file_operations minix_file_operations = {
NULL, /* no special open is needed */
NULL, /* flush */
NULL, /* release */
- minix_sync_file /* fsync */
+ minix_sync_file, /* fsync */
+ NULL, /* fasync */
+ NULL, /* check_media_change */
+ NULL /* revalidate */
};
struct inode_operations minix_file_inode_operations = {
@@ -104,12 +71,12 @@ struct inode_operations minix_file_inode_operations = {
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- generic_readpage, /* readpage */
- minix_writepage, /* writepage */
- minix_bmap, /* bmap */
+ minix_get_block, /* get_block */
+ block_read_full_page, /* readpage */
+ block_write_full_page, /* writepage */
+ block_flushpage, /* flushpage */
minix_truncate, /* truncate */
NULL, /* permission */
NULL, /* smap */
NULL, /* revalidate */
- block_flushpage, /* flushpage */
};
diff --git a/fs/minix/fsync.c b/fs/minix/fsync.c
index ef3d15db9..2fcdddf15 100644
--- a/fs/minix/fsync.c
+++ b/fs/minix/fsync.c
@@ -53,7 +53,7 @@ static int V1_sync_block (struct inode * inode, unsigned short * block, int wait
return 0;
}
ll_rw_block(WRITE, 1, &bh);
- bh->b_count--;
+ atomic_dec(&bh->b_count);
return 0;
}
@@ -190,7 +190,7 @@ static int V2_sync_block (struct inode * inode, unsigned long * block, int wait)
return 0;
}
ll_rw_block(WRITE, 1, &bh);
- bh->b_count--;
+ atomic_dec(&bh->b_count);
return 0;
}
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 088de42dc..e5352090d 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -19,6 +19,7 @@
#include <linux/stat.h>
#include <linux/locks.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -361,112 +362,127 @@ static int V1_block_bmap(struct buffer_head * bh, int nr)
return tmp;
}
-static int V1_minix_bmap(struct inode * inode,int block)
+static int V1_minix_block_map(struct inode * inode, long block)
{
- int i;
+ int i, ret;
- if (block<0) {
+ ret = 0;
+ lock_kernel();
+ if (block < 0) {
printk("minix_bmap: block<0");
- return 0;
+ goto out;
}
if (block >= (inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)) {
printk("minix_bmap: block>big");
- return 0;
+ goto out;
+ }
+ if (block < 7) {
+ ret = V1_inode_bmap(inode,block);
+ goto out;
}
- if (block < 7)
- return V1_inode_bmap(inode,block);
block -= 7;
if (block < 512) {
i = V1_inode_bmap(inode,7);
if (!i)
- return 0;
- return V1_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block);
+ 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)
- return 0;
+ goto out;
i = V1_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>9);
if (!i)
- return 0;
- return V1_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 511);
+ 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 long *)(inode)->u.minix_i.u.i2_data)[(nr)])
+#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 long *) bh->b_data)[nr];
+ tmp = ((unsigned int *) bh->b_data)[nr];
brelse(bh);
return tmp;
}
-static int V2_minix_bmap(struct inode * inode, int block)
+static int V2_minix_block_map(struct inode * inode, int block)
{
- int i;
+ int i, ret;
- if (block<0) {
+ ret = 0;
+ lock_kernel();
+ if (block < 0) {
printk("minix_bmap: block<0");
- return 0;
+ goto out;
}
if (block >= (inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)) {
printk("minix_bmap: block>big");
- return 0;
+ goto out;
+ }
+ if (block < 7) {
+ ret = V2_inode_bmap(inode,block);
+ goto out;
}
- if (block < 7)
- return V2_inode_bmap(inode,block);
block -= 7;
if (block < 256) {
- i = V2_inode_bmap(inode,7);
+ i = V2_inode_bmap(inode, 7);
if (!i)
- return 0;
- return V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block);
+ 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 (block < (256 * 256)) {
+ i = V2_inode_bmap(inode, 8);
if (!i)
- return 0;
- i = V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block >> 8);
+ goto out;
+ i = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
+ block >> 8);
if (!i)
- return 0;
- return V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
+ 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);
+ block -= (256 * 256);
+ i = V2_inode_bmap(inode, 9);
if (!i)
- return 0;
- i = V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block >> 16);
+ goto out;
+ i = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
+ block >> 16);
if (!i)
- return 0;
- i = V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),(block >> 8) & 255);
+ goto out;
+ i = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
+ (block >> 8) & 255);
if (!i)
- return 0;
- return V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
-}
-
-/*
- * The global minix fs bmap function.
- */
-int minix_bmap(struct inode * inode, int block)
-{
- if (INODE_VERSION(inode) == MINIX_V1)
- return V1_minix_bmap(inode, block);
- else
- return V2_minix_bmap(inode, block);
+ 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 create,
- int metadata, int *phys_block, int *created)
+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;
@@ -483,15 +499,30 @@ repeat:
brelse(result);
goto repeat;
} else {
- *phys_block = tmp;
+ *phys = tmp;
return NULL;
}
}
- if (!create)
- return NULL;
+ *err = -EFBIG;
+
+ /* Check file limits.. */
+ {
+ unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+ if (limit < RLIM_INFINITY) {
+ limit >>= BLOCK_SIZE_BITS;
+ if (new_block >= limit) {
+ send_sig(SIGXFSZ, current, 0);
+ *err = -EFBIG;
+ return NULL;
+ }
+ }
+ }
+
tmp = minix_new_block(inode->i_sb);
- if (!tmp)
+ if (!tmp) {
+ *err = -ENOSPC;
return NULL;
+ }
if (metadata) {
result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
if (*p) {
@@ -504,12 +535,18 @@ repeat:
mark_buffer_dirty(result, 1);
} else {
if (*p) {
+ /*
+ * Nobody is allowed to change block allocation
+ * state from under us:
+ */
+ BUG();
minix_free_block(inode->i_sb, tmp);
goto repeat;
}
- *phys_block = tmp;
+ *phys = tmp;
result = NULL;
- *created = 1;
+ *err = 0;
+ *new = 1;
}
*p = tmp;
@@ -519,22 +556,22 @@ repeat:
}
static struct buffer_head * V1_block_getblk(struct inode * inode,
- struct buffer_head * bh, int nr, int create,
- int metadata, int *phys_block, int *created)
+ 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;
+ unsigned long limit;
+ result = NULL;
if (!bh)
- return NULL;
+ goto out;
if (!buffer_uptodate(bh)) {
ll_rw_block(READ, 1, &bh);
wait_on_buffer(bh);
- if (!buffer_uptodate(bh)) {
- brelse(bh);
- return NULL;
- }
+ if (!buffer_uptodate(bh))
+ goto out;
}
p = nr + (unsigned short *) bh->b_data;
repeat:
@@ -542,27 +579,29 @@ repeat:
if (tmp) {
if (metadata) {
result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
- if (tmp == *p) {
- brelse(bh);
- return result;
- }
+ if (tmp == *p)
+ goto out;
brelse(result);
goto repeat;
} else {
- *phys_block = tmp;
- brelse(bh);
- return NULL;
+ *phys = tmp;
+ goto out;
}
}
- if (!create) {
- brelse(bh);
- return NULL;
+ *err = -EFBIG;
+
+ limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+ if (limit < RLIM_INFINITY) {
+ limit >>= BLOCK_SIZE_BITS;
+ if (new_block >= limit) {
+ send_sig(SIGXFSZ, current, 0);
+ goto out;
+ }
}
+
tmp = minix_new_block(inode->i_sb);
- if (!tmp) {
- brelse(bh);
- return NULL;
- }
+ if (!tmp)
+ goto out;
if (metadata) {
result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
if (*p) {
@@ -574,69 +613,118 @@ repeat:
mark_buffer_uptodate(result, 1);
mark_buffer_dirty(result, 1);
} else {
- if (*p) {
- minix_free_block(inode->i_sb, tmp);
- goto repeat;
- }
- *phys_block = tmp;
- result = NULL;
- *created = 1;
+ *phys = tmp;
+ *new = 1;
+ }
+ if (*p) {
+ minix_free_block(inode->i_sb, tmp);
+ brelse(result);
+ goto repeat;
}
*p = tmp;
mark_buffer_dirty(bh, 1);
+ *err = 0;
+out:
brelse(bh);
return result;
}
-int V1_getblk_block(struct inode * inode, long block, int create, int *err, int *created)
+static int V1_get_block(struct inode * inode, long block,
+ struct buffer_head *bh_result, int create)
{
- struct buffer_head *bh, *tmp;
- int phys_block;
+ int ret, err, new, phys, ptr;
+ struct buffer_head *bh;
- *err = -EIO;
- if (block < 0) {
- printk("minix_getblk: block<0");
- return 0;
- }
- if (block >= inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE) {
- printk("minix_getblk: block>big");
+ 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;
}
- *created = 0;
- if (block < 7) {
- tmp = V1_inode_getblk(inode, block, create,
- 0, &phys_block, created);
+
+ 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;
}
- block -= 7;
- if (block < 512) {
- bh = V1_inode_getblk(inode, 7, create, 1, NULL, NULL);
- tmp = V1_block_getblk(inode, bh, block, create,
- 0, &phys_block, created);
- goto out;
+ ptr -= 7;
+ if (ptr < 512) {
+ bh = GET_INODE_PTR(7);
+ goto get_indirect;
}
- block -= 512;
- bh = V1_inode_getblk(inode, 8, create, 1, NULL, NULL);
- bh = V1_block_getblk(inode, bh, (block>>9) & 511, create, 1, NULL, NULL);
- tmp = V1_block_getblk(inode, bh, block & 511, create, 0, &phys_block, created);
+ 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:
- *err = 0;
- return phys_block;
+ 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 create,
- int metadata, int *phys_block, int *created)
+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 long *p;
+ unsigned int *p;
struct buffer_head * result;
- p = (unsigned long *) inode->u.minix_i.u.i2_data + nr;
+ p = (unsigned int *) inode->u.minix_i.u.i2_data + nr;
repeat:
tmp = *p;
if (tmp) {
@@ -647,15 +735,30 @@ repeat:
brelse(result);
goto repeat;
} else {
- *phys_block = tmp;
+ *phys = tmp;
return NULL;
}
}
- if (!create)
- return NULL;
+ *err = -EFBIG;
+
+ /* Check file limits.. */
+ {
+ unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+ if (limit < RLIM_INFINITY) {
+ limit >>= BLOCK_SIZE_BITS;
+ if (new_block >= limit) {
+ send_sig(SIGXFSZ, current, 0);
+ *err = -EFBIG;
+ return NULL;
+ }
+ }
+ }
+
tmp = minix_new_block(inode->i_sb);
- if (!tmp)
+ if (!tmp) {
+ *err = -ENOSPC;
return NULL;
+ }
if (metadata) {
result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
if (*p) {
@@ -668,12 +771,18 @@ repeat:
mark_buffer_dirty(result, 1);
} else {
if (*p) {
+ /*
+ * Nobody is allowed to change block allocation
+ * state from under us:
+ */
+ BUG();
minix_free_block(inode->i_sb, tmp);
goto repeat;
}
- *phys_block = tmp;
+ *phys = tmp;
result = NULL;
- *created = 1;
+ *err = 0;
+ *new = 1;
}
*p = tmp;
@@ -683,50 +792,52 @@ repeat:
}
static struct buffer_head * V2_block_getblk(struct inode * inode,
- struct buffer_head * bh, int nr, int create,
- int metadata, int *phys_block, int *created)
+ struct buffer_head * bh, int nr, int new_block, int *err,
+ int metadata, int *phys, int *new)
{
int tmp;
- unsigned long *p;
+ unsigned int *p;
struct buffer_head * result;
+ unsigned long limit;
+ result = NULL;
if (!bh)
- return NULL;
+ goto out;
if (!buffer_uptodate(bh)) {
ll_rw_block(READ, 1, &bh);
wait_on_buffer(bh);
- if (!buffer_uptodate(bh)) {
- brelse(bh);
- return NULL;
- }
+ if (!buffer_uptodate(bh))
+ goto out;
}
- p = nr + (unsigned long *) bh->b_data;
+ 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) {
- brelse(bh);
- return result;
- }
+ if (tmp == *p)
+ goto out;
brelse(result);
goto repeat;
} else {
- *phys_block = tmp;
- brelse(bh);
- return NULL;
+ *phys = tmp;
+ goto out;
}
}
- if (!create) {
- brelse(bh);
- return NULL;
+ *err = -EFBIG;
+
+ limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+ if (limit < RLIM_INFINITY) {
+ limit >>= BLOCK_SIZE_BITS;
+ if (new_block >= limit) {
+ send_sig(SIGXFSZ, current, 0);
+ goto out;
+ }
}
+
tmp = minix_new_block(inode->i_sb);
- if (!tmp) {
- brelse(bh);
- return NULL;
- }
+ if (!tmp)
+ goto out;
if (metadata) {
result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
if (*p) {
@@ -738,103 +849,151 @@ repeat:
mark_buffer_uptodate(result, 1);
mark_buffer_dirty(result, 1);
} else {
- if (*p) {
- minix_free_block(inode->i_sb, tmp);
- goto repeat;
- }
- *phys_block = tmp;
- result = NULL;
- *created = 1;
+ *phys = tmp;
+ *new = 1;
+ }
+ if (*p) {
+ minix_free_block(inode->i_sb, tmp);
+ brelse(result);
+ goto repeat;
}
*p = tmp;
mark_buffer_dirty(bh, 1);
+ *err = 0;
+out:
brelse(bh);
return result;
}
-int V2_getblk_block(struct inode * inode, int block, int create, int *err, int *created)
+static int V2_get_block(struct inode * inode, long block,
+ struct buffer_head *bh_result, int create)
{
- struct buffer_head * bh, *tmp;
- int phys_block;
+ int ret, err, new, phys, ptr;
+ struct buffer_head * bh;
- *err = -EIO;
- if (block < 0) {
- printk("minix_getblk: block<0");
- return 0;
- }
- if (block >= inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE) {
- printk("minix_getblk: block>big");
+ 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;
}
- *created = 0;
- if (block < 7) {
- tmp = V2_inode_getblk(inode, block, create,
- 0, &phys_block, created);
+
+ 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;
}
- block -= 7;
- if (block < 256) {
- bh = V2_inode_getblk(inode, 7, create, 1, NULL, NULL);
- tmp = V2_block_getblk(inode, bh, block, create,
- 0, &phys_block, created);
- goto out;
+ ptr -= 7;
+ if (ptr < 256) {
+ bh = GET_INODE_PTR(7);
+ goto get_indirect;
}
- block -= 256;
- if (block < 256*256) {
- bh = V2_inode_getblk(inode, 8, create, 1, NULL, NULL);
- bh = V2_block_getblk(inode, bh, (block>>8) & 255, create,
- 1, NULL, NULL);
- tmp = V2_block_getblk(inode, bh, block & 255, create,
- 0, &phys_block, created);
- goto out;
+ ptr -= 256;
+ if (ptr < 256*256) {
+ bh = GET_INODE_PTR(8);
+ goto get_double;
}
- block -= 256*256;
- bh = V2_inode_getblk(inode, 9, create, 1, NULL, NULL);
- bh = V2_block_getblk(inode, bh, (block >> 16) & 255, create, 1, NULL, NULL);
- bh = V2_block_getblk(inode, bh, (block >> 8) & 255, create, 1, NULL, NULL);
- tmp = V2_block_getblk(inode, bh, block & 255, create, 0, &phys_block, created);
+ 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:
- *err = 0;
- return phys_block;
+ 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;
}
-int minix_getblk_block (struct inode *inode, long block,
- int create, int *err, int *created)
+int minix_get_block(struct inode *inode, long block,
+ struct buffer_head *bh_result, int create)
{
if (INODE_VERSION(inode) == MINIX_V1)
- return V1_getblk_block(inode, block, create, err, created);
+ return V1_get_block(inode, block, bh_result, create);
else
- return V2_getblk_block(inode, block, create, err, created);
+ return V2_get_block(inode, block, bh_result, create);
}
/*
* the global minix fs getblk function.
*/
-struct buffer_head *minix_getblk (struct inode *inode, int block, int create)
+struct buffer_head *minix_getblk(struct inode *inode, int block, int create)
{
- struct buffer_head *tmp = NULL;
- int phys_block;
- int err, created;
-
- phys_block = minix_getblk_block(inode, block, create, &err, &created);
- if (phys_block) {
- tmp = getblk(inode->i_dev, phys_block, BLOCK_SIZE);
- if (created) {
- memset(tmp->b_data, 0, BLOCK_SIZE);
- mark_buffer_uptodate(tmp, 1);
- mark_buffer_dirty(tmp, 1);
+ struct buffer_head dummy;
+ int error;
+
+ dummy.b_state = 0;
+ dummy.b_blocknr = -1000;
+ error = minix_get_block(inode, block, &dummy, create);
+ if (!error && buffer_mapped(&dummy)) {
+ struct buffer_head *bh;
+ bh = getblk(dummy.b_dev, dummy.b_blocknr, BLOCK_SIZE);
+ if (buffer_new(&dummy)) {
+ memset(bh->b_data, 0, BLOCK_SIZE);
+ mark_buffer_uptodate(bh, 1);
+ mark_buffer_dirty(bh, 1);
}
+ return bh;
}
- return tmp;
+ return NULL;
}
struct buffer_head * minix_bread(struct inode * inode, int block, int create)
{
struct buffer_head * bh;
- bh = minix_getblk(inode,block,create);
+ bh = minix_getblk(inode, block, create);
if (!bh || buffer_uptodate(bh))
return bh;
ll_rw_block(READ, 1, &bh);
diff --git a/fs/minix/symlink.c b/fs/minix/symlink.c
index 4f3661105..3a8951b09 100644
--- a/fs/minix/symlink.c
+++ b/fs/minix/symlink.c
@@ -33,11 +33,14 @@ struct inode_operations minix_symlink_inode_operations = {
NULL, /* rename */
minix_readlink, /* readlink */
minix_follow_link, /* follow_link */
+ NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* bmap */
+ NULL, /* flushpage */
NULL, /* truncate */
- NULL /* permission */
+ NULL, /* permission */
+ NULL, /* smap */
+ NULL /* revalidate */
};
static struct dentry * minix_follow_link(struct dentry * dentry,
diff --git a/fs/minix/truncate.c b/fs/minix/truncate.c
index 4718e092e..6724d0064 100644
--- a/fs/minix/truncate.c
+++ b/fs/minix/truncate.c
@@ -33,7 +33,7 @@
*/
#define DATA_BUFFER_USED(bh) \
- ((bh->b_count > 1) || buffer_locked(bh))
+ (atomic_read(&bh->b_count) || buffer_locked(bh))
/*
* The functions for minix V1 fs truncation.
@@ -121,7 +121,7 @@ repeat:
if (*(ind++))
break;
if (i >= 512) {
- if (ind_bh->b_count != 1)
+ if (atomic_read(&ind_bh->b_count) != 1)
retry = 1;
else {
tmp = *p;
@@ -166,7 +166,7 @@ repeat:
if (*(dind++))
break;
if (i >= 512) {
- if (dind_bh->b_count != 1)
+ if (atomic_read(&dind_bh->b_count) != 1)
retry = 1;
else {
tmp = *p;
@@ -285,7 +285,7 @@ repeat:
if (*(ind++))
break;
if (i >= 256) {
- if (ind_bh->b_count != 1)
+ if (atomic_read(&ind_bh->b_count) != 1)
retry = 1;
else {
tmp = *p;
@@ -330,7 +330,7 @@ repeat:
if (*(dind++))
break;
if (i >= 256) {
- if (dind_bh->b_count != 1)
+ if (atomic_read(&dind_bh->b_count) != 1)
retry = 1;
else {
tmp = *p;
@@ -376,7 +376,7 @@ repeat:
if (*(tind++))
break;
if (i >= 256) {
- if (tind_bh->b_count != 1)
+ if (atomic_read(&tind_bh->b_count) != 1)
retry = 1;
else {
tmp = *p;