Skip to content
  • Linus Torvalds's avatar
    fasync: split 'fasync_helper()' into separate add/remove functions · 53281b6d
    Linus Torvalds authored
    
    
    Yes, the add and remove cases do share the same basic loop and the
    locking, but the compiler can inline and then CSE some of the end result
    anyway.  And splitting it up makes the code way easier to follow,
    and makes it clearer exactly what the semantics are.
    
    In particular, we must make sure that the FASYNC flag in file->f_flags
    exactly matches the state of "is this file on any fasync list", since
    not only is that flag visible to user space (F_GETFL), but we also use
    that flag to check whether we need to remove any fasync entries on file
    close.
    
    We got that wrong for the case of a mixed use of file locking (which
    tries to remove any fasync entries for file leases) and fasync.
    
    Splitting the function up also makes it possible to do some future
    optimizations without making the function even messier.  In particular,
    since the FASYNC flag has to match the state of "is this on a list", we
    can do the following future optimizations:
    
     - on remove, we don't even need to get the locks and traverse the list
       if FASYNC isn't set, since we can know a priori that there is no
       point (this is effectively the same optimization that we already do
       in __fput() wrt removing fasync on file close)
    
     - on add, we can use the FASYNC flag to decide whether we are changing
       an existing entry or need to allocate a new one.
    
    but this is just the cleanup + fix for the FASYNC flag.
    
    Acked-by: default avatarAl Viro <viro@ZenIV.linux.org.uk>
    Tested-by: default avatarTavis Ormandy <taviso@google.com>
    Cc: Jeff Dike <jdike@addtoit.com>
    Cc: Matt Mackall <mpm@selenic.com>
    Cc: stable@kernel.org
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    53281b6d