# HG changeset patch # Parent 7f3784f20b127203ae2daea5ddece04c413016c8 Implement spec_fdiscard() using bdev_discard() and cdev_discard(). Also define spec_fallocate() to genfs_eopnotsupp(). diff -r 7f3784f20b12 sys/miscfs/specfs/spec_vnops.c --- a/sys/miscfs/specfs/spec_vnops.c Sun Mar 23 02:54:19 2014 -0400 +++ b/sys/miscfs/specfs/spec_vnops.c Sun Mar 23 03:02:37 2014 -0400 @@ -839,6 +839,49 @@ } /* + * fdiscard, which on disk devices becomes TRIM. + */ +int +spec_fdiscard(void *v) +{ + struct vop_fdiscard_args /* { + struct vnode *a_vp; + off_t a_pos; + off_t a_len; + } */ *ap = v; + struct vnode *vp; + dev_t dev; + + vp = ap->a_vp; + dev = NODEV; + + /* XXX: gross. Is this what we want and is it safe enough? blah */ + VOP_UNLOCK(vp); + mutex_enter(vp->v_interlock); + if ((vp->v_iflag & VI_XLOCK) == 0 && vp->v_specnode != NULL) { + dev = vp->v_rdev; + } + mutex_exit(vp->v_interlock); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + + if (dev == NODEV) { + return ENXIO; + } + + switch (vp->v_type) { + case VCHR: + // this is not stored for character devices + //KASSERT(vp == vp->v_specnode->sn_dev->sd_cdevvp); + return cdev_discard(dev, ap->a_pos, ap->a_len); + case VBLK: + KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp); + return bdev_discard(dev, ap->a_pos, ap->a_len); + default: + panic("spec_fdiscard: not a device\n"); + } +} + +/* * Device ioctl operation. */ /* ARGSUSED */ diff -r 7f3784f20b12 sys/miscfs/specfs/specdev.h --- a/sys/miscfs/specfs/specdev.h Sun Mar 23 02:54:19 2014 -0400 +++ b/sys/miscfs/specfs/specdev.h Sun Mar 23 03:02:37 2014 -0400 @@ -119,6 +119,8 @@ #define spec_setattr genfs_ebadf int spec_read(void *); int spec_write(void *); +#define spec_fallocate genfs_eopnotsupp +int spec_fdiscard(void *); #define spec_fcntl genfs_fcntl int spec_ioctl(void *); int spec_poll(void *);