aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-06-11 12:52:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-06-11 12:52:23 -0400
commit63c70a0d7b59bac08bd14cd24c36f76aafc25de6 (patch)
tree6dfc58c856e2ce3ca274d8d9f11f1b46cbe727c3 /fs
parent1082345290dbc66c19877662cb24c18ee4ae1296 (diff)
parent2b2300d62ea413bec631d5b880effa2cc5363acb (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: ceph: try to send partial cap release on cap message on missing inode ceph: release cap on import if we don't have the inode ceph: fix misleading/incorrect debug message ceph: fix atomic64_t initialization on ia64 ceph: fix lease revocation when seq doesn't match ceph: fix f_namelen reported by statfs ceph: fix memory leak in statfs ceph: fix d_subdirs ordering problem
Diffstat (limited to 'fs')
-rw-r--r--fs/ceph/caps.c93
-rw-r--r--fs/ceph/inode.c2
-rw-r--r--fs/ceph/mds_client.c28
-rw-r--r--fs/ceph/mds_client.h6
-rw-r--r--fs/ceph/mon_client.c2
-rw-r--r--fs/ceph/super.c4
6 files changed, 84 insertions, 51 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index ae3e3a306445..619b61655ee5 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -981,6 +981,46 @@ static int send_cap_msg(struct ceph_mds_session *session,
981 return 0; 981 return 0;
982} 982}
983 983
984static void __queue_cap_release(struct ceph_mds_session *session,
985 u64 ino, u64 cap_id, u32 migrate_seq,
986 u32 issue_seq)
987{
988 struct ceph_msg *msg;
989 struct ceph_mds_cap_release *head;
990 struct ceph_mds_cap_item *item;
991
992 spin_lock(&session->s_cap_lock);
993 BUG_ON(!session->s_num_cap_releases);
994 msg = list_first_entry(&session->s_cap_releases,
995 struct ceph_msg, list_head);
996
997 dout(" adding %llx release to mds%d msg %p (%d left)\n",
998 ino, session->s_mds, msg, session->s_num_cap_releases);
999
1000 BUG_ON(msg->front.iov_len + sizeof(*item) > PAGE_CACHE_SIZE);
1001 head = msg->front.iov_base;
1002 head->num = cpu_to_le32(le32_to_cpu(head->num) + 1);
1003 item = msg->front.iov_base + msg->front.iov_len;
1004 item->ino = cpu_to_le64(ino);
1005 item->cap_id = cpu_to_le64(cap_id);
1006 item->migrate_seq = cpu_to_le32(migrate_seq);
1007 item->seq = cpu_to_le32(issue_seq);
1008
1009 session->s_num_cap_releases--;
1010
1011 msg->front.iov_len += sizeof(*item);
1012 if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) {
1013 dout(" release msg %p full\n", msg);
1014 list_move_tail(&msg->list_head, &session->s_cap_releases_done);
1015 } else {
1016 dout(" release msg %p at %d/%d (%d)\n", msg,
1017 (int)le32_to_cpu(head->num),
1018 (int)CEPH_CAPS_PER_RELEASE,
1019 (int)msg->front.iov_len);
1020 }
1021 spin_unlock(&session->s_cap_lock);
1022}
1023
984/* 1024/*
985 * Queue cap releases when an inode is dropped from our cache. Since 1025 * Queue cap releases when an inode is dropped from our cache. Since
986 * inode is about to be destroyed, there is no need for i_lock. 1026 * inode is about to be destroyed, there is no need for i_lock.
@@ -994,41 +1034,9 @@ void ceph_queue_caps_release(struct inode *inode)
994 while (p) { 1034 while (p) {
995 struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node); 1035 struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node);
996 struct ceph_mds_session *session = cap->session; 1036 struct ceph_mds_session *session = cap->session;
997 struct ceph_msg *msg;
998 struct ceph_mds_cap_release *head;
999 struct ceph_mds_cap_item *item;
1000 1037
1001 spin_lock(&session->s_cap_lock); 1038 __queue_cap_release(session, ceph_ino(inode), cap->cap_id,
1002 BUG_ON(!session->s_num_cap_releases); 1039 cap->mseq, cap->issue_seq);
1003 msg = list_first_entry(&session->s_cap_releases,
1004 struct ceph_msg, list_head);
1005
1006 dout(" adding %p release to mds%d msg %p (%d left)\n",
1007 inode, session->s_mds, msg, session->s_num_cap_releases);
1008
1009 BUG_ON(msg->front.iov_len + sizeof(*item) > PAGE_CACHE_SIZE);
1010 head = msg->front.iov_base;
1011 head->num = cpu_to_le32(le32_to_cpu(head->num) + 1);
1012 item = msg->front.iov_base + msg->front.iov_len;
1013 item->ino = cpu_to_le64(ceph_ino(inode));
1014 item->cap_id = cpu_to_le64(cap->cap_id);
1015 item->migrate_seq = cpu_to_le32(cap->mseq);
1016 item->seq = cpu_to_le32(cap->issue_seq);
1017
1018 session->s_num_cap_releases--;
1019
1020 msg->front.iov_len += sizeof(*item);
1021 if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) {
1022 dout(" release msg %p full\n", msg);
1023 list_move_tail(&msg->list_head,
1024 &session->s_cap_releases_done);
1025 } else {
1026 dout(" release msg %p at %d/%d (%d)\n", msg,
1027 (int)le32_to_cpu(head->num),
1028 (int)CEPH_CAPS_PER_RELEASE,
1029 (int)msg->front.iov_len);
1030 }
1031 spin_unlock(&session->s_cap_lock);
1032 p = rb_next(p); 1040 p = rb_next(p);
1033 __ceph_remove_cap(cap); 1041 __ceph_remove_cap(cap);
1034 } 1042 }
@@ -2655,7 +2663,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
2655 struct ceph_mds_caps *h; 2663 struct ceph_mds_caps *h;
2656 int mds = session->s_mds; 2664 int mds = session->s_mds;
2657 int op; 2665 int op;
2658 u32 seq; 2666 u32 seq, mseq;
2659 struct ceph_vino vino; 2667 struct ceph_vino vino;
2660 u64 cap_id; 2668 u64 cap_id;
2661 u64 size, max_size; 2669 u64 size, max_size;
@@ -2675,6 +2683,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
2675 vino.snap = CEPH_NOSNAP; 2683 vino.snap = CEPH_NOSNAP;
2676 cap_id = le64_to_cpu(h->cap_id); 2684 cap_id = le64_to_cpu(h->cap_id);
2677 seq = le32_to_cpu(h->seq); 2685 seq = le32_to_cpu(h->seq);
2686 mseq = le32_to_cpu(h->migrate_seq);
2678 size = le64_to_cpu(h->size); 2687 size = le64_to_cpu(h->size);
2679 max_size = le64_to_cpu(h->max_size); 2688 max_size = le64_to_cpu(h->max_size);
2680 2689
@@ -2689,6 +2698,18 @@ void ceph_handle_caps(struct ceph_mds_session *session,
2689 vino.snap, inode); 2698 vino.snap, inode);
2690 if (!inode) { 2699 if (!inode) {
2691 dout(" i don't have ino %llx\n", vino.ino); 2700 dout(" i don't have ino %llx\n", vino.ino);
2701
2702 if (op == CEPH_CAP_OP_IMPORT)
2703 __queue_cap_release(session, vino.ino, cap_id,
2704 mseq, seq);
2705
2706 /*
2707 * send any full release message to try to move things
2708 * along for the mds (who clearly thinks we still have this
2709 * cap).
2710 */
2711 ceph_add_cap_releases(mdsc, session, -1);
2712 ceph_send_cap_releases(mdsc, session);
2692 goto done; 2713 goto done;
2693 } 2714 }
2694 2715
@@ -2714,7 +2735,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
2714 spin_lock(&inode->i_lock); 2735 spin_lock(&inode->i_lock);
2715 cap = __get_cap_for_mds(ceph_inode(inode), mds); 2736 cap = __get_cap_for_mds(ceph_inode(inode), mds);
2716 if (!cap) { 2737 if (!cap) {
2717 dout("no cap on %p ino %llx.%llx from mds%d, releasing\n", 2738 dout(" no cap on %p ino %llx.%llx from mds%d\n",
2718 inode, ceph_ino(inode), ceph_snap(inode), mds); 2739 inode, ceph_ino(inode), ceph_snap(inode), mds);
2719 spin_unlock(&inode->i_lock); 2740 spin_unlock(&inode->i_lock);
2720 goto done; 2741 goto done;
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 226f5a50d362..ab47f46ca282 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -827,7 +827,7 @@ static void ceph_set_dentry_offset(struct dentry *dn)
827 827
828 spin_lock(&dcache_lock); 828 spin_lock(&dcache_lock);
829 spin_lock(&dn->d_lock); 829 spin_lock(&dn->d_lock);
830 list_move_tail(&dir->d_subdirs, &dn->d_u.d_child); 830 list_move(&dn->d_u.d_child, &dir->d_subdirs);
831 dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset, 831 dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset,
832 dn->d_u.d_child.prev, dn->d_u.d_child.next); 832 dn->d_u.d_child.prev, dn->d_u.d_child.next);
833 spin_unlock(&dn->d_lock); 833 spin_unlock(&dn->d_lock);
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index b49f12822cbc..1766947fc07a 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1066,9 +1066,9 @@ static int trim_caps(struct ceph_mds_client *mdsc,
1066 * 1066 *
1067 * Called under s_mutex. 1067 * Called under s_mutex.
1068 */ 1068 */
1069static int add_cap_releases(struct ceph_mds_client *mdsc, 1069int ceph_add_cap_releases(struct ceph_mds_client *mdsc,
1070 struct ceph_mds_session *session, 1070 struct ceph_mds_session *session,
1071 int extra) 1071 int extra)
1072{ 1072{
1073 struct ceph_msg *msg; 1073 struct ceph_msg *msg;
1074 struct ceph_mds_cap_release *head; 1074 struct ceph_mds_cap_release *head;
@@ -1176,8 +1176,8 @@ static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq)
1176/* 1176/*
1177 * called under s_mutex 1177 * called under s_mutex
1178 */ 1178 */
1179static void send_cap_releases(struct ceph_mds_client *mdsc, 1179void ceph_send_cap_releases(struct ceph_mds_client *mdsc,
1180 struct ceph_mds_session *session) 1180 struct ceph_mds_session *session)
1181{ 1181{
1182 struct ceph_msg *msg; 1182 struct ceph_msg *msg;
1183 1183
@@ -1980,7 +1980,7 @@ out_err:
1980 } 1980 }
1981 mutex_unlock(&mdsc->mutex); 1981 mutex_unlock(&mdsc->mutex);
1982 1982
1983 add_cap_releases(mdsc, req->r_session, -1); 1983 ceph_add_cap_releases(mdsc, req->r_session, -1);
1984 mutex_unlock(&session->s_mutex); 1984 mutex_unlock(&session->s_mutex);
1985 1985
1986 /* kick calling process */ 1986 /* kick calling process */
@@ -2433,6 +2433,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
2433 struct ceph_dentry_info *di; 2433 struct ceph_dentry_info *di;
2434 int mds = session->s_mds; 2434 int mds = session->s_mds;
2435 struct ceph_mds_lease *h = msg->front.iov_base; 2435 struct ceph_mds_lease *h = msg->front.iov_base;
2436 u32 seq;
2436 struct ceph_vino vino; 2437 struct ceph_vino vino;
2437 int mask; 2438 int mask;
2438 struct qstr dname; 2439 struct qstr dname;
@@ -2446,6 +2447,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
2446 vino.ino = le64_to_cpu(h->ino); 2447 vino.ino = le64_to_cpu(h->ino);
2447 vino.snap = CEPH_NOSNAP; 2448 vino.snap = CEPH_NOSNAP;
2448 mask = le16_to_cpu(h->mask); 2449 mask = le16_to_cpu(h->mask);
2450 seq = le32_to_cpu(h->seq);
2449 dname.name = (void *)h + sizeof(*h) + sizeof(u32); 2451 dname.name = (void *)h + sizeof(*h) + sizeof(u32);
2450 dname.len = msg->front.iov_len - sizeof(*h) - sizeof(u32); 2452 dname.len = msg->front.iov_len - sizeof(*h) - sizeof(u32);
2451 if (dname.len != get_unaligned_le32(h+1)) 2453 if (dname.len != get_unaligned_le32(h+1))
@@ -2456,8 +2458,9 @@ static void handle_lease(struct ceph_mds_client *mdsc,
2456 2458
2457 /* lookup inode */ 2459 /* lookup inode */
2458 inode = ceph_find_inode(sb, vino); 2460 inode = ceph_find_inode(sb, vino);
2459 dout("handle_lease '%s', mask %d, ino %llx %p\n", 2461 dout("handle_lease %s, mask %d, ino %llx %p %.*s\n",
2460 ceph_lease_op_name(h->action), mask, vino.ino, inode); 2462 ceph_lease_op_name(h->action), mask, vino.ino, inode,
2463 dname.len, dname.name);
2461 if (inode == NULL) { 2464 if (inode == NULL) {
2462 dout("handle_lease no inode %llx\n", vino.ino); 2465 dout("handle_lease no inode %llx\n", vino.ino);
2463 goto release; 2466 goto release;
@@ -2482,7 +2485,8 @@ static void handle_lease(struct ceph_mds_client *mdsc,
2482 switch (h->action) { 2485 switch (h->action) {
2483 case CEPH_MDS_LEASE_REVOKE: 2486 case CEPH_MDS_LEASE_REVOKE:
2484 if (di && di->lease_session == session) { 2487 if (di && di->lease_session == session) {
2485 h->seq = cpu_to_le32(di->lease_seq); 2488 if (ceph_seq_cmp(di->lease_seq, seq) > 0)
2489 h->seq = cpu_to_le32(di->lease_seq);
2486 __ceph_mdsc_drop_dentry_lease(dentry); 2490 __ceph_mdsc_drop_dentry_lease(dentry);
2487 } 2491 }
2488 release = 1; 2492 release = 1;
@@ -2496,7 +2500,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
2496 unsigned long duration = 2500 unsigned long duration =
2497 le32_to_cpu(h->duration_ms) * HZ / 1000; 2501 le32_to_cpu(h->duration_ms) * HZ / 1000;
2498 2502
2499 di->lease_seq = le32_to_cpu(h->seq); 2503 di->lease_seq = seq;
2500 dentry->d_time = di->lease_renew_from + duration; 2504 dentry->d_time = di->lease_renew_from + duration;
2501 di->lease_renew_after = di->lease_renew_from + 2505 di->lease_renew_after = di->lease_renew_from +
2502 (duration >> 1); 2506 (duration >> 1);
@@ -2686,10 +2690,10 @@ static void delayed_work(struct work_struct *work)
2686 send_renew_caps(mdsc, s); 2690 send_renew_caps(mdsc, s);
2687 else 2691 else
2688 ceph_con_keepalive(&s->s_con); 2692 ceph_con_keepalive(&s->s_con);
2689 add_cap_releases(mdsc, s, -1); 2693 ceph_add_cap_releases(mdsc, s, -1);
2690 if (s->s_state == CEPH_MDS_SESSION_OPEN || 2694 if (s->s_state == CEPH_MDS_SESSION_OPEN ||
2691 s->s_state == CEPH_MDS_SESSION_HUNG) 2695 s->s_state == CEPH_MDS_SESSION_HUNG)
2692 send_cap_releases(mdsc, s); 2696 ceph_send_cap_releases(mdsc, s);
2693 mutex_unlock(&s->s_mutex); 2697 mutex_unlock(&s->s_mutex);
2694 ceph_put_mds_session(s); 2698 ceph_put_mds_session(s);
2695 2699
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index d9936c4f1212..b292fa42a66d 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -322,6 +322,12 @@ static inline void ceph_mdsc_put_request(struct ceph_mds_request *req)
322 kref_put(&req->r_kref, ceph_mdsc_release_request); 322 kref_put(&req->r_kref, ceph_mdsc_release_request);
323} 323}
324 324
325extern int ceph_add_cap_releases(struct ceph_mds_client *mdsc,
326 struct ceph_mds_session *session,
327 int extra);
328extern void ceph_send_cap_releases(struct ceph_mds_client *mdsc,
329 struct ceph_mds_session *session);
330
325extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc); 331extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc);
326 332
327extern char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base, 333extern char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base,
diff --git a/fs/ceph/mon_client.c b/fs/ceph/mon_client.c
index 21c62e9b7d1d..07a539906e67 100644
--- a/fs/ceph/mon_client.c
+++ b/fs/ceph/mon_client.c
@@ -400,6 +400,8 @@ static void release_generic_request(struct kref *kref)
400 ceph_msg_put(req->reply); 400 ceph_msg_put(req->reply);
401 if (req->request) 401 if (req->request)
402 ceph_msg_put(req->request); 402 ceph_msg_put(req->request);
403
404 kfree(req);
403} 405}
404 406
405static void put_generic_request(struct ceph_mon_generic_request *req) 407static void put_generic_request(struct ceph_mon_generic_request *req)
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 4e0bee240b9d..fa87f51e38e1 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -89,7 +89,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
89 89
90 buf->f_files = le64_to_cpu(st.num_objects); 90 buf->f_files = le64_to_cpu(st.num_objects);
91 buf->f_ffree = -1; 91 buf->f_ffree = -1;
92 buf->f_namelen = PATH_MAX; 92 buf->f_namelen = NAME_MAX;
93 buf->f_frsize = PAGE_CACHE_SIZE; 93 buf->f_frsize = PAGE_CACHE_SIZE;
94 94
95 /* leave fsid little-endian, regardless of host endianness */ 95 /* leave fsid little-endian, regardless of host endianness */
@@ -926,7 +926,7 @@ static int ceph_compare_super(struct super_block *sb, void *data)
926/* 926/*
927 * construct our own bdi so we can control readahead, etc. 927 * construct our own bdi so we can control readahead, etc.
928 */ 928 */
929static atomic_long_t bdi_seq = ATOMIC_INIT(0); 929static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0);
930 930
931static int ceph_register_bdi(struct super_block *sb, struct ceph_client *client) 931static int ceph_register_bdi(struct super_block *sb, struct ceph_client *client)
932{ 932{