Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src For devices, sockets and fifos ignore setting the file size ...



details:   https://anonhg.NetBSD.org/src/rev/134a67e0e428
branches:  trunk
changeset: 768164:134a67e0e428
user:      hannken <hannken%NetBSD.org@localhost>
date:      Wed Aug 10 06:27:02 2011 +0000

description:
For devices, sockets and fifos ignore setting the file size to zero to make
open(..., O_TRUNC) happy and allow them to write through the lower layer.

Fixes PR #43560 (writing to null device in unionfs fails)

diffstat:

 sys/fs/union/union_vnops.c |  55 ++++++++++++++++++++++++++++++++++++---------
 tests/fs/union/t_pr.c      |  24 +++++++++----------
 2 files changed, 55 insertions(+), 24 deletions(-)

diffs (166 lines):

diff -r bdc230317911 -r 134a67e0e428 sys/fs/union/union_vnops.c
--- a/sys/fs/union/union_vnops.c        Wed Aug 10 06:19:54 2011 +0000
+++ b/sys/fs/union/union_vnops.c        Wed Aug 10 06:27:02 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: union_vnops.c,v 1.42 2011/08/07 06:01:51 hannken Exp $ */
+/*     $NetBSD: union_vnops.c,v 1.43 2011/08/10 06:27:02 hannken Exp $ */
 
 /*
  * Copyright (c) 1992, 1993, 1994, 1995
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.42 2011/08/07 06:01:51 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.43 2011/08/10 06:27:02 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -888,12 +888,14 @@
        struct vattr *vap = ap->a_vap;
        struct vnode *vp = ap->a_vp;
        struct union_node *un = VTOUNION(vp);
+       bool size_only;         /* All but va_size are VNOVAL. */
        int error;
 
-       if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
-           vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
-           vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
-           (vp->v_mount->mnt_flag & MNT_RDONLY))
+       size_only = (vap->va_flags == VNOVAL && vap->va_uid == (uid_t)VNOVAL &&
+           vap->va_gid == (gid_t)VNOVAL && vap->va_atime.tv_sec == VNOVAL &&
+           vap->va_mtime.tv_sec == VNOVAL && vap->va_mode == (mode_t)VNOVAL);
+
+       if (!size_only && (vp->v_mount->mnt_flag & MNT_RDONLY))
                return (EROFS);
        if (vap->va_size != VNOVAL) {
                switch (vp->v_type) {
@@ -931,8 +933,9 @@
        }
 
        /*
-        * Try to set attributes in upper layer,
-        * otherwise return read-only filesystem error.
+        * Try to set attributes in upper layer, ignore size change to zero
+        * for devices to handle O_TRUNC and return read-only filesystem error
+        * otherwise.
         */
        if (un->un_uppervp != NULLVP) {
                FIXUP(un);
@@ -940,7 +943,22 @@
                if ((error == 0) && (vap->va_size != VNOVAL))
                        union_newsize(ap->a_vp, vap->va_size, VNOVAL);
        } else {
-               error = EROFS;
+               KASSERT(un->un_lowervp != NULLVP);
+               switch (un->un_lowervp->v_type) {
+               case VCHR:
+               case VBLK:
+               case VSOCK:
+               case VFIFO:
+                       if (size_only &&
+                           (vap->va_size == 0 || vap->va_size == VNOVAL))
+                               error = 0;
+                       else
+                               error = EROFS;
+                       break;
+               default:
+                       error = EROFS;
+                       break;
+               }
        }
 
        return (error);
@@ -1003,8 +1021,23 @@
        struct union_node *un = VTOUNION(ap->a_vp);
 
        vp = UPPERVP(ap->a_vp);
-       if (vp == NULLVP)
-               panic("union: missing upper layer in write");
+       if (vp == NULLVP) {
+               vp = LOWERVP(ap->a_vp);
+               KASSERT(vp != NULL);
+               switch (vp->v_type) {
+               case VBLK:
+               case VCHR:
+               case VSOCK:
+               case VFIFO:
+                       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+                       error = VOP_WRITE(vp, ap->a_uio, ap->a_ioflag,
+                           ap->a_cred);
+                       VOP_UNLOCK(vp);
+                       return error;
+               default:
+                       panic("union: missing upper layer in write");
+               }
+       }
 
        FIXUP(un);
        error = VOP_WRITE(vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
diff -r bdc230317911 -r 134a67e0e428 tests/fs/union/t_pr.c
--- a/tests/fs/union/t_pr.c     Wed Aug 10 06:19:54 2011 +0000
+++ b/tests/fs/union/t_pr.c     Wed Aug 10 06:27:02 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: t_pr.c,v 1.7 2010/07/03 13:37:22 pooka Exp $   */
+/*     $NetBSD: t_pr.c,v 1.8 2011/08/10 06:27:02 hannken Exp $ */
 
 #include <sys/types.h>
 #include <sys/mount.h>
@@ -50,7 +50,6 @@
        unionargs.target = __UNCONST("/Tunion2/B");
        unionargs.mntflags = UNMNT_BELOW;
 
-       /* atf_tc_expect_signal(-1, "PR kern/23986"); */
        rump_sys_mount(MOUNT_UNION, "/Tunion", 0,&unionargs,sizeof(unionargs));
 }
 
@@ -64,7 +63,7 @@
 ATF_TC_BODY(devnull1, tc)
 {
        struct union_args unionargs;
-       int fd;
+       int fd, res;
 
        rump_init();
 
@@ -80,14 +79,12 @@
 
        fd = rump_sys_open("/mp/null", O_WRONLY | O_CREAT | O_TRUNC);
 
-       atf_tc_expect_fail("PR kern/43560");
-       if (fd == -1 && errno == EROFS) {
-               atf_tc_fail("open returned EROFS");
-       } else if (fd == -1) {
-               atf_tc_expect_pass();
-               atf_tc_fail_errno("open fail");
-       }
+       if (fd == -1)
+               atf_tc_fail_errno("open");
 
+       res = rump_sys_write(fd, &fd, sizeof(fd));
+       if (res != sizeof(fd))
+               atf_tc_fail("write");
 }
 
 ATF_TC(devnull2);
@@ -100,7 +97,7 @@
 ATF_TC_BODY(devnull2, tc)
 {
        struct union_args unionargs;
-       int fd;
+       int fd, res;
 
        rump_init();
 
@@ -118,8 +115,9 @@
        if (fd == -1)
                atf_tc_fail_errno("open");
 
-       atf_tc_expect_signal(-1, "PR kern/43560");
-       rump_sys_write(fd, &fd, sizeof(fd));
+       res = rump_sys_write(fd, &fd, sizeof(fd));
+       if (res != sizeof(fd))
+               atf_tc_fail("write");
 }
 
 ATF_TP_ADD_TCS(tp)



Home | Main Index | Thread Index | Old Index