aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Scott <nathans@bruce>2006-03-14 23:14:45 -0500
committerNathan Scott <nathans@bruce>2006-03-14 23:14:45 -0500
commit3fb962bde48c413bfa419ec4413037e87955dcb6 (patch)
treeccce49b3fbdd8a3f38bbfd07a397092a3ae483b5
parent3759fa9c55923f719ae944a3f8fbb029b36f759d (diff)
Fix a direct I/O locking issue revealed by the new mutex code.
Affects only XFS (i.e. DIO_OWN_LOCKING case) - currently it is not possible to get i_mutex locking correct when using DIO_OWN direct I/O locking in a filesystem due to indeterminism in the possible return code/lock/unlock combinations. This can cause a direct read to attempt a double i_mutex unlock inside XFS. We're now ensuring __blockdev_direct_IO always exits with the inode i_mutex (still) held for a direct reader. Tested with the three different locking modes (via direct block device access, ext3 and XFS) - both reading and writing; cannot find any regressions resulting from this change, and it clearly fixes the mutex_unlock warning originally reported here: http://marc.theaimsgroup.com/?l=linux-kernel&m=114189068126253&w=2 Signed-off-by: Nathan Scott <nathans@sgi.com> Acked-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--fs/direct-io.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 848044af7e16..27f3e787faca 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -1155,15 +1155,16 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
1155 * For writes, i_mutex is not held on entry; it is never taken. 1155 * For writes, i_mutex is not held on entry; it is never taken.
1156 * 1156 *
1157 * DIO_LOCKING (simple locking for regular files) 1157 * DIO_LOCKING (simple locking for regular files)
1158 * For writes we are called under i_mutex and return with i_mutex held, even though 1158 * For writes we are called under i_mutex and return with i_mutex held, even
1159 * it is internally dropped. 1159 * though it is internally dropped.
1160 * For reads, i_mutex is not held on entry, but it is taken and dropped before 1160 * For reads, i_mutex is not held on entry, but it is taken and dropped before
1161 * returning. 1161 * returning.
1162 * 1162 *
1163 * DIO_OWN_LOCKING (filesystem provides synchronisation and handling of 1163 * DIO_OWN_LOCKING (filesystem provides synchronisation and handling of
1164 * uninitialised data, allowing parallel direct readers and writers) 1164 * uninitialised data, allowing parallel direct readers and writers)
1165 * For writes we are called without i_mutex, return without it, never touch it. 1165 * For writes we are called without i_mutex, return without it, never touch it.
1166 * For reads, i_mutex is held on entry and will be released before returning. 1166 * For reads we are called under i_mutex and return with i_mutex held, even
1167 * though it may be internally dropped.
1167 * 1168 *
1168 * Additional i_alloc_sem locking requirements described inline below. 1169 * Additional i_alloc_sem locking requirements described inline below.
1169 */ 1170 */
@@ -1182,7 +1183,8 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
1182 ssize_t retval = -EINVAL; 1183 ssize_t retval = -EINVAL;
1183 loff_t end = offset; 1184 loff_t end = offset;
1184 struct dio *dio; 1185 struct dio *dio;
1185 int reader_with_isem = (rw == READ && dio_lock_type == DIO_OWN_LOCKING); 1186 int release_i_mutex = 0;
1187 int acquire_i_mutex = 0;
1186 1188
1187 if (rw & WRITE) 1189 if (rw & WRITE)
1188 current->flags |= PF_SYNCWRITE; 1190 current->flags |= PF_SYNCWRITE;
@@ -1225,7 +1227,6 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
1225 * writers need to grab i_alloc_sem only (i_mutex is already held) 1227 * writers need to grab i_alloc_sem only (i_mutex is already held)
1226 * For regular files using DIO_OWN_LOCKING, 1228 * For regular files using DIO_OWN_LOCKING,
1227 * neither readers nor writers take any locks here 1229 * neither readers nor writers take any locks here
1228 * (i_mutex is already held and release for writers here)
1229 */ 1230 */
1230 dio->lock_type = dio_lock_type; 1231 dio->lock_type = dio_lock_type;
1231 if (dio_lock_type != DIO_NO_LOCKING) { 1232 if (dio_lock_type != DIO_NO_LOCKING) {
@@ -1236,7 +1237,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
1236 mapping = iocb->ki_filp->f_mapping; 1237 mapping = iocb->ki_filp->f_mapping;
1237 if (dio_lock_type != DIO_OWN_LOCKING) { 1238 if (dio_lock_type != DIO_OWN_LOCKING) {
1238 mutex_lock(&inode->i_mutex); 1239 mutex_lock(&inode->i_mutex);
1239 reader_with_isem = 1; 1240 release_i_mutex = 1;
1240 } 1241 }
1241 1242
1242 retval = filemap_write_and_wait_range(mapping, offset, 1243 retval = filemap_write_and_wait_range(mapping, offset,
@@ -1248,7 +1249,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
1248 1249
1249 if (dio_lock_type == DIO_OWN_LOCKING) { 1250 if (dio_lock_type == DIO_OWN_LOCKING) {
1250 mutex_unlock(&inode->i_mutex); 1251 mutex_unlock(&inode->i_mutex);
1251 reader_with_isem = 0; 1252 acquire_i_mutex = 1;
1252 } 1253 }
1253 } 1254 }
1254 1255
@@ -1269,11 +1270,13 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
1269 nr_segs, blkbits, get_blocks, end_io, dio); 1270 nr_segs, blkbits, get_blocks, end_io, dio);
1270 1271
1271 if (rw == READ && dio_lock_type == DIO_LOCKING) 1272 if (rw == READ && dio_lock_type == DIO_LOCKING)
1272 reader_with_isem = 0; 1273 release_i_mutex = 0;
1273 1274
1274out: 1275out:
1275 if (reader_with_isem) 1276 if (release_i_mutex)
1276 mutex_unlock(&inode->i_mutex); 1277 mutex_unlock(&inode->i_mutex);
1278 else if (acquire_i_mutex)
1279 mutex_lock(&inode->i_mutex);
1277 if (rw & WRITE) 1280 if (rw & WRITE)
1278 current->flags &= ~PF_SYNCWRITE; 1281 current->flags &= ~PF_SYNCWRITE;
1279 return retval; 1282 return retval;