All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dave Wysochanski <dwysocha@redhat.com>
To: lvm-devel@redhat.com
Subject: [PATCH 2/14] Provide _vg_lock_and_read, a new implementation of lock+vg_read_internal.
Date: Fri, 06 Feb 2009 13:21:43 -0500	[thread overview]
Message-ID: <1233944503.11630.5.camel@localhost.localdomain> (raw)
In-Reply-To: <1232619010-4858-3-git-send-email-prockai@redhat.com>


On Thu, 2009-01-22 at 11:09 +0100, Petr Rockai wrote:
> Thu Jan 22 10:36:41 CET 2009  Petr Rockai <me@mornfall.net>
>   * Provide _vg_lock_and_read, a new implementation of lock+vg_read_internal.
>   
>   This is an internal function, to be later used by vg_read and
>   vg_read_for_update. Not to be confused with the public function
>   vg_lock_and_read, which will be removed later.
> diff -rN -u -p old-temp.4430/lib/metadata/metadata.c new-temp.4430/lib/metadata/metadata.c
> --- old-temp.4430/lib/metadata/metadata.c	2009-01-22 11:02:34.894778074 +0100
> +++ new-temp.4430/lib/metadata/metadata.c	2009-01-22 11:02:34.942780194 +0100
> @@ -2377,7 +2377,37 @@ int pv_analyze(struct cmd_context *cmd, 
>  	return 1;
>  }
>  
> +static uint32_t _vg_check_status(const struct volume_group *vg, uint32_t status)
> +{
> +	uint32_t failure = 0;
>  
> +	if ((status & CLUSTERED) &&
> +	    (vg_is_clustered(vg)) && !locking_is_clustered() &&
> +	    !lockingfailed()) {
> +		log_error("Skipping clustered volume group %s", vg->name);
> +		return FAILED_CLUSTERED;
> +	}
> +
> +	if ((status & EXPORTED_VG) &&
> +	    (vg->status & EXPORTED_VG)) {
> +		log_error("Volume group %s is exported", vg->name);
> +		failure |= FAILED_EXPORTED;
> +	}
> +
> +	if ((status & LVM_WRITE) &&
> +	    !(vg->status & LVM_WRITE)) {
> +		log_error("Volume group %s is read-only", vg->name);
> +		failure |= FAILED_READ_ONLY;
> +	}
> +
> +	if ((status & RESIZEABLE_VG) &&
> +	    !(vg->status & RESIZEABLE_VG)) {
> +		log_error("Volume group %s is not resizeable.", vg->name);
> +		failure |= FAILED_RESIZEABLE;
> +	}
> +
> +	return failure;
> +}
>  
>  /**
>   * vg_check_status - check volume group status flags and log error
> @@ -2462,6 +2492,133 @@ vg_t *vg_lock_and_read(struct cmd_contex
>  }
>  
>  /*
> + * Create a (vg_t) volume group handle from a struct volume_group pointer and a
> + * possible failure code. Zero failure code = success.
> + */
> +static vg_t *_vg_make_handle(struct cmd_context *cmd,
> +			     struct volume_group *vg,
> +			     uint32_t failure)
> +{
> +	if (!vg && !(vg = dm_pool_zalloc(cmd->mem, sizeof(*vg)))) {
> +		log_error("Error allocating vg handle .");
> +		return_NULL;
> +	}
> +	vg->read_failed = failure;
> +	return (vg_t *) vg;
> +}
> +
> +static vg_t *_recover_vg(struct cmd_context *cmd, const char *lock,
> +			 const char *vg_name, const char *vgid,
> +			 uint32_t lock_flags)
> +{
> +	int consistent = 1;
> +	struct volume_group *vg;
> +
> +	lock_flags &= ~LCK_TYPE_MASK;
> +	lock_flags |= LCK_WRITE;
> +
> +	unlock_vg(cmd, lock);
> +
> +	dev_close_all();
> +
> +	if (!lock_vol(cmd, lock, lock_flags))
> +		return_NULL;
> +
> +	if (!(vg = vg_read_internal(cmd, vg_name, vgid, &consistent)))
> +		return_NULL;
> +	if (!consistent)
> +		return_NULL;
> +
> +	return (vg_t *)vg;
> +}
> +
> +/*
> + * _vg_lock_and_read - consolidate vg locking, reading, and status flag checking
> + * This is an internal function.
> + *
> + * misc_flags:
> + *  ALLOW_INCONSISTENT: disable autocorrection
> + *
> + * Setting ALLOW_INCONSISTENT might give you inconsistent metadata. You will
> + * *still* get FAILED_INCONSISTENT in case the metadata has *really* been
> + * inconsistent. However, you still get the latest version of metadata in VG.
> + *
> + * Returns:
> + * Use vg_read_error(vg) to determine the result. Nonzero vg_read_error(vg)
> + * means there were problems reading the volume group.
> + * Zero value means that the VG is open and appropriate locks are held.
> + */
> +static vg_t *_vg_lock_and_read(struct cmd_context *cmd, const char *vg_name,
> +			       const char *vgid,
> +			       uint32_t lock_flags, uint32_t status_flags,
> +			       uint32_t misc_flags)
> +{
> +	struct volume_group *vg = 0;
> +	const char *lock;
> + 	int consistent = 1;
> +	int consistent_in;
> +	uint32_t failure = 0;
> +
> +	if (misc_flags & ALLOW_INCONSISTENT || !(lock_flags & LCK_WRITE))
> +		consistent = 0;
> +
> +	if (!validate_name(vg_name) && !is_orphan_vg(vg_name)) {
> +		log_error("Volume group name %s has invalid characters",
> +			  vg_name);
> +		return NULL;
> +	}
> +
> +	lock = (misc_flags & ORPHAN_LOCK ? VG_ORPHANS : vg_name);
> +	if (!(misc_flags & DISABLE_LOCK) && !lock_vol(cmd, lock, lock_flags)) {
> +		log_error("Can't get lock for %s", vg_name);
> +		return _vg_make_handle(cmd, vg, FAILED_LOCKING);
> +	}

The above code doesn't work if vgid is given and vgname is NULL.
Name validation will fail - easy to fix.  But then the lock_vol fails.
I'm going to hack away at this and see how far I get.  We should
probably drop vgid from vg_read() and vg_read_for_update() for now
though.


> +
> +	if (misc_flags & ORPHAN_LOCK)
> +		status_flags &= ~LVM_WRITE;
> +
> +	if (misc_flags & EXISTENCE_CHECK)
> +		consistent = 0;
> +
> +	consistent_in = consistent;
> +
> +	/* If consistent == 1, we get NULL here if correction fails. */
> +	if (!(vg = vg_read_internal(cmd, vg_name, vgid, &consistent))) {
> +		if (consistent_in && !consistent) {
> +			log_error("Volume group \"%s\" inconsistent.", vg_name);
> +			failure |= FAILED_INCONSISTENT;
> +			goto_bad;
> +		}
> +		if (!(misc_flags & EXISTENCE_CHECK))
> +			log_error("Volume group \"%s\" not found", vg_name);
> +		failure |= FAILED_NOTFOUND | (misc_flags & EXISTENCE_CHECK);
> +		goto_bad;
> +	}
> +
> +	/* consistent == 0 when VG is not found, but failed == FAILED_NOTFOUND */
> +	if (!consistent && !failure) {
> +		if (!(vg = _recover_vg(cmd, lock, vg_name, vgid, lock_flags))) {
> +			log_error("Recovery of volume group \"%s\" failed.",
> +				  vg_name);
> +			failure |= FAILED_INCONSISTENT;
> +			goto_bad;
> +		}
> +	}
> +
> +	failure |= _vg_check_status(vg, status_flags);
> +	if (failure)
> +		goto_bad;
> +
> +	return _vg_make_handle(cmd, vg, failure);
> +
> + bad:
> +	if (failure != (FAILED_NOTFOUND | EXISTENCE_CHECK) &&
> +	    !(misc_flags & KEEP_LOCK) && !(misc_flags & DISABLE_LOCK))
> +			unlock_vg(cmd, lock);
> +	return _vg_make_handle(cmd, vg, failure);
> +}
> +
> +/*
>   * Gets/Sets for external LVM library
>   */
>  struct id pv_id(const pv_t *pv)
> diff -rN -u -p old-temp.4430/lib/metadata/metadata-exported.h new-temp.4430/lib/metadata/metadata-exported.h
> --- old-temp.4430/lib/metadata/metadata-exported.h	2009-01-22 11:02:34.898782074 +0100
> +++ new-temp.4430/lib/metadata/metadata-exported.h	2009-01-22 11:02:34.942780194 +0100
> @@ -104,6 +104,43 @@ struct pv_segment;
>  #define MIRROR_BY_LV		0x00000002U	/* mirror using whole mimage LVs */
>  #define MIRROR_SKIP_INIT_SYNC	0x00000010U	/* skip initial sync */
>  
> +/* vg_read and vg_read_for_update flags */
> +#define ALLOW_INCONSISTENT 0x1
> +#define ALLOW_EXPORTED     0x2
> +#define REQUIRE_RESIZEABLE 0x4
> +#define EXISTENCE_CHECK    0x8
> +
> +/* FIXME these should be removed when we get better internal locking logic that
> +   does not rely on caller to provide locking details. */
> +#define NONBLOCKING_LOCK 0x100 /* Give up instead of waiting for a lock;
> +                                  required when acquiring a second VG lock. */
> +#define KEEP_LOCK        0x200 /* Do not unlock upon read failure. */
> +
> +/* FIXME the following flags should be removed in favour of better APIs
> +   (vg_reread and vg_read_orphan?) */
> +#define DISABLE_LOCK     0x400 /* Disable locking altogether. DANGEROUS. Only
> +				  use when you already hold appropriate lock
> +				  for this VG. */
> +#define ORPHAN_LOCK      0x800 /* Use when you vg_read(_for_update) the orphan
> +				  VG. */
> +
> +/* A meta-flag, useful with toollib for_each_* functions. */
> +#define READ_FOR_UPDATE 0x1000
> +
> +/* vg's "read_failed" field */
> +#define FAILED_INCONSISTENT 0x1
> +#define FAILED_LOCKING      0x2
> +#define FAILED_NOTFOUND     0x4
> +/* #define EXISTENCE_CHECK  0x8 -- left out for EXISTENCE_CHECK above, as it can
> +   be or'd into failure flags */
> +
> +#define FAILED_READ_ONLY   0x10
> +#define FAILED_EXPORTED    0x20
> +#define FAILED_RESIZEABLE  0x40
> +#define FAILED_CLUSTERED   0x80
> +
> +#define FAILED_ALLOCATION 0x100
> +
>  /* Ordered list - see lv_manip.c */
>  typedef enum {
>  	ALLOC_INVALID,
> @@ -196,6 +233,9 @@ struct volume_group {
>  	char *name;
>  	char *system_id;
>  
> +	uint32_t read_failed; /* 0 = no, everything OK. Otherwise uses FAILED_*
> +				 flags as defined above. */
> +
>  	uint32_t status;
>  	alloc_policy_t alloc;
>  
> 
> --
> lvm-devel mailing list
> lvm-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/lvm-devel



  parent reply	other threads:[~2009-02-06 18:21 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-01-22 10:09 [PATCH] Another take on vg_read Petr Rockai
2009-01-22 10:09 ` [PATCH 1/14] Move vg_read out of the way, renaming it to vg_read_internal Petr Rockai
2009-01-22 10:09   ` [PATCH 2/14] Provide _vg_lock_and_read, a new implementation of lock+vg_read_internal Petr Rockai
2009-01-22 10:09     ` [PATCH 3/14] Properly enforce cluster locking in _vg_lock_and_read Petr Rockai
2009-01-22 10:10       ` [PATCH 4/14] Replace implementation of vg_check_status with a call to _vg_check_status Petr Rockai
2009-01-22 10:10         ` [PATCH 5/14] Implement vg_read and vg_read_for_update Petr Rockai
2009-01-22 10:10           ` [PATCH 6/14] Add vg_read_error and vg_might_exist Petr Rockai
2009-01-22 10:10             ` [PATCH 7/14] Convert the straight instances of vg_lock_and_read to new vg_read(_for_update) Petr Rockai
2009-01-22 10:10               ` [PATCH 8/14] Convert vgreduce to use vg_read_for_update Petr Rockai
2009-01-22 10:10                 ` [PATCH 9/14] Convert vgrename to vg_read_for_update Petr Rockai
2009-01-22 10:10                   ` [PATCH 10/14] Convert vgsplit to use vg_read_for_update Petr Rockai
2009-01-22 10:10                     ` [PATCH 11/14] Rework the toollib interface (process_each_*) on top of new vg_read Petr Rockai
2009-01-22 10:10                       ` [PATCH 12/14] Port process_each_pv to " Petr Rockai
2009-01-22 10:10                         ` [PATCH 13/14] Remove now-unused vg_lock_and_read Petr Rockai
2009-01-22 10:10                           ` [PATCH 14/14] Un-export vg_read_internal Petr Rockai
2009-01-26 16:05                             ` Dave Wysochanski
2009-01-22 16:13                         ` [PATCH 12/14] Port process_each_pv to new vg_read Dave Wysochanski
2009-01-24 21:45                 ` [PATCH updated] Convert vgreduce to use vg_read_for_update Dave Wysochanski
2009-01-24 21:46                   ` [PATCH] " Dave Wysochanski
2009-01-25  0:21                     ` [PATCH update2] " Dave Wysochanski
2009-01-25  0:21                       ` [PATCH] " Dave Wysochanski
2009-01-22 18:17       ` [PATCH 3/14] Properly enforce cluster locking in _vg_lock_and_read Dave Wysochanski
2009-01-22 20:15         ` Petr Rockai
2009-02-06 18:21     ` Dave Wysochanski [this message]
2009-01-22 17:36 ` [PATCH] Another take on vg_read Dave Wysochanski
2009-01-22 17:48   ` Petr Rockai

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=1233944503.11630.5.camel@localhost.localdomain \
    --to=dwysocha@redhat.com \
    --cc=lvm-devel@redhat.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.