From owner-freebsd-fs@freebsd.org Sun Jun 25 02:03:50 2017 Return-Path: Delivered-To: freebsd-fs@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id A1D0BD8654F for ; Sun, 25 Jun 2017 02:03:50 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from kenobi.freebsd.org (kenobi.freebsd.org [IPv6:2001:1900:2254:206a::16:76]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 7460B7FE92 for ; Sun, 25 Jun 2017 02:03:50 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from bugs.freebsd.org ([127.0.1.118]) by kenobi.freebsd.org (8.15.2/8.15.2) with ESMTP id v5P23oR8054320 for ; Sun, 25 Jun 2017 02:03:50 GMT (envelope-from bugzilla-noreply@freebsd.org) From: bugzilla-noreply@freebsd.org To: freebsd-fs@FreeBSD.org Subject: [Bug 220185] >> operator does not append in Fuse mounts Date: Sun, 25 Jun 2017 02:03:50 +0000 X-Bugzilla-Reason: AssignedTo X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: Base System X-Bugzilla-Component: kern X-Bugzilla-Version: CURRENT X-Bugzilla-Keywords: X-Bugzilla-Severity: Affects Many People X-Bugzilla-Who: cem@freebsd.org X-Bugzilla-Status: In Progress X-Bugzilla-Resolution: X-Bugzilla-Priority: --- X-Bugzilla-Assigned-To: cem@freebsd.org X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: assigned_to bug_status Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: https://bugs.freebsd.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: freebsd-fs@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Filesystems List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 25 Jun 2017 02:03:50 -0000 https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D220185 Conrad Meyer changed: What |Removed |Added ---------------------------------------------------------------------------- Assignee|freebsd-fs@FreeBSD.org |cem@freebsd.org Status|New |In Progress --- Comment #1 from Conrad Meyer --- I can reproduce this problem with lklfuse (ext4 image). Exact same steps as Ben provided. $ truss sh -c 'echo line4 >> test.txt' ... openat(AT_FDCWD,"test.txt",O_WRONLY|O_APPEND|O_CREAT,0666) =3D 3 (0x3) dup2(0x3,0x1) =3D 1 (0x1) close(3) =3D 0 (0x0) write(1,"line4\n",6) =3D 6 (0x6) >From lklfuse -o debug: unique: 2, opcode: LOOKUP (1), nodeid: 1, insize: 49, pid: 7005 LOOKUP /test.txt getattr /test.txt NODEID: 2 unique: 2, success, outsize: 136 unique: 3, opcode: OPEN (14), nodeid: 2, insize: 48, pid: 7005 open flags: 0x1 /test.txt open[0] flags: 0x1 /test.txt unique: 3, success, outsize: 32 // Flag 0x1 =3D=3D O_WRONLY. I'm not sure if FUSE clients are supposed to handle O_APPEND or if FUSE is supposed to emulate it on their behalf. Either way, it seems to be getting dropped. That said =E2=80=94 it doesn't look like UFS does anything specia= l with the APPEND flag either. After all, multiple file handles can reference the same vnode at different offsets. So the offset should be a property of the file handle, not the vnode. This suggests some higher layer is misbehaving; not individual FUSE filesystems. (Not really surprising, I know.) More from lklfuse -o debug: unique: 4, opcode: GETATTR (3), nodeid: 2, insize: 40, pid: 7005 getattr /test.txt unique: 4, success, outsize: 112 unique: 5, opcode: WRITE (16), nodeid: 2, insize: 70, pid: 7005 write[0] 6 bytes to 0 flags: 0x0 write[0] 6 bytes to 0 unique: 5, success, outsize: 24 // Note: "to 0" (offset 0), "flags: 0x0" (no IO_APPEND) That's a problem. kern_openat() installs O_APPEND from open(2) into the struct file referring= to test.txt. Then in vn_write(), f_flag means that ioflag has IO_APPEND added= .=20 This is passed into VOP_WRITE. What does fs/fuse do with that? Well, there's a check in fuse_write_biobackend() that sets the uio offset to the end of the file if that flag is present. Either we aren't hitting that path, or the uio's offset isn't getting communicated to fuse filesystems. VOP_WRITE -> fuse_vnop_write -> fuse_iop_dispatch(). From there we enter fuse_write_directbackend for IO_DIRECT uio's, or fuse_write_biobackend otherwise. The DIRECT backend completely ignores IO_APPEND. I'd guess we're not hitti= ng that path as the open did not use O_DIRECT. I'm pretty confused by what fuse_write_biobackend() is doing, but it looks = like it may be correct. Maybe we're seeing the DIRECT path. ...haha, yup. fuse_vnop_open(): 1147 /* 1148 * For WRONLY opens, force DIRECT_IO. This is necessa= ry 1149 * since writing a partial block through the buffer ca= che 1150 * will result in a read of the block and that read wo= n't 1151 * be allowed by the WRONLY open. 1152 */ 1153 if (fufh_type =3D=3D FUFH_WRONLY || 1154 (fvdat->flag & FN_DIRECTIO) !=3D 0) 1155 fuse_open_flags =3D FOPEN_DIRECT_IO; Sigh. --=20 You are receiving this mail because: You are the assignee for the bug.=