From mboxrd@z Thu Jan 1 00:00:00 1970 From: Oleg Drokin Subject: [PATCH] Oversight in generic_file_aio_write_nolock Date: Tue, 7 Apr 2009 20:16:08 +0400 Message-ID: <20090407161608.GA1514155@fiona.linuxhacker.ru> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="G4iJoqBmSsgzjUCe" To: linux-fsdevel@vger.kernel.org Return-path: Received: from linuxhacker.ru ([217.76.32.60]:36812 "EHLO fiona.linuxhacker.ru" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754373AbZDGQQL (ORCPT ); Tue, 7 Apr 2009 12:16:11 -0400 Received: from fiona.linuxhacker.ru (fiona [127.0.0.1]) by fiona.linuxhacker.ru (8.14.3/8.14.2) with ESMTP id n37GG86j1515252 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 7 Apr 2009 20:16:09 +0400 Received: (from green@localhost) by fiona.linuxhacker.ru (8.14.3/8.14.3/Submit) id n37GG8na1515250 for linux-fsdevel@vger.kernel.org; Tue, 7 Apr 2009 20:16:08 +0400 Content-Disposition: inline Sender: linux-fsdevel-owner@vger.kernel.org List-ID: --G4iJoqBmSsgzjUCe Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hello! There seems to be an oversight in generic_file_aio_write_nolock where when we open inode with O_SYNC and O_APPEND, then after we are done the writing, we flush wrong byterange from the file, from original offset for number of bytes written, instead from the actual oppended offset. This can lead to an unexpected data loss should the crash happen soon after such a write was performed. Here is a simple fix, though perhaps we can just throw away the pos argument from the ->aio_write prototype eventually. Bye, Oleg --G4iJoqBmSsgzjUCe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="osync_oappend_bug.diff" filemap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) --- mm/filemap.c.orig 2009-04-07 12:06:30.000000000 -0400 +++ mm/filemap.c 2009-04-07 12:06:49.000000000 -0400 @@ -2420,7 +2420,8 @@ if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) { ssize_t err; - err = sync_page_range_nolock(inode, mapping, pos, ret); + err = sync_page_range_nolock(inode, mapping, iocb->ki_pos - ret, + ret); if (err < 0) ret = err; } --G4iJoqBmSsgzjUCe--