aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ceph/auth.c7
-rw-r--r--fs/ceph/auth.h6
-rw-r--r--fs/ceph/auth_none.c8
-rw-r--r--fs/ceph/auth_x.c12
-rw-r--r--fs/ceph/ceph_fs.h21
-rw-r--r--fs/ceph/dir.c2
-rw-r--r--fs/ceph/export.c2
-rw-r--r--fs/ceph/file.c2
-rw-r--r--fs/ceph/inode.c2
-rw-r--r--fs/ceph/mds_client.c21
-rw-r--r--fs/ceph/messenger.c6
-rw-r--r--fs/ceph/messenger.h1
-rw-r--r--fs/ceph/mon_client.c5
-rw-r--r--fs/ceph/osd_client.c7
-rw-r--r--fs/ceph/osdmap.c2
-rw-r--r--fs/ceph/super.c12
-rw-r--r--fs/ceph/super.h1
-rw-r--r--include/linux/completion.h2
-rw-r--r--kernel/sched.c17
19 files changed, 104 insertions, 32 deletions
diff --git a/fs/ceph/auth.c b/fs/ceph/auth.c
index 9f46de2ba7a7..89490beaf537 100644
--- a/fs/ceph/auth.c
+++ b/fs/ceph/auth.c
@@ -1,7 +1,6 @@
1#include "ceph_debug.h" 1#include "ceph_debug.h"
2 2
3#include <linux/module.h> 3#include <linux/module.h>
4#include <linux/slab.h>
5#include <linux/err.h> 4#include <linux/err.h>
6#include <linux/slab.h> 5#include <linux/slab.h>
7 6
@@ -217,8 +216,8 @@ int ceph_handle_auth_reply(struct ceph_auth_client *ac,
217 if (ac->protocol != protocol) { 216 if (ac->protocol != protocol) {
218 ret = ceph_auth_init_protocol(ac, protocol); 217 ret = ceph_auth_init_protocol(ac, protocol);
219 if (ret) { 218 if (ret) {
220 pr_err("error %d on auth method %s init\n", 219 pr_err("error %d on auth protocol %d init\n",
221 ret, ac->ops->name); 220 ret, protocol);
222 goto out; 221 goto out;
223 } 222 }
224 } 223 }
@@ -247,7 +246,7 @@ int ceph_build_auth(struct ceph_auth_client *ac,
247 if (!ac->protocol) 246 if (!ac->protocol)
248 return ceph_auth_build_hello(ac, msg_buf, msg_len); 247 return ceph_auth_build_hello(ac, msg_buf, msg_len);
249 BUG_ON(!ac->ops); 248 BUG_ON(!ac->ops);
250 if (!ac->ops->is_authenticated(ac)) 249 if (ac->ops->should_authenticate(ac))
251 return ceph_build_auth_request(ac, msg_buf, msg_len); 250 return ceph_build_auth_request(ac, msg_buf, msg_len);
252 return 0; 251 return 0;
253} 252}
diff --git a/fs/ceph/auth.h b/fs/ceph/auth.h
index 4429a707c021..d38a2fb4a137 100644
--- a/fs/ceph/auth.h
+++ b/fs/ceph/auth.h
@@ -24,6 +24,12 @@ struct ceph_auth_client_ops {
24 int (*is_authenticated)(struct ceph_auth_client *ac); 24 int (*is_authenticated)(struct ceph_auth_client *ac);
25 25
26 /* 26 /*
27 * true if we should (re)authenticate, e.g., when our tickets
28 * are getting old and crusty.
29 */
30 int (*should_authenticate)(struct ceph_auth_client *ac);
31
32 /*
27 * build requests and process replies during monitor 33 * build requests and process replies during monitor
28 * handshake. if handle_reply returns -EAGAIN, we build 34 * handshake. if handle_reply returns -EAGAIN, we build
29 * another request. 35 * another request.
diff --git a/fs/ceph/auth_none.c b/fs/ceph/auth_none.c
index 24407c119291..ad1dc21286c7 100644
--- a/fs/ceph/auth_none.c
+++ b/fs/ceph/auth_none.c
@@ -31,6 +31,13 @@ static int is_authenticated(struct ceph_auth_client *ac)
31 return !xi->starting; 31 return !xi->starting;
32} 32}
33 33
34static int should_authenticate(struct ceph_auth_client *ac)
35{
36 struct ceph_auth_none_info *xi = ac->private;
37
38 return xi->starting;
39}
40
34/* 41/*
35 * the generic auth code decode the global_id, and we carry no actual 42 * the generic auth code decode the global_id, and we carry no actual
36 * authenticate state, so nothing happens here. 43 * authenticate state, so nothing happens here.
@@ -98,6 +105,7 @@ static const struct ceph_auth_client_ops ceph_auth_none_ops = {
98 .reset = reset, 105 .reset = reset,
99 .destroy = destroy, 106 .destroy = destroy,
100 .is_authenticated = is_authenticated, 107 .is_authenticated = is_authenticated,
108 .should_authenticate = should_authenticate,
101 .handle_reply = handle_reply, 109 .handle_reply = handle_reply,
102 .create_authorizer = ceph_auth_none_create_authorizer, 110 .create_authorizer = ceph_auth_none_create_authorizer,
103 .destroy_authorizer = ceph_auth_none_destroy_authorizer, 111 .destroy_authorizer = ceph_auth_none_destroy_authorizer,
diff --git a/fs/ceph/auth_x.c b/fs/ceph/auth_x.c
index 7b206231566d..83d4d2785ffe 100644
--- a/fs/ceph/auth_x.c
+++ b/fs/ceph/auth_x.c
@@ -27,6 +27,17 @@ static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
27 return (ac->want_keys & xi->have_keys) == ac->want_keys; 27 return (ac->want_keys & xi->have_keys) == ac->want_keys;
28} 28}
29 29
30static int ceph_x_should_authenticate(struct ceph_auth_client *ac)
31{
32 struct ceph_x_info *xi = ac->private;
33 int need;
34
35 ceph_x_validate_tickets(ac, &need);
36 dout("ceph_x_should_authenticate want=%d need=%d have=%d\n",
37 ac->want_keys, need, xi->have_keys);
38 return need != 0;
39}
40
30static int ceph_x_encrypt_buflen(int ilen) 41static int ceph_x_encrypt_buflen(int ilen)
31{ 42{
32 return sizeof(struct ceph_x_encrypt_header) + ilen + 16 + 43 return sizeof(struct ceph_x_encrypt_header) + ilen + 16 +
@@ -620,6 +631,7 @@ static void ceph_x_invalidate_authorizer(struct ceph_auth_client *ac,
620static const struct ceph_auth_client_ops ceph_x_ops = { 631static const struct ceph_auth_client_ops ceph_x_ops = {
621 .name = "x", 632 .name = "x",
622 .is_authenticated = ceph_x_is_authenticated, 633 .is_authenticated = ceph_x_is_authenticated,
634 .should_authenticate = ceph_x_should_authenticate,
623 .build_request = ceph_x_build_request, 635 .build_request = ceph_x_build_request,
624 .handle_reply = ceph_x_handle_reply, 636 .handle_reply = ceph_x_handle_reply,
625 .create_authorizer = ceph_x_create_authorizer, 637 .create_authorizer = ceph_x_create_authorizer,
diff --git a/fs/ceph/ceph_fs.h b/fs/ceph/ceph_fs.h
index 3b9eeed097b3..2fa992eaf7da 100644
--- a/fs/ceph/ceph_fs.h
+++ b/fs/ceph/ceph_fs.h
@@ -265,16 +265,17 @@ extern const char *ceph_mds_state_name(int s);
265 * - they also define the lock ordering by the MDS 265 * - they also define the lock ordering by the MDS
266 * - a few of these are internal to the mds 266 * - a few of these are internal to the mds
267 */ 267 */
268#define CEPH_LOCK_DN 1 268#define CEPH_LOCK_DVERSION 1
269#define CEPH_LOCK_ISNAP 2 269#define CEPH_LOCK_DN 2
270#define CEPH_LOCK_IVERSION 4 /* mds internal */ 270#define CEPH_LOCK_ISNAP 16
271#define CEPH_LOCK_IFILE 8 /* mds internal */ 271#define CEPH_LOCK_IVERSION 32 /* mds internal */
272#define CEPH_LOCK_IAUTH 32 272#define CEPH_LOCK_IFILE 64
273#define CEPH_LOCK_ILINK 64 273#define CEPH_LOCK_IAUTH 128
274#define CEPH_LOCK_IDFT 128 /* dir frag tree */ 274#define CEPH_LOCK_ILINK 256
275#define CEPH_LOCK_INEST 256 /* mds internal */ 275#define CEPH_LOCK_IDFT 512 /* dir frag tree */
276#define CEPH_LOCK_IXATTR 512 276#define CEPH_LOCK_INEST 1024 /* mds internal */
277#define CEPH_LOCK_INO 2048 /* immutable inode bits; not a lock */ 277#define CEPH_LOCK_IXATTR 2048
278#define CEPH_LOCK_INO 8192 /* immutable inode bits; not a lock */
278 279
279/* client_session ops */ 280/* client_session ops */
280enum { 281enum {
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 0057f4a07347..f85719310db2 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -587,7 +587,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
587 CEPH_MDS_OP_LOOKUPSNAP : CEPH_MDS_OP_LOOKUP; 587 CEPH_MDS_OP_LOOKUPSNAP : CEPH_MDS_OP_LOOKUP;
588 req = ceph_mdsc_create_request(mdsc, op, USE_ANY_MDS); 588 req = ceph_mdsc_create_request(mdsc, op, USE_ANY_MDS);
589 if (IS_ERR(req)) 589 if (IS_ERR(req))
590 return ERR_PTR(PTR_ERR(req)); 590 return ERR_CAST(req);
591 req->r_dentry = dget(dentry); 591 req->r_dentry = dget(dentry);
592 req->r_num_caps = 2; 592 req->r_num_caps = 2;
593 /* we only need inode linkage */ 593 /* we only need inode linkage */
diff --git a/fs/ceph/export.c b/fs/ceph/export.c
index 17447644d675..4480cb1c63e7 100644
--- a/fs/ceph/export.c
+++ b/fs/ceph/export.c
@@ -133,7 +133,7 @@ static struct dentry *__cfh_to_dentry(struct super_block *sb,
133 req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPHASH, 133 req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPHASH,
134 USE_ANY_MDS); 134 USE_ANY_MDS);
135 if (IS_ERR(req)) 135 if (IS_ERR(req))
136 return ERR_PTR(PTR_ERR(req)); 136 return ERR_CAST(req);
137 137
138 req->r_ino1 = vino; 138 req->r_ino1 = vino;
139 req->r_ino2.ino = cfh->parent_ino; 139 req->r_ino2.ino = cfh->parent_ino;
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 6512b6701b9e..6251a1574b94 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -230,7 +230,7 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
230 /* do the open */ 230 /* do the open */
231 req = prepare_open_request(dir->i_sb, flags, mode); 231 req = prepare_open_request(dir->i_sb, flags, mode);
232 if (IS_ERR(req)) 232 if (IS_ERR(req))
233 return ERR_PTR(PTR_ERR(req)); 233 return ERR_CAST(req);
234 req->r_dentry = dget(dentry); 234 req->r_dentry = dget(dentry);
235 req->r_num_caps = 2; 235 req->r_num_caps = 2;
236 if (flags & O_CREAT) { 236 if (flags & O_CREAT) {
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index a81b8b662c7b..226f5a50d362 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -69,7 +69,7 @@ struct inode *ceph_get_snapdir(struct inode *parent)
69 69
70 BUG_ON(!S_ISDIR(parent->i_mode)); 70 BUG_ON(!S_ISDIR(parent->i_mode));
71 if (IS_ERR(inode)) 71 if (IS_ERR(inode))
72 return ERR_PTR(PTR_ERR(inode)); 72 return inode;
73 inode->i_mode = parent->i_mode; 73 inode->i_mode = parent->i_mode;
74 inode->i_uid = parent->i_uid; 74 inode->i_uid = parent->i_uid;
75 inode->i_gid = parent->i_gid; 75 inode->i_gid = parent->i_gid;
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 885aa5710cfd..b49f12822cbc 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1768,12 +1768,12 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
1768 mutex_unlock(&mdsc->mutex); 1768 mutex_unlock(&mdsc->mutex);
1769 dout("do_request waiting\n"); 1769 dout("do_request waiting\n");
1770 if (req->r_timeout) { 1770 if (req->r_timeout) {
1771 err = (long)wait_for_completion_interruptible_timeout( 1771 err = (long)wait_for_completion_killable_timeout(
1772 &req->r_completion, req->r_timeout); 1772 &req->r_completion, req->r_timeout);
1773 if (err == 0) 1773 if (err == 0)
1774 err = -EIO; 1774 err = -EIO;
1775 } else { 1775 } else {
1776 err = wait_for_completion_interruptible(&req->r_completion); 1776 err = wait_for_completion_killable(&req->r_completion);
1777 } 1777 }
1778 dout("do_request waited, got %d\n", err); 1778 dout("do_request waited, got %d\n", err);
1779 mutex_lock(&mdsc->mutex); 1779 mutex_lock(&mdsc->mutex);
@@ -2014,16 +2014,21 @@ static void handle_forward(struct ceph_mds_client *mdsc,
2014 mutex_lock(&mdsc->mutex); 2014 mutex_lock(&mdsc->mutex);
2015 req = __lookup_request(mdsc, tid); 2015 req = __lookup_request(mdsc, tid);
2016 if (!req) { 2016 if (!req) {
2017 dout("forward %llu to mds%d - req dne\n", tid, next_mds); 2017 dout("forward tid %llu to mds%d - req dne\n", tid, next_mds);
2018 goto out; /* dup reply? */ 2018 goto out; /* dup reply? */
2019 } 2019 }
2020 2020
2021 if (fwd_seq <= req->r_num_fwd) { 2021 if (req->r_aborted) {
2022 dout("forward %llu to mds%d - old seq %d <= %d\n", 2022 dout("forward tid %llu aborted, unregistering\n", tid);
2023 __unregister_request(mdsc, req);
2024 } else if (fwd_seq <= req->r_num_fwd) {
2025 dout("forward tid %llu to mds%d - old seq %d <= %d\n",
2023 tid, next_mds, req->r_num_fwd, fwd_seq); 2026 tid, next_mds, req->r_num_fwd, fwd_seq);
2024 } else { 2027 } else {
2025 /* resend. forward race not possible; mds would drop */ 2028 /* resend. forward race not possible; mds would drop */
2026 dout("forward %llu to mds%d (we resend)\n", tid, next_mds); 2029 dout("forward tid %llu to mds%d (we resend)\n", tid, next_mds);
2030 BUG_ON(req->r_err);
2031 BUG_ON(req->r_got_result);
2027 req->r_num_fwd = fwd_seq; 2032 req->r_num_fwd = fwd_seq;
2028 req->r_resend_mds = next_mds; 2033 req->r_resend_mds = next_mds;
2029 put_request_session(req); 2034 put_request_session(req);
@@ -2541,7 +2546,7 @@ void ceph_mdsc_lease_send_msg(struct ceph_mds_session *session,
2541 return; 2546 return;
2542 lease = msg->front.iov_base; 2547 lease = msg->front.iov_base;
2543 lease->action = action; 2548 lease->action = action;
2544 lease->mask = cpu_to_le16(CEPH_LOCK_DN); 2549 lease->mask = cpu_to_le16(1);
2545 lease->ino = cpu_to_le64(ceph_vino(inode).ino); 2550 lease->ino = cpu_to_le64(ceph_vino(inode).ino);
2546 lease->first = lease->last = cpu_to_le64(ceph_vino(inode).snap); 2551 lease->first = lease->last = cpu_to_le64(ceph_vino(inode).snap);
2547 lease->seq = cpu_to_le32(seq); 2552 lease->seq = cpu_to_le32(seq);
@@ -2571,7 +2576,7 @@ void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode,
2571 2576
2572 BUG_ON(inode == NULL); 2577 BUG_ON(inode == NULL);
2573 BUG_ON(dentry == NULL); 2578 BUG_ON(dentry == NULL);
2574 BUG_ON(mask != CEPH_LOCK_DN); 2579 BUG_ON(mask == 0);
2575 2580
2576 /* is dentry lease valid? */ 2581 /* is dentry lease valid? */
2577 spin_lock(&dentry->d_lock); 2582 spin_lock(&dentry->d_lock);
diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c
index 60b74839ebec..64b8b1f7863d 100644
--- a/fs/ceph/messenger.c
+++ b/fs/ceph/messenger.c
@@ -120,6 +120,12 @@ void ceph_msgr_exit(void)
120 destroy_workqueue(ceph_msgr_wq); 120 destroy_workqueue(ceph_msgr_wq);
121} 121}
122 122
123void ceph_msgr_flush()
124{
125 flush_workqueue(ceph_msgr_wq);
126}
127
128
123/* 129/*
124 * socket callback functions 130 * socket callback functions
125 */ 131 */
diff --git a/fs/ceph/messenger.h b/fs/ceph/messenger.h
index 00a9430b1ffc..76fbc957bc13 100644
--- a/fs/ceph/messenger.h
+++ b/fs/ceph/messenger.h
@@ -213,6 +213,7 @@ extern int ceph_parse_ips(const char *c, const char *end,
213 213
214extern int ceph_msgr_init(void); 214extern int ceph_msgr_init(void);
215extern void ceph_msgr_exit(void); 215extern void ceph_msgr_exit(void);
216extern void ceph_msgr_flush(void);
216 217
217extern struct ceph_messenger *ceph_messenger_create( 218extern struct ceph_messenger *ceph_messenger_create(
218 struct ceph_entity_addr *myaddr); 219 struct ceph_entity_addr *myaddr);
diff --git a/fs/ceph/mon_client.c b/fs/ceph/mon_client.c
index f6510a476e7e..21c62e9b7d1d 100644
--- a/fs/ceph/mon_client.c
+++ b/fs/ceph/mon_client.c
@@ -704,8 +704,11 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
704 struct ceph_msg *msg) 704 struct ceph_msg *msg)
705{ 705{
706 int ret; 706 int ret;
707 int was_auth = 0;
707 708
708 mutex_lock(&monc->mutex); 709 mutex_lock(&monc->mutex);
710 if (monc->auth->ops)
711 was_auth = monc->auth->ops->is_authenticated(monc->auth);
709 monc->pending_auth = 0; 712 monc->pending_auth = 0;
710 ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base, 713 ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base,
711 msg->front.iov_len, 714 msg->front.iov_len,
@@ -716,7 +719,7 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
716 wake_up(&monc->client->auth_wq); 719 wake_up(&monc->client->auth_wq);
717 } else if (ret > 0) { 720 } else if (ret > 0) {
718 __send_prepared_auth_request(monc, ret); 721 __send_prepared_auth_request(monc, ret);
719 } else if (monc->auth->ops->is_authenticated(monc->auth)) { 722 } else if (!was_auth && monc->auth->ops->is_authenticated(monc->auth)) {
720 dout("authenticated, starting session\n"); 723 dout("authenticated, starting session\n");
721 724
722 monc->client->msgr->inst.name.type = CEPH_ENTITY_TYPE_CLIENT; 725 monc->client->msgr->inst.name.type = CEPH_ENTITY_TYPE_CLIENT;
diff --git a/fs/ceph/osd_client.c b/fs/ceph/osd_client.c
index afa7bb3895c4..d25b4add85b4 100644
--- a/fs/ceph/osd_client.c
+++ b/fs/ceph/osd_client.c
@@ -361,8 +361,13 @@ static void put_osd(struct ceph_osd *osd)
361{ 361{
362 dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref), 362 dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref),
363 atomic_read(&osd->o_ref) - 1); 363 atomic_read(&osd->o_ref) - 1);
364 if (atomic_dec_and_test(&osd->o_ref)) 364 if (atomic_dec_and_test(&osd->o_ref)) {
365 struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth;
366
367 if (osd->o_authorizer)
368 ac->ops->destroy_authorizer(ac, osd->o_authorizer);
365 kfree(osd); 369 kfree(osd);
370 }
366} 371}
367 372
368/* 373/*
diff --git a/fs/ceph/osdmap.c b/fs/ceph/osdmap.c
index cfdd8f4388b7..ddc656fb5c05 100644
--- a/fs/ceph/osdmap.c
+++ b/fs/ceph/osdmap.c
@@ -706,7 +706,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
706 len, *p, end); 706 len, *p, end);
707 newcrush = crush_decode(*p, min(*p+len, end)); 707 newcrush = crush_decode(*p, min(*p+len, end));
708 if (IS_ERR(newcrush)) 708 if (IS_ERR(newcrush))
709 return ERR_PTR(PTR_ERR(newcrush)); 709 return ERR_CAST(newcrush);
710 } 710 }
711 711
712 /* new flags? */ 712 /* new flags? */
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 7c663d9b9f81..4e0bee240b9d 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -669,9 +669,17 @@ static void ceph_destroy_client(struct ceph_client *client)
669 669
670 /* unmount */ 670 /* unmount */
671 ceph_mdsc_stop(&client->mdsc); 671 ceph_mdsc_stop(&client->mdsc);
672 ceph_monc_stop(&client->monc);
673 ceph_osdc_stop(&client->osdc); 672 ceph_osdc_stop(&client->osdc);
674 673
674 /*
675 * make sure mds and osd connections close out before destroying
676 * the auth module, which is needed to free those connections'
677 * ceph_authorizers.
678 */
679 ceph_msgr_flush();
680
681 ceph_monc_stop(&client->monc);
682
675 ceph_adjust_min_caps(-client->min_caps); 683 ceph_adjust_min_caps(-client->min_caps);
676 684
677 ceph_debugfs_client_cleanup(client); 685 ceph_debugfs_client_cleanup(client);
@@ -738,7 +746,7 @@ static struct dentry *open_root_dentry(struct ceph_client *client,
738 dout("open_root_inode opening '%s'\n", path); 746 dout("open_root_inode opening '%s'\n", path);
739 req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS); 747 req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS);
740 if (IS_ERR(req)) 748 if (IS_ERR(req))
741 return ERR_PTR(PTR_ERR(req)); 749 return ERR_CAST(req);
742 req->r_path1 = kstrdup(path, GFP_NOFS); 750 req->r_path1 = kstrdup(path, GFP_NOFS);
743 req->r_ino1.ino = CEPH_INO_ROOT; 751 req->r_ino1.ino = CEPH_INO_ROOT;
744 req->r_ino1.snap = CEPH_NOSNAP; 752 req->r_ino1.snap = CEPH_NOSNAP;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index dd1e7add656b..10a4a406e887 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -10,7 +10,6 @@
10#include <linux/fs.h> 10#include <linux/fs.h>
11#include <linux/mempool.h> 11#include <linux/mempool.h>
12#include <linux/pagemap.h> 12#include <linux/pagemap.h>
13#include <linux/slab.h>
14#include <linux/wait.h> 13#include <linux/wait.h>
15#include <linux/writeback.h> 14#include <linux/writeback.h>
16#include <linux/slab.h> 15#include <linux/slab.h>
diff --git a/include/linux/completion.h b/include/linux/completion.h
index 4a6b604ef7e4..51e3145196f6 100644
--- a/include/linux/completion.h
+++ b/include/linux/completion.h
@@ -83,6 +83,8 @@ extern unsigned long wait_for_completion_timeout(struct completion *x,
83 unsigned long timeout); 83 unsigned long timeout);
84extern unsigned long wait_for_completion_interruptible_timeout( 84extern unsigned long wait_for_completion_interruptible_timeout(
85 struct completion *x, unsigned long timeout); 85 struct completion *x, unsigned long timeout);
86extern unsigned long wait_for_completion_killable_timeout(
87 struct completion *x, unsigned long timeout);
86extern bool try_wait_for_completion(struct completion *x); 88extern bool try_wait_for_completion(struct completion *x);
87extern bool completion_done(struct completion *x); 89extern bool completion_done(struct completion *x);
88 90
diff --git a/kernel/sched.c b/kernel/sched.c
index 15b93f617fd7..d48408142503 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -4054,6 +4054,23 @@ int __sched wait_for_completion_killable(struct completion *x)
4054EXPORT_SYMBOL(wait_for_completion_killable); 4054EXPORT_SYMBOL(wait_for_completion_killable);
4055 4055
4056/** 4056/**
4057 * wait_for_completion_killable_timeout: - waits for completion of a task (w/(to,killable))
4058 * @x: holds the state of this particular completion
4059 * @timeout: timeout value in jiffies
4060 *
4061 * This waits for either a completion of a specific task to be
4062 * signaled or for a specified timeout to expire. It can be
4063 * interrupted by a kill signal. The timeout is in jiffies.
4064 */
4065unsigned long __sched
4066wait_for_completion_killable_timeout(struct completion *x,
4067 unsigned long timeout)
4068{
4069 return wait_for_common(x, timeout, TASK_KILLABLE);
4070}
4071EXPORT_SYMBOL(wait_for_completion_killable_timeout);
4072
4073/**
4057 * try_wait_for_completion - try to decrement a completion without blocking 4074 * try_wait_for_completion - try to decrement a completion without blocking
4058 * @x: completion structure 4075 * @x: completion structure
4059 * 4076 *