On Tue 18-07-17 06:44:20, Christoph Hellwig wrote: > > + if (dio->is_async && iov_iter_rw(iter) == WRITE) { > > + retval = 0; > > + if ((iocb->ki_filp->f_flags & O_DSYNC) || > > + IS_SYNC(iocb->ki_filp->f_mapping->host)) > > + retval = dio_set_defer_completion(dio); > > + else if (!dio->inode->i_sb->s_dio_done_wq) > > + /* > > + * In case of AIO write racing with buffered read we > > + * need to defer completion. We can't decide this now, > > + * however the workqueue needs to be initialized here. > > + */ > > + retval = sb_init_dio_done_wq(dio->inode->i_sb); > > So now we initialize the workqueue on the first aio write. Maybe we > should just always initialize it? Especially given that the cost of > a workqueue is rather cheap. I also don't really understand why > we even need the workqueue per-superblock instead of global. So the workqueue is WQ_MEM_RECLAIM which means there will be always "rescue" worker running. Not that it would make workqueue too expensive but it is not zero cost either. So saving the cost for filesystems that don't support AIO DIO makes sense to me. Regarding creating global workqueue - it would create IO completion dependencies between filesystems which could have unwanted side effects and possibly create deadlocks. The default paralelism of workqueues would mostly hide this but I'm not sure there won't be some corner case e.g. when memory is tight... Honza -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR