Buffer locking code failed to use BUF_KERNPROC and BUF_UNLOCK and
BUF_LOCKFREE a buffer prior to physically freeing it. While these bugs did not cause a crash, they might in the future. Added eof handling for unlabeled partitions. Submitted by: Tor.Egge@fast.no
This commit is contained in:
parent
889c1efb8d
commit
74427f90f2
@ -254,6 +254,7 @@ getccdbuf(struct ccdbuf *cpy)
|
|||||||
LIST_INIT(&cbp->cb_buf.b_dep);
|
LIST_INIT(&cbp->cb_buf.b_dep);
|
||||||
BUF_LOCKINIT(&cbp->cb_buf);
|
BUF_LOCKINIT(&cbp->cb_buf);
|
||||||
BUF_LOCK(&cbp->cb_buf, LK_EXCLUSIVE);
|
BUF_LOCK(&cbp->cb_buf, LK_EXCLUSIVE);
|
||||||
|
BUF_KERNPROC(&cbp->cb_buf);
|
||||||
|
|
||||||
return(cbp);
|
return(cbp);
|
||||||
}
|
}
|
||||||
@ -268,6 +269,9 @@ static __inline
|
|||||||
void
|
void
|
||||||
putccdbuf(struct ccdbuf *cbp)
|
putccdbuf(struct ccdbuf *cbp)
|
||||||
{
|
{
|
||||||
|
BUF_UNLOCK(&cbp->cb_buf);
|
||||||
|
BUF_LOCKFREE(&cbp->cb_buf);
|
||||||
|
|
||||||
if (numccdfreebufs < NCCDFREEHIWAT) {
|
if (numccdfreebufs < NCCDFREEHIWAT) {
|
||||||
cbp->cb_freenext = ccdfreebufs;
|
cbp->cb_freenext = ccdfreebufs;
|
||||||
ccdfreebufs = cbp;
|
ccdfreebufs = cbp;
|
||||||
@ -812,9 +816,38 @@ ccdstrategy(bp)
|
|||||||
* error, the bounds check will flag that for us.
|
* error, the bounds check will flag that for us.
|
||||||
*/
|
*/
|
||||||
wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING);
|
wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING);
|
||||||
if (ccdpart(bp->b_dev) != RAW_PART)
|
if (ccdpart(bp->b_dev) != RAW_PART) {
|
||||||
if (bounds_check_with_label(bp, lp, wlabel) <= 0)
|
if (bounds_check_with_label(bp, lp, wlabel) <= 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
} else {
|
||||||
|
int pbn; /* in sc_secsize chunks */
|
||||||
|
long sz; /* in sc_secsize chunks */
|
||||||
|
|
||||||
|
pbn = bp->b_blkno / (cs->sc_geom.ccg_secsize / DEV_BSIZE);
|
||||||
|
sz = howmany(bp->b_bcount, cs->sc_geom.ccg_secsize);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If out of bounds return an error. If at the EOF point,
|
||||||
|
* simply read or write less.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (pbn < 0 || pbn >= cs->sc_size) {
|
||||||
|
bp->b_resid = bp->b_bcount;
|
||||||
|
if (pbn != cs->sc_size) {
|
||||||
|
bp->b_error = EINVAL;
|
||||||
|
bp->b_flags |= B_ERROR | B_INVAL;
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the request crosses EOF, truncate the request.
|
||||||
|
*/
|
||||||
|
if (pbn + sz > cs->sc_size) {
|
||||||
|
bp->b_bcount = (cs->sc_size - pbn) *
|
||||||
|
cs->sc_geom.ccg_secsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bp->b_resid = bp->b_bcount;
|
bp->b_resid = bp->b_bcount;
|
||||||
|
|
||||||
|
@ -254,6 +254,7 @@ getccdbuf(struct ccdbuf *cpy)
|
|||||||
LIST_INIT(&cbp->cb_buf.b_dep);
|
LIST_INIT(&cbp->cb_buf.b_dep);
|
||||||
BUF_LOCKINIT(&cbp->cb_buf);
|
BUF_LOCKINIT(&cbp->cb_buf);
|
||||||
BUF_LOCK(&cbp->cb_buf, LK_EXCLUSIVE);
|
BUF_LOCK(&cbp->cb_buf, LK_EXCLUSIVE);
|
||||||
|
BUF_KERNPROC(&cbp->cb_buf);
|
||||||
|
|
||||||
return(cbp);
|
return(cbp);
|
||||||
}
|
}
|
||||||
@ -268,6 +269,9 @@ static __inline
|
|||||||
void
|
void
|
||||||
putccdbuf(struct ccdbuf *cbp)
|
putccdbuf(struct ccdbuf *cbp)
|
||||||
{
|
{
|
||||||
|
BUF_UNLOCK(&cbp->cb_buf);
|
||||||
|
BUF_LOCKFREE(&cbp->cb_buf);
|
||||||
|
|
||||||
if (numccdfreebufs < NCCDFREEHIWAT) {
|
if (numccdfreebufs < NCCDFREEHIWAT) {
|
||||||
cbp->cb_freenext = ccdfreebufs;
|
cbp->cb_freenext = ccdfreebufs;
|
||||||
ccdfreebufs = cbp;
|
ccdfreebufs = cbp;
|
||||||
@ -812,9 +816,38 @@ ccdstrategy(bp)
|
|||||||
* error, the bounds check will flag that for us.
|
* error, the bounds check will flag that for us.
|
||||||
*/
|
*/
|
||||||
wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING);
|
wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING);
|
||||||
if (ccdpart(bp->b_dev) != RAW_PART)
|
if (ccdpart(bp->b_dev) != RAW_PART) {
|
||||||
if (bounds_check_with_label(bp, lp, wlabel) <= 0)
|
if (bounds_check_with_label(bp, lp, wlabel) <= 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
} else {
|
||||||
|
int pbn; /* in sc_secsize chunks */
|
||||||
|
long sz; /* in sc_secsize chunks */
|
||||||
|
|
||||||
|
pbn = bp->b_blkno / (cs->sc_geom.ccg_secsize / DEV_BSIZE);
|
||||||
|
sz = howmany(bp->b_bcount, cs->sc_geom.ccg_secsize);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If out of bounds return an error. If at the EOF point,
|
||||||
|
* simply read or write less.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (pbn < 0 || pbn >= cs->sc_size) {
|
||||||
|
bp->b_resid = bp->b_bcount;
|
||||||
|
if (pbn != cs->sc_size) {
|
||||||
|
bp->b_error = EINVAL;
|
||||||
|
bp->b_flags |= B_ERROR | B_INVAL;
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the request crosses EOF, truncate the request.
|
||||||
|
*/
|
||||||
|
if (pbn + sz > cs->sc_size) {
|
||||||
|
bp->b_bcount = (cs->sc_size - pbn) *
|
||||||
|
cs->sc_geom.ccg_secsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bp->b_resid = bp->b_bcount;
|
bp->b_resid = bp->b_bcount;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user