diff options
Diffstat (limited to 'fs/ceph')
| -rw-r--r-- | fs/ceph/caps.c | 93 | ||||
| -rw-r--r-- | fs/ceph/inode.c | 2 | ||||
| -rw-r--r-- | fs/ceph/mds_client.c | 28 | ||||
| -rw-r--r-- | fs/ceph/mds_client.h | 6 | ||||
| -rw-r--r-- | fs/ceph/mon_client.c | 2 | ||||
| -rw-r--r-- | fs/ceph/super.c | 4 |
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 | ||
| 984 | static 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 | */ |
| 1069 | static int add_cap_releases(struct ceph_mds_client *mdsc, | 1069 | int 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 | */ |
| 1179 | static void send_cap_releases(struct ceph_mds_client *mdsc, | 1179 | void 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 | ||
| 325 | extern int ceph_add_cap_releases(struct ceph_mds_client *mdsc, | ||
| 326 | struct ceph_mds_session *session, | ||
| 327 | int extra); | ||
| 328 | extern void ceph_send_cap_releases(struct ceph_mds_client *mdsc, | ||
| 329 | struct ceph_mds_session *session); | ||
| 330 | |||
| 325 | extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc); | 331 | extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc); |
| 326 | 332 | ||
| 327 | extern char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base, | 333 | extern 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 | ||
| 405 | static void put_generic_request(struct ceph_mon_generic_request *req) | 407 | static 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 | */ |
| 929 | static atomic_long_t bdi_seq = ATOMIC_INIT(0); | 929 | static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0); |
| 930 | 930 | ||
| 931 | static int ceph_register_bdi(struct super_block *sb, struct ceph_client *client) | 931 | static int ceph_register_bdi(struct super_block *sb, struct ceph_client *client) |
| 932 | { | 932 | { |
