Commit 6ed0529f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfs-for-4.14-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull more NFS client updates from Trond Myklebust:
 "Hightlights include:

  Bugfixes:
   - Various changes relating to reporting IO errors.
   - pnfs: Use the standard I/O stateid when calling LAYOUTGET

  Features:
   - Add static NFS I/O tracepoints for debugging"

* tag 'nfs-for-4.14-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  NFS: various changes relating to reporting IO errors.
  NFS: Add static NFS I/O tracepoints
  pNFS: Use the standard I/O stateid when calling LAYOUTGET
parents 9e0ce554 bf4b4905
...@@ -208,21 +208,19 @@ EXPORT_SYMBOL_GPL(nfs_file_mmap); ...@@ -208,21 +208,19 @@ EXPORT_SYMBOL_GPL(nfs_file_mmap);
* fall back to doing a synchronous write. * fall back to doing a synchronous write.
*/ */
static int 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 nfs_open_context *ctx = nfs_file_open_context(file);
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
int have_error, do_resend, status; int do_resend, status;
int ret = 0; int ret = 0;
dprintk("NFS: fsync file(%pD2) datasync %d\n", file, datasync); dprintk("NFS: fsync file(%pD2) datasync %d\n", file, datasync);
nfs_inc_stats(inode, NFSIOS_VFSFSYNC); nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
do_resend = test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags); 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); status = nfs_commit_inode(inode, FLUSH_SYNC);
have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) {
if (have_error) {
ret = xchg(&ctx->error, 0); ret = xchg(&ctx->error, 0);
if (ret) if (ret)
goto out; goto out;
...@@ -247,10 +245,16 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) ...@@ -247,10 +245,16 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
trace_nfs_fsync_enter(inode); trace_nfs_fsync_enter(inode);
do { do {
struct nfs_open_context *ctx = nfs_file_open_context(file);
ret = filemap_write_and_wait_range(inode->i_mapping, start, end); 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) if (ret != 0)
break; break;
ret = nfs_file_fsync_commit(file, start, end, datasync); ret = nfs_file_fsync_commit(file, datasync);
if (!ret) if (!ret)
ret = pnfs_sync_inode(inode, !!datasync); ret = pnfs_sync_inode(inode, !!datasync);
/* /*
......
...@@ -768,3 +768,10 @@ static inline bool nfs_error_is_fatal(int err) ...@@ -768,3 +768,10 @@ static inline bool nfs_error_is_fatal(int err)
return false; return false;
} }
} }
static inline 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);
}
...@@ -719,6 +719,254 @@ TRACE_EVENT(nfs_sillyrename_unlink, ...@@ -719,6 +719,254 @@ TRACE_EVENT(nfs_sillyrename_unlink,
__get_str(name) __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 */ #endif /* _TRACE_NFS_H */
#undef TRACE_INCLUDE_PATH #undef TRACE_INCLUDE_PATH
......
...@@ -1170,8 +1170,8 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, ...@@ -1170,8 +1170,8 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
/* remember fatal errors */ /* remember fatal errors */
if (nfs_error_is_fatal(desc->pg_error)) if (nfs_error_is_fatal(desc->pg_error))
mapping_set_error(desc->pg_inode->i_mapping, nfs_context_set_write_error(req->wb_context,
desc->pg_error); desc->pg_error);
func = desc->pg_completion_ops->error_cleanup; func = desc->pg_completion_ops->error_cleanup;
for (midx = 0; midx < desc->pg_mirror_count; midx++) { for (midx = 0; midx < desc->pg_mirror_count; midx++) {
......
...@@ -1664,7 +1664,7 @@ pnfs_update_layout(struct inode *ino, ...@@ -1664,7 +1664,7 @@ pnfs_update_layout(struct inode *ino,
.offset = pos, .offset = pos,
.length = count, .length = count,
}; };
unsigned pg_offset, seq; unsigned pg_offset;
struct nfs_server *server = NFS_SERVER(ino); struct nfs_server *server = NFS_SERVER(ino);
struct nfs_client *clp = server->nfs_client; struct nfs_client *clp = server->nfs_client;
struct pnfs_layout_hdr *lo = NULL; struct pnfs_layout_hdr *lo = NULL;
...@@ -1754,10 +1754,14 @@ pnfs_update_layout(struct inode *ino, ...@@ -1754,10 +1754,14 @@ pnfs_update_layout(struct inode *ino,
} }
first = true; first = true;
do { if (nfs4_select_rw_stateid(ctx->state,
seq = read_seqbegin(&ctx->state->seqlock); iomode == IOMODE_RW ? FMODE_WRITE : FMODE_READ,
nfs4_stateid_copy(&stateid, &ctx->state->stateid); NULL, &stateid, NULL) != 0) {
} while (read_seqretry(&ctx->state->seqlock, seq)); trace_pnfs_update_layout(ino, pos, count,
iomode, lo, lseg,
PNFS_UPDATE_LAYOUT_INVALID_OPEN);
goto out_unlock;
}
} else { } else {
nfs4_stateid_copy(&stateid, &lo->plh_stateid); nfs4_stateid_copy(&stateid, &lo->plh_stateid);
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "iostat.h" #include "iostat.h"
#include "fscache.h" #include "fscache.h"
#include "pnfs.h" #include "pnfs.h"
#include "nfstrace.h"
#define NFSDBG_FACILITY NFSDBG_PAGECACHE #define NFSDBG_FACILITY NFSDBG_PAGECACHE
...@@ -200,6 +201,7 @@ static void nfs_initiate_read(struct nfs_pgio_header *hdr, ...@@ -200,6 +201,7 @@ static void nfs_initiate_read(struct nfs_pgio_header *hdr,
task_setup_data->flags |= swap_flags; task_setup_data->flags |= swap_flags;
rpc_ops->read_setup(hdr, msg); rpc_ops->read_setup(hdr, msg);
trace_nfs_initiate_read(inode, hdr->io_start, hdr->good_bytes);
} }
static void static void
...@@ -232,6 +234,8 @@ static int nfs_readpage_done(struct rpc_task *task, ...@@ -232,6 +234,8 @@ static int nfs_readpage_done(struct rpc_task *task,
return status; return status;
nfs_add_stats(inode, NFSIOS_SERVERREADBYTES, hdr->res.count); nfs_add_stats(inode, NFSIOS_SERVERREADBYTES, hdr->res.count);
trace_nfs_readpage_done(inode, task->tk_status,
hdr->args.offset, hdr->res.eof);
if (task->tk_status == -ESTALE) { if (task->tk_status == -ESTALE) {
set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); set_bit(NFS_INO_STALE, &NFS_I(inode)->flags);
......
...@@ -145,13 +145,6 @@ static void nfs_io_completion_put(struct nfs_io_completion *ioc) ...@@ -145,13 +145,6 @@ static void nfs_io_completion_put(struct nfs_io_completion *ioc)
kref_put(&ioc->refcount, nfs_io_completion_release); 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 * static struct nfs_page *
nfs_page_private_request(struct page *page) nfs_page_private_request(struct page *page)
{ {
...@@ -1383,6 +1376,8 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr, ...@@ -1383,6 +1376,8 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr,
task_setup_data->priority = priority; task_setup_data->priority = priority;
rpc_ops->write_setup(hdr, msg); 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, nfs4_state_protect_write(NFS_SERVER(hdr->inode)->nfs_client,
&task_setup_data->rpc_client, msg, hdr); &task_setup_data->rpc_client, msg, hdr);
...@@ -1540,7 +1535,10 @@ static int nfs_writeback_done(struct rpc_task *task, ...@@ -1540,7 +1535,10 @@ static int nfs_writeback_done(struct rpc_task *task,
status = NFS_PROTO(inode)->write_done(task, hdr); status = NFS_PROTO(inode)->write_done(task, hdr);
if (status != 0) if (status != 0)
return status; return status;
nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, hdr->res.count); 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 && if (hdr->res.verf->committed < hdr->args.stable &&
task->tk_status >= 0) { task->tk_status >= 0) {
...@@ -1669,6 +1667,7 @@ int nfs_initiate_commit(struct rpc_clnt *clnt, struct nfs_commit_data *data, ...@@ -1669,6 +1667,7 @@ int nfs_initiate_commit(struct rpc_clnt *clnt, struct nfs_commit_data *data,
}; };
/* Set up the initial task struct. */ /* Set up the initial task struct. */
nfs_ops->commit_setup(data, &msg); nfs_ops->commit_setup(data, &msg);
trace_nfs_initiate_commit(data);
dprintk("NFS: initiated commit call\n"); dprintk("NFS: initiated commit call\n");
...@@ -1793,6 +1792,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) ...@@ -1793,6 +1792,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
/* Call the NFS version-specific code */ /* Call the NFS version-specific code */
NFS_PROTO(data->inode)->commit_done(task, data); NFS_PROTO(data->inode)->commit_done(task, data);
trace_nfs_commit_done(data);
} }
static void nfs_commit_release_pages(struct nfs_commit_data *data) static void nfs_commit_release_pages(struct nfs_commit_data *data)
......
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