Loading fs/direct-io.c +12 −9 Original line number Original line Diff line number Diff line Loading @@ -1155,15 +1155,16 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, * For writes, i_mutex is not held on entry; it is never taken. * For writes, i_mutex is not held on entry; it is never taken. * * * DIO_LOCKING (simple locking for regular files) * DIO_LOCKING (simple locking for regular files) * For writes we are called under i_mutex and return with i_mutex held, even though * For writes we are called under i_mutex and return with i_mutex held, even * it is internally dropped. * though it is internally dropped. * For reads, i_mutex is not held on entry, but it is taken and dropped before * For reads, i_mutex is not held on entry, but it is taken and dropped before * returning. * returning. * * * DIO_OWN_LOCKING (filesystem provides synchronisation and handling of * DIO_OWN_LOCKING (filesystem provides synchronisation and handling of * uninitialised data, allowing parallel direct readers and writers) * uninitialised data, allowing parallel direct readers and writers) * For writes we are called without i_mutex, return without it, never touch it. * For writes we are called without i_mutex, return without it, never touch it. * For reads, i_mutex is held on entry and will be released before returning. * For reads we are called under i_mutex and return with i_mutex held, even * though it may be internally dropped. * * * Additional i_alloc_sem locking requirements described inline below. * Additional i_alloc_sem locking requirements described inline below. */ */ Loading @@ -1182,7 +1183,8 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, ssize_t retval = -EINVAL; ssize_t retval = -EINVAL; loff_t end = offset; loff_t end = offset; struct dio *dio; struct dio *dio; int reader_with_isem = (rw == READ && dio_lock_type == DIO_OWN_LOCKING); int release_i_mutex = 0; int acquire_i_mutex = 0; if (rw & WRITE) if (rw & WRITE) current->flags |= PF_SYNCWRITE; current->flags |= PF_SYNCWRITE; Loading Loading @@ -1225,7 +1227,6 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, * writers need to grab i_alloc_sem only (i_mutex is already held) * writers need to grab i_alloc_sem only (i_mutex is already held) * For regular files using DIO_OWN_LOCKING, * For regular files using DIO_OWN_LOCKING, * neither readers nor writers take any locks here * neither readers nor writers take any locks here * (i_mutex is already held and release for writers here) */ */ dio->lock_type = dio_lock_type; dio->lock_type = dio_lock_type; if (dio_lock_type != DIO_NO_LOCKING) { if (dio_lock_type != DIO_NO_LOCKING) { Loading @@ -1236,7 +1237,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, mapping = iocb->ki_filp->f_mapping; mapping = iocb->ki_filp->f_mapping; if (dio_lock_type != DIO_OWN_LOCKING) { if (dio_lock_type != DIO_OWN_LOCKING) { mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex); reader_with_isem = 1; release_i_mutex = 1; } } retval = filemap_write_and_wait_range(mapping, offset, retval = filemap_write_and_wait_range(mapping, offset, Loading @@ -1248,7 +1249,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, if (dio_lock_type == DIO_OWN_LOCKING) { if (dio_lock_type == DIO_OWN_LOCKING) { mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex); reader_with_isem = 0; acquire_i_mutex = 1; } } } } Loading @@ -1269,11 +1270,13 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, nr_segs, blkbits, get_blocks, end_io, dio); nr_segs, blkbits, get_blocks, end_io, dio); if (rw == READ && dio_lock_type == DIO_LOCKING) if (rw == READ && dio_lock_type == DIO_LOCKING) reader_with_isem = 0; release_i_mutex = 0; out: out: if (reader_with_isem) if (release_i_mutex) mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex); else if (acquire_i_mutex) mutex_lock(&inode->i_mutex); if (rw & WRITE) if (rw & WRITE) current->flags &= ~PF_SYNCWRITE; current->flags &= ~PF_SYNCWRITE; return retval; return retval; Loading Loading
fs/direct-io.c +12 −9 Original line number Original line Diff line number Diff line Loading @@ -1155,15 +1155,16 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, * For writes, i_mutex is not held on entry; it is never taken. * For writes, i_mutex is not held on entry; it is never taken. * * * DIO_LOCKING (simple locking for regular files) * DIO_LOCKING (simple locking for regular files) * For writes we are called under i_mutex and return with i_mutex held, even though * For writes we are called under i_mutex and return with i_mutex held, even * it is internally dropped. * though it is internally dropped. * For reads, i_mutex is not held on entry, but it is taken and dropped before * For reads, i_mutex is not held on entry, but it is taken and dropped before * returning. * returning. * * * DIO_OWN_LOCKING (filesystem provides synchronisation and handling of * DIO_OWN_LOCKING (filesystem provides synchronisation and handling of * uninitialised data, allowing parallel direct readers and writers) * uninitialised data, allowing parallel direct readers and writers) * For writes we are called without i_mutex, return without it, never touch it. * For writes we are called without i_mutex, return without it, never touch it. * For reads, i_mutex is held on entry and will be released before returning. * For reads we are called under i_mutex and return with i_mutex held, even * though it may be internally dropped. * * * Additional i_alloc_sem locking requirements described inline below. * Additional i_alloc_sem locking requirements described inline below. */ */ Loading @@ -1182,7 +1183,8 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, ssize_t retval = -EINVAL; ssize_t retval = -EINVAL; loff_t end = offset; loff_t end = offset; struct dio *dio; struct dio *dio; int reader_with_isem = (rw == READ && dio_lock_type == DIO_OWN_LOCKING); int release_i_mutex = 0; int acquire_i_mutex = 0; if (rw & WRITE) if (rw & WRITE) current->flags |= PF_SYNCWRITE; current->flags |= PF_SYNCWRITE; Loading Loading @@ -1225,7 +1227,6 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, * writers need to grab i_alloc_sem only (i_mutex is already held) * writers need to grab i_alloc_sem only (i_mutex is already held) * For regular files using DIO_OWN_LOCKING, * For regular files using DIO_OWN_LOCKING, * neither readers nor writers take any locks here * neither readers nor writers take any locks here * (i_mutex is already held and release for writers here) */ */ dio->lock_type = dio_lock_type; dio->lock_type = dio_lock_type; if (dio_lock_type != DIO_NO_LOCKING) { if (dio_lock_type != DIO_NO_LOCKING) { Loading @@ -1236,7 +1237,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, mapping = iocb->ki_filp->f_mapping; mapping = iocb->ki_filp->f_mapping; if (dio_lock_type != DIO_OWN_LOCKING) { if (dio_lock_type != DIO_OWN_LOCKING) { mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex); reader_with_isem = 1; release_i_mutex = 1; } } retval = filemap_write_and_wait_range(mapping, offset, retval = filemap_write_and_wait_range(mapping, offset, Loading @@ -1248,7 +1249,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, if (dio_lock_type == DIO_OWN_LOCKING) { if (dio_lock_type == DIO_OWN_LOCKING) { mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex); reader_with_isem = 0; acquire_i_mutex = 1; } } } } Loading @@ -1269,11 +1270,13 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, nr_segs, blkbits, get_blocks, end_io, dio); nr_segs, blkbits, get_blocks, end_io, dio); if (rw == READ && dio_lock_type == DIO_LOCKING) if (rw == READ && dio_lock_type == DIO_LOCKING) reader_with_isem = 0; release_i_mutex = 0; out: out: if (reader_with_isem) if (release_i_mutex) mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex); else if (acquire_i_mutex) mutex_lock(&inode->i_mutex); if (rw & WRITE) if (rw & WRITE) current->flags &= ~PF_SYNCWRITE; current->flags &= ~PF_SYNCWRITE; return retval; return retval; Loading