Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a319bf56 authored by Ilya Dryomov's avatar Ilya Dryomov
Browse files

libceph: store timeouts in jiffies, verify user input



There are currently three libceph-level timeouts that the user can
specify on mount: mount_timeout, osd_idle_ttl and osdkeepalive.  All of
these are in seconds and no checking is done on user input: negative
values are accepted, we multiply them all by HZ which may or may not
overflow, arbitrarily large jiffies then get added together, etc.

There is also a bug in the way mount_timeout=0 is handled.  It's
supposed to mean "infinite timeout", but that's not how wait.h APIs
treat it and so __ceph_open_session() for example will busy loop
without much chance of being interrupted if none of ceph-mons are
there.

Fix all this by verifying user input, storing timeouts capped by
msecs_to_jiffies() in jiffies and using the new ceph_timeout_jiffies()
helper for all user-specified waits to handle infinite timeouts
correctly.

Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
Reviewed-by: default avatarAlex Elder <elder@linaro.org>
parent d50c97b5
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -4963,8 +4963,8 @@ static int rbd_add_parse_args(const char *buf,
 */
 */
static int rbd_add_get_pool_id(struct rbd_client *rbdc, const char *pool_name)
static int rbd_add_get_pool_id(struct rbd_client *rbdc, const char *pool_name)
{
{
	struct ceph_options *opts = rbdc->client->options;
	u64 newest_epoch;
	u64 newest_epoch;
	unsigned long timeout = rbdc->client->options->mount_timeout * HZ;
	int tries = 0;
	int tries = 0;
	int ret;
	int ret;


@@ -4979,7 +4979,8 @@ static int rbd_add_get_pool_id(struct rbd_client *rbdc, const char *pool_name)
		if (rbdc->client->osdc.osdmap->epoch < newest_epoch) {
		if (rbdc->client->osdc.osdmap->epoch < newest_epoch) {
			ceph_monc_request_next_osdmap(&rbdc->client->monc);
			ceph_monc_request_next_osdmap(&rbdc->client->monc);
			(void) ceph_monc_wait_osdmap(&rbdc->client->monc,
			(void) ceph_monc_wait_osdmap(&rbdc->client->monc,
						     newest_epoch, timeout);
						     newest_epoch,
						     opts->mount_timeout);
			goto again;
			goto again;
		} else {
		} else {
			/* the osdmap we have is new enough */
			/* the osdmap we have is new enough */
+2 −2
Original line number Original line Diff line number Diff line
@@ -1260,7 +1260,7 @@ static int ceph_dir_fsync(struct file *file, loff_t start, loff_t end,
		if (req->r_timeout) {
		if (req->r_timeout) {
			unsigned long time_left = wait_for_completion_timeout(
			unsigned long time_left = wait_for_completion_timeout(
					&req->r_safe_completion,
					&req->r_safe_completion,
							req->r_timeout);
					ceph_timeout_jiffies(req->r_timeout));
			if (time_left > 0)
			if (time_left > 0)
				ret = 0;
				ret = 0;
			else
			else
+6 −6
Original line number Original line Diff line number Diff line
@@ -2268,7 +2268,8 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
	dout("do_request waiting\n");
	dout("do_request waiting\n");
	if (req->r_timeout) {
	if (req->r_timeout) {
		err = (long)wait_for_completion_killable_timeout(
		err = (long)wait_for_completion_killable_timeout(
			&req->r_completion, req->r_timeout);
					&req->r_completion,
					ceph_timeout_jiffies(req->r_timeout));
		if (err == 0)
		if (err == 0)
			err = -EIO;
			err = -EIO;
	} else if (req->r_wait_for_completion) {
	} else if (req->r_wait_for_completion) {
@@ -3424,8 +3425,8 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
 */
 */
static void wait_requests(struct ceph_mds_client *mdsc)
static void wait_requests(struct ceph_mds_client *mdsc)
{
{
	struct ceph_options *opts = mdsc->fsc->client->options;
	struct ceph_mds_request *req;
	struct ceph_mds_request *req;
	struct ceph_fs_client *fsc = mdsc->fsc;


	mutex_lock(&mdsc->mutex);
	mutex_lock(&mdsc->mutex);
	if (__get_oldest_req(mdsc)) {
	if (__get_oldest_req(mdsc)) {
@@ -3433,7 +3434,7 @@ static void wait_requests(struct ceph_mds_client *mdsc)


		dout("wait_requests waiting for requests\n");
		dout("wait_requests waiting for requests\n");
		wait_for_completion_timeout(&mdsc->safe_umount_waiters,
		wait_for_completion_timeout(&mdsc->safe_umount_waiters,
				    fsc->client->options->mount_timeout * HZ);
				    ceph_timeout_jiffies(opts->mount_timeout));


		/* tear down remaining requests */
		/* tear down remaining requests */
		mutex_lock(&mdsc->mutex);
		mutex_lock(&mdsc->mutex);
@@ -3556,10 +3557,9 @@ static bool done_closing_sessions(struct ceph_mds_client *mdsc)
 */
 */
void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
{
{
	struct ceph_options *opts = mdsc->fsc->client->options;
	struct ceph_mds_session *session;
	struct ceph_mds_session *session;
	int i;
	int i;
	struct ceph_fs_client *fsc = mdsc->fsc;
	unsigned long timeout = fsc->client->options->mount_timeout * HZ;


	dout("close_sessions\n");
	dout("close_sessions\n");


@@ -3580,7 +3580,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)


	dout("waiting for sessions to close\n");
	dout("waiting for sessions to close\n");
	wait_event_timeout(mdsc->session_close_wq, done_closing_sessions(mdsc),
	wait_event_timeout(mdsc->session_close_wq, done_closing_sessions(mdsc),
			   timeout);
			   ceph_timeout_jiffies(opts->mount_timeout));


	/* tear down remaining sessions */
	/* tear down remaining sessions */
	mutex_lock(&mdsc->mutex);
	mutex_lock(&mdsc->mutex);
+1 −1
Original line number Original line Diff line number Diff line
@@ -227,7 +227,7 @@ struct ceph_mds_request {
	int r_err;
	int r_err;
	bool r_aborted;
	bool r_aborted;


	unsigned long r_timeout;  /* optional.  jiffies */
	unsigned long r_timeout;  /* optional.  jiffies, 0 is "wait forever" */
	unsigned long r_started;  /* start time to measure timeout against */
	unsigned long r_started;  /* start time to measure timeout against */
	unsigned long r_request_started; /* start time for mds request only,
	unsigned long r_request_started; /* start time for mds request only,
					    used to measure lease durations */
					    used to measure lease durations */
+1 −1
Original line number Original line Diff line number Diff line
@@ -742,7 +742,7 @@ static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
	req->r_ino1.ino = CEPH_INO_ROOT;
	req->r_ino1.ino = CEPH_INO_ROOT;
	req->r_ino1.snap = CEPH_NOSNAP;
	req->r_ino1.snap = CEPH_NOSNAP;
	req->r_started = started;
	req->r_started = started;
	req->r_timeout = fsc->client->options->mount_timeout * HZ;
	req->r_timeout = fsc->client->options->mount_timeout;
	req->r_args.getattr.mask = cpu_to_le32(CEPH_STAT_CAP_INODE);
	req->r_args.getattr.mask = cpu_to_le32(CEPH_STAT_CAP_INODE);
	req->r_num_caps = 2;
	req->r_num_caps = 2;
	err = ceph_mdsc_do_request(mdsc, NULL, req);
	err = ceph_mdsc_do_request(mdsc, NULL, req);
Loading