diff options
Diffstat (limited to 'fs/afs/write.c')
| -rw-r--r-- | fs/afs/write.c | 18 | 
1 files changed, 14 insertions, 4 deletions
| diff --git a/fs/afs/write.c b/fs/afs/write.c index b806285ff853..9aa52d93c73c 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -681,9 +681,10 @@ int afs_writeback_all(struct afs_vnode *vnode)   * - the return status from this call provides a reliable indication of   *   whether any write errors occurred for this process.   */ -int afs_fsync(struct file *file, int datasync) +int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync)  {  	struct dentry *dentry = file->f_path.dentry; +	struct inode *inode = file->f_mapping->host;  	struct afs_writeback *wb, *xwb;  	struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);  	int ret; @@ -692,12 +693,19 @@ int afs_fsync(struct file *file, int datasync)  	       vnode->fid.vid, vnode->fid.vnode, dentry->d_name.name,  	       datasync); +	ret = filemap_write_and_wait_range(inode->i_mapping, start, end); +	if (ret) +		return ret; +	mutex_lock(&inode->i_mutex); +  	/* use a writeback record as a marker in the queue - when this reaches  	 * the front of the queue, all the outstanding writes are either  	 * completed or rejected */  	wb = kzalloc(sizeof(*wb), GFP_KERNEL); -	if (!wb) -		return -ENOMEM; +	if (!wb) { +		ret = -ENOMEM; +		goto out; +	}  	wb->vnode = vnode;  	wb->first = 0;  	wb->last = -1; @@ -720,7 +728,7 @@ int afs_fsync(struct file *file, int datasync)  	if (ret < 0) {  		afs_put_writeback(wb);  		_leave(" = %d [wb]", ret); -		return ret; +		goto out;  	}  	/* wait for the preceding writes to actually complete */ @@ -729,6 +737,8 @@ int afs_fsync(struct file *file, int datasync)  				       vnode->writebacks.next == &wb->link);  	afs_put_writeback(wb);  	_leave(" = %d", ret); +out: +	mutex_unlock(&inode->i_mutex);  	return ret;  } |