* fall back to doing a synchronous write.
*/
static int
-nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync)
+nfs_file_fsync_commit(struct file *file, int datasync)
{
struct nfs_open_context *ctx = nfs_file_open_context(file);
struct inode *inode = file_inode(file);
- int have_error, do_resend, status;
+ int do_resend, status;
int ret = 0;
dprintk("NFS: fsync file(%pD2) datasync %d\n", file, datasync);
nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
do_resend = test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags);
- have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
status = nfs_commit_inode(inode, FLUSH_SYNC);
- have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
- if (have_error) {
+ if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) {
ret = xchg(&ctx->error, 0);
if (ret)
goto out;
trace_nfs_fsync_enter(inode);
do {
+ struct nfs_open_context *ctx = nfs_file_open_context(file);
ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+ if (test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) {
+ int ret2 = xchg(&ctx->error, 0);
+ if (ret2)
+ ret = ret2;
+ }
if (ret != 0)
break;
- ret = nfs_file_fsync_commit(file, start, end, datasync);
+ ret = nfs_file_fsync_commit(file, datasync);
if (!ret)
ret = pnfs_sync_inode(inode, !!datasync);
/*
__get_str(name)
)
);
+
+TRACE_EVENT(nfs_initiate_read,
+ TP_PROTO(
+ const struct inode *inode,
+ loff_t offset, unsigned long count
+ ),
+
+ TP_ARGS(inode, offset, count),
+
+ TP_STRUCT__entry(
+ __field(loff_t, offset)
+ __field(unsigned long, count)
+ __field(dev_t, dev)
+ __field(u32, fhandle)
+ __field(u64, fileid)
+ ),
+
+ TP_fast_assign(
+ const struct nfs_inode *nfsi = NFS_I(inode);
+
+ __entry->offset = offset;
+ __entry->count = count;
+ __entry->dev = inode->i_sb->s_dev;
+ __entry->fileid = nfsi->fileid;
+ __entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
+ ),
+
+ TP_printk(
+ "fileid=%02x:%02x:%llu fhandle=0x%08x "
+ "offset=%lld count=%lu",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ (unsigned long long)__entry->fileid,
+ __entry->fhandle,
+ __entry->offset, __entry->count
+ )
+);
+
+TRACE_EVENT(nfs_readpage_done,
+ TP_PROTO(
+ const struct inode *inode,
+ int status, loff_t offset, bool eof
+ ),
+
+ TP_ARGS(inode, status, offset, eof),
+
+ TP_STRUCT__entry(
+ __field(int, status)
+ __field(loff_t, offset)
+ __field(bool, eof)
+ __field(dev_t, dev)
+ __field(u32, fhandle)
+ __field(u64, fileid)
+ ),
+
+ TP_fast_assign(
+ const struct nfs_inode *nfsi = NFS_I(inode);
+
+ __entry->status = status;
+ __entry->offset = offset;
+ __entry->eof = eof;
+ __entry->dev = inode->i_sb->s_dev;
+ __entry->fileid = nfsi->fileid;
+ __entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
+ ),
+
+ TP_printk(
+ "fileid=%02x:%02x:%llu fhandle=0x%08x "
+ "offset=%lld status=%d%s",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ (unsigned long long)__entry->fileid,
+ __entry->fhandle,
+ __entry->offset, __entry->status,
+ __entry->eof ? " eof" : ""
+ )
+);
+
+/*
+ * XXX: I tried using NFS_UNSTABLE and friends in this table, but they
+ * all evaluate to 0 for some reason, even if I include linux/nfs.h.
+ */
+#define nfs_show_stable(stable) \
+ __print_symbolic(stable, \
+ { 0, " (UNSTABLE)" }, \
+ { 1, " (DATA_SYNC)" }, \
+ { 2, " (FILE_SYNC)" })
+
+TRACE_EVENT(nfs_initiate_write,
+ TP_PROTO(
+ const struct inode *inode,
+ loff_t offset, unsigned long count,
+ enum nfs3_stable_how stable
+ ),
+
+ TP_ARGS(inode, offset, count, stable),
+
+ TP_STRUCT__entry(
+ __field(loff_t, offset)
+ __field(unsigned long, count)
+ __field(enum nfs3_stable_how, stable)
+ __field(dev_t, dev)
+ __field(u32, fhandle)
+ __field(u64, fileid)
+ ),
+
+ TP_fast_assign(
+ const struct nfs_inode *nfsi = NFS_I(inode);
+
+ __entry->offset = offset;
+ __entry->count = count;
+ __entry->stable = stable;
+ __entry->dev = inode->i_sb->s_dev;
+ __entry->fileid = nfsi->fileid;
+ __entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
+ ),
+
+ TP_printk(
+ "fileid=%02x:%02x:%llu fhandle=0x%08x "
+ "offset=%lld count=%lu stable=%d%s",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ (unsigned long long)__entry->fileid,
+ __entry->fhandle,
+ __entry->offset, __entry->count,
+ __entry->stable, nfs_show_stable(__entry->stable)
+ )
+);
+
+TRACE_EVENT(nfs_writeback_done,
+ TP_PROTO(
+ const struct inode *inode,
+ int status,
+ loff_t offset,
+ struct nfs_writeverf *writeverf
+ ),
+
+ TP_ARGS(inode, status, offset, writeverf),
+
+ TP_STRUCT__entry(
+ __field(int, status)
+ __field(loff_t, offset)
+ __field(enum nfs3_stable_how, stable)
+ __field(unsigned long long, verifier)
+ __field(dev_t, dev)
+ __field(u32, fhandle)
+ __field(u64, fileid)
+ ),
+
+ TP_fast_assign(
+ const struct nfs_inode *nfsi = NFS_I(inode);
+
+ __entry->status = status;
+ __entry->offset = offset;
+ __entry->stable = writeverf->committed;
+ memcpy(&__entry->verifier, &writeverf->verifier,
+ sizeof(__entry->verifier));
+ __entry->dev = inode->i_sb->s_dev;
+ __entry->fileid = nfsi->fileid;
+ __entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
+ ),
+
+ TP_printk(
+ "fileid=%02x:%02x:%llu fhandle=0x%08x "
+ "offset=%lld status=%d stable=%d%s "
+ "verifier 0x%016llx",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ (unsigned long long)__entry->fileid,
+ __entry->fhandle,
+ __entry->offset, __entry->status,
+ __entry->stable, nfs_show_stable(__entry->stable),
+ __entry->verifier
+ )
+);
+
+TRACE_EVENT(nfs_initiate_commit,
+ TP_PROTO(
+ const struct nfs_commit_data *data
+ ),
+
+ TP_ARGS(data),
+
+ TP_STRUCT__entry(
+ __field(loff_t, offset)
+ __field(unsigned long, count)
+ __field(dev_t, dev)
+ __field(u32, fhandle)
+ __field(u64, fileid)
+ ),
+
+ TP_fast_assign(
+ const struct inode *inode = data->inode;
+ const struct nfs_inode *nfsi = NFS_I(inode);
+
+ __entry->offset = data->args.offset;
+ __entry->count = data->args.count;
+ __entry->dev = inode->i_sb->s_dev;
+ __entry->fileid = nfsi->fileid;
+ __entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
+ ),
+
+ TP_printk(
+ "fileid=%02x:%02x:%llu fhandle=0x%08x "
+ "offset=%lld count=%lu",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ (unsigned long long)__entry->fileid,
+ __entry->fhandle,
+ __entry->offset, __entry->count
+ )
+);
+
+TRACE_EVENT(nfs_commit_done,
+ TP_PROTO(
+ const struct nfs_commit_data *data
+ ),
+
+ TP_ARGS(data),
+
+ TP_STRUCT__entry(
+ __field(int, status)
+ __field(loff_t, offset)
+ __field(unsigned long long, verifier)
+ __field(dev_t, dev)
+ __field(u32, fhandle)
+ __field(u64, fileid)
+ ),
+
+ TP_fast_assign(
+ const struct inode *inode = data->inode;
+ const struct nfs_inode *nfsi = NFS_I(inode);
+
+ __entry->status = data->res.op_status;
+ __entry->offset = data->args.offset;
+ memcpy(&__entry->verifier, &data->verf.verifier,
+ sizeof(__entry->verifier));
+ __entry->dev = inode->i_sb->s_dev;
+ __entry->fileid = nfsi->fileid;
+ __entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
+ ),
+
+ TP_printk(
+ "fileid=%02x:%02x:%llu fhandle=0x%08x "
+ "offset=%lld status=%d verifier 0x%016llx",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ (unsigned long long)__entry->fileid,
+ __entry->fhandle,
+ __entry->offset, __entry->status,
+ __entry->verifier
+ )
+);
+
#endif /* _TRACE_NFS_H */
#undef TRACE_INCLUDE_PATH
kref_put(&ioc->refcount, nfs_io_completion_release);
}
-static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
-{
- ctx->error = error;
- smp_wmb();
- set_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
-}
-
static struct nfs_page *
nfs_page_private_request(struct page *page)
{
task_setup_data->priority = priority;
rpc_ops->write_setup(hdr, msg);
+ trace_nfs_initiate_write(hdr->inode, hdr->io_start, hdr->good_bytes,
+ hdr->args.stable);
nfs4_state_protect_write(NFS_SERVER(hdr->inode)->nfs_client,
&task_setup_data->rpc_client, msg, hdr);
status = NFS_PROTO(inode)->write_done(task, hdr);
if (status != 0)
return status;
+
nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, hdr->res.count);
+ trace_nfs_writeback_done(inode, task->tk_status,
+ hdr->args.offset, hdr->res.verf);
if (hdr->res.verf->committed < hdr->args.stable &&
task->tk_status >= 0) {
};
/* Set up the initial task struct. */
nfs_ops->commit_setup(data, &msg);
+ trace_nfs_initiate_commit(data);
dprintk("NFS: initiated commit call\n");
/* Call the NFS version-specific code */
NFS_PROTO(data->inode)->commit_done(task, data);
+ trace_nfs_commit_done(data);
}
static void nfs_commit_release_pages(struct nfs_commit_data *data)