Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull NFS client bugfixes from Trond Myklebust:
"Highlights include:

Stable patches:
- fix v4.2 SEEK on files over 2 gigs
- Fix a layout segment reference leak when pNFS I/O falls back to inband I/O.
- Fix recovery of recalled read delegations

Bugfixes:
- Fix a case where NFSv4 fails to send CLOSE after a server reboot
- Fix sunrpc to wait for connections to complete before retrying
- Fix sunrpc races between transport connect/disconnect and shutdown
- Fix an infinite loop when layoutget fail with BAD_STATEID
- nfs/filelayout: Fix NULL reference caused by double freeing of fh_array
- Fix a bogus WARN_ON_ONCE() in O_DIRECT when layout commit_through_mds is set
- Fix layoutreturn/close ordering issues"

* tag 'nfs-for-4.3-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
NFS41: make close wait for layoutreturn
NFS: Skip checking ds_cinfo.buckets when lseg's commit_through_mds is set
NFSv4.x/pnfs: Don't try to recover stateids twice in layoutget
NFSv4: Recovery of recalled read delegations is broken
NFS: Fix an infinite loop when layoutget fail with BAD_STATEID
NFS: Do cleanup before resetting pageio read/write to mds
SUNRPC: xs_sock_mark_closed() does not need to trigger socket autoclose
SUNRPC: Lock the transport layer on shutdown
nfs/filelayout: Fix NULL reference caused by double freeing of fh_array
SUNRPC: Ensure that we wait for connections to complete before retrying
SUNRPC: drop null test before destroy functions
nfs: fix v4.2 SEEK on files over 2 gigs
SUNRPC: Fix races between socket connection and destroy code
nfs: fix pg_test page count calculation
Failing to send a CLOSE if file is opened WRONLY and server reboots on a 4.x mount

+172 -95
+5 -3
fs/nfs/delegation.c
··· 113 113 return status; 114 114 } 115 115 116 - static int nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid) 116 + static int nfs_delegation_claim_opens(struct inode *inode, 117 + const nfs4_stateid *stateid, fmode_t type) 117 118 { 118 119 struct nfs_inode *nfsi = NFS_I(inode); 119 120 struct nfs_open_context *ctx; ··· 141 140 /* Block nfs4_proc_unlck */ 142 141 mutex_lock(&sp->so_delegreturn_mutex); 143 142 seq = raw_seqcount_begin(&sp->so_reclaim_seqcount); 144 - err = nfs4_open_delegation_recall(ctx, state, stateid); 143 + err = nfs4_open_delegation_recall(ctx, state, stateid, type); 145 144 if (!err) 146 145 err = nfs_delegation_claim_locks(ctx, state, stateid); 147 146 if (!err && read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) ··· 412 411 do { 413 412 if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) 414 413 break; 415 - err = nfs_delegation_claim_opens(inode, &delegation->stateid); 414 + err = nfs_delegation_claim_opens(inode, &delegation->stateid, 415 + delegation->type); 416 416 if (!issync || err != -EAGAIN) 417 417 break; 418 418 /*
+1 -1
fs/nfs/delegation.h
··· 54 54 55 55 /* NFSv4 delegation-related procedures */ 56 56 int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync); 57 - int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid); 57 + int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid, fmode_t type); 58 58 int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, const nfs4_stateid *stateid); 59 59 bool nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode, fmode_t flags); 60 60
+5 -2
fs/nfs/direct.c
··· 166 166 struct nfs_writeverf *verfp = &dreq->verf; 167 167 168 168 #ifdef CONFIG_NFS_V4_1 169 - if (ds_clp) { 170 - /* pNFS is in use, use the DS verf */ 169 + /* 170 + * pNFS is in use, use the DS verf except commit_through_mds is set 171 + * for layout segment where nbuckets is zero. 172 + */ 173 + if (ds_clp && dreq->ds_cinfo.nbuckets > 0) { 171 174 if (commit_idx >= 0 && commit_idx < dreq->ds_cinfo.nbuckets) 172 175 verfp = &dreq->ds_cinfo.buckets[commit_idx].direct_verf; 173 176 else
+12 -19
fs/nfs/filelayout/filelayout.c
··· 629 629 goto out; 630 630 } 631 631 632 - static void filelayout_free_fh_array(struct nfs4_filelayout_segment *fl) 632 + static void _filelayout_free_lseg(struct nfs4_filelayout_segment *fl) 633 633 { 634 634 int i; 635 635 636 - for (i = 0; i < fl->num_fh; i++) { 637 - if (!fl->fh_array[i]) 638 - break; 639 - kfree(fl->fh_array[i]); 636 + if (fl->fh_array) { 637 + for (i = 0; i < fl->num_fh; i++) { 638 + if (!fl->fh_array[i]) 639 + break; 640 + kfree(fl->fh_array[i]); 641 + } 642 + kfree(fl->fh_array); 640 643 } 641 - kfree(fl->fh_array); 642 - fl->fh_array = NULL; 643 - } 644 - 645 - static void 646 - _filelayout_free_lseg(struct nfs4_filelayout_segment *fl) 647 - { 648 - filelayout_free_fh_array(fl); 649 644 kfree(fl); 650 645 } 651 646 ··· 711 716 /* Do we want to use a mempool here? */ 712 717 fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), gfp_flags); 713 718 if (!fl->fh_array[i]) 714 - goto out_err_free; 719 + goto out_err; 715 720 716 721 p = xdr_inline_decode(&stream, 4); 717 722 if (unlikely(!p)) 718 - goto out_err_free; 723 + goto out_err; 719 724 fl->fh_array[i]->size = be32_to_cpup(p++); 720 725 if (sizeof(struct nfs_fh) < fl->fh_array[i]->size) { 721 726 printk(KERN_ERR "NFS: Too big fh %d received %d\n", 722 727 i, fl->fh_array[i]->size); 723 - goto out_err_free; 728 + goto out_err; 724 729 } 725 730 726 731 p = xdr_inline_decode(&stream, fl->fh_array[i]->size); 727 732 if (unlikely(!p)) 728 - goto out_err_free; 733 + goto out_err; 729 734 memcpy(fl->fh_array[i]->data, p, fl->fh_array[i]->size); 730 735 dprintk("DEBUG: %s: fh len %d\n", __func__, 731 736 fl->fh_array[i]->size); ··· 734 739 __free_page(scratch); 735 740 return 0; 736 741 737 - out_err_free: 738 - filelayout_free_fh_array(fl); 739 742 out_err: 740 743 __free_page(scratch); 741 744 return -EIO;
+3 -1
fs/nfs/nfs42proc.c
··· 175 175 { 176 176 struct nfs_server *server = NFS_SERVER(file_inode(filep)); 177 177 struct nfs4_exception exception = { }; 178 - int err; 178 + loff_t err; 179 179 180 180 do { 181 181 err = _nfs42_proc_llseek(filep, offset, whence); 182 + if (err >= 0) 183 + break; 182 184 if (err == -ENOTSUPP) 183 185 return -EOPNOTSUPP; 184 186 err = nfs4_handle_exception(server, err, &exception);
+82 -45
fs/nfs/nfs4proc.c
··· 1127 1127 return ret; 1128 1128 } 1129 1129 1130 + static bool nfs4_mode_match_open_stateid(struct nfs4_state *state, 1131 + fmode_t fmode) 1132 + { 1133 + switch(fmode & (FMODE_READ|FMODE_WRITE)) { 1134 + case FMODE_READ|FMODE_WRITE: 1135 + return state->n_rdwr != 0; 1136 + case FMODE_WRITE: 1137 + return state->n_wronly != 0; 1138 + case FMODE_READ: 1139 + return state->n_rdonly != 0; 1140 + } 1141 + WARN_ON_ONCE(1); 1142 + return false; 1143 + } 1144 + 1130 1145 static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode) 1131 1146 { 1132 1147 int ret = 0; ··· 1586 1571 return opendata; 1587 1572 } 1588 1573 1589 - static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmode, struct nfs4_state **res) 1574 + static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, 1575 + fmode_t fmode) 1590 1576 { 1591 1577 struct nfs4_state *newstate; 1592 1578 int ret; 1593 1579 1594 - if ((opendata->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR || 1595 - opendata->o_arg.claim == NFS4_OPEN_CLAIM_DELEG_CUR_FH) && 1596 - (opendata->o_arg.u.delegation_type & fmode) != fmode) 1597 - /* This mode can't have been delegated, so we must have 1598 - * a valid open_stateid to cover it - not need to reclaim. 1599 - */ 1580 + if (!nfs4_mode_match_open_stateid(opendata->state, fmode)) 1600 1581 return 0; 1601 1582 opendata->o_arg.open_flags = 0; 1602 1583 opendata->o_arg.fmode = fmode; ··· 1608 1597 newstate = nfs4_opendata_to_nfs4_state(opendata); 1609 1598 if (IS_ERR(newstate)) 1610 1599 return PTR_ERR(newstate); 1600 + if (newstate != opendata->state) 1601 + ret = -ESTALE; 1611 1602 nfs4_close_state(newstate, fmode); 1612 - *res = newstate; 1613 - return 0; 1603 + return ret; 1614 1604 } 1615 1605 1616 1606 static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *state) 1617 1607 { 1618 - struct nfs4_state *newstate; 1619 1608 int ret; 1620 1609 1621 1610 /* Don't trigger recovery in nfs_test_and_clear_all_open_stateid */ ··· 1626 1615 clear_bit(NFS_DELEGATED_STATE, &state->flags); 1627 1616 clear_bit(NFS_OPEN_STATE, &state->flags); 1628 1617 smp_rmb(); 1629 - if (state->n_rdwr != 0) { 1630 - ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate); 1631 - if (ret != 0) 1632 - return ret; 1633 - if (newstate != state) 1634 - return -ESTALE; 1635 - } 1636 - if (state->n_wronly != 0) { 1637 - ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate); 1638 - if (ret != 0) 1639 - return ret; 1640 - if (newstate != state) 1641 - return -ESTALE; 1642 - } 1643 - if (state->n_rdonly != 0) { 1644 - ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate); 1645 - if (ret != 0) 1646 - return ret; 1647 - if (newstate != state) 1648 - return -ESTALE; 1649 - } 1618 + ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE); 1619 + if (ret != 0) 1620 + return ret; 1621 + ret = nfs4_open_recover_helper(opendata, FMODE_WRITE); 1622 + if (ret != 0) 1623 + return ret; 1624 + ret = nfs4_open_recover_helper(opendata, FMODE_READ); 1625 + if (ret != 0) 1626 + return ret; 1650 1627 /* 1651 1628 * We may have performed cached opens for all three recoveries. 1652 1629 * Check if we need to update the current stateid. ··· 1758 1759 return err; 1759 1760 } 1760 1761 1761 - int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid) 1762 + int nfs4_open_delegation_recall(struct nfs_open_context *ctx, 1763 + struct nfs4_state *state, const nfs4_stateid *stateid, 1764 + fmode_t type) 1762 1765 { 1763 1766 struct nfs_server *server = NFS_SERVER(state->inode); 1764 1767 struct nfs4_opendata *opendata; 1765 - int err; 1768 + int err = 0; 1766 1769 1767 1770 opendata = nfs4_open_recoverdata_alloc(ctx, state, 1768 1771 NFS4_OPEN_CLAIM_DELEG_CUR_FH); 1769 1772 if (IS_ERR(opendata)) 1770 1773 return PTR_ERR(opendata); 1771 1774 nfs4_stateid_copy(&opendata->o_arg.u.delegation, stateid); 1772 - err = nfs4_open_recover(opendata, state); 1775 + clear_bit(NFS_DELEGATED_STATE, &state->flags); 1776 + switch (type & (FMODE_READ|FMODE_WRITE)) { 1777 + case FMODE_READ|FMODE_WRITE: 1778 + case FMODE_WRITE: 1779 + err = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE); 1780 + if (err) 1781 + break; 1782 + err = nfs4_open_recover_helper(opendata, FMODE_WRITE); 1783 + if (err) 1784 + break; 1785 + case FMODE_READ: 1786 + err = nfs4_open_recover_helper(opendata, FMODE_READ); 1787 + } 1773 1788 nfs4_opendata_put(opendata); 1774 1789 return nfs4_handle_delegation_recall_error(server, state, stateid, err); 1775 1790 } ··· 2658 2645 return err; 2659 2646 } 2660 2647 2648 + static bool 2649 + nfs4_wait_on_layoutreturn(struct inode *inode, struct rpc_task *task) 2650 + { 2651 + if (inode == NULL || !nfs_have_layout(inode)) 2652 + return false; 2653 + 2654 + return pnfs_wait_on_layoutreturn(inode, task); 2655 + } 2656 + 2661 2657 struct nfs4_closedata { 2662 2658 struct inode *inode; 2663 2659 struct nfs4_state *state; ··· 2783 2761 if (!call_close) { 2784 2762 /* Note: exit _without_ calling nfs4_close_done */ 2785 2763 goto out_no_action; 2764 + } 2765 + 2766 + if (nfs4_wait_on_layoutreturn(inode, task)) { 2767 + nfs_release_seqid(calldata->arg.seqid); 2768 + goto out_wait; 2786 2769 } 2787 2770 2788 2771 if (calldata->arg.fmode == 0) ··· 5335 5308 5336 5309 d_data = (struct nfs4_delegreturndata *)data; 5337 5310 5311 + if (nfs4_wait_on_layoutreturn(d_data->inode, task)) 5312 + return; 5313 + 5338 5314 if (d_data->roc) 5339 5315 pnfs_roc_get_barrier(d_data->inode, &d_data->roc_barrier); 5340 5316 ··· 7830 7800 dprintk("%s: NFS4ERR_RECALLCONFLICT waiting %lu\n", 7831 7801 __func__, delay); 7832 7802 rpc_delay(task, delay); 7833 - task->tk_status = 0; 7834 - rpc_restart_call_prepare(task); 7835 - goto out; /* Do not call nfs4_async_handle_error() */ 7803 + /* Do not call nfs4_async_handle_error() */ 7804 + goto out_restart; 7836 7805 } 7837 7806 break; 7838 7807 case -NFS4ERR_EXPIRED: 7839 7808 case -NFS4ERR_BAD_STATEID: 7840 7809 spin_lock(&inode->i_lock); 7841 - lo = NFS_I(inode)->layout; 7842 - if (!lo || list_empty(&lo->plh_segs)) { 7810 + if (nfs4_stateid_match(&lgp->args.stateid, 7811 + &lgp->args.ctx->state->stateid)) { 7843 7812 spin_unlock(&inode->i_lock); 7844 7813 /* If the open stateid was bad, then recover it. */ 7845 7814 state = lgp->args.ctx->state; 7846 - } else { 7815 + break; 7816 + } 7817 + lo = NFS_I(inode)->layout; 7818 + if (lo && nfs4_stateid_match(&lgp->args.stateid, 7819 + &lo->plh_stateid)) { 7847 7820 LIST_HEAD(head); 7848 7821 7849 7822 /* 7850 7823 * Mark the bad layout state as invalid, then retry 7851 7824 * with the current stateid. 7852 7825 */ 7826 + set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); 7853 7827 pnfs_mark_matching_lsegs_invalid(lo, &head, NULL); 7854 7828 spin_unlock(&inode->i_lock); 7855 7829 pnfs_free_lseg_list(&head); 7856 - 7857 - task->tk_status = 0; 7858 - rpc_restart_call_prepare(task); 7859 - } 7830 + } else 7831 + spin_unlock(&inode->i_lock); 7832 + goto out_restart; 7860 7833 } 7861 7834 if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN) 7862 - rpc_restart_call_prepare(task); 7835 + goto out_restart; 7863 7836 out: 7864 7837 dprintk("<-- %s\n", __func__); 7838 + return; 7839 + out_restart: 7840 + task->tk_status = 0; 7841 + rpc_restart_call_prepare(task); 7865 7842 return; 7866 7843 out_overflow: 7867 7844 task->tk_status = -EOVERFLOW;
+1 -1
fs/nfs/nfs4state.c
··· 1481 1481 spin_unlock(&state->state_lock); 1482 1482 } 1483 1483 nfs4_put_open_state(state); 1484 - clear_bit(NFS4CLNT_RECLAIM_NOGRACE, 1484 + clear_bit(NFS_STATE_RECLAIM_NOGRACE, 1485 1485 &state->flags); 1486 1486 spin_lock(&sp->so_lock); 1487 1487 goto restart;
+1 -1
fs/nfs/pagelist.c
··· 508 508 * for it without upsetting the slab allocator. 509 509 */ 510 510 if (((mirror->pg_count + req->wb_bytes) >> PAGE_SHIFT) * 511 - sizeof(struct page) > PAGE_SIZE) 511 + sizeof(struct page *) > PAGE_SIZE) 512 512 return 0; 513 513 514 514 return min(mirror->pg_bsize - mirror->pg_count, (size_t)req->wb_bytes);
+25 -10
fs/nfs/pnfs.c
··· 1104 1104 mark_lseg_invalid(lseg, &tmp_list); 1105 1105 found = true; 1106 1106 } 1107 - /* pnfs_prepare_layoutreturn() grabs lo ref and it will be put 1108 - * in pnfs_roc_release(). We don't really send a layoutreturn but 1109 - * still want others to view us like we are sending one! 1110 - * 1111 - * If pnfs_prepare_layoutreturn() fails, it means someone else is doing 1112 - * LAYOUTRETURN, so we proceed like there are no layouts to return. 1113 - * 1114 - * ROC in three conditions: 1107 + /* ROC in two conditions: 1115 1108 * 1. there are ROC lsegs 1116 1109 * 2. we don't send layoutreturn 1117 - * 3. no others are sending layoutreturn 1118 1110 */ 1119 - if (found && !layoutreturn && pnfs_prepare_layoutreturn(lo)) 1111 + if (found && !layoutreturn) { 1112 + /* lo ref dropped in pnfs_roc_release() */ 1113 + pnfs_get_layout_hdr(lo); 1120 1114 roc = true; 1115 + } 1121 1116 1122 1117 out_noroc: 1123 1118 spin_unlock(&ino->i_lock); ··· 1165 1170 */ 1166 1171 *barrier = current_seqid + atomic_read(&lo->plh_outstanding); 1167 1172 spin_unlock(&ino->i_lock); 1173 + } 1174 + 1175 + bool pnfs_wait_on_layoutreturn(struct inode *ino, struct rpc_task *task) 1176 + { 1177 + struct nfs_inode *nfsi = NFS_I(ino); 1178 + struct pnfs_layout_hdr *lo; 1179 + bool sleep = false; 1180 + 1181 + /* we might not have grabbed lo reference. so need to check under 1182 + * i_lock */ 1183 + spin_lock(&ino->i_lock); 1184 + lo = nfsi->layout; 1185 + if (lo && test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) 1186 + sleep = true; 1187 + spin_unlock(&ino->i_lock); 1188 + 1189 + if (sleep) 1190 + rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL); 1191 + 1192 + return sleep; 1168 1193 } 1169 1194 1170 1195 /*
+7
fs/nfs/pnfs.h
··· 270 270 void pnfs_roc_release(struct inode *ino); 271 271 void pnfs_roc_set_barrier(struct inode *ino, u32 barrier); 272 272 void pnfs_roc_get_barrier(struct inode *ino, u32 *barrier); 273 + bool pnfs_wait_on_layoutreturn(struct inode *ino, struct rpc_task *task); 273 274 void pnfs_set_layoutcommit(struct inode *, struct pnfs_layout_segment *, loff_t); 274 275 void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data); 275 276 int pnfs_layoutcommit_inode(struct inode *inode, bool sync); ··· 638 637 static inline void 639 638 pnfs_roc_get_barrier(struct inode *ino, u32 *barrier) 640 639 { 640 + } 641 + 642 + static inline bool 643 + pnfs_wait_on_layoutreturn(struct inode *ino, struct rpc_task *task) 644 + { 645 + return false; 641 646 } 642 647 643 648 static inline void set_pnfs_layoutdriver(struct nfs_server *s,
+3
fs/nfs/read.c
··· 72 72 { 73 73 struct nfs_pgio_mirror *mirror; 74 74 75 + if (pgio->pg_ops && pgio->pg_ops->pg_cleanup) 76 + pgio->pg_ops->pg_cleanup(pgio); 77 + 75 78 pgio->pg_ops = &nfs_pgio_rw_ops; 76 79 77 80 /* read path should never have more than one mirror */
+3
fs/nfs/write.c
··· 1351 1351 { 1352 1352 struct nfs_pgio_mirror *mirror; 1353 1353 1354 + if (pgio->pg_ops && pgio->pg_ops->pg_cleanup) 1355 + pgio->pg_ops->pg_cleanup(pgio); 1356 + 1354 1357 pgio->pg_ops = &nfs_pgio_rw_ops; 1355 1358 1356 1359 nfs_pageio_stop_mirroring(pgio);
+3
include/linux/sunrpc/xprtsock.h
··· 42 42 /* 43 43 * Connection of transports 44 44 */ 45 + unsigned long sock_state; 45 46 struct delayed_work connect_worker; 46 47 struct sockaddr_storage srcaddr; 47 48 unsigned short srcport; ··· 76 75 * TCP RPC flags 77 76 */ 78 77 #define TCP_RPC_REPLY (1UL << 6) 78 + 79 + #define XPRT_SOCK_CONNECTING 1U 79 80 80 81 #endif /* __KERNEL__ */ 81 82
+4 -8
net/sunrpc/sched.c
··· 1092 1092 rpc_destroy_mempool(void) 1093 1093 { 1094 1094 rpciod_stop(); 1095 - if (rpc_buffer_mempool) 1096 - mempool_destroy(rpc_buffer_mempool); 1097 - if (rpc_task_mempool) 1098 - mempool_destroy(rpc_task_mempool); 1099 - if (rpc_task_slabp) 1100 - kmem_cache_destroy(rpc_task_slabp); 1101 - if (rpc_buffer_slabp) 1102 - kmem_cache_destroy(rpc_buffer_slabp); 1095 + mempool_destroy(rpc_buffer_mempool); 1096 + mempool_destroy(rpc_task_mempool); 1097 + kmem_cache_destroy(rpc_task_slabp); 1098 + kmem_cache_destroy(rpc_buffer_slabp); 1103 1099 rpc_destroy_wait_queue(&delay_queue); 1104 1100 } 1105 1101
+6
net/sunrpc/xprt.c
··· 614 614 clear_bit(XPRT_CLOSE_WAIT, &xprt->state); 615 615 xprt->ops->close(xprt); 616 616 xprt_release_write(xprt, NULL); 617 + wake_up_bit(&xprt->state, XPRT_LOCKED); 617 618 } 618 619 619 620 /** ··· 724 723 xprt->ops->release_xprt(xprt, NULL); 725 724 out: 726 725 spin_unlock_bh(&xprt->transport_lock); 726 + wake_up_bit(&xprt->state, XPRT_LOCKED); 727 727 } 728 728 729 729 /** ··· 1396 1394 static void xprt_destroy(struct rpc_xprt *xprt) 1397 1395 { 1398 1396 dprintk("RPC: destroying transport %p\n", xprt); 1397 + 1398 + /* Exclude transport connect/disconnect handlers */ 1399 + wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_UNINTERRUPTIBLE); 1400 + 1399 1401 del_timer_sync(&xprt->timer); 1400 1402 1401 1403 rpc_xprt_debugfs_unregister(xprt);
+11 -4
net/sunrpc/xprtsock.c
··· 777 777 xs_sock_reset_connection_flags(xprt); 778 778 /* Mark transport as closed and wake up all pending tasks */ 779 779 xprt_disconnect_done(xprt); 780 - xprt_force_disconnect(xprt); 781 780 } 782 781 783 782 /** ··· 880 881 */ 881 882 static void xs_destroy(struct rpc_xprt *xprt) 882 883 { 884 + struct sock_xprt *transport = container_of(xprt, 885 + struct sock_xprt, xprt); 883 886 dprintk("RPC: xs_destroy xprt %p\n", xprt); 884 887 888 + cancel_delayed_work_sync(&transport->connect_worker); 885 889 xs_close(xprt); 886 890 xs_xprt_free(xprt); 887 891 module_put(THIS_MODULE); ··· 1437 1435 static void xs_tcp_state_change(struct sock *sk) 1438 1436 { 1439 1437 struct rpc_xprt *xprt; 1438 + struct sock_xprt *transport; 1440 1439 1441 1440 read_lock_bh(&sk->sk_callback_lock); 1442 1441 if (!(xprt = xprt_from_sock(sk))) ··· 1449 1446 sock_flag(sk, SOCK_ZAPPED), 1450 1447 sk->sk_shutdown); 1451 1448 1449 + transport = container_of(xprt, struct sock_xprt, xprt); 1452 1450 trace_rpc_socket_state_change(xprt, sk->sk_socket); 1453 1451 switch (sk->sk_state) { 1454 1452 case TCP_ESTABLISHED: 1455 1453 spin_lock(&xprt->transport_lock); 1456 1454 if (!xprt_test_and_set_connected(xprt)) { 1457 - struct sock_xprt *transport = container_of(xprt, 1458 - struct sock_xprt, xprt); 1459 1455 1460 1456 /* Reset TCP record info */ 1461 1457 transport->tcp_offset = 0; ··· 1463 1461 transport->tcp_flags = 1464 1462 TCP_RCV_COPY_FRAGHDR | TCP_RCV_COPY_XID; 1465 1463 xprt->connect_cookie++; 1464 + clear_bit(XPRT_SOCK_CONNECTING, &transport->sock_state); 1465 + xprt_clear_connecting(xprt); 1466 1466 1467 1467 xprt_wake_pending_tasks(xprt, -EAGAIN); 1468 1468 } ··· 1500 1496 smp_mb__after_atomic(); 1501 1497 break; 1502 1498 case TCP_CLOSE: 1499 + if (test_and_clear_bit(XPRT_SOCK_CONNECTING, 1500 + &transport->sock_state)) 1501 + xprt_clear_connecting(xprt); 1503 1502 xs_sock_mark_closed(xprt); 1504 1503 } 1505 1504 out: ··· 2186 2179 /* Tell the socket layer to start connecting... */ 2187 2180 xprt->stat.connect_count++; 2188 2181 xprt->stat.connect_start = jiffies; 2182 + set_bit(XPRT_SOCK_CONNECTING, &transport->sock_state); 2189 2183 ret = kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK); 2190 2184 switch (ret) { 2191 2185 case 0: ··· 2248 2240 case -EINPROGRESS: 2249 2241 case -EALREADY: 2250 2242 xprt_unlock_connect(xprt, transport); 2251 - xprt_clear_connecting(xprt); 2252 2243 return; 2253 2244 case -EINVAL: 2254 2245 /* Happens, for instance, if the user specified a link