diff options
-rw-r--r-- | fs/ceph/snap.c | 26 | ||||
-rw-r--r-- | fs/ceph/super.c | 10 | ||||
-rw-r--r-- | fs/ceph/super.h | 2 |
3 files changed, 35 insertions, 3 deletions
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index c1cc993225e3..f64576e72b79 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c | |||
@@ -288,6 +288,9 @@ static int cmpu64_rev(const void *a, const void *b) | |||
288 | return 0; | 288 | return 0; |
289 | } | 289 | } |
290 | 290 | ||
291 | |||
292 | static struct ceph_snap_context *empty_snapc; | ||
293 | |||
291 | /* | 294 | /* |
292 | * build the snap context for a given realm. | 295 | * build the snap context for a given realm. |
293 | */ | 296 | */ |
@@ -328,6 +331,12 @@ static int build_snap_context(struct ceph_snap_realm *realm) | |||
328 | return 0; | 331 | return 0; |
329 | } | 332 | } |
330 | 333 | ||
334 | if (num == 0 && realm->seq == empty_snapc->seq) { | ||
335 | ceph_get_snap_context(empty_snapc); | ||
336 | snapc = empty_snapc; | ||
337 | goto done; | ||
338 | } | ||
339 | |||
331 | /* alloc new snap context */ | 340 | /* alloc new snap context */ |
332 | err = -ENOMEM; | 341 | err = -ENOMEM; |
333 | if (num > (SIZE_MAX - sizeof(*snapc)) / sizeof(u64)) | 342 | if (num > (SIZE_MAX - sizeof(*snapc)) / sizeof(u64)) |
@@ -365,6 +374,7 @@ static int build_snap_context(struct ceph_snap_realm *realm) | |||
365 | realm->ino, realm, snapc, snapc->seq, | 374 | realm->ino, realm, snapc, snapc->seq, |
366 | (unsigned int) snapc->num_snaps); | 375 | (unsigned int) snapc->num_snaps); |
367 | 376 | ||
377 | done: | ||
368 | ceph_put_snap_context(realm->cached_context); | 378 | ceph_put_snap_context(realm->cached_context); |
369 | realm->cached_context = snapc; | 379 | realm->cached_context = snapc; |
370 | return 0; | 380 | return 0; |
@@ -465,6 +475,9 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci) | |||
465 | cap_snap. lucky us. */ | 475 | cap_snap. lucky us. */ |
466 | dout("queue_cap_snap %p already pending\n", inode); | 476 | dout("queue_cap_snap %p already pending\n", inode); |
467 | kfree(capsnap); | 477 | kfree(capsnap); |
478 | } else if (ci->i_snap_realm->cached_context == empty_snapc) { | ||
479 | dout("queue_cap_snap %p empty snapc\n", inode); | ||
480 | kfree(capsnap); | ||
468 | } else if (dirty & (CEPH_CAP_AUTH_EXCL|CEPH_CAP_XATTR_EXCL| | 481 | } else if (dirty & (CEPH_CAP_AUTH_EXCL|CEPH_CAP_XATTR_EXCL| |
469 | CEPH_CAP_FILE_EXCL|CEPH_CAP_FILE_WR)) { | 482 | CEPH_CAP_FILE_EXCL|CEPH_CAP_FILE_WR)) { |
470 | struct ceph_snap_context *snapc = ci->i_head_snapc; | 483 | struct ceph_snap_context *snapc = ci->i_head_snapc; |
@@ -925,5 +938,16 @@ out: | |||
925 | return; | 938 | return; |
926 | } | 939 | } |
927 | 940 | ||
941 | int __init ceph_snap_init(void) | ||
942 | { | ||
943 | empty_snapc = ceph_create_snap_context(0, GFP_NOFS); | ||
944 | if (!empty_snapc) | ||
945 | return -ENOMEM; | ||
946 | empty_snapc->seq = 1; | ||
947 | return 0; | ||
948 | } | ||
928 | 949 | ||
929 | 950 | void ceph_snap_exit(void) | |
951 | { | ||
952 | ceph_put_snap_context(empty_snapc); | ||
953 | } | ||
diff --git a/fs/ceph/super.c b/fs/ceph/super.c index f6e12377335c..3b5c1e3335db 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c | |||
@@ -1028,15 +1028,20 @@ static int __init init_ceph(void) | |||
1028 | 1028 | ||
1029 | ceph_flock_init(); | 1029 | ceph_flock_init(); |
1030 | ceph_xattr_init(); | 1030 | ceph_xattr_init(); |
1031 | ret = ceph_snap_init(); | ||
1032 | if (ret) | ||
1033 | goto out_xattr; | ||
1031 | ret = register_filesystem(&ceph_fs_type); | 1034 | ret = register_filesystem(&ceph_fs_type); |
1032 | if (ret) | 1035 | if (ret) |
1033 | goto out_icache; | 1036 | goto out_snap; |
1034 | 1037 | ||
1035 | pr_info("loaded (mds proto %d)\n", CEPH_MDSC_PROTOCOL); | 1038 | pr_info("loaded (mds proto %d)\n", CEPH_MDSC_PROTOCOL); |
1036 | 1039 | ||
1037 | return 0; | 1040 | return 0; |
1038 | 1041 | ||
1039 | out_icache: | 1042 | out_snap: |
1043 | ceph_snap_exit(); | ||
1044 | out_xattr: | ||
1040 | ceph_xattr_exit(); | 1045 | ceph_xattr_exit(); |
1041 | destroy_caches(); | 1046 | destroy_caches(); |
1042 | out: | 1047 | out: |
@@ -1047,6 +1052,7 @@ static void __exit exit_ceph(void) | |||
1047 | { | 1052 | { |
1048 | dout("exit_ceph\n"); | 1053 | dout("exit_ceph\n"); |
1049 | unregister_filesystem(&ceph_fs_type); | 1054 | unregister_filesystem(&ceph_fs_type); |
1055 | ceph_snap_exit(); | ||
1050 | ceph_xattr_exit(); | 1056 | ceph_xattr_exit(); |
1051 | destroy_caches(); | 1057 | destroy_caches(); |
1052 | } | 1058 | } |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index aca22879b41f..fc1c8255dead 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -699,6 +699,8 @@ extern void ceph_queue_cap_snap(struct ceph_inode_info *ci); | |||
699 | extern int __ceph_finish_cap_snap(struct ceph_inode_info *ci, | 699 | extern int __ceph_finish_cap_snap(struct ceph_inode_info *ci, |
700 | struct ceph_cap_snap *capsnap); | 700 | struct ceph_cap_snap *capsnap); |
701 | extern void ceph_cleanup_empty_realms(struct ceph_mds_client *mdsc); | 701 | extern void ceph_cleanup_empty_realms(struct ceph_mds_client *mdsc); |
702 | extern int ceph_snap_init(void); | ||
703 | extern void ceph_snap_exit(void); | ||
702 | 704 | ||
703 | /* | 705 | /* |
704 | * a cap_snap is "pending" if it is still awaiting an in-progress | 706 | * a cap_snap is "pending" if it is still awaiting an in-progress |