diff options
Diffstat (limited to 'fs/ceph')
-rw-r--r-- | fs/ceph/caps.c | 82 |
1 files changed, 50 insertions, 32 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 4958a2ef3e04..e1e6df0f549e 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -1362,6 +1362,41 @@ static int __mark_caps_flushing(struct inode *inode, | |||
1362 | } | 1362 | } |
1363 | 1363 | ||
1364 | /* | 1364 | /* |
1365 | * try to invalidate mapping pages without blocking. | ||
1366 | */ | ||
1367 | static int mapping_is_empty(struct address_space *mapping) | ||
1368 | { | ||
1369 | struct page *page = find_get_page(mapping, 0); | ||
1370 | |||
1371 | if (!page) | ||
1372 | return 1; | ||
1373 | |||
1374 | put_page(page); | ||
1375 | return 0; | ||
1376 | } | ||
1377 | |||
1378 | static int try_nonblocking_invalidate(struct inode *inode) | ||
1379 | { | ||
1380 | struct ceph_inode_info *ci = ceph_inode(inode); | ||
1381 | u32 invalidating_gen = ci->i_rdcache_gen; | ||
1382 | |||
1383 | spin_unlock(&inode->i_lock); | ||
1384 | invalidate_mapping_pages(&inode->i_data, 0, -1); | ||
1385 | spin_lock(&inode->i_lock); | ||
1386 | |||
1387 | if (mapping_is_empty(&inode->i_data) && | ||
1388 | invalidating_gen == ci->i_rdcache_gen) { | ||
1389 | /* success. */ | ||
1390 | dout("try_nonblocking_invalidate %p success\n", inode); | ||
1391 | ci->i_rdcache_gen = 0; | ||
1392 | ci->i_rdcache_revoking = 0; | ||
1393 | return 0; | ||
1394 | } | ||
1395 | dout("try_nonblocking_invalidate %p failed\n", inode); | ||
1396 | return -1; | ||
1397 | } | ||
1398 | |||
1399 | /* | ||
1365 | * Swiss army knife function to examine currently used and wanted | 1400 | * Swiss army knife function to examine currently used and wanted |
1366 | * versus held caps. Release, flush, ack revoked caps to mds as | 1401 | * versus held caps. Release, flush, ack revoked caps to mds as |
1367 | * appropriate. | 1402 | * appropriate. |
@@ -1451,27 +1486,19 @@ retry_locked: | |||
1451 | (file_wanted == 0 || /* no open files */ | 1486 | (file_wanted == 0 || /* no open files */ |
1452 | (revoking & CEPH_CAP_FILE_CACHE)) && /* or revoking cache */ | 1487 | (revoking & CEPH_CAP_FILE_CACHE)) && /* or revoking cache */ |
1453 | !tried_invalidate) { | 1488 | !tried_invalidate) { |
1454 | u32 invalidating_gen = ci->i_rdcache_gen; | ||
1455 | int ret; | ||
1456 | |||
1457 | dout("check_caps trying to invalidate on %p\n", inode); | 1489 | dout("check_caps trying to invalidate on %p\n", inode); |
1458 | spin_unlock(&inode->i_lock); | 1490 | if (try_nonblocking_invalidate(inode) < 0) { |
1459 | ret = invalidate_mapping_pages(&inode->i_data, 0, -1); | 1491 | if (revoking & CEPH_CAP_FILE_CACHE) { |
1460 | spin_lock(&inode->i_lock); | 1492 | dout("check_caps queuing invalidate\n"); |
1461 | if (ret == 0 && invalidating_gen == ci->i_rdcache_gen) { | 1493 | queue_invalidate = 1; |
1462 | /* success. */ | 1494 | ci->i_rdcache_revoking = ci->i_rdcache_gen; |
1463 | ci->i_rdcache_gen = 0; | 1495 | } else { |
1464 | ci->i_rdcache_revoking = 0; | 1496 | dout("check_caps failed to invalidate pages\n"); |
1465 | } else if (revoking & CEPH_CAP_FILE_CACHE) { | 1497 | /* we failed to invalidate pages. check these |
1466 | dout("check_caps queuing invalidate\n"); | 1498 | caps again later. */ |
1467 | queue_invalidate = 1; | 1499 | force_requeue = 1; |
1468 | ci->i_rdcache_revoking = ci->i_rdcache_gen; | 1500 | __cap_set_timeouts(mdsc, ci); |
1469 | } else { | 1501 | } |
1470 | dout("check_caps failed to invalidate pages\n"); | ||
1471 | /* we failed to invalidate pages. check these | ||
1472 | caps again later. */ | ||
1473 | force_requeue = 1; | ||
1474 | __cap_set_timeouts(mdsc, ci); | ||
1475 | } | 1502 | } |
1476 | tried_invalidate = 1; | 1503 | tried_invalidate = 1; |
1477 | goto retry_locked; | 1504 | goto retry_locked; |
@@ -2184,7 +2211,6 @@ static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2184 | int revoked_rdcache = 0; | 2211 | int revoked_rdcache = 0; |
2185 | int queue_invalidate = 0; | 2212 | int queue_invalidate = 0; |
2186 | int tried_invalidate = 0; | 2213 | int tried_invalidate = 0; |
2187 | int ret; | ||
2188 | 2214 | ||
2189 | dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n", | 2215 | dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n", |
2190 | inode, cap, mds, seq, ceph_cap_string(newcaps)); | 2216 | inode, cap, mds, seq, ceph_cap_string(newcaps)); |
@@ -2199,24 +2225,16 @@ static int handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2199 | restart: | 2225 | restart: |
2200 | if (((cap->issued & ~newcaps) & CEPH_CAP_FILE_CACHE) && | 2226 | if (((cap->issued & ~newcaps) & CEPH_CAP_FILE_CACHE) && |
2201 | !ci->i_wrbuffer_ref && !tried_invalidate) { | 2227 | !ci->i_wrbuffer_ref && !tried_invalidate) { |
2202 | dout("CACHE invalidation\n"); | ||
2203 | spin_unlock(&inode->i_lock); | ||
2204 | tried_invalidate = 1; | 2228 | tried_invalidate = 1; |
2205 | 2229 | if (try_nonblocking_invalidate(inode) == 0) { | |
2206 | ret = invalidate_mapping_pages(&inode->i_data, 0, -1); | 2230 | revoked_rdcache = 1; |
2207 | spin_lock(&inode->i_lock); | 2231 | } else { |
2208 | if (ret < 0) { | ||
2209 | /* there were locked pages.. invalidate later | 2232 | /* there were locked pages.. invalidate later |
2210 | in a separate thread. */ | 2233 | in a separate thread. */ |
2211 | if (ci->i_rdcache_revoking != ci->i_rdcache_gen) { | 2234 | if (ci->i_rdcache_revoking != ci->i_rdcache_gen) { |
2212 | queue_invalidate = 1; | 2235 | queue_invalidate = 1; |
2213 | ci->i_rdcache_revoking = ci->i_rdcache_gen; | 2236 | ci->i_rdcache_revoking = ci->i_rdcache_gen; |
2214 | } | 2237 | } |
2215 | } else { | ||
2216 | /* we successfully invalidated those pages */ | ||
2217 | revoked_rdcache = 1; | ||
2218 | ci->i_rdcache_gen = 0; | ||
2219 | ci->i_rdcache_revoking = 0; | ||
2220 | } | 2238 | } |
2221 | goto restart; | 2239 | goto restart; |
2222 | } | 2240 | } |