* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: ceph: no .snap inside of snapped namespace libceph: fix msgr standby handling libceph: fix msgr keepalive flag libceph: fix msgr backoff libceph: retry after authorization failure libceph: fix handling of short returns from get_user_pages ceph: do not clear I_COMPLETE from d_release ceph: do not set I_COMPLETE Revert "ceph: keep reference to parent inode on ceph_dentry"
Unified · Split
| @@ -60,7 +60,6 @@ int ceph_init_dentry(struct dentry *dentry) · 59 unmodified lines | ||
| 60 | 60 | } |
| 61 | 61 | di->dentry = dentry; |
| 62 | 62 | di->lease_session = NULL; |
| 63 | − di->parent_inode = igrab(dentry->d_parent->d_inode); | |
| 64 | 63 | dentry->d_fsdata = di; |
| 65 | 64 | dentry->d_time = jiffies; |
| 66 | 65 | ceph_dentry_lru_add(dentry); |
| @@ -410,7 +409,7 @@ more: · 343 unmodified lines | ||
| 410 | 409 | spin_lock(&inode->i_lock); |
| 411 | 410 | if (ci->i_release_count == fi->dir_release_count) { |
| 412 | 411 | dout(" marking %p complete\n", inode); |
| 413 | − ci->i_ceph_flags |= CEPH_I_COMPLETE; | |
| 412 | + /* ci->i_ceph_flags |= CEPH_I_COMPLETE; */ | |
| 414 | 413 | ci->i_max_offset = filp->f_pos; |
| 415 | 414 | } |
| 416 | 415 | spin_unlock(&inode->i_lock); |
| @@ -497,6 +496,7 @@ struct dentry *ceph_finish_lookup(struct ceph_mds_request *req, · 80 unmodified lines | ||
| 497 | 496 | |
| 498 | 497 | /* .snap dir? */ |
| 499 | 498 | if (err == -ENOENT && |
| 499 | + ceph_snap(parent) == CEPH_NOSNAP && | |
| 500 | 500 | strcmp(dentry->d_name.name, |
| 501 | 501 | fsc->mount_options->snapdir_name) == 0) { |
| 502 | 502 | struct inode *inode = ceph_get_snapdir(parent); |
| @@ -1030,28 +1030,8 @@ out_touch: · 527 unmodified lines | ||
| 1030 | 1030 | static void ceph_dentry_release(struct dentry *dentry) |
| 1031 | 1031 | { |
| 1032 | 1032 | struct ceph_dentry_info *di = ceph_dentry(dentry); |
| 1033 | − struct inode *parent_inode = NULL; | |
| 1034 | − u64 snapid = CEPH_NOSNAP; | |
| 1035 | 1033 | |
| 1036 | − if (!IS_ROOT(dentry)) { | |
| 1037 | − parent_inode = di->parent_inode; | |
| 1038 | − if (parent_inode) | |
| 1039 | − snapid = ceph_snap(parent_inode); | |
| 1040 | − } | |
| 1041 | − dout("dentry_release %p parent %p\n", dentry, parent_inode); | |
| 1042 | − if (parent_inode && snapid != CEPH_SNAPDIR) { | |
| 1043 | − struct ceph_inode_info *ci = ceph_inode(parent_inode); | |
| 1044 | − | |
| 1045 | − spin_lock(&parent_inode->i_lock); | |
| 1046 | − if (ci->i_shared_gen == di->lease_shared_gen || | |
| 1047 | − snapid <= CEPH_MAXSNAP) { | |
| 1048 | − dout(" clearing %p complete (d_release)\n", | |
| 1049 | − parent_inode); | |
| 1050 | − ci->i_ceph_flags &= ~CEPH_I_COMPLETE; | |
| 1051 | − ci->i_release_count++; | |
| 1052 | − } | |
| 1053 | − spin_unlock(&parent_inode->i_lock); | |
| 1054 | − } | |
| 1034 | + dout("dentry_release %p\n", dentry); | |
| 1055 | 1035 | if (di) { |
| 1056 | 1036 | ceph_dentry_lru_del(dentry); |
| 1057 | 1037 | if (di->lease_session) |
| @@ -1059,8 +1039,6 @@ static void ceph_dentry_release(struct dentry *dentry) · 1 unmodified line | ||
| 1059 | 1039 | kmem_cache_free(ceph_dentry_cachep, di); |
| 1060 | 1040 | dentry->d_fsdata = NULL; |
| 1061 | 1041 | } |
| 1062 | − if (parent_inode) | |
| 1063 | − iput(parent_inode); | |
| 1064 | 1042 | } |
| 1065 | 1043 | |
| 1066 | 1044 | static int ceph_snapdir_d_revalidate(struct dentry *dentry, |
| @@ -707,7 +707,7 @@ static int fill_inode(struct inode *inode, · 706 unmodified lines | ||
| 707 | 707 | (issued & CEPH_CAP_FILE_EXCL) == 0 && |
| 708 | 708 | (ci->i_ceph_flags & CEPH_I_COMPLETE) == 0) { |
| 709 | 709 | dout(" marking %p complete (empty)\n", inode); |
| 710 | − ci->i_ceph_flags |= CEPH_I_COMPLETE; | |
| 710 | + /* ci->i_ceph_flags |= CEPH_I_COMPLETE; */ | |
| 711 | 711 | ci->i_max_offset = 2; |
| 712 | 712 | } |
| 713 | 713 | break; |
| @@ -207,7 +207,6 @@ struct ceph_dentry_info { · 206 unmodified lines | ||
| 207 | 207 | struct dentry *dentry; |
| 208 | 208 | u64 time; |
| 209 | 209 | u64 offset; |
| 210 | − struct inode *parent_inode; | |
| 211 | 210 | }; |
| 212 | 211 | |
| 213 | 212 | struct ceph_inode_xattrs_info { |
| @@ -123,6 +123,7 @@ struct ceph_msg_pos { · 122 unmodified lines | ||
| 123 | 123 | #define SOCK_CLOSED 11 /* socket state changed to closed */ |
| 124 | 124 | #define OPENING 13 /* open connection w/ (possibly new) peer */ |
| 125 | 125 | #define DEAD 14 /* dead, about to kfree */ |
| 126 | +#define BACKOFF 15 | |
| 126 | 127 | |
| 127 | 128 | /* |
| 128 | 129 | * A single connection with another host. |
| @@ -160,7 +161,6 @@ struct ceph_connection { · 31 unmodified lines | ||
| 160 | 161 | struct list_head out_queue; |
| 161 | 162 | struct list_head out_sent; /* sending or sent but unacked */ |
| 162 | 163 | u64 out_seq; /* last message queued for send */ |
| 163 | − bool out_keepalive_pending; | |
| 164 | 164 | |
| 165 | 165 | u64 in_seq, in_seq_acked; /* last message received, acked */ |
| 166 | 166 | |
| @@ -336,7 +336,6 @@ static void reset_connection(struct ceph_connection *con) · 335 unmodified lines | ||
| 336 | 336 | ceph_msg_put(con->out_msg); |
| 337 | 337 | con->out_msg = NULL; |
| 338 | 338 | } |
| 339 | − con->out_keepalive_pending = false; | |
| 340 | 339 | con->in_seq = 0; |
| 341 | 340 | con->in_seq_acked = 0; |
| 342 | 341 | } |
| @@ -1248,8 +1247,6 @@ static int process_connect(struct ceph_connection *con) · 905 unmodified lines | ||
| 1248 | 1247 | con->auth_retry); |
| 1249 | 1248 | if (con->auth_retry == 2) { |
| 1250 | 1249 | con->error_msg = "connect authorization failure"; |
| 1251 | − reset_connection(con); | |
| 1252 | − set_bit(CLOSED, &con->state); | |
| 1253 | 1250 | return -1; |
| 1254 | 1251 | } |
| 1255 | 1252 | con->auth_retry = 1; |
| @@ -1715,14 +1712,6 @@ more: · 459 unmodified lines | ||
| 1715 | 1712 | |
| 1716 | 1713 | /* open the socket first? */ |
| 1717 | 1714 | if (con->sock == NULL) { |
| 1718 | − /* | |
| 1719 | − * if we were STANDBY and are reconnecting _this_ | |
| 1720 | − * connection, bump connect_seq now. Always bump | |
| 1721 | − * global_seq. | |
| 1722 | − */ | |
| 1723 | − if (test_and_clear_bit(STANDBY, &con->state)) | |
| 1724 | − con->connect_seq++; | |
| 1725 | − | |
| 1726 | 1715 | prepare_write_banner(msgr, con); |
| 1727 | 1716 | prepare_write_connect(msgr, con, 1); |
| 1728 | 1717 | prepare_read_banner(con); |
| @@ -1951,7 +1940,24 @@ static void con_work(struct work_struct *work) · 222 unmodified lines | ||
| 1951 | 1940 | work.work); |
| 1952 | 1941 | |
| 1953 | 1942 | mutex_lock(&con->mutex); |
| 1943 | + if (test_and_clear_bit(BACKOFF, &con->state)) { | |
| 1944 | + dout("con_work %p backing off\n", con); | |
| 1945 | + if (queue_delayed_work(ceph_msgr_wq, &con->work, | |
| 1946 | + round_jiffies_relative(con->delay))) { | |
| 1947 | + dout("con_work %p backoff %lu\n", con, con->delay); | |
| 1948 | + mutex_unlock(&con->mutex); | |
| 1949 | + return; | |
| 1950 | + } else { | |
| 1951 | + con->ops->put(con); | |
| 1952 | + dout("con_work %p FAILED to back off %lu\n", con, | |
| 1953 | + con->delay); | |
| 1954 | + } | |
| 1955 | + } | |
| 1954 | 1956 | |
| 1957 | + if (test_bit(STANDBY, &con->state)) { | |
| 1958 | + dout("con_work %p STANDBY\n", con); | |
| 1959 | + goto done; | |
| 1960 | + } | |
| 1955 | 1961 | if (test_bit(CLOSED, &con->state)) { /* e.g. if we are replaced */ |
| 1956 | 1962 | dout("con_work CLOSED\n"); |
| 1957 | 1963 | con_close_socket(con); |
| @@ -2008,10 +2014,12 @@ static void ceph_fault(struct ceph_connection *con) · 50 unmodified lines | ||
| 2008 | 2014 | /* Requeue anything that hasn't been acked */ |
| 2009 | 2015 | list_splice_init(&con->out_sent, &con->out_queue); |
| 2010 | 2016 | |
| 2011 | − /* If there are no messages in the queue, place the connection | |
| 2012 | − * in a STANDBY state (i.e., don't try to reconnect just yet). */ | |
| 2013 | − if (list_empty(&con->out_queue) && !con->out_keepalive_pending) { | |
| 2014 | − dout("fault setting STANDBY\n"); | |
| 2017 | + /* If there are no messages queued or keepalive pending, place | |
| 2018 | + * the connection in a STANDBY state */ | |
| 2019 | + if (list_empty(&con->out_queue) && | |
| 2020 | + !test_bit(KEEPALIVE_PENDING, &con->state)) { | |
| 2021 | + dout("fault %p setting STANDBY clearing WRITE_PENDING\n", con); | |
| 2022 | + clear_bit(WRITE_PENDING, &con->state); | |
| 2015 | 2023 | set_bit(STANDBY, &con->state); |
| 2016 | 2024 | } else { |
| 2017 | 2025 | /* retry after a delay. */ |
| @@ -2019,11 +2027,24 @@ static void ceph_fault(struct ceph_connection *con) · 1 unmodified line | ||
| 2019 | 2027 | con->delay = BASE_DELAY_INTERVAL; |
| 2020 | 2028 | else if (con->delay < MAX_DELAY_INTERVAL) |
| 2021 | 2029 | con->delay *= 2; |
| 2022 | − dout("fault queueing %p delay %lu\n", con, con->delay); | |
| 2023 | 2030 | con->ops->get(con); |
| 2024 | 2031 | if (queue_delayed_work(ceph_msgr_wq, &con->work, |
| 2025 | − round_jiffies_relative(con->delay)) == 0) | |
| 2032 | + round_jiffies_relative(con->delay))) { | |
| 2033 | + dout("fault queued %p delay %lu\n", con, con->delay); | |
| 2034 | + } else { | |
| 2026 | 2035 | con->ops->put(con); |
| 2036 | + dout("fault failed to queue %p delay %lu, backoff\n", | |
| 2037 | + con, con->delay); | |
| 2038 | + /* | |
| 2039 | + * In many cases we see a socket state change | |
| 2040 | + * while con_work is running and end up | |
| 2041 | + * queuing (non-delayed) work, such that we | |
| 2042 | + * can't backoff with a delay. Set a flag so | |
| 2043 | + * that when con_work restarts we schedule the | |
| 2044 | + * delay then. | |
| 2045 | + */ | |
| 2046 | + set_bit(BACKOFF, &con->state); | |
| 2047 | + } | |
| 2027 | 2048 | } |
| 2028 | 2049 | |
| 2029 | 2050 | out_unlock: |
| @@ -2094,6 +2115,19 @@ void ceph_messenger_destroy(struct ceph_messenger *msgr) · 64 unmodified lines | ||
| 2094 | 2115 | } |
| 2095 | 2116 | EXPORT_SYMBOL(ceph_messenger_destroy); |
| 2096 | 2117 | |
| 2118 | +static void clear_standby(struct ceph_connection *con) | |
| 2119 | +{ | |
| 2120 | + /* come back from STANDBY? */ | |
| 2121 | + if (test_and_clear_bit(STANDBY, &con->state)) { | |
| 2122 | + mutex_lock(&con->mutex); | |
| 2123 | + dout("clear_standby %p and ++connect_seq\n", con); | |
| 2124 | + con->connect_seq++; | |
| 2125 | + WARN_ON(test_bit(WRITE_PENDING, &con->state)); | |
| 2126 | + WARN_ON(test_bit(KEEPALIVE_PENDING, &con->state)); | |
| 2127 | + mutex_unlock(&con->mutex); | |
| 2128 | + } | |
| 2129 | +} | |
| 2130 | + | |
| 2097 | 2131 | /* |
| 2098 | 2132 | * Queue up an outgoing message on the given connection. |
| 2099 | 2133 | */ |
| @@ -2126,6 +2160,7 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) · 26 unmodified lines | ||
| 2126 | 2160 | |
| 2127 | 2161 | /* if there wasn't anything waiting to send before, queue |
| 2128 | 2162 | * new work */ |
| 2163 | + clear_standby(con); | |
| 2129 | 2164 | if (test_and_set_bit(WRITE_PENDING, &con->state) == 0) |
| 2130 | 2165 | queue_con(con); |
| 2131 | 2166 | } |
| @@ -2191,6 +2226,8 @@ void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg) · 59 unmodified lines | ||
| 2191 | 2226 | */ |
| 2192 | 2227 | void ceph_con_keepalive(struct ceph_connection *con) |
| 2193 | 2228 | { |
| 2229 | + dout("con_keepalive %p\n", con); | |
| 2230 | + clear_standby(con); | |
| 2194 | 2231 | if (test_and_set_bit(KEEPALIVE_PENDING, &con->state) == 0 && |
| 2195 | 2232 | test_and_set_bit(WRITE_PENDING, &con->state) == 0) |
| 2196 | 2233 | queue_con(con); |
| @@ -16,22 +16,30 @@ struct page **ceph_get_direct_page_vector(const char __user *data, · 15 unmodified lines | ||
| 16 | 16 | int num_pages, bool write_page) |
| 17 | 17 | { |
| 18 | 18 | struct page **pages; |
| 19 | − int rc; | |
| 19 | + int got = 0; | |
| 20 | + int rc = 0; | |
| 20 | 21 | |
| 21 | 22 | pages = kmalloc(sizeof(*pages) * num_pages, GFP_NOFS); |
| 22 | 23 | if (!pages) |
| 23 | 24 | return ERR_PTR(-ENOMEM); |
| 24 | 25 | |
| 25 | 26 | down_read(¤t->mm->mmap_sem); |
| 26 | − rc = get_user_pages(current, current->mm, (unsigned long)data, | |
| 27 | − num_pages, write_page, 0, pages, NULL); | |
| 27 | + while (got < num_pages) { | |
| 28 | + rc = get_user_pages(current, current->mm, | |
| 29 | + (unsigned long)data + ((unsigned long)got * PAGE_SIZE), | |
| 30 | + num_pages - got, write_page, 0, pages + got, NULL); | |
| 31 | + if (rc < 0) | |
| 32 | + break; | |
| 33 | + BUG_ON(rc == 0); | |
| 34 | + got += rc; | |
| 35 | + } | |
| 28 | 36 | up_read(¤t->mm->mmap_sem); |
| 29 | − if (rc < num_pages) | |
| 37 | + if (rc < 0) | |
| 30 | 38 | goto fail; |
| 31 | 39 | return pages; |
| 32 | 40 | |
| 33 | 41 | fail: |
| 34 | − ceph_put_page_vector(pages, rc > 0 ? rc : 0, false); | |
| 42 | + ceph_put_page_vector(pages, got, false); | |
| 35 | 43 | return ERR_PTR(rc); |
| 36 | 44 | } |
| 37 | 45 | EXPORT_SYMBOL(ceph_get_direct_page_vector); |