From owner-freebsd-bugs@FreeBSD.ORG Wed Sep 29 17:50:01 2010 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 98D701065674 for ; Wed, 29 Sep 2010 17:50:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 5B7228FC13 for ; Wed, 29 Sep 2010 17:50:01 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id o8THo18t099387 for ; Wed, 29 Sep 2010 17:50:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id o8THo1mW099386; Wed, 29 Sep 2010 17:50:01 GMT (envelope-from gnats) Resent-Date: Wed, 29 Sep 2010 17:50:01 GMT Resent-Message-Id: <201009291750.o8THo1mW099386@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Michael Naef Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id AD16F1065696 for ; Wed, 29 Sep 2010 17:41:38 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 9C1048FC17 for ; Wed, 29 Sep 2010 17:41:38 +0000 (UTC) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id o8THfcqt047398 for ; Wed, 29 Sep 2010 17:41:38 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id o8THfcJf047397; Wed, 29 Sep 2010 17:41:38 GMT (envelope-from nobody) Message-Id: <201009291741.o8THfcJf047397@www.freebsd.org> Date: Wed, 29 Sep 2010 17:41:38 GMT From: Michael Naef To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/151082: [patch] sappend-flaged files on ZFS not working correctly X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 29 Sep 2010 17:50:01 -0000 >Number: 151082 >Category: kern >Synopsis: [patch] sappend-flaged files on ZFS not working correctly >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Sep 29 17:50:00 UTC 2010 >Closed-Date: >Last-Modified: >Originator: Michael Naef >Release: FreeBSD 8.1 >Organization: >Environment: FreeBSD server2 8.1-RELEASE FreeBSD 8.1-RELEASE #1: Thu Aug 26 11:16:20 UTC 2010 root@port8:/usr/obj/usr/src/sys/HOSTPOINT-WEB-SH amd64 >Description: Background: When moving from pre-8.0 to FreeBSD 8.1 on ZFS I realised that the bash history is no longer beeing written if the file has the sappend flag set. Other programs like script (1) however are surprisingly still able to write to such files. So it seemed that they handle file IO differently. (Looking at the source code of both I learned that bash uses write (2) while script uses fwrite (3)... After some more testing and investigation,) it seems that zfs behaves differently to ufs in one point. If I open (2) a file with O_APPEND the fd position pointer is set to the start of the file. When I then write to an fd on a ufs FS in FB6.4, it is automatically moved to the end and the bytes are appended. No problems appear with write to the sappend-flages file. However if I do the same on FB8.1/ZFS, the write fails as "not permitted". When I manually move the position pointer to the end of the file, it works as axpected (see test case below). See also the thread on the freebsd-fs mailinglist: http://lists.freebsd.org/pipermail/freebsd-fs/2010-September/thread.html#9528 >How-To-Repeat: FreeBSD 6.4/UFS: OK root@fb64 [~/michi]# touch gaga root@fb64 [~/michi]# chflags sappend gaga root@fb64 [~/michi]# ./write fd: 3 pos: 0 bytes written: 6 pos: 50 bytes written: 6 FreeBSD 8.1/ZFS: BROKEN root@fb81 [~/michi]# touch gaga root@fb81 [~/michi]# chflags sappend gaga root@fb81 [~/michi]# ./write fd: 3 pos: 0 ERROR: Operation not permitted pos: 147 bytes written: 6 The test source code: #include #include #include #include #include int main(void){ int file= open("gaga",O_WRONLY|O_APPEND|O_CREAT,0666); int bytes_written= 0; printf("fd: %i\n",file); printf("pos: %i\n",lseek(file,0,SEEK_CUR)); if ((bytes_written= write(file,"write\n",6)) == -1){ printf("ERROR: %s\n",strerror(errno)); }else{ printf("bytes written: %i\n",bytes_written); } lseek(file,0,SEEK_END); printf("pos: %i\n",lseek(file,0,SEEK_CUR)); if ((bytes_written= write(file,"write\n",6)) == -1){ printf("ERROR: %s\n",strerror(errno)); }else{ printf("bytes written: %i\n",bytes_written); } close(file); } >Fix: by Markus Gebert, original (and follow ups): http://lists.freebsd.org/pipermail/freebsd-fs/2010-September/009529.html ------------------------------- To me, it seems that the zfs_write() VOP incorrectly uses FAPPEND instead of IO_APPEND when checking the ioflag argument to see if the current write is an appending one, here: ---- /* * If immutable or not appending then return EPERM */ pflags = zp->z_phys->zp_flags; if ((pflags & (ZFS_IMMUTABLE | ZFS_READONLY)) || ((pflags & ZFS_APPENDONLY) && !(ioflag & FAPPEND) && (uio->uio_loffset < zp->z_phys->zp_size))) { ZFS_EXIT(zfsvfs); return (EPERM); } ---- The function comment only mentions IO_APPEND and even later on in zfs_write() IO_APPEND is used to check wether the offset should be changed to EOF, so FAPPEND really seems to wrong in the above permission check. CURRENT and STABLE-8 seem to be affected to. The following patch seems to fix it (at least Michi's test case works fine with it): ---- diff -ru ../src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c ./sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c --- ../src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 2010-05-19 08:49:52.000000000 +0200 +++ ./sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 2010-09-23 23:24:43.549846948 +0200 @@ -709,7 +709,7 @@ */ pflags = zp->z_phys->zp_flags; if ((pflags & (ZFS_IMMUTABLE | ZFS_READONLY)) || - ((pflags & ZFS_APPENDONLY) && !(ioflag & FAPPEND) && + ((pflags & ZFS_APPENDONLY) && !(ioflag & IO_APPEND) && (uio->uio_loffset < zp->z_phys->zp_size))) { ZFS_EXIT(zfsvfs); return (EPERM); ---- >Release-Note: >Audit-Trail: >Unformatted: