mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-28 01:21:58 +00:00
Merge branch 'bugfixes'
* bugfixes: pNFS/flexfiles: Fix an XDR encoding bug in layoutreturn pNFS/flexfiles: Improve merging of errors in LAYOUTRETURN
This commit is contained in:
commit
6d45c042f3
2 changed files with 41 additions and 62 deletions
|
@ -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__);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue