Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752953AbaDDNIk (ORCPT ); Fri, 4 Apr 2014 09:08:40 -0400 Received: from mail-ie0-f176.google.com ([209.85.223.176]:33024 "EHLO mail-ie0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752439AbaDDNIi (ORCPT ); Fri, 4 Apr 2014 09:08:38 -0400 MIME-Version: 1.0 In-Reply-To: References: Date: Fri, 4 Apr 2014 15:08:38 +0200 Message-ID: Subject: Re: Things I wish I'd known about Inotify From: David Herrmann To: Michael Kerrisk-manpages Cc: Robert Love , Eric Paris , "linux-fsdevel@vger.kernel.org" , linux-man , gamin-list@gnome.org, lkml , inotify-tools-general@lists.sourceforge.net Content-Type: text/plain; charset=ISO-8859-1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi On Fri, Apr 4, 2014 at 3:00 PM, David Herrmann wrote: > 1) > IN_IGNORED is async and _immediate_ in case a file got deleted. So if > you use watch-descriptors as keys for your objects, an _already_ used > key might be returned by inotify_add_watch() if an IN_IGNORED is > queued for the old watch (which implicitly destroys the watch). Once > you read the IN_IGNORED from the queue, there is usually no way to > know whether it's generated by the old watch or by the new. The > man-page mentions this in: > "IN_IGNORED: Watch was removed explicitly (inotify_rm_watch(2)) or > automatically (file was deleted, or filesystem was unmounted)." > I think we should add a note to BUGS that mentions this race (which is > really not obvious from the description). > > This race could be fixed by requiring an explicit inotify_rm_watch() > if an IN_IGNORED was generated asynchronously. > > 2) > inotify_add_watch() is based on inodes. So if you call it on > hardlinks, you will modify the existing watch instead of creating a > new one. This is often really annoying and I think an IN_FORCE_NEW > flag that disables this would be really nice. Imagine the following > code: > > wd1 = inotify_add_watch(fd, A); > wd2 = inotify_add_watch(fd, B); > ... > inotify_rm_watch(fd, wd2); > wd3 = inotify_add_watch(fd, C); > ... > inotify_rm_watch(fd, wd1); > ... > inotify_rm_watch(fd, wd3); > > If A and B are hardlinks to the same file, then wd1==wd2. Therefore, > after wd2 was removed, we _might_ end up with wd3==wd1 and thus remove > wd3 early (which obviously is not intended). So simple code like this > doesn't work. You have to verify whether returned handles are > duplicates or new. An IN_FORCE_NEW flag would really help here. Note that both of these races rely on watch-descriptors being reused after they were freed. Turns out, that was "fixed" about exactly 1 year ago in: commit a66c04b4534f9b25e1241dff9a9d94dff9fd66f8 Author: Jeff Layton Date: Mon Apr 29 16:21:21 2013 -0700 inotify: convert inotify_add_to_idr() to use idr_alloc_cyclic() So in case that was never backported, only older kernels are affected. In newer kernels, wd reuse is quite unlikely. The races are still there, though. Thanks David -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/