From: Marcelo T. <ma...@co...> - 2001-01-26 20:06:17
|
On Fri, 26 Jan 2001, Andi Kleen wrote: > On Fri, Jan 26, 2001 at 03:29:43PM -0200, Marcelo Tosatti wrote: > > > > On Fri, 26 Jan 2001, Andi Kleen wrote: > > > > > On Tue, Jan 23, 2001 at 05:53:55PM -0200, Marcelo Tosatti wrote: > > > > The right thing is to make the ext2 functions flush dirty buffers, if > > > > needed, after unlocking the sb lock. > > > > > > Hopefully you can do that without additional memory allocation. > > > > > > This means that some random process can get blocked when you run out of > > > elevator entries, even when it doesn't do any IO anymore. > > > > You mean some other process will have to block because I'm "bypassing" the > > buffer dirty watermark? > > Maybe I misunderstood your suggestion. As I understand you basically want > to create a construct like the linux socket lock -- when a try_lock() fails > queue the work item somehow and the original lock holder processes it > in its context after it freed the lock. Not exactly. > flushing would probably end up doing a ll_rw_block(), right? > The problem is that ll_rw_block is not 100% asynchronous, when you run out > of elevator entries it'll block. This means that the lock freer could > block on some foreign IO. Not nice. Right now we potentially call ll_rw_block with the superblock lock held. Example (I've removed a lot of code): void ext2_free_inode (struct inode * inode) { struct super_block * sb = inode->i_sb; int is_directory; lock_super (sb); mark_buffer_dirty(bh2); mark_buffer_dirty(sb->u.ext2_sb.s_sbh); mark_buffer_dirty(bh); error_return: unlock_super (sb); } Each "mark_buffer_dirty" will call balance_dirty() if we're really dirtying a buffer (if it was previously clean), and from there we potentially reach ll_rw_block(). Instead sleeping with the superblock lock held we can call balance_dirty() after "unlock_super()" if we actually freed any buffer, so we avoid sleeping with the superblock lock held. |