Author: kib
Date: Sat May 26 05:28:47 2012
New Revision: 236043
URL: http://svn.freebsd.org/changeset/base/236043

Log:
  Add a vn_bmap_seekhole(9) vnode helper which can be used by any
  filesystem which supports VOP_BMAP(9) to implement SEEK_HOLE/SEEK_DATA
  commands for lseek(2).
  
  MFC after:    2 weeks

Modified:
  head/sys/kern/vfs_vnops.c
  head/sys/sys/vnode.h

Modified: head/sys/kern/vfs_vnops.c
==============================================================================
--- head/sys/kern/vfs_vnops.c   Sat May 26 05:25:55 2012        (r236042)
+++ head/sys/kern/vfs_vnops.c   Sat May 26 05:28:47 2012        (r236043)
@@ -1466,3 +1466,56 @@ vn_pages_remove(struct vnode *vp, vm_pin
        vm_object_page_remove(object, start, end, 0);
        VM_OBJECT_UNLOCK(object);
 }
+
+int
+vn_bmap_seekhole(struct vnode *vp, u_long cmd, off_t *off, struct ucred *cred)
+{
+       struct vattr va;
+       daddr_t bn, bnp;
+       uint64_t bsize;
+       off_t noff;
+       int error;
+
+       KASSERT(cmd == FIOSEEKHOLE || cmd == FIOSEEKDATA,
+           ("Wrong command %lu", cmd));
+
+       if (vn_lock(vp, LK_SHARED) != 0)
+               return (EBADF);
+       if (vp->v_type != VREG) {
+               error = ENOTTY;
+               goto unlock;
+       }
+       error = VOP_GETATTR(vp, &va, cred);
+       if (error != 0)
+               goto unlock;
+       noff = *off;
+       if (noff >= va.va_size) {
+               error = ENXIO;
+               goto unlock;
+       }
+       bsize = vp->v_mount->mnt_stat.f_iosize;
+       for (bn = noff / bsize; noff < va.va_size; bn++, noff += bsize) {
+               error = VOP_BMAP(vp, bn, NULL, &bnp, NULL, NULL);
+               if (error == EOPNOTSUPP) {
+                       error = ENOTTY;
+                       goto unlock;
+               }
+               if ((bnp == -1 && cmd == FIOSEEKHOLE) ||
+                   (bnp != -1 && cmd == FIOSEEKDATA)) {
+                       noff = bn * bsize;
+                       if (noff < *off)
+                               noff = *off;
+                       goto unlock;
+               }
+       }
+       if (noff > va.va_size)
+               noff = va.va_size;
+       /* noff == va.va_size. There is an implicit hole at the end of file. */
+       if (cmd == FIOSEEKDATA)
+               error = ENXIO;
+unlock:
+       VOP_UNLOCK(vp, 0);
+       if (error == 0)
+               *off = noff;
+       return (error);
+}

Modified: head/sys/sys/vnode.h
==============================================================================
--- head/sys/sys/vnode.h        Sat May 26 05:25:55 2012        (r236042)
+++ head/sys/sys/vnode.h        Sat May 26 05:28:47 2012        (r236043)
@@ -640,6 +640,8 @@ void        vunref(struct vnode *);
 void   vn_printf(struct vnode *vp, const char *fmt, ...) __printflike(2,3);
 #define vprint(label, vp) vn_printf((vp), "%s\n", (label))
 int    vrecycle(struct vnode *vp);
+int    vn_bmap_seekhole(struct vnode *vp, u_long cmd, off_t *off,
+           struct ucred *cred);
 int    vn_close(struct vnode *vp,
            int flags, struct ucred *file_cred, struct thread *td);
 void   vn_finished_write(struct mount *mp);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to