forked from Minki/linux
NFS client bugfixes for Linux 4.14
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 -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJZuuXZAAoJEGcL54qWCgDy1MAQAIMJR7SZhc6i5PpGXDLx+lRp HiNldIlW/TXMcHKQ/35cIkt+KPy49EJiB54USZkdiKeiGqMUKtrGgxLVqLY6GELV gORRHxYY4SkNCWSDqwkpM+4XCQ56Tqrh6PxPmiOd+zsKAiqWzL5WFydbdVZcN3Dr e/lVHktefKZ3ks0DJ+qbYY2MCVqJ8HLlsQ7ZhvGzNNXHHhmWZHAL2LtXdAZ3e5Wt fkEuZLhSSVT52VFreS8Z+SZr8Q5kbaNrihT+rNuE3IDg+HqJ0+P99ZbABt0ZIzwI 9Om8R7WKhDeZQKOVHN6UvLX6p04U56VsM43PLdenQ9JeMTjgjSCA47s2rYl/b9GM hPgp51urhj2k7CrjVE9oMOdgMBO6lCpeQT4K4PAtQeeTWb00sPOGr2PGoPb6r1Pa UqybzwdKZxpv+/jIiZffd+GYRoETmDW4UnlXq0aE2IMxXUWVI+liJuKVXk/zT5cz N/n4rJrJTEJFSOMd0UF8TfbnsR+OgNDo76HWOBWbJ2JZ46qmCufZAOgXhN7XtC0O Kbatgsbi9lRBRBT80Agdr3OOoT2mzuzaY+VwrfiV2vkLOsdhmW039oUUws4V91ii TksS9JFBtJP30m/qxEUDSisrQpLrEcPaT4zYY3tFHywL2Dn1t300iTPeW+LXX0c7 aJfE4XNfYgs7BEHgl1Q3 =p93H -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
6ed0529fef
@ -208,21 +208,19 @@ EXPORT_SYMBOL_GPL(nfs_file_mmap);
|
||||
* 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;
|
||||
@ -247,10 +245,16 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
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);
|
||||
/*
|
||||
|
@ -768,3 +768,10 @@ static inline bool nfs_error_is_fatal(int err)
|
||||
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,
|
||||
__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
|
||||
|
@ -1170,8 +1170,8 @@ out_failed:
|
||||
|
||||
/* remember fatal errors */
|
||||
if (nfs_error_is_fatal(desc->pg_error))
|
||||
mapping_set_error(desc->pg_inode->i_mapping,
|
||||
desc->pg_error);
|
||||
nfs_context_set_write_error(req->wb_context,
|
||||
desc->pg_error);
|
||||
|
||||
func = desc->pg_completion_ops->error_cleanup;
|
||||
for (midx = 0; midx < desc->pg_mirror_count; midx++) {
|
||||
|
@ -1664,7 +1664,7 @@ pnfs_update_layout(struct inode *ino,
|
||||
.offset = pos,
|
||||
.length = count,
|
||||
};
|
||||
unsigned pg_offset, seq;
|
||||
unsigned pg_offset;
|
||||
struct nfs_server *server = NFS_SERVER(ino);
|
||||
struct nfs_client *clp = server->nfs_client;
|
||||
struct pnfs_layout_hdr *lo = NULL;
|
||||
@ -1754,10 +1754,14 @@ lookup_again:
|
||||
}
|
||||
|
||||
first = true;
|
||||
do {
|
||||
seq = read_seqbegin(&ctx->state->seqlock);
|
||||
nfs4_stateid_copy(&stateid, &ctx->state->stateid);
|
||||
} while (read_seqretry(&ctx->state->seqlock, seq));
|
||||
if (nfs4_select_rw_stateid(ctx->state,
|
||||
iomode == IOMODE_RW ? FMODE_WRITE : FMODE_READ,
|
||||
NULL, &stateid, NULL) != 0) {
|
||||
trace_pnfs_update_layout(ino, pos, count,
|
||||
iomode, lo, lseg,
|
||||
PNFS_UPDATE_LAYOUT_INVALID_OPEN);
|
||||
goto out_unlock;
|
||||
}
|
||||
} else {
|
||||
nfs4_stateid_copy(&stateid, &lo->plh_stateid);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "iostat.h"
|
||||
#include "fscache.h"
|
||||
#include "pnfs.h"
|
||||
#include "nfstrace.h"
|
||||
|
||||
#define NFSDBG_FACILITY NFSDBG_PAGECACHE
|
||||
|
||||
@ -200,6 +201,7 @@ static void nfs_initiate_read(struct nfs_pgio_header *hdr,
|
||||
|
||||
task_setup_data->flags |= swap_flags;
|
||||
rpc_ops->read_setup(hdr, msg);
|
||||
trace_nfs_initiate_read(inode, hdr->io_start, hdr->good_bytes);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -232,6 +234,8 @@ static int nfs_readpage_done(struct rpc_task *task,
|
||||
return status;
|
||||
|
||||
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) {
|
||||
set_bit(NFS_INO_STALE, &NFS_I(inode)->flags);
|
||||
|
@ -145,13 +145,6 @@ static void nfs_io_completion_put(struct nfs_io_completion *ioc)
|
||||
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)
|
||||
{
|
||||
@ -1383,6 +1376,8 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr,
|
||||
|
||||
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);
|
||||
@ -1540,7 +1535,10 @@ static int nfs_writeback_done(struct rpc_task *task,
|
||||
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) {
|
||||
@ -1669,6 +1667,7 @@ int nfs_initiate_commit(struct rpc_clnt *clnt, struct nfs_commit_data *data,
|
||||
};
|
||||
/* Set up the initial task struct. */
|
||||
nfs_ops->commit_setup(data, &msg);
|
||||
trace_nfs_initiate_commit(data);
|
||||
|
||||
dprintk("NFS: initiated commit call\n");
|
||||
|
||||
@ -1793,6 +1792,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
|
||||
|
||||
/* 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)
|
||||
|
Loading…
Reference in New Issue
Block a user