andrea & i discussed this off-list a few days ago... see fs/fcntl.c
case F_SETFL:
lock_kernel();
err = setfl(fd, filp, arg);
unlock_kernel();
setfl() does:
if ((arg ^ filp->f_flags) & FASYNC) {
if (filp->f_op && filp->f_op->fasync) {
error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0);
and:
if (arg & O_DIRECT) {
down(&inode->i_sem);
if (!filp->f_iobuf)
error = alloc_kiovec(1, &filp->f_iobuf);
up(&inode->i_sem);
and finally:
filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK);
i pointed out that if alloc_kiovec slept, the BKL provides no protection
against someone else doing a setfl at the same time, so we can get the
wrong number of fasync events sent. Marcus Alanen pointed out that
fasync can also sleep, so we're at risk anyway. i don't think that
abusing i_sem as andrea did is the Right Thing to do...
-- Revolutions do not require corporate support. - 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/