diff options
| -rw-r--r-- | fs/locks.c | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/fs/locks.c b/fs/locks.c index 1260c265ba62..f2fa1465046b 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -710,6 +710,20 @@ static void __locks_wake_up_blocks(struct file_lock *blocker) | |||
| 710 | 710 | ||
| 711 | static void locks_delete_block(struct file_lock *waiter) | 711 | static void locks_delete_block(struct file_lock *waiter) |
| 712 | { | 712 | { |
| 713 | /* | ||
| 714 | * If fl_blocker is NULL, it won't be set again as this thread | ||
| 715 | * "owns" the lock and is the only one that might try to claim | ||
| 716 | * the lock. So it is safe to test fl_blocker locklessly. | ||
| 717 | * Also if fl_blocker is NULL, this waiter is not listed on | ||
| 718 | * fl_blocked_requests for some lock, so no other request can | ||
| 719 | * be added to the list of fl_blocked_requests for this | ||
| 720 | * request. So if fl_blocker is NULL, it is safe to | ||
| 721 | * locklessly check if fl_blocked_requests is empty. If both | ||
| 722 | * of these checks succeed, there is no need to take the lock. | ||
| 723 | */ | ||
| 724 | if (waiter->fl_blocker == NULL && | ||
| 725 | list_empty(&waiter->fl_blocked_requests)) | ||
| 726 | return; | ||
| 713 | spin_lock(&blocked_lock_lock); | 727 | spin_lock(&blocked_lock_lock); |
| 714 | __locks_wake_up_blocks(waiter); | 728 | __locks_wake_up_blocks(waiter); |
| 715 | __locks_delete_block(waiter); | 729 | __locks_delete_block(waiter); |
| @@ -1279,12 +1293,10 @@ static int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl) | |||
| 1279 | if (error != FILE_LOCK_DEFERRED) | 1293 | if (error != FILE_LOCK_DEFERRED) |
| 1280 | break; | 1294 | break; |
| 1281 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_blocker); | 1295 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_blocker); |
| 1282 | if (!error) | 1296 | if (error) |
| 1283 | continue; | 1297 | break; |
| 1284 | |||
| 1285 | locks_delete_block(fl); | ||
| 1286 | break; | ||
| 1287 | } | 1298 | } |
| 1299 | locks_delete_block(fl); | ||
| 1288 | return error; | 1300 | return error; |
| 1289 | } | 1301 | } |
| 1290 | 1302 | ||
| @@ -1375,9 +1387,9 @@ int locks_mandatory_area(struct inode *inode, struct file *filp, loff_t start, | |||
| 1375 | continue; | 1387 | continue; |
| 1376 | } | 1388 | } |
| 1377 | 1389 | ||
| 1378 | locks_delete_block(&fl); | ||
| 1379 | break; | 1390 | break; |
| 1380 | } | 1391 | } |
| 1392 | locks_delete_block(&fl); | ||
| 1381 | 1393 | ||
| 1382 | return error; | 1394 | return error; |
| 1383 | } | 1395 | } |
| @@ -1973,12 +1985,10 @@ static int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl) | |||
| 1973 | if (error != FILE_LOCK_DEFERRED) | 1985 | if (error != FILE_LOCK_DEFERRED) |
| 1974 | break; | 1986 | break; |
| 1975 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_blocker); | 1987 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_blocker); |
| 1976 | if (!error) | 1988 | if (error) |
| 1977 | continue; | 1989 | break; |
| 1978 | |||
| 1979 | locks_delete_block(fl); | ||
| 1980 | break; | ||
| 1981 | } | 1990 | } |
| 1991 | locks_delete_block(fl); | ||
| 1982 | return error; | 1992 | return error; |
| 1983 | } | 1993 | } |
| 1984 | 1994 | ||
| @@ -2252,12 +2262,10 @@ static int do_lock_file_wait(struct file *filp, unsigned int cmd, | |||
| 2252 | if (error != FILE_LOCK_DEFERRED) | 2262 | if (error != FILE_LOCK_DEFERRED) |
| 2253 | break; | 2263 | break; |
| 2254 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_blocker); | 2264 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_blocker); |
| 2255 | if (!error) | 2265 | if (error) |
| 2256 | continue; | 2266 | break; |
| 2257 | |||
| 2258 | locks_delete_block(fl); | ||
| 2259 | break; | ||
| 2260 | } | 2267 | } |
| 2268 | locks_delete_block(fl); | ||
| 2261 | 2269 | ||
| 2262 | return error; | 2270 | return error; |
| 2263 | } | 2271 | } |
