aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/locks.c49
1 files changed, 25 insertions, 24 deletions
diff --git a/fs/locks.c b/fs/locks.c
index 4e8cf5da2868..7d627ac0ed87 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1351,6 +1351,20 @@ static bool leases_conflict(struct file_lock *lease, struct file_lock *breaker)
1351 return locks_conflict(breaker, lease); 1351 return locks_conflict(breaker, lease);
1352} 1352}
1353 1353
1354static bool
1355any_leases_conflict(struct inode *inode, struct file_lock *breaker)
1356{
1357 struct file_lock *fl;
1358
1359 lockdep_assert_held(&inode->i_lock);
1360
1361 for (fl = inode->i_flock ; fl && IS_LEASE(fl); fl = fl->fl_next) {
1362 if (leases_conflict(fl, breaker))
1363 return true;
1364 }
1365 return false;
1366}
1367
1354/** 1368/**
1355 * __break_lease - revoke all outstanding leases on file 1369 * __break_lease - revoke all outstanding leases on file
1356 * @inode: the inode of the file to return 1370 * @inode: the inode of the file to return
@@ -1367,10 +1381,9 @@ static bool leases_conflict(struct file_lock *lease, struct file_lock *breaker)
1367int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) 1381int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1368{ 1382{
1369 int error = 0; 1383 int error = 0;
1370 struct file_lock *new_fl, *flock; 1384 struct file_lock *new_fl;
1371 struct file_lock *fl; 1385 struct file_lock *fl;
1372 unsigned long break_time; 1386 unsigned long break_time;
1373 bool lease_conflict = false;
1374 int want_write = (mode & O_ACCMODE) != O_RDONLY; 1387 int want_write = (mode & O_ACCMODE) != O_RDONLY;
1375 LIST_HEAD(dispose); 1388 LIST_HEAD(dispose);
1376 1389
@@ -1383,17 +1396,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1383 1396
1384 time_out_leases(inode, &dispose); 1397 time_out_leases(inode, &dispose);
1385 1398
1386 flock = inode->i_flock; 1399 if (!any_leases_conflict(inode, new_fl))
1387 if ((flock == NULL) || !IS_LEASE(flock))
1388 goto out;
1389
1390 for (fl = flock; fl && IS_LEASE(fl); fl = fl->fl_next) {
1391 if (leases_conflict(fl, new_fl)) {
1392 lease_conflict = true;
1393 break;
1394 }
1395 }
1396 if (!lease_conflict)
1397 goto out; 1400 goto out;
1398 1401
1399 break_time = 0; 1402 break_time = 0;
@@ -1403,7 +1406,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1403 break_time++; /* so that 0 means no break time */ 1406 break_time++; /* so that 0 means no break time */
1404 } 1407 }
1405 1408
1406 for (fl = flock; fl && IS_LEASE(fl); fl = fl->fl_next) { 1409 for (fl = inode->i_flock; fl && IS_LEASE(fl); fl = fl->fl_next) {
1407 if (!leases_conflict(fl, new_fl)) 1410 if (!leases_conflict(fl, new_fl))
1408 continue; 1411 continue;
1409 if (want_write) { 1412 if (want_write) {
@@ -1412,7 +1415,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1412 fl->fl_flags |= FL_UNLOCK_PENDING; 1415 fl->fl_flags |= FL_UNLOCK_PENDING;
1413 fl->fl_break_time = break_time; 1416 fl->fl_break_time = break_time;
1414 } else { 1417 } else {
1415 if (lease_breaking(flock)) 1418 if (lease_breaking(inode->i_flock))
1416 continue; 1419 continue;
1417 fl->fl_flags |= FL_DOWNGRADE_PENDING; 1420 fl->fl_flags |= FL_DOWNGRADE_PENDING;
1418 fl->fl_downgrade_time = break_time; 1421 fl->fl_downgrade_time = break_time;
@@ -1427,12 +1430,12 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
1427 } 1430 }
1428 1431
1429restart: 1432restart:
1430 break_time = flock->fl_break_time; 1433 break_time = inode->i_flock->fl_break_time;
1431 if (break_time != 0) 1434 if (break_time != 0)
1432 break_time -= jiffies; 1435 break_time -= jiffies;
1433 if (break_time == 0) 1436 if (break_time == 0)
1434 break_time++; 1437 break_time++;
1435 locks_insert_block(flock, new_fl); 1438 locks_insert_block(inode->i_flock, new_fl);
1436 trace_break_lease_block(inode, new_fl); 1439 trace_break_lease_block(inode, new_fl);
1437 spin_unlock(&inode->i_lock); 1440 spin_unlock(&inode->i_lock);
1438 locks_dispose_list(&dispose); 1441 locks_dispose_list(&dispose);
@@ -1442,17 +1445,15 @@ restart:
1442 trace_break_lease_unblock(inode, new_fl); 1445 trace_break_lease_unblock(inode, new_fl);
1443 locks_delete_block(new_fl); 1446 locks_delete_block(new_fl);
1444 if (error >= 0) { 1447 if (error >= 0) {
1445 if (error == 0)
1446 time_out_leases(inode, &dispose);
1447 /* 1448 /*
1448 * Wait for the next conflicting lease that has not been 1449 * Wait for the next conflicting lease that has not been
1449 * broken yet 1450 * broken yet
1450 */ 1451 */
1451 for (flock = inode->i_flock; flock && IS_LEASE(flock); 1452 if (error == 0)
1452 flock = flock->fl_next) { 1453 time_out_leases(inode, &dispose);
1453 if (leases_conflict(new_fl, flock)) 1454 if (any_leases_conflict(inode, new_fl))
1454 goto restart; 1455 goto restart;
1455 } 1456
1456 error = 0; 1457 error = 0;
1457 } 1458 }
1458 1459