--- sys/dev/md/md.c 2006/12/14 11:36:47 +++ sys/dev/md/md.c 2007/02/03 00:33:55 @@ -609,15 +609,14 @@ for (i = bp->bio_offset / PAGE_SIZE; i <= lastp; i++) { len = ((i == lastp) ? lastend : PAGE_SIZE) - offs; - m = vm_page_grab(sc->object, i, - VM_ALLOC_NORMAL|VM_ALLOC_RETRY); + m = vm_page_grab(sc->object, i, VM_ALLOC_NORMAL|VM_ALLOC_RETRY); VM_OBJECT_UNLOCK(sc->object); sched_pin(); sf = sf_buf_alloc(m, SFB_CPUPRIVATE); VM_OBJECT_LOCK(sc->object); - if (bp->bio_cmd == BIO_READ) { - if (m->valid != VM_PAGE_BITS_ALL) - rv = vm_pager_get_pages(sc->object, &m, 1, 0); + if ((bp->bio_cmd == BIO_READ || len != PAGE_SIZE) && + m->valid != VM_PAGE_BITS_ALL) { + rv = vm_pager_get_pages(sc->object, &m, 1, 0); if (rv == VM_PAGER_ERROR) { sf_buf_free(sf); sched_unpin(); @@ -626,44 +625,47 @@ vm_page_unlock_queues(); break; } + } + switch (bp->bio_cmd) { + case BIO_READ: bcopy((void *)(sf_buf_kva(sf) + offs), p, len); - } else if (bp->bio_cmd == BIO_WRITE) { - if (len != PAGE_SIZE && m->valid != VM_PAGE_BITS_ALL) - rv = vm_pager_get_pages(sc->object, &m, 1, 0); - if (rv == VM_PAGER_ERROR) { - sf_buf_free(sf); - sched_unpin(); - vm_page_lock_queues(); - vm_page_wakeup(m); - vm_page_unlock_queues(); - break; - } + break; + case BIO_WRITE: bcopy(p, (void *)(sf_buf_kva(sf) + offs), len); m->valid = VM_PAGE_BITS_ALL; -#if 0 - } else if (bp->bio_cmd == BIO_DELETE) { - if (len != PAGE_SIZE && m->valid != VM_PAGE_BITS_ALL) - rv = vm_pager_get_pages(sc->object, &m, 1, 0); - if (rv == VM_PAGER_ERROR) { - sf_buf_free(sf); - sched_unpin(); - vm_page_lock_queues(); - vm_page_wakeup(m); - vm_page_unlock_queues(); - break; - } + break; + case BIO_DELETE: bzero((void *)(sf_buf_kva(sf) + offs), len); - vm_page_dirty(m); - m->valid = VM_PAGE_BITS_ALL; -#endif + break; } sf_buf_free(sf); sched_unpin(); vm_page_lock_queues(); - vm_page_wakeup(m); - vm_page_activate(m); - if (bp->bio_cmd == BIO_WRITE) + switch (bp->bio_cmd) { + case BIO_READ: + vm_page_wakeup(m); + vm_page_activate(m); + break; + case BIO_WRITE: + vm_page_wakeup(m); + vm_page_activate(m); vm_page_dirty(m); + break; + case BIO_DELETE: +#if 0 + vm_page_set_invalid(m, offs, len); + if (m->valid != 0) { + vm_page_wakeup(m); + vm_page_activate(m); + } else { +#endif + vm_pager_page_unswapped(m); + vm_page_free(m); +#if 0 + } +#endif + break; + } vm_page_unlock_queues(); /* Actions on further pages start at offset 0 */ --- sys/geom/geom.h 2006/10/31 21:16:32 +++ sys/geom/geom.h 2007/02/01 08:46:18 @@ -274,6 +274,7 @@ struct bio *g_alloc_bio(void); void * g_read_data(struct g_consumer *cp, off_t offset, off_t length, int *error); int g_write_data(struct g_consumer *cp, off_t offset, void *ptr, off_t length); +int g_delete_data(struct g_consumer *cp, off_t offset, off_t length); void g_print_bio(struct bio *bp); /* geom_kern.c / geom_kernsim.c */ @@ -286,6 +287,10 @@ off_t offset; off_t length; }; +struct g_delete { + off_t offset; + off_t length; +}; MALLOC_DECLARE(M_GEOM); --- sys/geom/geom_dev.c 2006/06/18 22:01:39 +++ sys/geom/geom_dev.c 2007/02/01 09:02:09 @@ -253,6 +253,7 @@ struct g_geom *gp; struct g_consumer *cp; struct g_kerneldump kd; + struct g_delete *del; int i, error; u_int u; @@ -302,6 +303,19 @@ if (!error) dev->si_flags |= SI_DUMPDEV; break; + case DIOCGFLUSH: + error = g_io_flush(cp); + break; + case DIOCGDELETE: + del = (struct g_delete *)data; + if ((del->offset % cp->provider->sectorsize) != 0 || + (del->length % cp->provider->sectorsize) != 0 || + del->length <= 0 || del->length > MAXPHYS) { + error = EINVAL; + break; + } + error = g_delete_data(cp, del->offset, del->length); + break; default: if (cp->provider->geom->ioctl != NULL) { --- sys/geom/geom_io.c 2007/01/28 23:41:05 +++ sys/geom/geom_io.c 2007/02/01 08:40:42 @@ -646,6 +646,28 @@ return (error); } +int +g_delete_data(struct g_consumer *cp, off_t offset, off_t length) +{ + struct bio *bp; + int error; + + KASSERT(length > 0 && length >= cp->provider->sectorsize && + length <= MAXPHYS, ("g_delete_data(): invalid length %jd", + (intmax_t)length)); + + bp = g_alloc_bio(); + bp->bio_cmd = BIO_DELETE; + bp->bio_done = NULL; + bp->bio_offset = offset; + bp->bio_length = length; + bp->bio_data = NULL; + g_io_request(bp, cp); + error = biowait(bp, "gdelete"); + g_destroy_bio(bp); + return (error); +} + void g_print_bio(struct bio *bp) { --- sys/sys/disk.h 2006/03/11 10:35:20 +++ sys/sys/disk.h 2007/02/01 10:36:16 @@ -57,7 +57,7 @@ * Enable/Disable (the argument is boolean) the device for kernel * core dumps. */ - + #define DIOCGFRONTSTUFF _IOR('d', 134, off_t) /*- * Many disk formats have some amount of space reserved at the @@ -66,4 +66,18 @@ * which may apply to the device. */ +#define DIOCGFLUSH _IO('d', 135) /* Flush write cache */ + /*- + * Flush write cache of the device. + */ + +struct g_offlen { + off_t offset; + off_t length; +}; +#define DIOCGDELETE _IOW('d', 136, struct g_offlen) /* Delete data */ + /*- + * Mark data on the device as unused. + */ + #endif /* _SYS_DISK_H_ */ --- sys/ufs/ffs/ffs_alloc.c 2007/01/20 12:02:48 +++ sys/ufs/ffs/ffs_alloc.c 2007/01/28 04:13:44 @@ -79,6 +79,8 @@ #include #include +#include + #include #include #include @@ -1809,7 +1811,7 @@ struct buf *bp; ufs1_daddr_t fragno, cgbno; ufs2_daddr_t cgblkno; - int i, cg, blk, frags, bbase; + int i, cg, blk, frags, bbase, error; u_int8_t *blksfree; struct cdev *dev; @@ -1920,6 +1922,9 @@ ACTIVECLEAR(fs, cg); UFS_UNLOCK(ump); bdwrite(bp); + error = g_delete_data(ump->um_cp, bno * fs->fs_fsize, size); + if (error != 0 && error != EOPNOTSUPP) + ffs_fserr(fs, inum, "cannot delete data"); } #ifdef DIAGNOSTIC