mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
NFS client bugfixe and cleanup for Linux 4.5
Bugfix: - pNFS: Fix for missing layoutreturn calls Cleanup: - pNFS: rename NFS_LAYOUT_RETURN_BEFORE_CLOSE for code clarity -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWsUFjAAoJEGcL54qWCgDyipwP/0byMIrCx+B+w/tyBAhyb3Er 7V9hM/r51EYwWVQp7POOV10oX2rEde9eyz3q5fRhLgximUNxtqLOTcaYIZH3r29q apuDyEKHSgj6JFu3UG1a8FtBCy8oGkvHglsw7xSq6PcX26rpP95vnSrsA1iDheyU zeYTcYgsYuhfXzwriNmAKD1ziPyTw5aeiSfzdBCDi+T9LnP2bKhPQ6j749vOwyO8 wmRuwoAxFjt1xMmogUH9Bste7jX4YTF6Ww1PX1/A9LseipR9nW2ANO5yjupCnLLh ky4AVgunbjsbVt6XLo1DmageSqFtf340YyIX/ZFpb97I15qu7Vnzhmkgo2FjYdZE S/LRnUp8oDlSWRDAILnvD47br0jrjB7DUVThmyiYFTc135FTluzhzsWWJOT0DOp2 uI6VtJ4pGd2gUo6K4R1PLAgzP6nxM+IulEbxhYrE4Eu9YfbdICQUmSFkszyv8Lej +yQXm3zx69i62/V/ipU4VQwt7943noVzRFyZMDCcLaN2S7J6JhN41/tI//SUlbHb e4N6Tb35HUrW6pBh1qeFnZqiN2mvB8RpZLQwpX8VnrYijljN1vh5szqj16fkVkiK MMoRS8c4fmIKc1Lxa54/kTKS1CWW7dVl35U5aBm+E7CvnemhA9AqTXrRTJOKgOE1 SyTPxTEWwG658jy7xKLZ =ZSKC -----END PGP SIGNATURE----- Merge tag 'nfs-for-4.5-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs Pull NFS client bugfix and cleanup from Trond Myklebust: "Bugfix: - pNFS: Fix for missing layoutreturn calls Cleanup: - pNFS: rename NFS_LAYOUT_RETURN_BEFORE_CLOSE for code clarity" * tag 'nfs-for-4.5-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFS: Cleanup - rename NFS_LAYOUT_RETURN_BEFORE_CLOSE pNFS: Fix missing layoutreturn calls
This commit is contained in:
commit
81b676bd87
4 changed files with 62 additions and 68 deletions
|
@ -1215,7 +1215,7 @@ static int ff_layout_read_done_cb(struct rpc_task *task,
|
|||
hdr->pgio_mirror_idx + 1,
|
||||
&hdr->pgio_mirror_idx))
|
||||
goto out_eagain;
|
||||
set_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
|
||||
set_bit(NFS_LAYOUT_RETURN_REQUESTED,
|
||||
&hdr->lseg->pls_layout->plh_flags);
|
||||
pnfs_read_resend_pnfs(hdr);
|
||||
return task->tk_status;
|
||||
|
|
|
@ -412,7 +412,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
|
|||
OP_ILLEGAL, GFP_NOIO);
|
||||
if (!fail_return) {
|
||||
if (ff_layout_has_available_ds(lseg))
|
||||
set_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
|
||||
set_bit(NFS_LAYOUT_RETURN_REQUESTED,
|
||||
&lseg->pls_layout->plh_flags);
|
||||
else
|
||||
pnfs_error_mark_layout_for_return(ino, lseg);
|
||||
|
|
122
fs/nfs/pnfs.c
122
fs/nfs/pnfs.c
|
@ -52,9 +52,7 @@ static DEFINE_SPINLOCK(pnfs_spinlock);
|
|||
*/
|
||||
static LIST_HEAD(pnfs_modules_tbl);
|
||||
|
||||
static int
|
||||
pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, const nfs4_stateid *stateid,
|
||||
enum pnfs_iomode iomode, bool sync);
|
||||
static void pnfs_layoutreturn_before_put_layout_hdr(struct pnfs_layout_hdr *lo);
|
||||
|
||||
/* Return the registered pnfs layout driver module matching given id */
|
||||
static struct pnfs_layoutdriver_type *
|
||||
|
@ -243,6 +241,8 @@ pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo)
|
|||
{
|
||||
struct inode *inode = lo->plh_inode;
|
||||
|
||||
pnfs_layoutreturn_before_put_layout_hdr(lo);
|
||||
|
||||
if (atomic_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) {
|
||||
if (!list_empty(&lo->plh_segs))
|
||||
WARN_ONCE(1, "NFS: BUG unfreed layout segments.\n");
|
||||
|
@ -345,58 +345,6 @@ pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo,
|
|||
rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq);
|
||||
}
|
||||
|
||||
/* Return true if layoutreturn is needed */
|
||||
static bool
|
||||
pnfs_layout_need_return(struct pnfs_layout_hdr *lo,
|
||||
struct pnfs_layout_segment *lseg)
|
||||
{
|
||||
struct pnfs_layout_segment *s;
|
||||
|
||||
if (!test_and_clear_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))
|
||||
return false;
|
||||
|
||||
list_for_each_entry(s, &lo->plh_segs, pls_list)
|
||||
if (s != lseg && test_bit(NFS_LSEG_LAYOUTRETURN, &s->pls_flags))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo)
|
||||
{
|
||||
if (test_and_set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
|
||||
return false;
|
||||
lo->plh_return_iomode = 0;
|
||||
pnfs_get_layout_hdr(lo);
|
||||
clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, &lo->plh_flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void pnfs_layoutreturn_before_put_lseg(struct pnfs_layout_segment *lseg,
|
||||
struct pnfs_layout_hdr *lo, struct inode *inode)
|
||||
{
|
||||
lo = lseg->pls_layout;
|
||||
inode = lo->plh_inode;
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
if (pnfs_layout_need_return(lo, lseg)) {
|
||||
nfs4_stateid stateid;
|
||||
enum pnfs_iomode iomode;
|
||||
bool send;
|
||||
|
||||
nfs4_stateid_copy(&stateid, &lo->plh_stateid);
|
||||
iomode = lo->plh_return_iomode;
|
||||
send = pnfs_prepare_layoutreturn(lo);
|
||||
spin_unlock(&inode->i_lock);
|
||||
if (send) {
|
||||
/* Send an async layoutreturn so we dont deadlock */
|
||||
pnfs_send_layoutreturn(lo, &stateid, iomode, false);
|
||||
}
|
||||
} else
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
|
||||
void
|
||||
pnfs_put_lseg(struct pnfs_layout_segment *lseg)
|
||||
{
|
||||
|
@ -410,15 +358,8 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg)
|
|||
atomic_read(&lseg->pls_refcount),
|
||||
test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
|
||||
|
||||
/* Handle the case where refcount != 1 */
|
||||
if (atomic_add_unless(&lseg->pls_refcount, -1, 1))
|
||||
return;
|
||||
|
||||
lo = lseg->pls_layout;
|
||||
inode = lo->plh_inode;
|
||||
/* Do we need a layoutreturn? */
|
||||
if (test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))
|
||||
pnfs_layoutreturn_before_put_lseg(lseg, lo, inode);
|
||||
|
||||
if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) {
|
||||
if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) {
|
||||
|
@ -937,6 +878,17 @@ void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo)
|
|||
rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq);
|
||||
}
|
||||
|
||||
static bool
|
||||
pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo)
|
||||
{
|
||||
if (test_and_set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
|
||||
return false;
|
||||
lo->plh_return_iomode = 0;
|
||||
pnfs_get_layout_hdr(lo);
|
||||
clear_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, const nfs4_stateid *stateid,
|
||||
enum pnfs_iomode iomode, bool sync)
|
||||
|
@ -971,6 +923,48 @@ pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, const nfs4_stateid *stateid,
|
|||
return status;
|
||||
}
|
||||
|
||||
/* Return true if layoutreturn is needed */
|
||||
static bool
|
||||
pnfs_layout_need_return(struct pnfs_layout_hdr *lo)
|
||||
{
|
||||
struct pnfs_layout_segment *s;
|
||||
|
||||
if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags))
|
||||
return false;
|
||||
|
||||
/* Defer layoutreturn until all lsegs are done */
|
||||
list_for_each_entry(s, &lo->plh_segs, pls_list) {
|
||||
if (test_bit(NFS_LSEG_LAYOUTRETURN, &s->pls_flags))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void pnfs_layoutreturn_before_put_layout_hdr(struct pnfs_layout_hdr *lo)
|
||||
{
|
||||
struct inode *inode= lo->plh_inode;
|
||||
|
||||
if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags))
|
||||
return;
|
||||
spin_lock(&inode->i_lock);
|
||||
if (pnfs_layout_need_return(lo)) {
|
||||
nfs4_stateid stateid;
|
||||
enum pnfs_iomode iomode;
|
||||
bool send;
|
||||
|
||||
nfs4_stateid_copy(&stateid, &lo->plh_stateid);
|
||||
iomode = lo->plh_return_iomode;
|
||||
send = pnfs_prepare_layoutreturn(lo);
|
||||
spin_unlock(&inode->i_lock);
|
||||
if (send) {
|
||||
/* Send an async layoutreturn so we dont deadlock */
|
||||
pnfs_send_layoutreturn(lo, &stateid, iomode, false);
|
||||
}
|
||||
} else
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr
|
||||
* when the layout segment list is empty.
|
||||
|
@ -1091,7 +1085,7 @@ bool pnfs_roc(struct inode *ino)
|
|||
|
||||
nfs4_stateid_copy(&stateid, &lo->plh_stateid);
|
||||
/* always send layoutreturn if being marked so */
|
||||
if (test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
|
||||
if (test_and_clear_bit(NFS_LAYOUT_RETURN_REQUESTED,
|
||||
&lo->plh_flags))
|
||||
layoutreturn = pnfs_prepare_layoutreturn(lo);
|
||||
|
||||
|
@ -1772,7 +1766,7 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
|
|||
pnfs_set_plh_return_iomode(lo, return_range->iomode);
|
||||
if (!mark_lseg_invalid(lseg, tmp_list))
|
||||
remaining++;
|
||||
set_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
|
||||
set_bit(NFS_LAYOUT_RETURN_REQUESTED,
|
||||
&lo->plh_flags);
|
||||
}
|
||||
return remaining;
|
||||
|
|
|
@ -94,8 +94,8 @@ enum {
|
|||
NFS_LAYOUT_RO_FAILED = 0, /* get ro layout failed stop trying */
|
||||
NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */
|
||||
NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */
|
||||
NFS_LAYOUT_RETURN, /* Return this layout ASAP */
|
||||
NFS_LAYOUT_RETURN_BEFORE_CLOSE, /* Return this layout before close */
|
||||
NFS_LAYOUT_RETURN, /* layoutreturn in progress */
|
||||
NFS_LAYOUT_RETURN_REQUESTED, /* Return this layout ASAP */
|
||||
NFS_LAYOUT_INVALID_STID, /* layout stateid id is invalid */
|
||||
NFS_LAYOUT_FIRST_LAYOUTGET, /* Serialize first layoutget */
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue