Author: jh
Date: Fri Jan  6 10:12:59 2012
New Revision: 229694
URL: http://svn.freebsd.org/changeset/base/229694

Log:
  r222004 changed sbuf_finish() to not clear the buffer error status. As a
  consequence sbuf_len() will return -1 for buffers which had the error
  status set prior to sbuf_finish() call. This causes a problem in
  pfs_read() which purposely uses a fixed size sbuf to discard bytes which
  are not needed to fulfill the read request.
  
  Work around the problem by using the full buffer length when
  sbuf_finish() indicates an overflow. An overflowed sbuf with fixed size
  is always full.
  
  PR:           kern/163076
  Approved by:  des
  MFC after:    2 weeks

Modified:
  head/sys/fs/pseudofs/pseudofs_vnops.c

Modified: head/sys/fs/pseudofs/pseudofs_vnops.c
==============================================================================
--- head/sys/fs/pseudofs/pseudofs_vnops.c       Fri Jan  6 09:21:40 2012        
(r229693)
+++ head/sys/fs/pseudofs/pseudofs_vnops.c       Fri Jan  6 10:12:59 2012        
(r229694)
@@ -630,14 +630,14 @@ pfs_read(struct vop_read_args *va)
        if (uio->uio_offset < 0 || uio->uio_resid < 0 ||
            (offset = uio->uio_offset) != uio->uio_offset ||
            (resid = uio->uio_resid) != uio->uio_resid ||
-           (buflen = offset + resid + 1) < offset || buflen > INT_MAX) {
+           (buflen = offset + resid) < offset || buflen >= INT_MAX) {
                error = EINVAL;
                goto ret;
        }
-       if (buflen > MAXPHYS + 1)
-               buflen = MAXPHYS + 1;
+       if (buflen > MAXPHYS)
+               buflen = MAXPHYS;
 
-       sb = sbuf_new(sb, NULL, buflen, 0);
+       sb = sbuf_new(sb, NULL, buflen + 1, 0);
        if (sb == NULL) {
                error = EIO;
                goto ret;
@@ -650,8 +650,14 @@ pfs_read(struct vop_read_args *va)
                goto ret;
        }
 
-       sbuf_finish(sb);
-       error = uiomove_frombuf(sbuf_data(sb), sbuf_len(sb), uio);
+       /*
+        * XXX: If the buffer overflowed, sbuf_len() will not return
+        * the data length. Then just use the full length because an
+        * overflowed sbuf must be full.
+        */
+       if (sbuf_finish(sb) == 0)
+               buflen = sbuf_len(sb);
+       error = uiomove_frombuf(sbuf_data(sb), buflen, uio);
        sbuf_delete(sb);
 ret:
        vn_lock(vn, locked | LK_RETRY);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to