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
|
@ -1215,7 +1215,7 @@ static int ff_layout_read_done_cb(struct rpc_task *task,
|
||||||
hdr->pgio_mirror_idx + 1,
|
hdr->pgio_mirror_idx + 1,
|
||||||
&hdr->pgio_mirror_idx))
|
&hdr->pgio_mirror_idx))
|
||||||
goto out_eagain;
|
goto out_eagain;
|
||||||
set_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
|
set_bit(NFS_LAYOUT_RETURN_REQUESTED,
|
||||||
&hdr->lseg->pls_layout->plh_flags);
|
&hdr->lseg->pls_layout->plh_flags);
|
||||||
pnfs_read_resend_pnfs(hdr);
|
pnfs_read_resend_pnfs(hdr);
|
||||||
return task->tk_status;
|
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);
|
OP_ILLEGAL, GFP_NOIO);
|
||||||
if (!fail_return) {
|
if (!fail_return) {
|
||||||
if (ff_layout_has_available_ds(lseg))
|
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);
|
&lseg->pls_layout->plh_flags);
|
||||||
else
|
else
|
||||||
pnfs_error_mark_layout_for_return(ino, lseg);
|
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 LIST_HEAD(pnfs_modules_tbl);
|
||||||
|
|
||||||
static int
|
static void pnfs_layoutreturn_before_put_layout_hdr(struct pnfs_layout_hdr *lo);
|
||||||
pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, const nfs4_stateid *stateid,
|
|
||||||
enum pnfs_iomode iomode, bool sync);
|
|
||||||
|
|
||||||
/* Return the registered pnfs layout driver module matching given id */
|
/* Return the registered pnfs layout driver module matching given id */
|
||||||
static struct pnfs_layoutdriver_type *
|
static struct pnfs_layoutdriver_type *
|
||||||
|
@ -243,6 +241,8 @@ pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo)
|
||||||
{
|
{
|
||||||
struct inode *inode = lo->plh_inode;
|
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 (atomic_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) {
|
||||||
if (!list_empty(&lo->plh_segs))
|
if (!list_empty(&lo->plh_segs))
|
||||||
WARN_ONCE(1, "NFS: BUG unfreed layout segments.\n");
|
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);
|
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
|
void
|
||||||
pnfs_put_lseg(struct pnfs_layout_segment *lseg)
|
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),
|
atomic_read(&lseg->pls_refcount),
|
||||||
test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
|
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;
|
lo = lseg->pls_layout;
|
||||||
inode = lo->plh_inode;
|
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 (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) {
|
||||||
if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) {
|
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);
|
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
|
static int
|
||||||
pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, const nfs4_stateid *stateid,
|
pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, const nfs4_stateid *stateid,
|
||||||
enum pnfs_iomode iomode, bool sync)
|
enum pnfs_iomode iomode, bool sync)
|
||||||
|
@ -971,6 +923,48 @@ out:
|
||||||
return status;
|
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
|
* Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr
|
||||||
* when the layout segment list is empty.
|
* when the layout segment list is empty.
|
||||||
|
@ -1091,7 +1085,7 @@ bool pnfs_roc(struct inode *ino)
|
||||||
|
|
||||||
nfs4_stateid_copy(&stateid, &lo->plh_stateid);
|
nfs4_stateid_copy(&stateid, &lo->plh_stateid);
|
||||||
/* always send layoutreturn if being marked so */
|
/* 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))
|
&lo->plh_flags))
|
||||||
layoutreturn = pnfs_prepare_layoutreturn(lo);
|
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);
|
pnfs_set_plh_return_iomode(lo, return_range->iomode);
|
||||||
if (!mark_lseg_invalid(lseg, tmp_list))
|
if (!mark_lseg_invalid(lseg, tmp_list))
|
||||||
remaining++;
|
remaining++;
|
||||||
set_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
|
set_bit(NFS_LAYOUT_RETURN_REQUESTED,
|
||||||
&lo->plh_flags);
|
&lo->plh_flags);
|
||||||
}
|
}
|
||||||
return remaining;
|
return remaining;
|
||||||
|
|
|
@ -94,8 +94,8 @@ enum {
|
||||||
NFS_LAYOUT_RO_FAILED = 0, /* get ro layout failed stop trying */
|
NFS_LAYOUT_RO_FAILED = 0, /* get ro layout failed stop trying */
|
||||||
NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */
|
NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */
|
||||||
NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */
|
NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */
|
||||||
NFS_LAYOUT_RETURN, /* Return this layout ASAP */
|
NFS_LAYOUT_RETURN, /* layoutreturn in progress */
|
||||||
NFS_LAYOUT_RETURN_BEFORE_CLOSE, /* Return this layout before close */
|
NFS_LAYOUT_RETURN_REQUESTED, /* Return this layout ASAP */
|
||||||
NFS_LAYOUT_INVALID_STID, /* layout stateid id is invalid */
|
NFS_LAYOUT_INVALID_STID, /* layout stateid id is invalid */
|
||||||
NFS_LAYOUT_FIRST_LAYOUTGET, /* Serialize first layoutget */
|
NFS_LAYOUT_FIRST_LAYOUTGET, /* Serialize first layoutget */
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue