diff options
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r-- | fs/ceph/caps.c | 211 |
1 files changed, 117 insertions, 94 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 5e9da996a151..f605753c8fe9 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -1,4 +1,4 @@ | |||
1 | #include "ceph_debug.h" | 1 | #include <linux/ceph/ceph_debug.h> |
2 | 2 | ||
3 | #include <linux/fs.h> | 3 | #include <linux/fs.h> |
4 | #include <linux/kernel.h> | 4 | #include <linux/kernel.h> |
@@ -9,8 +9,9 @@ | |||
9 | #include <linux/writeback.h> | 9 | #include <linux/writeback.h> |
10 | 10 | ||
11 | #include "super.h" | 11 | #include "super.h" |
12 | #include "decode.h" | 12 | #include "mds_client.h" |
13 | #include "messenger.h" | 13 | #include <linux/ceph/decode.h> |
14 | #include <linux/ceph/messenger.h> | ||
14 | 15 | ||
15 | /* | 16 | /* |
16 | * Capability management | 17 | * Capability management |
@@ -287,11 +288,11 @@ void ceph_put_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap) | |||
287 | spin_unlock(&mdsc->caps_list_lock); | 288 | spin_unlock(&mdsc->caps_list_lock); |
288 | } | 289 | } |
289 | 290 | ||
290 | void ceph_reservation_status(struct ceph_client *client, | 291 | void ceph_reservation_status(struct ceph_fs_client *fsc, |
291 | int *total, int *avail, int *used, int *reserved, | 292 | int *total, int *avail, int *used, int *reserved, |
292 | int *min) | 293 | int *min) |
293 | { | 294 | { |
294 | struct ceph_mds_client *mdsc = &client->mdsc; | 295 | struct ceph_mds_client *mdsc = fsc->mdsc; |
295 | 296 | ||
296 | if (total) | 297 | if (total) |
297 | *total = mdsc->caps_total_count; | 298 | *total = mdsc->caps_total_count; |
@@ -399,7 +400,7 @@ static void __insert_cap_node(struct ceph_inode_info *ci, | |||
399 | static void __cap_set_timeouts(struct ceph_mds_client *mdsc, | 400 | static void __cap_set_timeouts(struct ceph_mds_client *mdsc, |
400 | struct ceph_inode_info *ci) | 401 | struct ceph_inode_info *ci) |
401 | { | 402 | { |
402 | struct ceph_mount_args *ma = mdsc->client->mount_args; | 403 | struct ceph_mount_options *ma = mdsc->fsc->mount_options; |
403 | 404 | ||
404 | ci->i_hold_caps_min = round_jiffies(jiffies + | 405 | ci->i_hold_caps_min = round_jiffies(jiffies + |
405 | ma->caps_wanted_delay_min * HZ); | 406 | ma->caps_wanted_delay_min * HZ); |
@@ -515,7 +516,7 @@ int ceph_add_cap(struct inode *inode, | |||
515 | unsigned seq, unsigned mseq, u64 realmino, int flags, | 516 | unsigned seq, unsigned mseq, u64 realmino, int flags, |
516 | struct ceph_cap_reservation *caps_reservation) | 517 | struct ceph_cap_reservation *caps_reservation) |
517 | { | 518 | { |
518 | struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc; | 519 | struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; |
519 | struct ceph_inode_info *ci = ceph_inode(inode); | 520 | struct ceph_inode_info *ci = ceph_inode(inode); |
520 | struct ceph_cap *new_cap = NULL; | 521 | struct ceph_cap *new_cap = NULL; |
521 | struct ceph_cap *cap; | 522 | struct ceph_cap *cap; |
@@ -568,7 +569,8 @@ retry: | |||
568 | list_add_tail(&cap->session_caps, &session->s_caps); | 569 | list_add_tail(&cap->session_caps, &session->s_caps); |
569 | session->s_nr_caps++; | 570 | session->s_nr_caps++; |
570 | spin_unlock(&session->s_cap_lock); | 571 | spin_unlock(&session->s_cap_lock); |
571 | } | 572 | } else if (new_cap) |
573 | ceph_put_cap(mdsc, new_cap); | ||
572 | 574 | ||
573 | if (!ci->i_snap_realm) { | 575 | if (!ci->i_snap_realm) { |
574 | /* | 576 | /* |
@@ -764,7 +766,7 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch) | |||
764 | if (touch) { | 766 | if (touch) { |
765 | struct rb_node *q; | 767 | struct rb_node *q; |
766 | 768 | ||
767 | /* touch this + preceeding caps */ | 769 | /* touch this + preceding caps */ |
768 | __touch_cap(cap); | 770 | __touch_cap(cap); |
769 | for (q = rb_first(&ci->i_caps); q != p; | 771 | for (q = rb_first(&ci->i_caps); q != p; |
770 | q = rb_next(q)) { | 772 | q = rb_next(q)) { |
@@ -818,7 +820,7 @@ int __ceph_caps_used(struct ceph_inode_info *ci) | |||
818 | used |= CEPH_CAP_FILE_CACHE; | 820 | used |= CEPH_CAP_FILE_CACHE; |
819 | if (ci->i_wr_ref) | 821 | if (ci->i_wr_ref) |
820 | used |= CEPH_CAP_FILE_WR; | 822 | used |= CEPH_CAP_FILE_WR; |
821 | if (ci->i_wrbuffer_ref) | 823 | if (ci->i_wb_ref || ci->i_wrbuffer_ref) |
822 | used |= CEPH_CAP_FILE_BUFFER; | 824 | used |= CEPH_CAP_FILE_BUFFER; |
823 | return used; | 825 | return used; |
824 | } | 826 | } |
@@ -873,7 +875,7 @@ void __ceph_remove_cap(struct ceph_cap *cap) | |||
873 | struct ceph_mds_session *session = cap->session; | 875 | struct ceph_mds_session *session = cap->session; |
874 | struct ceph_inode_info *ci = cap->ci; | 876 | struct ceph_inode_info *ci = cap->ci; |
875 | struct ceph_mds_client *mdsc = | 877 | struct ceph_mds_client *mdsc = |
876 | &ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc; | 878 | ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc; |
877 | int removed = 0; | 879 | int removed = 0; |
878 | 880 | ||
879 | dout("__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode); | 881 | dout("__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode); |
@@ -1210,7 +1212,7 @@ void __ceph_flush_snaps(struct ceph_inode_info *ci, | |||
1210 | int mds; | 1212 | int mds; |
1211 | struct ceph_cap_snap *capsnap; | 1213 | struct ceph_cap_snap *capsnap; |
1212 | u32 mseq; | 1214 | u32 mseq; |
1213 | struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc; | 1215 | struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; |
1214 | struct ceph_mds_session *session = NULL; /* if session != NULL, we hold | 1216 | struct ceph_mds_session *session = NULL; /* if session != NULL, we hold |
1215 | session->s_mutex */ | 1217 | session->s_mutex */ |
1216 | u64 next_follows = 0; /* keep track of how far we've gotten through the | 1218 | u64 next_follows = 0; /* keep track of how far we've gotten through the |
@@ -1330,13 +1332,14 @@ static void ceph_flush_snaps(struct ceph_inode_info *ci) | |||
1330 | } | 1332 | } |
1331 | 1333 | ||
1332 | /* | 1334 | /* |
1333 | * Mark caps dirty. If inode is newly dirty, add to the global dirty | 1335 | * Mark caps dirty. If inode is newly dirty, return the dirty flags. |
1334 | * list. | 1336 | * Caller is then responsible for calling __mark_inode_dirty with the |
1337 | * returned flags value. | ||
1335 | */ | 1338 | */ |
1336 | void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) | 1339 | int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) |
1337 | { | 1340 | { |
1338 | struct ceph_mds_client *mdsc = | 1341 | struct ceph_mds_client *mdsc = |
1339 | &ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc; | 1342 | ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc; |
1340 | struct inode *inode = &ci->vfs_inode; | 1343 | struct inode *inode = &ci->vfs_inode; |
1341 | int was = ci->i_dirty_caps; | 1344 | int was = ci->i_dirty_caps; |
1342 | int dirty = 0; | 1345 | int dirty = 0; |
@@ -1356,7 +1359,7 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) | |||
1356 | list_add(&ci->i_dirty_item, &mdsc->cap_dirty); | 1359 | list_add(&ci->i_dirty_item, &mdsc->cap_dirty); |
1357 | spin_unlock(&mdsc->cap_dirty_lock); | 1360 | spin_unlock(&mdsc->cap_dirty_lock); |
1358 | if (ci->i_flushing_caps == 0) { | 1361 | if (ci->i_flushing_caps == 0) { |
1359 | igrab(inode); | 1362 | ihold(inode); |
1360 | dirty |= I_DIRTY_SYNC; | 1363 | dirty |= I_DIRTY_SYNC; |
1361 | } | 1364 | } |
1362 | } | 1365 | } |
@@ -1364,9 +1367,8 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) | |||
1364 | if (((was | ci->i_flushing_caps) & CEPH_CAP_FILE_BUFFER) && | 1367 | if (((was | ci->i_flushing_caps) & CEPH_CAP_FILE_BUFFER) && |
1365 | (mask & CEPH_CAP_FILE_BUFFER)) | 1368 | (mask & CEPH_CAP_FILE_BUFFER)) |
1366 | dirty |= I_DIRTY_DATASYNC; | 1369 | dirty |= I_DIRTY_DATASYNC; |
1367 | if (dirty) | ||
1368 | __mark_inode_dirty(inode, dirty); | ||
1369 | __cap_delay_requeue(mdsc, ci); | 1370 | __cap_delay_requeue(mdsc, ci); |
1371 | return dirty; | ||
1370 | } | 1372 | } |
1371 | 1373 | ||
1372 | /* | 1374 | /* |
@@ -1378,7 +1380,7 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) | |||
1378 | static int __mark_caps_flushing(struct inode *inode, | 1380 | static int __mark_caps_flushing(struct inode *inode, |
1379 | struct ceph_mds_session *session) | 1381 | struct ceph_mds_session *session) |
1380 | { | 1382 | { |
1381 | struct ceph_mds_client *mdsc = &ceph_sb_to_client(inode->i_sb)->mdsc; | 1383 | struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; |
1382 | struct ceph_inode_info *ci = ceph_inode(inode); | 1384 | struct ceph_inode_info *ci = ceph_inode(inode); |
1383 | int flushing; | 1385 | int flushing; |
1384 | 1386 | ||
@@ -1416,17 +1418,6 @@ static int __mark_caps_flushing(struct inode *inode, | |||
1416 | /* | 1418 | /* |
1417 | * try to invalidate mapping pages without blocking. | 1419 | * try to invalidate mapping pages without blocking. |
1418 | */ | 1420 | */ |
1419 | static int mapping_is_empty(struct address_space *mapping) | ||
1420 | { | ||
1421 | struct page *page = find_get_page(mapping, 0); | ||
1422 | |||
1423 | if (!page) | ||
1424 | return 1; | ||
1425 | |||
1426 | put_page(page); | ||
1427 | return 0; | ||
1428 | } | ||
1429 | |||
1430 | static int try_nonblocking_invalidate(struct inode *inode) | 1421 | static int try_nonblocking_invalidate(struct inode *inode) |
1431 | { | 1422 | { |
1432 | struct ceph_inode_info *ci = ceph_inode(inode); | 1423 | struct ceph_inode_info *ci = ceph_inode(inode); |
@@ -1436,12 +1427,12 @@ static int try_nonblocking_invalidate(struct inode *inode) | |||
1436 | invalidate_mapping_pages(&inode->i_data, 0, -1); | 1427 | invalidate_mapping_pages(&inode->i_data, 0, -1); |
1437 | spin_lock(&inode->i_lock); | 1428 | spin_lock(&inode->i_lock); |
1438 | 1429 | ||
1439 | if (mapping_is_empty(&inode->i_data) && | 1430 | if (inode->i_data.nrpages == 0 && |
1440 | invalidating_gen == ci->i_rdcache_gen) { | 1431 | invalidating_gen == ci->i_rdcache_gen) { |
1441 | /* success. */ | 1432 | /* success. */ |
1442 | dout("try_nonblocking_invalidate %p success\n", inode); | 1433 | dout("try_nonblocking_invalidate %p success\n", inode); |
1443 | ci->i_rdcache_gen = 0; | 1434 | /* save any racing async invalidate some trouble */ |
1444 | ci->i_rdcache_revoking = 0; | 1435 | ci->i_rdcache_revoking = ci->i_rdcache_gen - 1; |
1445 | return 0; | 1436 | return 0; |
1446 | } | 1437 | } |
1447 | dout("try_nonblocking_invalidate %p failed\n", inode); | 1438 | dout("try_nonblocking_invalidate %p failed\n", inode); |
@@ -1462,8 +1453,8 @@ static int try_nonblocking_invalidate(struct inode *inode) | |||
1462 | void ceph_check_caps(struct ceph_inode_info *ci, int flags, | 1453 | void ceph_check_caps(struct ceph_inode_info *ci, int flags, |
1463 | struct ceph_mds_session *session) | 1454 | struct ceph_mds_session *session) |
1464 | { | 1455 | { |
1465 | struct ceph_client *client = ceph_inode_to_client(&ci->vfs_inode); | 1456 | struct ceph_fs_client *fsc = ceph_inode_to_client(&ci->vfs_inode); |
1466 | struct ceph_mds_client *mdsc = &client->mdsc; | 1457 | struct ceph_mds_client *mdsc = fsc->mdsc; |
1467 | struct inode *inode = &ci->vfs_inode; | 1458 | struct inode *inode = &ci->vfs_inode; |
1468 | struct ceph_cap *cap; | 1459 | struct ceph_cap *cap; |
1469 | int file_wanted, used; | 1460 | int file_wanted, used; |
@@ -1533,7 +1524,7 @@ retry_locked: | |||
1533 | */ | 1524 | */ |
1534 | if ((!is_delayed || mdsc->stopping) && | 1525 | if ((!is_delayed || mdsc->stopping) && |
1535 | ci->i_wrbuffer_ref == 0 && /* no dirty pages... */ | 1526 | ci->i_wrbuffer_ref == 0 && /* no dirty pages... */ |
1536 | ci->i_rdcache_gen && /* may have cached pages */ | 1527 | inode->i_data.nrpages && /* have cached pages */ |
1537 | (file_wanted == 0 || /* no open files */ | 1528 | (file_wanted == 0 || /* no open files */ |
1538 | (revoking & (CEPH_CAP_FILE_CACHE| | 1529 | (revoking & (CEPH_CAP_FILE_CACHE| |
1539 | CEPH_CAP_FILE_LAZYIO))) && /* or revoking cache */ | 1530 | CEPH_CAP_FILE_LAZYIO))) && /* or revoking cache */ |
@@ -1570,9 +1561,10 @@ retry_locked: | |||
1570 | /* NOTE: no side-effects allowed, until we take s_mutex */ | 1561 | /* NOTE: no side-effects allowed, until we take s_mutex */ |
1571 | 1562 | ||
1572 | revoking = cap->implemented & ~cap->issued; | 1563 | revoking = cap->implemented & ~cap->issued; |
1573 | if (revoking) | 1564 | dout(" mds%d cap %p issued %s implemented %s revoking %s\n", |
1574 | dout(" mds%d revoking %s\n", cap->mds, | 1565 | cap->mds, cap, ceph_cap_string(cap->issued), |
1575 | ceph_cap_string(revoking)); | 1566 | ceph_cap_string(cap->implemented), |
1567 | ceph_cap_string(revoking)); | ||
1576 | 1568 | ||
1577 | if (cap == ci->i_auth_cap && | 1569 | if (cap == ci->i_auth_cap && |
1578 | (cap->issued & CEPH_CAP_FILE_WR)) { | 1570 | (cap->issued & CEPH_CAP_FILE_WR)) { |
@@ -1668,6 +1660,8 @@ ack: | |||
1668 | 1660 | ||
1669 | if (cap == ci->i_auth_cap && ci->i_dirty_caps) | 1661 | if (cap == ci->i_auth_cap && ci->i_dirty_caps) |
1670 | flushing = __mark_caps_flushing(inode, session); | 1662 | flushing = __mark_caps_flushing(inode, session); |
1663 | else | ||
1664 | flushing = 0; | ||
1671 | 1665 | ||
1672 | mds = cap->mds; /* remember mds, so we don't repeat */ | 1666 | mds = cap->mds; /* remember mds, so we don't repeat */ |
1673 | sent++; | 1667 | sent++; |
@@ -1706,7 +1700,7 @@ ack: | |||
1706 | static int try_flush_caps(struct inode *inode, struct ceph_mds_session *session, | 1700 | static int try_flush_caps(struct inode *inode, struct ceph_mds_session *session, |
1707 | unsigned *flush_tid) | 1701 | unsigned *flush_tid) |
1708 | { | 1702 | { |
1709 | struct ceph_mds_client *mdsc = &ceph_sb_to_client(inode->i_sb)->mdsc; | 1703 | struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; |
1710 | struct ceph_inode_info *ci = ceph_inode(inode); | 1704 | struct ceph_inode_info *ci = ceph_inode(inode); |
1711 | int unlock_session = session ? 0 : 1; | 1705 | int unlock_session = session ? 0 : 1; |
1712 | int flushing = 0; | 1706 | int flushing = 0; |
@@ -1872,7 +1866,7 @@ int ceph_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
1872 | caps_are_flushed(inode, flush_tid)); | 1866 | caps_are_flushed(inode, flush_tid)); |
1873 | } else { | 1867 | } else { |
1874 | struct ceph_mds_client *mdsc = | 1868 | struct ceph_mds_client *mdsc = |
1875 | &ceph_sb_to_client(inode->i_sb)->mdsc; | 1869 | ceph_sb_to_client(inode->i_sb)->mdsc; |
1876 | 1870 | ||
1877 | spin_lock(&inode->i_lock); | 1871 | spin_lock(&inode->i_lock); |
1878 | if (__ceph_caps_dirty(ci)) | 1872 | if (__ceph_caps_dirty(ci)) |
@@ -1950,6 +1944,35 @@ void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc, | |||
1950 | } | 1944 | } |
1951 | } | 1945 | } |
1952 | 1946 | ||
1947 | static void kick_flushing_inode_caps(struct ceph_mds_client *mdsc, | ||
1948 | struct ceph_mds_session *session, | ||
1949 | struct inode *inode) | ||
1950 | { | ||
1951 | struct ceph_inode_info *ci = ceph_inode(inode); | ||
1952 | struct ceph_cap *cap; | ||
1953 | int delayed = 0; | ||
1954 | |||
1955 | spin_lock(&inode->i_lock); | ||
1956 | cap = ci->i_auth_cap; | ||
1957 | dout("kick_flushing_inode_caps %p flushing %s flush_seq %lld\n", inode, | ||
1958 | ceph_cap_string(ci->i_flushing_caps), ci->i_cap_flush_seq); | ||
1959 | __ceph_flush_snaps(ci, &session, 1); | ||
1960 | if (ci->i_flushing_caps) { | ||
1961 | delayed = __send_cap(mdsc, cap, CEPH_CAP_OP_FLUSH, | ||
1962 | __ceph_caps_used(ci), | ||
1963 | __ceph_caps_wanted(ci), | ||
1964 | cap->issued | cap->implemented, | ||
1965 | ci->i_flushing_caps, NULL); | ||
1966 | if (delayed) { | ||
1967 | spin_lock(&inode->i_lock); | ||
1968 | __cap_delay_requeue(mdsc, ci); | ||
1969 | spin_unlock(&inode->i_lock); | ||
1970 | } | ||
1971 | } else { | ||
1972 | spin_unlock(&inode->i_lock); | ||
1973 | } | ||
1974 | } | ||
1975 | |||
1953 | 1976 | ||
1954 | /* | 1977 | /* |
1955 | * Take references to capabilities we hold, so that we don't release | 1978 | * Take references to capabilities we hold, so that we don't release |
@@ -1968,11 +1991,11 @@ static void __take_cap_refs(struct ceph_inode_info *ci, int got) | |||
1968 | if (got & CEPH_CAP_FILE_WR) | 1991 | if (got & CEPH_CAP_FILE_WR) |
1969 | ci->i_wr_ref++; | 1992 | ci->i_wr_ref++; |
1970 | if (got & CEPH_CAP_FILE_BUFFER) { | 1993 | if (got & CEPH_CAP_FILE_BUFFER) { |
1971 | if (ci->i_wrbuffer_ref == 0) | 1994 | if (ci->i_wb_ref == 0) |
1972 | igrab(&ci->vfs_inode); | 1995 | ihold(&ci->vfs_inode); |
1973 | ci->i_wrbuffer_ref++; | 1996 | ci->i_wb_ref++; |
1974 | dout("__take_cap_refs %p wrbuffer %d -> %d (?)\n", | 1997 | dout("__take_cap_refs %p wb %d -> %d (?)\n", |
1975 | &ci->vfs_inode, ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref); | 1998 | &ci->vfs_inode, ci->i_wb_ref-1, ci->i_wb_ref); |
1976 | } | 1999 | } |
1977 | } | 2000 | } |
1978 | 2001 | ||
@@ -2147,12 +2170,12 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had) | |||
2147 | if (--ci->i_rdcache_ref == 0) | 2170 | if (--ci->i_rdcache_ref == 0) |
2148 | last++; | 2171 | last++; |
2149 | if (had & CEPH_CAP_FILE_BUFFER) { | 2172 | if (had & CEPH_CAP_FILE_BUFFER) { |
2150 | if (--ci->i_wrbuffer_ref == 0) { | 2173 | if (--ci->i_wb_ref == 0) { |
2151 | last++; | 2174 | last++; |
2152 | put++; | 2175 | put++; |
2153 | } | 2176 | } |
2154 | dout("put_cap_refs %p wrbuffer %d -> %d (?)\n", | 2177 | dout("put_cap_refs %p wb %d -> %d (?)\n", |
2155 | inode, ci->i_wrbuffer_ref+1, ci->i_wrbuffer_ref); | 2178 | inode, ci->i_wb_ref+1, ci->i_wb_ref); |
2156 | } | 2179 | } |
2157 | if (had & CEPH_CAP_FILE_WR) | 2180 | if (had & CEPH_CAP_FILE_WR) |
2158 | if (--ci->i_wr_ref == 0) { | 2181 | if (--ci->i_wr_ref == 0) { |
@@ -2283,8 +2306,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2283 | { | 2306 | { |
2284 | struct ceph_inode_info *ci = ceph_inode(inode); | 2307 | struct ceph_inode_info *ci = ceph_inode(inode); |
2285 | int mds = session->s_mds; | 2308 | int mds = session->s_mds; |
2286 | unsigned seq = le32_to_cpu(grant->seq); | 2309 | int seq = le32_to_cpu(grant->seq); |
2287 | unsigned issue_seq = le32_to_cpu(grant->issue_seq); | ||
2288 | int newcaps = le32_to_cpu(grant->caps); | 2310 | int newcaps = le32_to_cpu(grant->caps); |
2289 | int issued, implemented, used, wanted, dirty; | 2311 | int issued, implemented, used, wanted, dirty; |
2290 | u64 size = le64_to_cpu(grant->size); | 2312 | u64 size = le64_to_cpu(grant->size); |
@@ -2296,8 +2318,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2296 | int revoked_rdcache = 0; | 2318 | int revoked_rdcache = 0; |
2297 | int queue_invalidate = 0; | 2319 | int queue_invalidate = 0; |
2298 | 2320 | ||
2299 | dout("handle_cap_grant inode %p cap %p mds%d seq %u/%u %s\n", | 2321 | dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n", |
2300 | inode, cap, mds, seq, issue_seq, ceph_cap_string(newcaps)); | 2322 | inode, cap, mds, seq, ceph_cap_string(newcaps)); |
2301 | dout(" size %llu max_size %llu, i_size %llu\n", size, max_size, | 2323 | dout(" size %llu max_size %llu, i_size %llu\n", size, max_size, |
2302 | inode->i_size); | 2324 | inode->i_size); |
2303 | 2325 | ||
@@ -2393,7 +2415,6 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2393 | } | 2415 | } |
2394 | 2416 | ||
2395 | cap->seq = seq; | 2417 | cap->seq = seq; |
2396 | cap->issue_seq = issue_seq; | ||
2397 | 2418 | ||
2398 | /* file layout may have changed */ | 2419 | /* file layout may have changed */ |
2399 | ci->i_layout = grant->layout; | 2420 | ci->i_layout = grant->layout; |
@@ -2465,7 +2486,7 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid, | |||
2465 | __releases(inode->i_lock) | 2486 | __releases(inode->i_lock) |
2466 | { | 2487 | { |
2467 | struct ceph_inode_info *ci = ceph_inode(inode); | 2488 | struct ceph_inode_info *ci = ceph_inode(inode); |
2468 | struct ceph_mds_client *mdsc = &ceph_sb_to_client(inode->i_sb)->mdsc; | 2489 | struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; |
2469 | unsigned seq = le32_to_cpu(m->seq); | 2490 | unsigned seq = le32_to_cpu(m->seq); |
2470 | int dirty = le32_to_cpu(m->dirty); | 2491 | int dirty = le32_to_cpu(m->dirty); |
2471 | int cleaned = 0; | 2492 | int cleaned = 0; |
@@ -2614,6 +2635,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, | |||
2614 | struct ceph_mds_session *session, | 2635 | struct ceph_mds_session *session, |
2615 | int *open_target_sessions) | 2636 | int *open_target_sessions) |
2616 | { | 2637 | { |
2638 | struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; | ||
2617 | struct ceph_inode_info *ci = ceph_inode(inode); | 2639 | struct ceph_inode_info *ci = ceph_inode(inode); |
2618 | int mds = session->s_mds; | 2640 | int mds = session->s_mds; |
2619 | unsigned mseq = le32_to_cpu(ex->migrate_seq); | 2641 | unsigned mseq = le32_to_cpu(ex->migrate_seq); |
@@ -2650,6 +2672,19 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, | |||
2650 | * export targets, so that we get the matching IMPORT | 2672 | * export targets, so that we get the matching IMPORT |
2651 | */ | 2673 | */ |
2652 | *open_target_sessions = 1; | 2674 | *open_target_sessions = 1; |
2675 | |||
2676 | /* | ||
2677 | * we can't flush dirty caps that we've seen the | ||
2678 | * EXPORT but no IMPORT for | ||
2679 | */ | ||
2680 | spin_lock(&mdsc->cap_dirty_lock); | ||
2681 | if (!list_empty(&ci->i_dirty_item)) { | ||
2682 | dout(" moving %p to cap_dirty_migrating\n", | ||
2683 | inode); | ||
2684 | list_move(&ci->i_dirty_item, | ||
2685 | &mdsc->cap_dirty_migrating); | ||
2686 | } | ||
2687 | spin_unlock(&mdsc->cap_dirty_lock); | ||
2653 | } | 2688 | } |
2654 | __ceph_remove_cap(cap); | 2689 | __ceph_remove_cap(cap); |
2655 | } | 2690 | } |
@@ -2687,6 +2722,13 @@ static void handle_cap_import(struct ceph_mds_client *mdsc, | |||
2687 | ci->i_cap_exporting_issued = 0; | 2722 | ci->i_cap_exporting_issued = 0; |
2688 | ci->i_cap_exporting_mseq = 0; | 2723 | ci->i_cap_exporting_mseq = 0; |
2689 | ci->i_cap_exporting_mds = -1; | 2724 | ci->i_cap_exporting_mds = -1; |
2725 | |||
2726 | spin_lock(&mdsc->cap_dirty_lock); | ||
2727 | if (!list_empty(&ci->i_dirty_item)) { | ||
2728 | dout(" moving %p back to cap_dirty\n", inode); | ||
2729 | list_move(&ci->i_dirty_item, &mdsc->cap_dirty); | ||
2730 | } | ||
2731 | spin_unlock(&mdsc->cap_dirty_lock); | ||
2690 | } else { | 2732 | } else { |
2691 | dout("handle_cap_import inode %p ci %p mds%d mseq %d\n", | 2733 | dout("handle_cap_import inode %p ci %p mds%d mseq %d\n", |
2692 | inode, ci, mds, mseq); | 2734 | inode, ci, mds, mseq); |
@@ -2699,8 +2741,13 @@ static void handle_cap_import(struct ceph_mds_client *mdsc, | |||
2699 | ceph_add_cap(inode, session, cap_id, -1, | 2741 | ceph_add_cap(inode, session, cap_id, -1, |
2700 | issued, wanted, seq, mseq, realmino, CEPH_CAP_FLAG_AUTH, | 2742 | issued, wanted, seq, mseq, realmino, CEPH_CAP_FLAG_AUTH, |
2701 | NULL /* no caps context */); | 2743 | NULL /* no caps context */); |
2702 | try_flush_caps(inode, session, NULL); | 2744 | kick_flushing_inode_caps(mdsc, session, inode); |
2703 | up_read(&mdsc->snap_rwsem); | 2745 | up_read(&mdsc->snap_rwsem); |
2746 | |||
2747 | /* make sure we re-request max_size, if necessary */ | ||
2748 | spin_lock(&inode->i_lock); | ||
2749 | ci->i_requested_max_size = 0; | ||
2750 | spin_unlock(&inode->i_lock); | ||
2704 | } | 2751 | } |
2705 | 2752 | ||
2706 | /* | 2753 | /* |
@@ -2713,7 +2760,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
2713 | struct ceph_msg *msg) | 2760 | struct ceph_msg *msg) |
2714 | { | 2761 | { |
2715 | struct ceph_mds_client *mdsc = session->s_mdsc; | 2762 | struct ceph_mds_client *mdsc = session->s_mdsc; |
2716 | struct super_block *sb = mdsc->client->sb; | 2763 | struct super_block *sb = mdsc->fsc->sb; |
2717 | struct inode *inode; | 2764 | struct inode *inode; |
2718 | struct ceph_cap *cap; | 2765 | struct ceph_cap *cap; |
2719 | struct ceph_mds_caps *h; | 2766 | struct ceph_mds_caps *h; |
@@ -2792,8 +2839,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
2792 | case CEPH_CAP_OP_IMPORT: | 2839 | case CEPH_CAP_OP_IMPORT: |
2793 | handle_cap_import(mdsc, inode, h, session, | 2840 | handle_cap_import(mdsc, inode, h, session, |
2794 | snaptrace, snaptrace_len); | 2841 | snaptrace, snaptrace_len); |
2795 | ceph_check_caps(ceph_inode(inode), CHECK_CAPS_NODELAY, | 2842 | ceph_check_caps(ceph_inode(inode), 0, session); |
2796 | session); | ||
2797 | goto done_unlocked; | 2843 | goto done_unlocked; |
2798 | } | 2844 | } |
2799 | 2845 | ||
@@ -2886,47 +2932,24 @@ void ceph_check_delayed_caps(struct ceph_mds_client *mdsc) | |||
2886 | */ | 2932 | */ |
2887 | void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc) | 2933 | void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc) |
2888 | { | 2934 | { |
2889 | struct ceph_inode_info *ci, *nci = NULL; | 2935 | struct ceph_inode_info *ci; |
2890 | struct inode *inode, *ninode = NULL; | 2936 | struct inode *inode; |
2891 | struct list_head *p, *n; | ||
2892 | 2937 | ||
2893 | dout("flush_dirty_caps\n"); | 2938 | dout("flush_dirty_caps\n"); |
2894 | spin_lock(&mdsc->cap_dirty_lock); | 2939 | spin_lock(&mdsc->cap_dirty_lock); |
2895 | list_for_each_safe(p, n, &mdsc->cap_dirty) { | 2940 | while (!list_empty(&mdsc->cap_dirty)) { |
2896 | if (nci) { | 2941 | ci = list_first_entry(&mdsc->cap_dirty, struct ceph_inode_info, |
2897 | ci = nci; | 2942 | i_dirty_item); |
2898 | inode = ninode; | 2943 | inode = &ci->vfs_inode; |
2899 | ci->i_ceph_flags &= ~CEPH_I_NOFLUSH; | 2944 | ihold(inode); |
2900 | dout("flush_dirty_caps inode %p (was next inode)\n", | 2945 | dout("flush_dirty_caps %p\n", inode); |
2901 | inode); | ||
2902 | } else { | ||
2903 | ci = list_entry(p, struct ceph_inode_info, | ||
2904 | i_dirty_item); | ||
2905 | inode = igrab(&ci->vfs_inode); | ||
2906 | BUG_ON(!inode); | ||
2907 | dout("flush_dirty_caps inode %p\n", inode); | ||
2908 | } | ||
2909 | if (n != &mdsc->cap_dirty) { | ||
2910 | nci = list_entry(n, struct ceph_inode_info, | ||
2911 | i_dirty_item); | ||
2912 | ninode = igrab(&nci->vfs_inode); | ||
2913 | BUG_ON(!ninode); | ||
2914 | nci->i_ceph_flags |= CEPH_I_NOFLUSH; | ||
2915 | dout("flush_dirty_caps next inode %p, noflush\n", | ||
2916 | ninode); | ||
2917 | } else { | ||
2918 | nci = NULL; | ||
2919 | ninode = NULL; | ||
2920 | } | ||
2921 | spin_unlock(&mdsc->cap_dirty_lock); | 2946 | spin_unlock(&mdsc->cap_dirty_lock); |
2922 | if (inode) { | 2947 | ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_FLUSH, NULL); |
2923 | ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_FLUSH, | 2948 | iput(inode); |
2924 | NULL); | ||
2925 | iput(inode); | ||
2926 | } | ||
2927 | spin_lock(&mdsc->cap_dirty_lock); | 2949 | spin_lock(&mdsc->cap_dirty_lock); |
2928 | } | 2950 | } |
2929 | spin_unlock(&mdsc->cap_dirty_lock); | 2951 | spin_unlock(&mdsc->cap_dirty_lock); |
2952 | dout("flush_dirty_caps done\n"); | ||
2930 | } | 2953 | } |
2931 | 2954 | ||
2932 | /* | 2955 | /* |