Commit 9eb90f43 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFS: Serialise O_DIRECT i/o and truncate()



Ensure that all O_DIRECT reads and writes are complete, and prevent the
initiation of new i/o until the setattr operation that will truncate the
file is complete.

Fixes: a5864c99 ("NFS: Do not serialise O_DIRECT reads and writes")
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent b2036bb6
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -768,8 +768,10 @@ nfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
	trace_nfs_setattr_enter(inode);

	/* Write all dirty data */
	if (S_ISREG(inode->i_mode))
	if (S_ISREG(inode->i_mode)) {
		nfs_file_block_o_direct(NFS_I(inode));
		nfs_sync_inode(inode);
	}

	fattr = nfs_alloc_fattr_with_label(NFS_SERVER(inode));
	if (fattr == NULL) {
+10 −0
Original line number Diff line number Diff line
@@ -532,6 +532,16 @@ static inline bool nfs_file_io_is_buffered(struct nfs_inode *nfsi)
	return test_bit(NFS_INO_ODIRECT, &nfsi->flags) == 0;
}

/* Must be called with exclusively locked inode->i_rwsem */
static inline void nfs_file_block_o_direct(struct nfs_inode *nfsi)
{
	if (test_bit(NFS_INO_ODIRECT, &nfsi->flags)) {
		clear_bit(NFS_INO_ODIRECT, &nfsi->flags);
		inode_dio_wait(&nfsi->vfs_inode);
	}
}


/* namespace.c */
#define NFS_PATH_CANONICAL 1
extern char *nfs_path(char **p, struct dentry *dentry,
+2 −11
Original line number Diff line number Diff line
@@ -14,15 +14,6 @@

#include "internal.h"

/* Call with exclusively locked inode->i_rwsem */
static void nfs_block_o_direct(struct nfs_inode *nfsi, struct inode *inode)
{
	if (test_bit(NFS_INO_ODIRECT, &nfsi->flags)) {
		clear_bit(NFS_INO_ODIRECT, &nfsi->flags);
		inode_dio_wait(inode);
	}
}

/**
 * nfs_start_io_read - declare the file is being used for buffered reads
 * @inode: file inode
@@ -57,7 +48,7 @@ nfs_start_io_read(struct inode *inode)
	err = down_write_killable(&inode->i_rwsem);
	if (err)
		return err;
	nfs_block_o_direct(nfsi, inode);
	nfs_file_block_o_direct(nfsi);
	downgrade_write(&inode->i_rwsem);

	return 0;
@@ -90,7 +81,7 @@ nfs_start_io_write(struct inode *inode)

	err = down_write_killable(&inode->i_rwsem);
	if (!err)
		nfs_block_o_direct(NFS_I(inode), inode);
		nfs_file_block_o_direct(NFS_I(inode));
	return err;
}