summaryrefslogtreecommitdiffstats
path: root/fs/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/buffer.c')
-rw-r--r--fs/buffer.c89
1 files changed, 63 insertions, 26 deletions
diff --git a/fs/buffer.c b/fs/buffer.c
index bd06972f3..3e1b5cc35 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -289,16 +289,35 @@ int file_fsync (struct inode *inode, struct file *filp)
asmlinkage int sys_fsync(unsigned int fd)
{
struct file * file;
+ struct dentry * dentry;
struct inode * inode;
- int err = 0;
+ int err;
lock_kernel();
- if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
- err = -EBADF;
- else if (!file->f_op || !file->f_op->fsync)
- err = -EINVAL;
- else if (file->f_op->fsync(inode,file))
- err = -EIO;
+ err = -EBADF;
+
+ if (fd >= NR_OPEN)
+ goto out;
+
+ file = current->files->fd[fd];
+ if (!file)
+ goto out;
+
+ dentry = file->f_dentry;
+ if (!dentry)
+ goto out;
+
+ inode = dentry->d_inode;
+ if (!inode)
+ goto out;
+
+ err = -EINVAL;
+ if (!file->f_op || !file->f_op->fsync)
+ goto out;
+
+ err = file->f_op->fsync(inode,file);
+
+out:
unlock_kernel();
return err;
}
@@ -306,20 +325,35 @@ asmlinkage int sys_fsync(unsigned int fd)
asmlinkage int sys_fdatasync(unsigned int fd)
{
struct file * file;
+ struct dentry * dentry;
struct inode * inode;
- int err = -EBADF;
+ int err;
lock_kernel();
- if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
+ err = -EBADF;
+
+ if (fd >= NR_OPEN)
+ goto out;
+
+ file = current->files->fd[fd];
+ if (!file)
+ goto out;
+
+ dentry = file->f_dentry;
+ if (!dentry)
goto out;
+
+ inode = dentry->d_inode;
+ if (!inode)
+ goto out;
+
err = -EINVAL;
if (!file->f_op || !file->f_op->fsync)
goto out;
+
/* this needs further work, at the moment it is identical to fsync() */
- if (file->f_op->fsync(inode,file))
- err = -EIO;
- else
- err = 0;
+ err = file->f_op->fsync(inode,file);
+
out:
unlock_kernel();
return err;
@@ -495,17 +529,18 @@ static inline void insert_into_queues(struct buffer_head * bh)
static inline struct buffer_head * find_buffer(kdev_t dev, int block, int size)
{
- struct buffer_head * tmp;
-
- for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
- if (tmp->b_blocknr == block && tmp->b_dev == dev) {
- if (tmp->b_size == size)
- return tmp;
+ struct buffer_head * next;
- printk("VFS: Wrong blocksize on device %s\n",
- kdevname(dev));
- return NULL;
- }
+ next = hash(dev,block);
+ for (;;) {
+ struct buffer_head *tmp = next;
+ if (!next)
+ break;
+ next = tmp->b_next;
+ if (tmp->b_blocknr != block || tmp->b_size != size || tmp->b_dev != dev)
+ continue;
+ return tmp;
+ }
return NULL;
}
@@ -518,10 +553,11 @@ static inline struct buffer_head * find_buffer(kdev_t dev, int block, int size)
*/
struct buffer_head * get_hash_table(kdev_t dev, int block, int size)
{
- struct buffer_head * bh;
-
for (;;) {
- if (!(bh=find_buffer(dev,block,size)))
+ struct buffer_head * bh;
+
+ bh=find_buffer(dev,block,size);
+ if (!bh)
return NULL;
bh->b_count++;
wait_on_buffer(bh);
@@ -1610,6 +1646,7 @@ asmlinkage int sync_old_buffers(void)
next->b_count--;
}
}
+ run_task_queue(&tq_disk);
#ifdef DEBUG
if (ncount) printk("sync_old_buffers: %d dirty buffers not on dirty list\n", ncount);
printk("Wrote %d/%d buffers\n", nwritten, ndirty);