diff options
Diffstat (limited to 'fs/buffer.c')
-rw-r--r-- | fs/buffer.c | 89 |
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); |