aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ceph/snap.c26
-rw-r--r--fs/ceph/super.c10
-rw-r--r--fs/ceph/super.h2
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
292static 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
377done:
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
941int __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 950void 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
1039out_icache: 1042out_snap:
1043 ceph_snap_exit();
1044out_xattr:
1040 ceph_xattr_exit(); 1045 ceph_xattr_exit();
1041 destroy_caches(); 1046 destroy_caches();
1042out: 1047out:
@@ -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);
699extern int __ceph_finish_cap_snap(struct ceph_inode_info *ci, 699extern int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
700 struct ceph_cap_snap *capsnap); 700 struct ceph_cap_snap *capsnap);
701extern void ceph_cleanup_empty_realms(struct ceph_mds_client *mdsc); 701extern void ceph_cleanup_empty_realms(struct ceph_mds_client *mdsc);
702extern int ceph_snap_init(void);
703extern 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