lkml.org 
[lkml]   [1999]   [Jun]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[fixpatch] 2.3.9-pre7, DANGER

2.3.9-pre7 can rather badly damage filesystems, because block_dev.c does
buffer-cache access without the kernel lock held.

i suspect that this patch will clash with David's cool buffer-cache
patches - but i've just trashed one of my filesystems so i suppose people
want to apply it ... Maybe we want to add the -DANGEROUS flag again? :)

-- mingo
--- linux/fs/block_dev.c.orig Tue Jun 29 11:29:41 1999
+++ linux/fs/block_dev.c Tue Jun 29 12:04:17 1999
@@ -7,6 +7,7 @@
#include <linux/mm.h>
#include <linux/locks.h>
#include <linux/fcntl.h>
+#include <linux/smp_lock.h>

#include <asm/uaccess.h>

@@ -30,11 +31,14 @@
kdev_t dev;
struct buffer_head * bh, *bufferlist[NBUF];
register char * p;
+ int err;

+ lock_kernel();
write_error = buffercount = 0;
dev = inode->i_rdev;
+ err = -EPERM;
if ( is_read_only( inode->i_rdev ))
- return -EPERM;
+ goto out;
blocksize = BLOCK_SIZE;
if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
@@ -54,8 +58,10 @@
else
size = INT_MAX;
while (count>0) {
- if (block >= size)
- return written ? written : -ENOSPC;
+ if (block >= size) {
+ err = written ? written : -ENOSPC;
+ goto out;
+ }
chars = blocksize - offset;
if (chars > count)
chars=count;
@@ -87,7 +93,8 @@
bhlist[i] = getblk (dev, block+i, blocksize);
if(!bhlist[i]){
while(i >= 0) brelse(bhlist[i--]);
- return written ? written : -EIO;
+ err = written ? written : -EIO;
+ goto out;
};
};
ll_rw_block(READ, blocks, bhlist);
@@ -98,8 +105,10 @@
};
#endif
block++;
- if (!bh)
- return written ? written : -EIO;
+ if (!bh) {
+ err = written ? written : -EIO;
+ goto out;
+ }
p = offset + bh->b_data;
offset = 0;
*ppos += chars;
@@ -138,9 +147,12 @@
}
}
filp->f_reada = 1;
+ err = written;
if(write_error)
- return -EIO;
- return written;
+ err = -EIO;
+out:
+ unlock_kernel();
+ return err;
}

ssize_t block_read(struct file * filp, char * buf, size_t count, loff_t *ppos)
@@ -151,7 +163,7 @@
ssize_t blocksize;
ssize_t blocksize_bits, i;
size_t blocks, rblocks, left;
- int bhrequest, uptodate;
+ int bhrequest, uptodate, err;
struct buffer_head ** bhb, ** bhe;
struct buffer_head * buflist[NBUF];
struct buffer_head * bhreq[NBUF];
@@ -160,6 +172,7 @@
kdev_t dev;
ssize_t read;

+ lock_kernel();
dev = inode->i_rdev;
blocksize = BLOCK_SIZE;
if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
@@ -186,8 +199,10 @@
left = size - offset;
if (left > count)
left = count;
- if (left <= 0)
- return 0;
+ if (left <= 0) {
+ err = 0;
+ goto out;
+ }
read = 0;
block = offset >> blocksize_bits;
offset &= blocksize-1;
@@ -203,8 +218,10 @@
}
if (block + blocks > size) {
blocks = size - block;
- if (blocks == 0)
- return 0;
+ if (blocks == 0) {
+ err = 0;
+ goto out;
+ }
}

/* We do this in a two stage process. We first try to request
@@ -284,10 +301,15 @@
if (++bhe == &buflist[NBUF])
bhe = buflist;
};
- if (!read)
- return -EIO;
- filp->f_reada = 1;
- return read;
+ if (!read) {
+ err = -EIO;
+ } else {
+ err = read;
+ filp->f_reada = 1;
+ }
+out:
+ unlock_kernel();
+ return err;
}

/*
\
 
 \ /
  Last update: 2005-03-22 13:52    [W:0.315 / U:0.052 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site