Date: Tue, 19 Apr 2011 16:36:25 +0000 (UTC) From: Matthew D Fleming <mdf@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r220846 - head/sys/kern Message-ID: <201104191636.p3JGaPdW014233@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mdf Date: Tue Apr 19 16:36:24 2011 New Revision: 220846 URL: http://svn.freebsd.org/changeset/base/220846 Log: Allow VOP_ALLOCATE to be iterative, and have kern_posix_fallocate(9) drive looping and potentially yielding. Requested by: kib Modified: head/sys/kern/vfs_default.c head/sys/kern/vfs_syscalls.c head/sys/kern/vnode_if.src Modified: head/sys/kern/vfs_default.c ============================================================================== --- head/sys/kern/vfs_default.c Tue Apr 19 16:33:08 2011 (r220845) +++ head/sys/kern/vfs_default.c Tue Apr 19 16:36:24 2011 (r220846) @@ -865,25 +865,25 @@ vop_stdallocate(struct vop_allocate_args struct iovec aiov; struct vattr vattr, *vap; struct uio auio; - off_t len, cur, offset; + off_t fsize, len, cur, offset; uint8_t *buf; struct thread *td; struct vnode *vp; size_t iosize; - int error, locked; + int error; buf = NULL; error = 0; - locked = 1; td = curthread; vap = &vattr; vp = ap->a_vp; - len = ap->a_len; - offset = ap->a_offset; + len = *ap->a_len; + offset = *ap->a_offset; error = VOP_GETATTR(vp, vap, td->td_ucred); if (error != 0) goto out; + fsize = vap->va_size; iosize = vap->va_blocksize; if (iosize == 0) iosize = BLKDEV_IOSIZE; @@ -908,27 +908,22 @@ vop_stdallocate(struct vop_allocate_args } else #endif if (offset + len > vap->va_size) { + /* + * Test offset + len against the filesystem's maxfilesize. + */ VATTR_NULL(vap); vap->va_size = offset + len; error = VOP_SETATTR(vp, vap, td->td_ucred); if (error != 0) goto out; + VATTR_NULL(vap); + vap->va_size = fsize; + error = VOP_SETATTR(vp, vap, td->td_ucred); + if (error != 0) + goto out; } - while (len > 0) { - if (should_yield()) { - VOP_UNLOCK(vp, 0); - locked = 0; - kern_yield(-1); - error = vn_lock(vp, LK_EXCLUSIVE); - if (error != 0) - break; - locked = 1; - error = VOP_GETATTR(vp, vap, td->td_ucred); - if (error != 0) - break; - } - + for (;;) { /* * Read and write back anything below the nominal file * size. There's currently no way outside the filesystem @@ -939,7 +934,7 @@ vop_stdallocate(struct vop_allocate_args cur -= (offset % iosize); if (cur > len) cur = len; - if (offset < vap->va_size) { + if (offset < fsize) { aiov.iov_base = buf; aiov.iov_len = cur; auio.uio_iov = &aiov; @@ -976,12 +971,15 @@ vop_stdallocate(struct vop_allocate_args len -= cur; offset += cur; + if (len == 0) + break; + if (should_yield()) + break; } out: - KASSERT(locked || error != 0, ("How'd I get unlocked with no error?")); - if (locked && error != 0) - VOP_UNLOCK(vp, 0); + *ap->a_len = len; + *ap->a_offset = offset; free(buf, M_TEMP); return (error); } Modified: head/sys/kern/vfs_syscalls.c ============================================================================== --- head/sys/kern/vfs_syscalls.c Tue Apr 19 16:33:08 2011 (r220845) +++ head/sys/kern/vfs_syscalls.c Tue Apr 19 16:36:24 2011 (r220846) @@ -4678,12 +4678,11 @@ kern_posix_fallocate(struct thread *td, struct file *fp; struct mount *mp; struct vnode *vp; - int error, vfslocked, vnlocked; + off_t olen, ooffset; + int error, vfslocked; fp = NULL; - mp = NULL; vfslocked = 0; - vnlocked = 0; error = fget(td, fd, &fp); if (error != 0) goto out; @@ -4718,28 +4717,44 @@ kern_posix_fallocate(struct thread *td, goto out; } - bwillwrite(); - vfslocked = VFS_LOCK_GIANT(vp->v_mount); - error = vn_start_write(vp, &mp, V_WAIT | PCATCH); - if (error != 0) - goto out; - error = vn_lock(vp, LK_EXCLUSIVE); - if (error != 0) - goto out; - vnlocked = 1; + /* Allocating blocks may take a long time, so iterate. */ + for (;;) { + olen = len; + ooffset = offset; + + bwillwrite(); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + mp = NULL; + error = vn_start_write(vp, &mp, V_WAIT | PCATCH); + if (error != 0) { + VFS_UNLOCK_GIANT(vfslocked); + break; + } + error = vn_lock(vp, LK_EXCLUSIVE); + if (error != 0) { + vn_finished_write(mp); + VFS_UNLOCK_GIANT(vfslocked); + break; + } #ifdef MAC - error = mac_vnode_check_write(td->td_ucred, fp->f_cred, vp); - if (error != 0) - goto out; + error = mac_vnode_check_write(td->td_ucred, fp->f_cred, vp); + if (error == 0) #endif - error = VOP_ALLOCATE(vp, offset, len); - if (error != 0) - vnlocked = 0; - out: - if (vnlocked) + error = VOP_ALLOCATE(vp, &offset, &len); VOP_UNLOCK(vp, 0); - vn_finished_write(mp); - VFS_UNLOCK_GIANT(vfslocked); + vn_finished_write(mp); + VFS_UNLOCK_GIANT(vfslocked); + + if (olen + ooffset != offset + len) { + panic("offset + len changed from %jx/%jx to %jx/%jx", + ooffset, olen, offset, len); + } + if (error != 0 || len == 0) + break; + KASSERT(olen > len, ("Iteration did not make progress?")); + maybe_yield(); + } + out: if (fp != NULL) fdrop(fp, td); return (error); Modified: head/sys/kern/vnode_if.src ============================================================================== --- head/sys/kern/vnode_if.src Tue Apr 19 16:33:08 2011 (r220845) +++ head/sys/kern/vnode_if.src Tue Apr 19 16:36:24 2011 (r220846) @@ -621,10 +621,10 @@ vop_vptocnp { }; -%% allocate vp E E U +%% allocate vp E E E vop_allocate { IN struct vnode *vp; - IN off_t offset; - IN off_t len; + IN off_t *offset; + IN off_t *len; };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201104191636.p3JGaPdW014233>