Merge branch 'bugfixes'

* bugfixes:
  SUNRPC: Fix a thinko in xs_connect()
  NFSv4.1/pNFS: Fix borken function _same_data_server_addrs_locked()
  NFS: nfs_set_pgio_error sometimes misses errors
This commit is contained in:
Trond Myklebust 2015-08-17 13:36:22 -05:00
commit 37bfcc14b2
3 changed files with 25 additions and 19 deletions

View File

@ -77,8 +77,8 @@ EXPORT_SYMBOL_GPL(nfs_pgheader_init);
void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos) void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos)
{ {
spin_lock(&hdr->lock); spin_lock(&hdr->lock);
if (pos < hdr->io_start + hdr->good_bytes) { if (!test_and_set_bit(NFS_IOHDR_ERROR, &hdr->flags)
set_bit(NFS_IOHDR_ERROR, &hdr->flags); || pos < hdr->io_start + hdr->good_bytes) {
clear_bit(NFS_IOHDR_EOF, &hdr->flags); clear_bit(NFS_IOHDR_EOF, &hdr->flags);
hdr->good_bytes = pos - hdr->io_start; hdr->good_bytes = pos - hdr->io_start;
hdr->error = error; hdr->error = error;

View File

@ -359,26 +359,31 @@ same_sockaddr(struct sockaddr *addr1, struct sockaddr *addr2)
return false; return false;
} }
/*
* Checks if 'dsaddrs1' contains a subset of 'dsaddrs2'. If it does,
* declare a match.
*/
static bool static bool
_same_data_server_addrs_locked(const struct list_head *dsaddrs1, _same_data_server_addrs_locked(const struct list_head *dsaddrs1,
const struct list_head *dsaddrs2) const struct list_head *dsaddrs2)
{ {
struct nfs4_pnfs_ds_addr *da1, *da2; struct nfs4_pnfs_ds_addr *da1, *da2;
struct sockaddr *sa1, *sa2;
bool match = false;
/* step through both lists, comparing as we go */ list_for_each_entry(da1, dsaddrs1, da_node) {
for (da1 = list_first_entry(dsaddrs1, typeof(*da1), da_node), sa1 = (struct sockaddr *)&da1->da_addr;
da2 = list_first_entry(dsaddrs2, typeof(*da2), da_node); match = false;
da1 != NULL && da2 != NULL; list_for_each_entry(da2, dsaddrs2, da_node) {
da1 = list_entry(da1->da_node.next, typeof(*da1), da_node), sa2 = (struct sockaddr *)&da2->da_addr;
da2 = list_entry(da2->da_node.next, typeof(*da2), da_node)) { match = same_sockaddr(sa1, sa2);
if (!same_sockaddr((struct sockaddr *)&da1->da_addr, if (match)
(struct sockaddr *)&da2->da_addr)) break;
return false; }
if (!match)
break;
} }
if (da1 == NULL && da2 == NULL) return match;
return true;
return false;
} }
/* /*

View File

@ -2279,13 +2279,14 @@ static void xs_connect(struct rpc_xprt *xprt, struct rpc_task *task)
WARN_ON_ONCE(!xprt_lock_connect(xprt, task, transport)); WARN_ON_ONCE(!xprt_lock_connect(xprt, task, transport));
/* Start by resetting any existing state */ if (transport->sock != NULL) {
xs_reset_transport(transport);
if (transport->sock != NULL && !RPC_IS_SOFTCONN(task)) {
dprintk("RPC: xs_connect delayed xprt %p for %lu " dprintk("RPC: xs_connect delayed xprt %p for %lu "
"seconds\n", "seconds\n",
xprt, xprt->reestablish_timeout / HZ); xprt, xprt->reestablish_timeout / HZ);
/* Start by resetting any existing state */
xs_reset_transport(transport);
queue_delayed_work(rpciod_workqueue, queue_delayed_work(rpciod_workqueue,
&transport->connect_worker, &transport->connect_worker,
xprt->reestablish_timeout); xprt->reestablish_timeout);