NFS client bugfixes and cleanups for Linux 4.5

Bugfixes:
 - pNFS/flexfiles: Fix an XDR encoding bug in layoutreturn
 - pNFS/flexfiles: Improve merging of errors in LAYOUTRETURN
 
 Cleanups:
 - NFS: Simplify nfs_request_add_commit_list() arguments
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJWo7eYAAoJEGcL54qWCgDyqWIP/iJFYMdOGwPd6zKA4cfPryTs
 PavS96vzFMsXkr26WyibS6J/pWBSlZA4u7PMqmkR68KhPFRlKDIkaBPUskD4kZS+
 DyTzT3VCBCrDdpnZi+Hk5PfFE6j/fyIs5Im/R+TJFHpdkF3/cLr9o2nuIrm8WOI3
 e+pgcDHJNJSdMvILz9OEGT/s9zi22sqebT0KoTVa19VwisWyjQeB6p2LNAmZF1TZ
 dWRDDcBBw/f5MTnwiS5yqTFtSUnMaiMS7QmNQiX2AiN/rUvNkt6fk45K1XtCmuFV
 X9rv1rsBn1wqW5Knb90eS8OMfNYirFOZZxjuSyOP7dzUxDlWSeTLCkXvUKgKVp0A
 ycu8yckfGR7U1f+jDA87xFMwe4LaP965pprWxIRdqXPMzbDR5x2+b4kVly9TtaD0
 ZploPen9eJTcqh/tzh9RsE30n8UINBPgdh+kEZMeTaAp2mDj1Y220Y7v3s2wvb3/
 xr++FoWlW3EQ/TPEWOtRnVPVPOViZ/xsZmmTMvLfETpTYfC3hpSRWyU4dyQk1bhc
 Kw/rmGWAXU/Y7Du9TM5uExveb/mZK29hLRuhgFAOnMClZ2W6e4yflmjiGJIPw6wA
 E1YuhRUv7nv2EgM190KbDGPbVJ2e54bob9lm3JdcDwSSnqaEcr3imcqjEsEUIeMF
 431tAoroBsf8si0pIX35
 =+1hy
 -----END PGP SIGNATURE-----

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

Pull NFS client bugfixes and cleanups from Trond Myklebust:
 "Bugfixes:
   - pNFS/flexfiles: Fix an XDR encoding bug in layoutreturn
   - pNFS/flexfiles: Improve merging of errors in LAYOUTRETURN

  Cleanups:
   - NFS: Simplify nfs_request_add_commit_list() arguments"

* tag 'nfs-for-4.5-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  pNFS/flexfiles: Fix an XDR encoding bug in layoutreturn
  NFS: Simplify nfs_request_add_commit_list() arguments
  pNFS/flexfiles: Improve merging of errors in LAYOUTRETURN
This commit is contained in:
Linus Torvalds 2016-01-23 11:47:13 -08:00
commit fa7d9a1d28
5 changed files with 46 additions and 68 deletions

View File

@ -971,7 +971,7 @@ filelayout_mark_request_commit(struct nfs_page *req,
u32 i, j; u32 i, j;
if (fl->commit_through_mds) { if (fl->commit_through_mds) {
nfs_request_add_commit_list(req, &cinfo->mds->list, cinfo); nfs_request_add_commit_list(req, cinfo);
} else { } else {
/* Note that we are calling nfs4_fl_calc_j_index on each page /* Note that we are calling nfs4_fl_calc_j_index on each page
* that ends up being committed to a data server. An attractive * that ends up being committed to a data server. An attractive

View File

@ -1948,11 +1948,9 @@ ff_layout_encode_layoutreturn(struct pnfs_layout_hdr *lo,
start = xdr_reserve_space(xdr, 4); start = xdr_reserve_space(xdr, 4);
BUG_ON(!start); BUG_ON(!start);
if (ff_layout_encode_ioerr(flo, xdr, args)) ff_layout_encode_ioerr(flo, xdr, args);
goto out;
ff_layout_encode_iostats(flo, xdr, args); ff_layout_encode_iostats(flo, xdr, args);
out:
*start = cpu_to_be32((xdr->p - start - 1) * 4); *start = cpu_to_be32((xdr->p - start - 1) * 4);
dprintk("%s: Return\n", __func__); dprintk("%s: Return\n", __func__);
} }

View File

@ -218,63 +218,55 @@ static void extend_ds_error(struct nfs4_ff_layout_ds_err *err,
err->length = end - err->offset; err->length = end - err->offset;
} }
static bool ds_error_can_merge(struct nfs4_ff_layout_ds_err *err, u64 offset, static int
u64 length, int status, enum nfs_opnum4 opnum, ff_ds_error_match(const struct nfs4_ff_layout_ds_err *e1,
nfs4_stateid *stateid, const struct nfs4_ff_layout_ds_err *e2)
struct nfs4_deviceid *deviceid)
{ {
return err->status == status && err->opnum == opnum && int ret;
nfs4_stateid_match(&err->stateid, stateid) &&
!memcmp(&err->deviceid, deviceid, sizeof(*deviceid)) && if (e1->opnum != e2->opnum)
end_offset(err->offset, err->length) >= offset && return e1->opnum < e2->opnum ? -1 : 1;
err->offset <= end_offset(offset, length); if (e1->status != e2->status)
return e1->status < e2->status ? -1 : 1;
ret = memcmp(&e1->stateid, &e2->stateid, sizeof(e1->stateid));
if (ret != 0)
return ret;
ret = memcmp(&e1->deviceid, &e2->deviceid, sizeof(e1->deviceid));
if (ret != 0)
return ret;
if (end_offset(e1->offset, e1->length) < e2->offset)
return -1;
if (e1->offset > end_offset(e2->offset, e2->length))
return 1;
/* If ranges overlap or are contiguous, they are the same */
return 0;
} }
static bool merge_ds_error(struct nfs4_ff_layout_ds_err *old, static void
struct nfs4_ff_layout_ds_err *new)
{
if (!ds_error_can_merge(old, new->offset, new->length, new->status,
new->opnum, &new->stateid, &new->deviceid))
return false;
extend_ds_error(old, new->offset, new->length);
return true;
}
static bool
ff_layout_add_ds_error_locked(struct nfs4_flexfile_layout *flo, ff_layout_add_ds_error_locked(struct nfs4_flexfile_layout *flo,
struct nfs4_ff_layout_ds_err *dserr) struct nfs4_ff_layout_ds_err *dserr)
{ {
struct nfs4_ff_layout_ds_err *err; struct nfs4_ff_layout_ds_err *err, *tmp;
struct list_head *head = &flo->error_list;
int match;
list_for_each_entry(err, &flo->error_list, list) { /* Do insertion sort w/ merges */
if (merge_ds_error(err, dserr)) { list_for_each_entry_safe(err, tmp, &flo->error_list, list) {
return true; match = ff_ds_error_match(err, dserr);
} if (match < 0)
} continue;
if (match > 0) {
list_add(&dserr->list, &flo->error_list); /* Add entry "dserr" _before_ entry "err" */
return false; head = &err->list;
}
static bool
ff_layout_update_ds_error(struct nfs4_flexfile_layout *flo, u64 offset,
u64 length, int status, enum nfs_opnum4 opnum,
nfs4_stateid *stateid, struct nfs4_deviceid *deviceid)
{
bool found = false;
struct nfs4_ff_layout_ds_err *err;
list_for_each_entry(err, &flo->error_list, list) {
if (ds_error_can_merge(err, offset, length, status, opnum,
stateid, deviceid)) {
found = true;
extend_ds_error(err, offset, length);
break; break;
} }
/* Entries match, so merge "err" into "dserr" */
extend_ds_error(dserr, err->offset, err->length);
list_del(&err->list);
kfree(err);
} }
return found; list_add_tail(&dserr->list, head);
} }
int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo, int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo,
@ -283,7 +275,6 @@ int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo,
gfp_t gfp_flags) gfp_t gfp_flags)
{ {
struct nfs4_ff_layout_ds_err *dserr; struct nfs4_ff_layout_ds_err *dserr;
bool needfree;
if (status == 0) if (status == 0)
return 0; return 0;
@ -291,14 +282,6 @@ int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo,
if (mirror->mirror_ds == NULL) if (mirror->mirror_ds == NULL)
return -EINVAL; return -EINVAL;
spin_lock(&flo->generic_hdr.plh_inode->i_lock);
if (ff_layout_update_ds_error(flo, offset, length, status, opnum,
&mirror->stateid,
&mirror->mirror_ds->id_node.deviceid)) {
spin_unlock(&flo->generic_hdr.plh_inode->i_lock);
return 0;
}
spin_unlock(&flo->generic_hdr.plh_inode->i_lock);
dserr = kmalloc(sizeof(*dserr), gfp_flags); dserr = kmalloc(sizeof(*dserr), gfp_flags);
if (!dserr) if (!dserr)
return -ENOMEM; return -ENOMEM;
@ -313,10 +296,8 @@ int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo,
NFS4_DEVICEID4_SIZE); NFS4_DEVICEID4_SIZE);
spin_lock(&flo->generic_hdr.plh_inode->i_lock); spin_lock(&flo->generic_hdr.plh_inode->i_lock);
needfree = ff_layout_add_ds_error_locked(flo, dserr); ff_layout_add_ds_error_locked(flo, dserr);
spin_unlock(&flo->generic_hdr.plh_inode->i_lock); spin_unlock(&flo->generic_hdr.plh_inode->i_lock);
if (needfree)
kfree(dserr);
return 0; return 0;
} }

View File

@ -484,7 +484,7 @@ void nfs_retry_commit(struct list_head *page_list,
struct nfs_commit_info *cinfo, struct nfs_commit_info *cinfo,
u32 ds_commit_idx); u32 ds_commit_idx);
void nfs_commitdata_release(struct nfs_commit_data *data); void nfs_commitdata_release(struct nfs_commit_data *data);
void nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst, void nfs_request_add_commit_list(struct nfs_page *req,
struct nfs_commit_info *cinfo); struct nfs_commit_info *cinfo);
void nfs_request_add_commit_list_locked(struct nfs_page *req, void nfs_request_add_commit_list_locked(struct nfs_page *req,
struct list_head *dst, struct list_head *dst,

View File

@ -830,11 +830,10 @@ EXPORT_SYMBOL_GPL(nfs_request_add_commit_list_locked);
* holding the nfs_page lock. * holding the nfs_page lock.
*/ */
void void
nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst, nfs_request_add_commit_list(struct nfs_page *req, struct nfs_commit_info *cinfo)
struct nfs_commit_info *cinfo)
{ {
spin_lock(cinfo->lock); spin_lock(cinfo->lock);
nfs_request_add_commit_list_locked(req, dst, cinfo); nfs_request_add_commit_list_locked(req, &cinfo->mds->list, cinfo);
spin_unlock(cinfo->lock); spin_unlock(cinfo->lock);
nfs_mark_page_unstable(req->wb_page, cinfo); nfs_mark_page_unstable(req->wb_page, cinfo);
} }
@ -892,7 +891,7 @@ nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg,
{ {
if (pnfs_mark_request_commit(req, lseg, cinfo, ds_commit_idx)) if (pnfs_mark_request_commit(req, lseg, cinfo, ds_commit_idx))
return; return;
nfs_request_add_commit_list(req, &cinfo->mds->list, cinfo); nfs_request_add_commit_list(req, cinfo);
} }
static void static void