Commit 54df7662 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] bdev: use correct mapping's i_sem

From: viro@parcelfarce.linux.theplanet.co.uk <viro@parcelfarce.linux.theplanet.co.uk>

In a bunch of places we used file->f_dentry->d_inode->i_sem to protect
fdatasync et.al.  Replaced with corrent file->f_mapping->host->i_sem - the
object we are protecting is address_space, so we want an exclusion that would
work for redirected ->i_mapping.  For normal files (not coda, not bdev) it's
all the same, of course - there we have

 	file->f_mapping->host == file->f_dentry->d_inode

and change above is an equivalent transfromation.
parent 32d66678
......@@ -314,8 +314,7 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
asmlinkage long sys_fsync(unsigned int fd)
{
struct file * file;
struct dentry * dentry;
struct inode * inode;
struct address_space *mapping;
int ret, err;
ret = -EBADF;
......@@ -323,8 +322,7 @@ asmlinkage long sys_fsync(unsigned int fd)
if (!file)
goto out;
dentry = file->f_dentry;
inode = dentry->d_inode;
mapping = file->f_mapping;
ret = -EINVAL;
if (!file->f_op || !file->f_op->fsync) {
......@@ -333,17 +331,17 @@ asmlinkage long sys_fsync(unsigned int fd)
}
/* We need to protect against concurrent writers.. */
down(&inode->i_sem);
down(&mapping->host->i_sem);
current->flags |= PF_SYNCWRITE;
ret = filemap_fdatawrite(inode->i_mapping);
err = file->f_op->fsync(file, dentry, 0);
ret = filemap_fdatawrite(mapping);
err = file->f_op->fsync(file, file->f_dentry, 0);
if (!ret)
ret = err;
err = filemap_fdatawait(inode->i_mapping);
err = filemap_fdatawait(mapping);
if (!ret)
ret = err;
current->flags &= ~PF_SYNCWRITE;
up(&inode->i_sem);
up(&mapping->host->i_sem);
out_putf:
fput(file);
......@@ -354,8 +352,7 @@ asmlinkage long sys_fsync(unsigned int fd)
asmlinkage long sys_fdatasync(unsigned int fd)
{
struct file * file;
struct dentry * dentry;
struct inode * inode;
struct address_space *mapping;
int ret, err;
ret = -EBADF;
......@@ -363,24 +360,23 @@ asmlinkage long sys_fdatasync(unsigned int fd)
if (!file)
goto out;
dentry = file->f_dentry;
inode = dentry->d_inode;
ret = -EINVAL;
if (!file->f_op || !file->f_op->fsync)
goto out_putf;
down(&inode->i_sem);
mapping = file->f_mapping;
down(&mapping->host->i_sem);
current->flags |= PF_SYNCWRITE;
ret = filemap_fdatawrite(inode->i_mapping);
err = file->f_op->fsync(file, dentry, 1);
ret = filemap_fdatawrite(mapping);
err = file->f_op->fsync(file, file->f_dentry, 1);
if (!ret)
ret = err;
err = filemap_fdatawait(inode->i_mapping);
err = filemap_fdatawait(mapping);
if (!ret)
ret = err;
current->flags &= ~PF_SYNCWRITE;
up(&inode->i_sem);
up(&mapping->host->i_sem);
out_putf:
fput(file);
......
......@@ -266,7 +266,7 @@ nfs_file_write(struct kiocb *iocb, const char *buf, size_t count, loff_t pos)
int
nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
{
struct inode * inode = filp->f_dentry->d_inode;
struct inode * inode = filp->f_mapping->host;
int status = 0;
int status2;
......@@ -309,13 +309,13 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
* Flush all pending writes before doing anything
* with locks..
*/
status = filemap_fdatawrite(inode->i_mapping);
status = filemap_fdatawrite(filp->f_mapping);
down(&inode->i_sem);
status2 = nfs_wb_all(inode);
if (!status)
status = status2;
up(&inode->i_sem);
status2 = filemap_fdatawait(inode->i_mapping);
status2 = filemap_fdatawait(filp->f_mapping);
if (!status)
status = status2;
if (status < 0)
......@@ -335,11 +335,11 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
*/
out_ok:
if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
filemap_fdatawrite(inode->i_mapping);
filemap_fdatawrite(filp->f_mapping);
down(&inode->i_sem);
nfs_wb_all(inode); /* we may have slept */
up(&inode->i_sem);
filemap_fdatawait(inode->i_mapping);
filemap_fdatawait(filp->f_mapping);
nfs_zap_caches(inode);
}
return status;
......
......@@ -1970,7 +1970,7 @@ EXPORT_SYMBOL(generic_file_readv);
ssize_t generic_file_writev(struct file *file, const struct iovec *iov,
unsigned long nr_segs, loff_t * ppos)
{
struct inode *inode = file->f_dentry->d_inode;
struct inode *inode = file->f_mapping->host;
ssize_t ret;
down(&inode->i_sem);
......
......@@ -146,20 +146,20 @@ static int msync_interval(struct vm_area_struct * vma,
ret = filemap_sync(vma, start, end-start, flags);
if (!ret && (flags & MS_SYNC)) {
struct inode *inode = file->f_dentry->d_inode;
struct address_space *mapping = file->f_mapping;
int err;
down(&inode->i_sem);
ret = filemap_fdatawrite(inode->i_mapping);
down(&mapping->host->i_sem);
ret = filemap_fdatawrite(mapping);
if (file->f_op && file->f_op->fsync) {
err = file->f_op->fsync(file,file->f_dentry,1);
if (err && !ret)
ret = err;
}
err = filemap_fdatawait(inode->i_mapping);
err = filemap_fdatawait(mapping);
if (!ret)
ret = err;
up(&inode->i_sem);
up(&mapping->host->i_sem);
}
}
return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment