Linux Container Development
 help / color / mirror / Atom feed
From: "Serge E. Hallyn" <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
To: Oren Laadan <orenl-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Subject: Re: [PATCH] c/r: pin down modules registered to obj-ops
Date: Thu, 29 Apr 2010 18:11:21 -0500	[thread overview]
Message-ID: <20100429231121.GA3862@us.ibm.com> (raw)
In-Reply-To: <1272580878-7268-1-git-send-email-orenl-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>

Quoting Oren Laadan (orenl-eQaUEPhvms7ENvBUuze7eA@public.gmane.org):
> To ensure that a module does not unload in the middle of a checkpoint
> or a restart operation, pin (module_get) all the modules during either
> operation.  For that, add a new memeber ->owner in ckpt_obj_ops.
> 
> Also add a counter that keeps track of how many module_gets we have
> going on, to properly handle new modules that register when an
> operation is underway.
> 
> This is a proof of concept, applies on top of the patch that introduces
> objhash on rc7 (patch 33).
> 
> Todo:
> 
> - I put the initialization part in init_*_ctx(), but it could be moved
> to ckpt_ctx_alloc() which is common to both checkpoint and restart.
> 
> - If this is ok, then additional patches should adjust those modules
> that indeed register...
> 
> Signed-off-by: Oren Laadan <orenl-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>

Yes this looks good to me

Acked-by: Serge Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Were you going to stick this into v21 too, or queue that up as
first patch after the patchbomb?

thanks,
-serge

> 
> ---
> diff --git a/include/linux/checkpoint.h b/include/linux/checkpoint.h
> index 2f5af3c..4ed8a8c 100644
> --- a/include/linux/checkpoint.h
> +++ b/include/linux/checkpoint.h
> @@ -40,11 +40,13 @@ extern long do_sys_restart(pid_t pid, int fd,
>  #define CKPT_CTX_RESTART_BIT		1
>  #define CKPT_CTX_SUCCESS_BIT		2
>  #define CKPT_CTX_ERROR_BIT		3
> +#define CKPT_CTX_PINNED_BIT		4
> 
>  #define CKPT_CTX_CHECKPOINT	(1 << CKPT_CTX_CHECKPOINT_BIT)
>  #define CKPT_CTX_RESTART	(1 << CKPT_CTX_RESTART_BIT)
>  #define CKPT_CTX_SUCCESS	(1 << CKPT_CTX_SUCCESS_BIT)
>  #define CKPT_CTX_ERROR		(1 << CKPT_CTX_ERROR_BIT)
> +#define CKPT_CTX_PINNED		(1 << CKPT_CTX_PINNED_BIT)
> 
>  /* ckpt_ctx: uflags */
>  #define CHECKPOINT_USER_FLAGS		CHECKPOINT_SUBTREE
> @@ -107,6 +109,9 @@ static inline int ckpt_get_error(struct ckpt_ctx *ctx)
>  extern void restore_notify_error(struct ckpt_ctx *ctx);
> 
>  /* obj_hash */
> +extern int ckpt_obj_module_get(void);
> +extern void ckpt_obj_module_put(void);
> +
>  extern void ckpt_obj_hash_free(struct ckpt_ctx *ctx);
>  extern int ckpt_obj_hash_alloc(struct ckpt_ctx *ctx);
> 
> @@ -284,6 +289,7 @@ extern void _ckpt_msg_complete(struct ckpt_ctx *ctx);
> 
>  struct ckpt_obj_ops;
>  extern int register_checkpoint_obj(const struct ckpt_obj_ops *ops);
> +extern void unregister_checkpoint_obj(const struct ckpt_obj_ops *ops);
> 
>  #else /* CONFIG_CHEKCPOINT */
> 
> @@ -293,6 +299,10 @@ static inline int register_checkpoint_obj(const struct ckpt_obj_ops *ops)
>  	return 0;
>  }
> 
> +static inline void unregister_checkpoint_obj(const struct ckpt_obj_ops *ops)
> +{
> +}
> +
>  #endif /* CONFIG_CHECKPOINT */
>  #endif /* __KERNEL__ */
> 
> diff --git a/include/linux/checkpoint_types.h b/include/linux/checkpoint_types.h
> index 912e06a..8035556 100644
> --- a/include/linux/checkpoint_types.h
> +++ b/include/linux/checkpoint_types.h
> @@ -79,6 +79,7 @@ struct ckpt_obj_ops {
>  	int (*ref_grab)(void *ptr);
>  	int (*checkpoint)(struct ckpt_ctx *ctx, void *ptr);
>  	void *(*restore)(struct ckpt_ctx *ctx);
> +	struct module *owner;
>  };
> 
> 
> diff --git a/kernel/checkpoint/checkpoint.c b/kernel/checkpoint/checkpoint.c
> index f451f8f..1a08bfb 100644
> --- a/kernel/checkpoint/checkpoint.c
> +++ b/kernel/checkpoint/checkpoint.c
> @@ -473,6 +473,7 @@ static int init_checkpoint_ctx(struct ckpt_ctx *ctx, pid_t pid)
>  {
>  	struct task_struct *task;
>  	struct nsproxy *nsproxy;
> +	int ret;
> 
>  	/*
>  	 * No need for explicit cleanup here, because if an error
> @@ -514,6 +515,12 @@ static int init_checkpoint_ctx(struct ckpt_ctx *ctx, pid_t pid)
>  		return -EINVAL;  /* cleanup by ckpt_ctx_free() */
>  	}
> 
> +	/* pin down modules - cleanup by ckpt_ctx_free() */
> +	ret = ckpt_obj_module_get();
> +	if (ret < 0)
> +		return ret;
> +	ckpt_ctx_set_kflag(ctx, CKPT_CTX_PINNED);
> +
>  	return 0;
>  }
> 
> diff --git a/kernel/checkpoint/objhash.c b/kernel/checkpoint/objhash.c
> index 1ee06d0..db795e3 100644
> --- a/kernel/checkpoint/objhash.c
> +++ b/kernel/checkpoint/objhash.c
> @@ -45,17 +45,80 @@ static const struct ckpt_obj_ops *ckpt_obj_ops[CKPT_OBJ_MAX] = {
>  	[CKPT_OBJ_IGNORE] = &ckpt_obj_ignored_ops,
>  };
> 
> +static int ckpt_obj_pinned_count;
> +static DEFINE_SPINLOCK(ckpt_obj_pinned_lock);
> +
>  int register_checkpoint_obj(const struct ckpt_obj_ops *ops)
>  {
> +	int ret = -EINVAL;
> +	int i;
> +
>  	if (ops->obj_type < 0 || ops->obj_type >= CKPT_OBJ_MAX)
>  		return -EINVAL;
> -	if (ckpt_obj_ops[ops->obj_type] != NULL)
> -		return -EINVAL;
> -	ckpt_obj_ops[ops->obj_type] = ops;
> -	return 0;
> +	spin_lock(&ckpt_obj_pinned_lock);
> +	if (ckpt_obj_ops[ops->obj_type] == NULL) {
> +		if (ops->owner) {
> +			for (i = 0; i < ckpt_obj_pinned_count)
> +				__module_get(owner->module);
> +		}
> +		ckpt_obj_ops[ops->obj_type] = ops;
> +		ret = 0;
> +	}
> +	spin_unlock(&ckpt_obj_pinned_lock);
> +	return ret;
>  }
>  EXPORT_SYMBOL(register_checkpoint_obj);
> 
> +void unregister_checkpoint_obj(const struct ckpt_obj_ops *ops)
> +{
> +	if (ops->obj_type < 0 || ops->obj_type >= CKPT_OBJ_MAX)
> +		return;
> +	spin_lock(&ckpt_obj_pinned_lock);
> +	if (ckpt_obj_ops[ops->obj_type] == ops)
> +		ckpt_obj_ops[ops->obj_type] = NULL;
> +	spin_unlock(&ckpt_obj_pinned_lock);
> +	return ret;
> +}
> +EXPORT_SYMBOL(unregister_checkpoint_obj);
> +
> +static void _ckpt_obj_module_put(int last)
> +{
> +	int i;
> +
> +	for (i = 0; i < last; i++) {
> +		if (!ckpt_obj_ops[i] || !ckpt_obj_ops[i]->owner)
> +			continue;
> +		module_put(ckpt_obj_ops[i]->owner);
> +	}
> +}
> +void ckpt_obj_module_put(void)
> +{
> +	spin_lock(&ckpt_obj_pinned_lock);
> +	_ckpt_obj_module_put(CKPT_OBJ_MAX);
> +	ckpt_obj_pinned_count--;
> +	spin_unlock(&ckpt_obj_pinned_lock);
> +}
> +
> +int ckpt_obj_module_get(void)
> +{
> +	int i, ret = 0;
> +
> +	spin_lock(&ckpt_obj_pinned_lock);
> +	for (i = 0; i < CKPT_OBJ_MAX; i++) {
> +		if (!ckpt_obj_ops[i] || !ckpt_obj_ops[i]->owner)
> +			continue;
> +		ret = try_module_get(ckpt_obj_ops[i]->owner);
> +		if (ret < 0)
> +			break;
> +	}
> +	if (ret < 0)
> +		_ckpt_obj_module_put(i);
> +	else
> +		ckpt_obj_pinned_count++;
> +	spin_unlock(&ckpt_obj_pinned_lock);
> +	return ret;
> +}
> +
>  #define CKPT_OBJ_HASH_NBITS  10
>  #define CKPT_OBJ_HASH_TOTAL  (1UL << CKPT_OBJ_HASH_NBITS)
> 
> diff --git a/kernel/checkpoint/restart.c b/kernel/checkpoint/restart.c
> index 437de4f..582e1f1 100644
> --- a/kernel/checkpoint/restart.c
> +++ b/kernel/checkpoint/restart.c
> @@ -1084,6 +1084,12 @@ static int init_restart_ctx(struct ckpt_ctx *ctx, pid_t pid)
> 
>  	ctx->active_pid = -1;	/* see restore_activate_next, get_active_pid */
> 
> +	/* pin down modules - cleanup by ckpt_ctx_free() */
> +	ret = ckpt_obj_module_get();
> +	if (ret < 0)
> +		return ret;
> +	ckpt_ctx_set_kflag(ctx, CKPT_CTX_PINNED);
> +
>  	return 0;
>  }
> 
> diff --git a/kernel/checkpoint/sys.c b/kernel/checkpoint/sys.c
> index 5e84915..e1a1f96 100644
> --- a/kernel/checkpoint/sys.c
> +++ b/kernel/checkpoint/sys.c
> @@ -217,6 +217,10 @@ static void ckpt_ctx_free(struct ckpt_ctx *ctx)
> 
>  	kfree(ctx->pids_arr);
> 
> +	/* un-pin modules */
> +	if (ctx->kflags & CKPT_CTX_PINNED)
> +		ckpt_obj_module_put();
> +
>  	kfree(ctx);
>  }

  parent reply	other threads:[~2010-04-29 23:11 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-04-29 22:41 [PATCH] c/r: pin down modules registered to obj-ops Oren Laadan
     [not found] ` <1272580878-7268-1-git-send-email-orenl-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
2010-04-29 23:11   ` Serge E. Hallyn [this message]
     [not found]     ` <20100429231121.GA3862-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-04-30  4:34       ` Oren Laadan
     [not found]         ` <4BDA5DDA.3010701-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
2010-04-30  4:34           ` Serge E. Hallyn
     [not found]             ` <20100430043432.GA15098-A9i7LUbDfNHQT0dZR+AlfA@public.gmane.org>
2010-04-30  4:55               ` Oren Laadan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100429231121.GA3862@us.ibm.com \
    --to=serue-r/jw6+rmf7hqt0dzr+alfa@public.gmane.org \
    --cc=containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \
    --cc=orenl-eQaUEPhvms7ENvBUuze7eA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox