Implement BIO_DELETE for vnode devices by simply overwriting the deleted
sectors with all-zeroes. The zeroes come from a static buffer; null(4) uses a dynamic buffer for the same purpose (for /dev/zero). It might be a good idea to have a static, shared, read-only all-zeroes page somewhere in the kernel that md(4), null(4) and any other code that needs zeroes could use. Reviewed by: kib MFC after: 3 weeks
This commit is contained in:
parent
1d29baf81e
commit
0abd21bdb8
@ -205,6 +205,9 @@ struct md_s {
|
||||
vm_object_t object;
|
||||
};
|
||||
|
||||
/* Used for BIO_DELETE on MD_VNODE */
|
||||
static u_char zero[PAGE_SIZE];
|
||||
|
||||
static struct indir *
|
||||
new_indir(u_int shift)
|
||||
{
|
||||
@ -514,10 +517,12 @@ mdstart_vnode(struct md_s *sc, struct bio *bp)
|
||||
struct mount *mp;
|
||||
struct vnode *vp;
|
||||
struct thread *td;
|
||||
off_t end, zerosize;
|
||||
|
||||
switch (bp->bio_cmd) {
|
||||
case BIO_READ:
|
||||
case BIO_WRITE:
|
||||
case BIO_DELETE:
|
||||
case BIO_FLUSH:
|
||||
break;
|
||||
default:
|
||||
@ -548,6 +553,43 @@ mdstart_vnode(struct md_s *sc, struct bio *bp)
|
||||
|
||||
bzero(&auio, sizeof(auio));
|
||||
|
||||
/*
|
||||
* Special case for BIO_DELETE. On the surface, this is very
|
||||
* similar to BIO_WRITE, except that we write from our own
|
||||
* fixed-length buffer, so we have to loop. The net result is
|
||||
* that the two cases end up having very little in common.
|
||||
*/
|
||||
if (bp->bio_cmd == BIO_DELETE) {
|
||||
zerosize = sizeof(zero) - (sizeof(zero) % sc->sectorsize);
|
||||
auio.uio_iov = &aiov;
|
||||
auio.uio_iovcnt = 1;
|
||||
auio.uio_offset = (vm_ooffset_t)bp->bio_offset;
|
||||
auio.uio_segflg = UIO_SYSSPACE;
|
||||
auio.uio_rw = UIO_WRITE;
|
||||
auio.uio_td = td;
|
||||
end = bp->bio_offset + bp->bio_length;
|
||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||
(void) vn_start_write(vp, &mp, V_WAIT);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
||||
error = 0;
|
||||
while (auio.uio_offset < end) {
|
||||
aiov.iov_base = zero;
|
||||
aiov.iov_len = end - auio.uio_offset;
|
||||
if (aiov.iov_len > zerosize)
|
||||
aiov.iov_len = zerosize;
|
||||
auio.uio_resid = aiov.iov_len;
|
||||
error = VOP_WRITE(vp, &auio,
|
||||
sc->flags & MD_ASYNC ? 0 : IO_SYNC, sc->cred);
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
VOP_UNLOCK(vp, 0);
|
||||
vn_finished_write(mp);
|
||||
bp->bio_resid = end - auio.uio_offset;
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
return (error);
|
||||
}
|
||||
|
||||
aiov.iov_base = bp->bio_data;
|
||||
aiov.iov_len = bp->bio_length;
|
||||
auio.uio_iov = &aiov;
|
||||
|
Loading…
Reference in New Issue
Block a user