diff options
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r-- | fs/ceph/caps.c | 91 |
1 files changed, 46 insertions, 45 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 5323c330bbf3..1f72b00447c4 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -569,7 +569,8 @@ retry: | |||
569 | list_add_tail(&cap->session_caps, &session->s_caps); | 569 | list_add_tail(&cap->session_caps, &session->s_caps); |
570 | session->s_nr_caps++; | 570 | session->s_nr_caps++; |
571 | spin_unlock(&session->s_cap_lock); | 571 | spin_unlock(&session->s_cap_lock); |
572 | } | 572 | } else if (new_cap) |
573 | ceph_put_cap(mdsc, new_cap); | ||
573 | 574 | ||
574 | if (!ci->i_snap_realm) { | 575 | if (!ci->i_snap_realm) { |
575 | /* | 576 | /* |
@@ -819,7 +820,7 @@ int __ceph_caps_used(struct ceph_inode_info *ci) | |||
819 | used |= CEPH_CAP_FILE_CACHE; | 820 | used |= CEPH_CAP_FILE_CACHE; |
820 | if (ci->i_wr_ref) | 821 | if (ci->i_wr_ref) |
821 | used |= CEPH_CAP_FILE_WR; | 822 | used |= CEPH_CAP_FILE_WR; |
822 | if (ci->i_wrbuffer_ref) | 823 | if (ci->i_wb_ref || ci->i_wrbuffer_ref) |
823 | used |= CEPH_CAP_FILE_BUFFER; | 824 | used |= CEPH_CAP_FILE_BUFFER; |
824 | return used; | 825 | return used; |
825 | } | 826 | } |
@@ -1331,10 +1332,11 @@ static void ceph_flush_snaps(struct ceph_inode_info *ci) | |||
1331 | } | 1332 | } |
1332 | 1333 | ||
1333 | /* | 1334 | /* |
1334 | * 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. |
1335 | * list. | 1336 | * Caller is then responsible for calling __mark_inode_dirty with the |
1337 | * returned flags value. | ||
1336 | */ | 1338 | */ |
1337 | 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) |
1338 | { | 1340 | { |
1339 | struct ceph_mds_client *mdsc = | 1341 | struct ceph_mds_client *mdsc = |
1340 | ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc; | 1342 | ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc; |
@@ -1357,7 +1359,7 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) | |||
1357 | list_add(&ci->i_dirty_item, &mdsc->cap_dirty); | 1359 | list_add(&ci->i_dirty_item, &mdsc->cap_dirty); |
1358 | spin_unlock(&mdsc->cap_dirty_lock); | 1360 | spin_unlock(&mdsc->cap_dirty_lock); |
1359 | if (ci->i_flushing_caps == 0) { | 1361 | if (ci->i_flushing_caps == 0) { |
1360 | igrab(inode); | 1362 | ihold(inode); |
1361 | dirty |= I_DIRTY_SYNC; | 1363 | dirty |= I_DIRTY_SYNC; |
1362 | } | 1364 | } |
1363 | } | 1365 | } |
@@ -1365,9 +1367,8 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) | |||
1365 | if (((was | ci->i_flushing_caps) & CEPH_CAP_FILE_BUFFER) && | 1367 | if (((was | ci->i_flushing_caps) & CEPH_CAP_FILE_BUFFER) && |
1366 | (mask & CEPH_CAP_FILE_BUFFER)) | 1368 | (mask & CEPH_CAP_FILE_BUFFER)) |
1367 | dirty |= I_DIRTY_DATASYNC; | 1369 | dirty |= I_DIRTY_DATASYNC; |
1368 | if (dirty) | ||
1369 | __mark_inode_dirty(inode, dirty); | ||
1370 | __cap_delay_requeue(mdsc, ci); | 1370 | __cap_delay_requeue(mdsc, ci); |
1371 | return dirty; | ||
1371 | } | 1372 | } |
1372 | 1373 | ||
1373 | /* | 1374 | /* |
@@ -1990,11 +1991,11 @@ static void __take_cap_refs(struct ceph_inode_info *ci, int got) | |||
1990 | if (got & CEPH_CAP_FILE_WR) | 1991 | if (got & CEPH_CAP_FILE_WR) |
1991 | ci->i_wr_ref++; | 1992 | ci->i_wr_ref++; |
1992 | if (got & CEPH_CAP_FILE_BUFFER) { | 1993 | if (got & CEPH_CAP_FILE_BUFFER) { |
1993 | if (ci->i_wrbuffer_ref == 0) | 1994 | if (ci->i_wb_ref == 0) |
1994 | igrab(&ci->vfs_inode); | 1995 | ihold(&ci->vfs_inode); |
1995 | ci->i_wrbuffer_ref++; | 1996 | ci->i_wb_ref++; |
1996 | dout("__take_cap_refs %p wrbuffer %d -> %d (?)\n", | 1997 | dout("__take_cap_refs %p wb %d -> %d (?)\n", |
1997 | &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); |
1998 | } | 1999 | } |
1999 | } | 2000 | } |
2000 | 2001 | ||
@@ -2169,12 +2170,12 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had) | |||
2169 | if (--ci->i_rdcache_ref == 0) | 2170 | if (--ci->i_rdcache_ref == 0) |
2170 | last++; | 2171 | last++; |
2171 | if (had & CEPH_CAP_FILE_BUFFER) { | 2172 | if (had & CEPH_CAP_FILE_BUFFER) { |
2172 | if (--ci->i_wrbuffer_ref == 0) { | 2173 | if (--ci->i_wb_ref == 0) { |
2173 | last++; | 2174 | last++; |
2174 | put++; | 2175 | put++; |
2175 | } | 2176 | } |
2176 | dout("put_cap_refs %p wrbuffer %d -> %d (?)\n", | 2177 | dout("put_cap_refs %p wb %d -> %d (?)\n", |
2177 | inode, ci->i_wrbuffer_ref+1, ci->i_wrbuffer_ref); | 2178 | inode, ci->i_wb_ref+1, ci->i_wb_ref); |
2178 | } | 2179 | } |
2179 | if (had & CEPH_CAP_FILE_WR) | 2180 | if (had & CEPH_CAP_FILE_WR) |
2180 | if (--ci->i_wr_ref == 0) { | 2181 | if (--ci->i_wr_ref == 0) { |
@@ -2634,6 +2635,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, | |||
2634 | struct ceph_mds_session *session, | 2635 | struct ceph_mds_session *session, |
2635 | int *open_target_sessions) | 2636 | int *open_target_sessions) |
2636 | { | 2637 | { |
2638 | struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; | ||
2637 | struct ceph_inode_info *ci = ceph_inode(inode); | 2639 | struct ceph_inode_info *ci = ceph_inode(inode); |
2638 | int mds = session->s_mds; | 2640 | int mds = session->s_mds; |
2639 | unsigned mseq = le32_to_cpu(ex->migrate_seq); | 2641 | unsigned mseq = le32_to_cpu(ex->migrate_seq); |
@@ -2670,6 +2672,19 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, | |||
2670 | * export targets, so that we get the matching IMPORT | 2672 | * export targets, so that we get the matching IMPORT |
2671 | */ | 2673 | */ |
2672 | *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); | ||
2673 | } | 2688 | } |
2674 | __ceph_remove_cap(cap); | 2689 | __ceph_remove_cap(cap); |
2675 | } | 2690 | } |
@@ -2707,6 +2722,13 @@ static void handle_cap_import(struct ceph_mds_client *mdsc, | |||
2707 | ci->i_cap_exporting_issued = 0; | 2722 | ci->i_cap_exporting_issued = 0; |
2708 | ci->i_cap_exporting_mseq = 0; | 2723 | ci->i_cap_exporting_mseq = 0; |
2709 | 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); | ||
2710 | } else { | 2732 | } else { |
2711 | 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", |
2712 | inode, ci, mds, mseq); | 2734 | inode, ci, mds, mseq); |
@@ -2910,38 +2932,16 @@ void ceph_check_delayed_caps(struct ceph_mds_client *mdsc) | |||
2910 | */ | 2932 | */ |
2911 | void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc) | 2933 | void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc) |
2912 | { | 2934 | { |
2913 | struct ceph_inode_info *ci, *nci = NULL; | 2935 | struct ceph_inode_info *ci; |
2914 | struct inode *inode, *ninode = NULL; | 2936 | struct inode *inode; |
2915 | struct list_head *p, *n; | ||
2916 | 2937 | ||
2917 | dout("flush_dirty_caps\n"); | 2938 | dout("flush_dirty_caps\n"); |
2918 | spin_lock(&mdsc->cap_dirty_lock); | 2939 | spin_lock(&mdsc->cap_dirty_lock); |
2919 | list_for_each_safe(p, n, &mdsc->cap_dirty) { | 2940 | while (!list_empty(&mdsc->cap_dirty)) { |
2920 | if (nci) { | 2941 | ci = list_first_entry(&mdsc->cap_dirty, struct ceph_inode_info, |
2921 | ci = nci; | 2942 | i_dirty_item); |
2922 | inode = ninode; | 2943 | inode = igrab(&ci->vfs_inode); |
2923 | ci->i_ceph_flags &= ~CEPH_I_NOFLUSH; | 2944 | dout("flush_dirty_caps %p\n", inode); |
2924 | dout("flush_dirty_caps inode %p (was next inode)\n", | ||
2925 | inode); | ||
2926 | } else { | ||
2927 | ci = list_entry(p, struct ceph_inode_info, | ||
2928 | i_dirty_item); | ||
2929 | inode = igrab(&ci->vfs_inode); | ||
2930 | BUG_ON(!inode); | ||
2931 | dout("flush_dirty_caps inode %p\n", inode); | ||
2932 | } | ||
2933 | if (n != &mdsc->cap_dirty) { | ||
2934 | nci = list_entry(n, struct ceph_inode_info, | ||
2935 | i_dirty_item); | ||
2936 | ninode = igrab(&nci->vfs_inode); | ||
2937 | BUG_ON(!ninode); | ||
2938 | nci->i_ceph_flags |= CEPH_I_NOFLUSH; | ||
2939 | dout("flush_dirty_caps next inode %p, noflush\n", | ||
2940 | ninode); | ||
2941 | } else { | ||
2942 | nci = NULL; | ||
2943 | ninode = NULL; | ||
2944 | } | ||
2945 | spin_unlock(&mdsc->cap_dirty_lock); | 2945 | spin_unlock(&mdsc->cap_dirty_lock); |
2946 | if (inode) { | 2946 | if (inode) { |
2947 | ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_FLUSH, | 2947 | ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_FLUSH, |
@@ -2951,6 +2951,7 @@ void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc) | |||
2951 | spin_lock(&mdsc->cap_dirty_lock); | 2951 | spin_lock(&mdsc->cap_dirty_lock); |
2952 | } | 2952 | } |
2953 | spin_unlock(&mdsc->cap_dirty_lock); | 2953 | spin_unlock(&mdsc->cap_dirty_lock); |
2954 | dout("flush_dirty_caps done\n"); | ||
2954 | } | 2955 | } |
2955 | 2956 | ||
2956 | /* | 2957 | /* |