All of lore.kernel.org
 help / color / mirror / Atom feed
From: Adrian Hunter <adrian.hunter@intel.com>
To: Richard Weinberger <richard@nod.at>
Cc: dedekind1@gmail.com, linux-kernel@vger.kernel.org,
	Heinz.Egger@linutronix.de, linux-mtd@lists.infradead.org,
	tim.bird@am.sony.com, tglx@linutronix.de
Subject: Re: [PATCH] [RFC] UBI: Implement Fastmap support
Date: Fri, 01 Jun 2012 08:47:44 +0300	[thread overview]
Message-ID: <4FC85780.9070200@intel.com> (raw)
In-Reply-To: <1337771191-95358-2-git-send-email-richard@nod.at>

On 23/05/12 14:06, Richard Weinberger wrote:
> Fastmap (aka checkpointing) allows attaching of an UBI volume in nearly
> constant time. Only a fixed number of PEBs has to be scanned.
> 
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
>  drivers/mtd/ubi/Makefile    |    2 +-
>  drivers/mtd/ubi/attach.c    |   34 +-
>  drivers/mtd/ubi/build.c     |   25 +
>  drivers/mtd/ubi/eba.c       |   18 +-
>  drivers/mtd/ubi/fastmap.c   | 1240 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/mtd/ubi/ubi-media.h |  119 +++++
>  drivers/mtd/ubi/ubi.h       |   68 +++-
>  drivers/mtd/ubi/wl.c        |  184 +++++++-
>  8 files changed, 1667 insertions(+), 23 deletions(-)
>  create mode 100644 drivers/mtd/ubi/fastmap.c
> 

...

> diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
> new file mode 100644
> index 0000000..7757e5a
> --- /dev/null
> +++ b/drivers/mtd/ubi/fastmap.c

...

> +/**
> + * ubi_update_fastmap - will be called by UBI if a volume changes or
> + * a fastmap pool becomes full.
> + * @ubi: UBI device object
> + */
> +int ubi_update_fastmap(struct ubi_device *ubi)
> +{
> +	int ret, i;
> +	struct ubi_fastmap_layout *new_fm;
> +
> +	if (ubi->ro_mode)
> +		return 0;
> +
> +	new_fm = kzalloc(sizeof(*new_fm), GFP_KERNEL);
> +	if (!new_fm)
> +		return -ENOMEM;
> +
> +	new_fm->size = sizeof(struct ubi_fm_hdr) + \
> +			sizeof(struct ubi_fm_scan_pool) + \
> +			(ubi->peb_count * sizeof(struct ubi_fm_ec)) + \
> +			(sizeof(struct ubi_fm_eba) + \
> +			(ubi->peb_count * sizeof(__be32))) + \
> +			sizeof(struct ubi_fm_volhdr) * UBI_MAX_VOLUMES;
> +	new_fm->size = roundup(new_fm->size, ubi->leb_size);
> +
> +	new_fm->used_blocks = new_fm->size / ubi->leb_size;
> +
> +	for (i = 0; i < new_fm->used_blocks; i++) {
> +		new_fm->e[i] = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
> +		if (!new_fm->e[i]) {
> +			while (i--)
> +				kfree(new_fm->e[i]);
> +
> +			kfree(new_fm);
> +			return -ENOMEM;
> +		}
> +	}
> +
> +	ubi->old_fm = ubi->fm;
> +	ubi->fm = NULL;
> +
> +	spin_lock(&ubi->wl_lock);
> +	new_fm->e[0]->pnum = ubi_wl_get_fm_peb(ubi, UBI_FM_MAX_START);
> +	spin_unlock(&ubi->wl_lock);
> +
> +	if (ubi->old_fm) {
> +		/* no fresh early PEB was found, reuse the old one */
> +		if (new_fm->e[0]->pnum < 0) {
> +			struct ubi_ec_hdr *ec_hdr;
> +
> +			ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
> +			if (!ec_hdr) {
> +				kfree(new_fm);
> +
> +				return -ENOMEM;
> +			}
> +
> +			/* we have to erase the block by hand */
> +
> +			ret = ubi_io_read_ec_hdr(ubi, ubi->old_fm->e[0]->pnum,
> +				ec_hdr, 0);
> +			if (ret) {
> +				ubi_err("Unable to read EC header");
> +				kfree(new_fm);
> +				kfree(ec_hdr);
> +
> +				return ret;
> +			}
> +
> +			ret = ubi_io_sync_erase(ubi, ubi->old_fm->e[0]->pnum,
> +				0);
> +			if (ret < 0) {
> +				ubi_err("Unable to erase old SB");
> +				kfree(new_fm);
> +				kfree(ec_hdr);
> +
> +				return ret;
> +			}
> +
> +			ec_hdr->ec += ret;
> +			if (ec_hdr->ec > UBI_MAX_ERASECOUNTER) {
> +				ubi_err("Erase counter overflow!");
> +				kfree(new_fm);
> +				kfree(ec_hdr);
> +
> +				return -EINVAL;
> +			}
> +
> +			ret = ubi_io_write_ec_hdr(ubi, ubi->old_fm->e[0]->pnum,
> +				ec_hdr);
> +			kfree(ec_hdr);
> +			if (ret) {
> +				ubi_err("Unable to write new EC header");
> +				kfree(new_fm);
> +
> +				return ret;
> +			}
> +
> +			new_fm->e[0]->pnum = ubi->old_fm->e[0]->pnum;
> +			new_fm->e[0]->ec = ubi->old_fm->e[0]->ec;
> +		} else {
> +			/* we've got a new early PEB, return the old one */
> +			ubi_wl_put_fm_peb(ubi, ubi->old_fm->e[0]->pnum, 0);
> +			new_fm->e[0]->ec = get_ec(ubi, new_fm->e[0]->pnum);
> +		}
> +
> +		/* return all other fastmap block to the wl system */
> +		for (i = 1; i < ubi->old_fm->used_blocks; i++)
> +			ubi_wl_put_fm_peb(ubi, ubi->old_fm->e[i]->pnum, 0);

It looks like, if you lose power at this point, the old fastmap may have
been erased but the new fastmap has not been written.  That would mean
you lose the fastmap.  Is that correct?  I guess you need to write the
new fastmap first and then erase the old one.

> +	} else {
> +		if (new_fm->e[0]->pnum < 0) {
> +			ubi_err("Could not find an early PEB");
> +			kfree(new_fm);
> +
> +			return -ENOSPC;
> +		}
> +		new_fm->e[0]->ec = get_ec(ubi, new_fm->e[0]->pnum);
> +	}
> +
> +	if (new_fm->used_blocks > UBI_FM_MAX_BLOCKS) {
> +		ubi_err("Fastmap too large");
> +		kfree(new_fm);
> +
> +		return -ENOSPC;
> +	}
> +
> +	/* give the wl subsystem a chance to produce some free blocks */
> +	cond_resched();
> +
> +	for (i = 1; i < new_fm->used_blocks; i++) {
> +		spin_lock(&ubi->wl_lock);
> +		new_fm->e[i]->pnum = ubi_wl_get_fm_peb(ubi, -1);
> +		spin_unlock(&ubi->wl_lock);
> +
> +		if (new_fm->e[i]->pnum < 0) {
> +			ubi_err("Could not get any free erase block");
> +
> +			while (i--) {
> +				ubi_wl_put_fm_peb(ubi, new_fm->e[i]->pnum, 0);
> +				kfree(new_fm->e[i]);
> +			}
> +
> +			kfree(new_fm);
> +
> +			return -ENOSPC;
> +		}
> +
> +		new_fm->e[i]->ec = get_ec(ubi, new_fm->e[i]->pnum);
> +	}
> +
> +	if (ubi->old_fm) {
> +		for (i = 0; i < ubi->old_fm->used_blocks; i++)
> +			kfree(ubi->old_fm->e[i]);
> +
> +		kfree(ubi->old_fm);
> +		ubi->old_fm = NULL;
> +	}
> +
> +	return ubi_write_fastmap(ubi, new_fm);
> +}

WARNING: multiple messages have this Message-ID (diff)
From: Adrian Hunter <adrian.hunter@intel.com>
To: Richard Weinberger <richard@nod.at>
Cc: linux-mtd@lists.infradead.org, tglx@linutronix.de,
	dedekind1@gmail.com, linux-kernel@vger.kernel.org,
	Heinz.Egger@linutronix.de, tim.bird@am.sony.com
Subject: Re: [PATCH] [RFC] UBI: Implement Fastmap support
Date: Fri, 01 Jun 2012 08:47:44 +0300	[thread overview]
Message-ID: <4FC85780.9070200@intel.com> (raw)
In-Reply-To: <1337771191-95358-2-git-send-email-richard@nod.at>

On 23/05/12 14:06, Richard Weinberger wrote:
> Fastmap (aka checkpointing) allows attaching of an UBI volume in nearly
> constant time. Only a fixed number of PEBs has to be scanned.
> 
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
>  drivers/mtd/ubi/Makefile    |    2 +-
>  drivers/mtd/ubi/attach.c    |   34 +-
>  drivers/mtd/ubi/build.c     |   25 +
>  drivers/mtd/ubi/eba.c       |   18 +-
>  drivers/mtd/ubi/fastmap.c   | 1240 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/mtd/ubi/ubi-media.h |  119 +++++
>  drivers/mtd/ubi/ubi.h       |   68 +++-
>  drivers/mtd/ubi/wl.c        |  184 +++++++-
>  8 files changed, 1667 insertions(+), 23 deletions(-)
>  create mode 100644 drivers/mtd/ubi/fastmap.c
> 

...

> diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
> new file mode 100644
> index 0000000..7757e5a
> --- /dev/null
> +++ b/drivers/mtd/ubi/fastmap.c

...

> +/**
> + * ubi_update_fastmap - will be called by UBI if a volume changes or
> + * a fastmap pool becomes full.
> + * @ubi: UBI device object
> + */
> +int ubi_update_fastmap(struct ubi_device *ubi)
> +{
> +	int ret, i;
> +	struct ubi_fastmap_layout *new_fm;
> +
> +	if (ubi->ro_mode)
> +		return 0;
> +
> +	new_fm = kzalloc(sizeof(*new_fm), GFP_KERNEL);
> +	if (!new_fm)
> +		return -ENOMEM;
> +
> +	new_fm->size = sizeof(struct ubi_fm_hdr) + \
> +			sizeof(struct ubi_fm_scan_pool) + \
> +			(ubi->peb_count * sizeof(struct ubi_fm_ec)) + \
> +			(sizeof(struct ubi_fm_eba) + \
> +			(ubi->peb_count * sizeof(__be32))) + \
> +			sizeof(struct ubi_fm_volhdr) * UBI_MAX_VOLUMES;
> +	new_fm->size = roundup(new_fm->size, ubi->leb_size);
> +
> +	new_fm->used_blocks = new_fm->size / ubi->leb_size;
> +
> +	for (i = 0; i < new_fm->used_blocks; i++) {
> +		new_fm->e[i] = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
> +		if (!new_fm->e[i]) {
> +			while (i--)
> +				kfree(new_fm->e[i]);
> +
> +			kfree(new_fm);
> +			return -ENOMEM;
> +		}
> +	}
> +
> +	ubi->old_fm = ubi->fm;
> +	ubi->fm = NULL;
> +
> +	spin_lock(&ubi->wl_lock);
> +	new_fm->e[0]->pnum = ubi_wl_get_fm_peb(ubi, UBI_FM_MAX_START);
> +	spin_unlock(&ubi->wl_lock);
> +
> +	if (ubi->old_fm) {
> +		/* no fresh early PEB was found, reuse the old one */
> +		if (new_fm->e[0]->pnum < 0) {
> +			struct ubi_ec_hdr *ec_hdr;
> +
> +			ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
> +			if (!ec_hdr) {
> +				kfree(new_fm);
> +
> +				return -ENOMEM;
> +			}
> +
> +			/* we have to erase the block by hand */
> +
> +			ret = ubi_io_read_ec_hdr(ubi, ubi->old_fm->e[0]->pnum,
> +				ec_hdr, 0);
> +			if (ret) {
> +				ubi_err("Unable to read EC header");
> +				kfree(new_fm);
> +				kfree(ec_hdr);
> +
> +				return ret;
> +			}
> +
> +			ret = ubi_io_sync_erase(ubi, ubi->old_fm->e[0]->pnum,
> +				0);
> +			if (ret < 0) {
> +				ubi_err("Unable to erase old SB");
> +				kfree(new_fm);
> +				kfree(ec_hdr);
> +
> +				return ret;
> +			}
> +
> +			ec_hdr->ec += ret;
> +			if (ec_hdr->ec > UBI_MAX_ERASECOUNTER) {
> +				ubi_err("Erase counter overflow!");
> +				kfree(new_fm);
> +				kfree(ec_hdr);
> +
> +				return -EINVAL;
> +			}
> +
> +			ret = ubi_io_write_ec_hdr(ubi, ubi->old_fm->e[0]->pnum,
> +				ec_hdr);
> +			kfree(ec_hdr);
> +			if (ret) {
> +				ubi_err("Unable to write new EC header");
> +				kfree(new_fm);
> +
> +				return ret;
> +			}
> +
> +			new_fm->e[0]->pnum = ubi->old_fm->e[0]->pnum;
> +			new_fm->e[0]->ec = ubi->old_fm->e[0]->ec;
> +		} else {
> +			/* we've got a new early PEB, return the old one */
> +			ubi_wl_put_fm_peb(ubi, ubi->old_fm->e[0]->pnum, 0);
> +			new_fm->e[0]->ec = get_ec(ubi, new_fm->e[0]->pnum);
> +		}
> +
> +		/* return all other fastmap block to the wl system */
> +		for (i = 1; i < ubi->old_fm->used_blocks; i++)
> +			ubi_wl_put_fm_peb(ubi, ubi->old_fm->e[i]->pnum, 0);

It looks like, if you lose power at this point, the old fastmap may have
been erased but the new fastmap has not been written.  That would mean
you lose the fastmap.  Is that correct?  I guess you need to write the
new fastmap first and then erase the old one.

> +	} else {
> +		if (new_fm->e[0]->pnum < 0) {
> +			ubi_err("Could not find an early PEB");
> +			kfree(new_fm);
> +
> +			return -ENOSPC;
> +		}
> +		new_fm->e[0]->ec = get_ec(ubi, new_fm->e[0]->pnum);
> +	}
> +
> +	if (new_fm->used_blocks > UBI_FM_MAX_BLOCKS) {
> +		ubi_err("Fastmap too large");
> +		kfree(new_fm);
> +
> +		return -ENOSPC;
> +	}
> +
> +	/* give the wl subsystem a chance to produce some free blocks */
> +	cond_resched();
> +
> +	for (i = 1; i < new_fm->used_blocks; i++) {
> +		spin_lock(&ubi->wl_lock);
> +		new_fm->e[i]->pnum = ubi_wl_get_fm_peb(ubi, -1);
> +		spin_unlock(&ubi->wl_lock);
> +
> +		if (new_fm->e[i]->pnum < 0) {
> +			ubi_err("Could not get any free erase block");
> +
> +			while (i--) {
> +				ubi_wl_put_fm_peb(ubi, new_fm->e[i]->pnum, 0);
> +				kfree(new_fm->e[i]);
> +			}
> +
> +			kfree(new_fm);
> +
> +			return -ENOSPC;
> +		}
> +
> +		new_fm->e[i]->ec = get_ec(ubi, new_fm->e[i]->pnum);
> +	}
> +
> +	if (ubi->old_fm) {
> +		for (i = 0; i < ubi->old_fm->used_blocks; i++)
> +			kfree(ubi->old_fm->e[i]);
> +
> +		kfree(ubi->old_fm);
> +		ubi->old_fm = NULL;
> +	}
> +
> +	return ubi_write_fastmap(ubi, new_fm);
> +}

  parent reply	other threads:[~2012-06-01  5:47 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-23 11:06 [RFC v7] UBI: Fastmap support (aka checkpointing) Richard Weinberger
2012-05-23 11:06 ` Richard Weinberger
2012-05-23 11:06 ` [PATCH] [RFC] UBI: Implement Fastmap support Richard Weinberger
2012-05-23 11:06   ` Richard Weinberger
2012-05-26 13:22   ` Artem Bityutskiy
2012-05-26 13:22     ` Artem Bityutskiy
2012-05-31 10:37   ` Adrian Hunter
2012-05-31 10:37     ` Adrian Hunter
2012-05-31 13:31     ` Richard Weinberger
2012-05-31 13:31       ` Richard Weinberger
2012-06-01  5:47   ` Adrian Hunter [this message]
2012-06-01  5:47     ` Adrian Hunter
2012-06-01  8:00     ` Richard Weinberger
2012-06-01  8:00       ` Richard Weinberger
2012-06-01  8:10       ` Artem Bityutskiy
2012-06-01  8:10         ` Artem Bityutskiy
2012-06-01  8:10         ` Richard Weinberger
2012-06-01  8:10           ` Richard Weinberger
2012-06-01  8:47           ` Adrian Hunter
2012-06-01  8:47             ` Adrian Hunter
2012-05-26 12:41 ` [RFC v7] UBI: Fastmap support (aka checkpointing) Artem Bityutskiy
2012-05-26 12:41   ` Artem Bityutskiy
2012-05-26 14:01   ` Richard Weinberger
2012-05-26 14:01     ` Richard Weinberger
2012-05-26 14:15     ` Artem Bityutskiy
2012-05-26 14:15       ` Artem Bityutskiy
2012-05-28  6:36   ` Shmulik Ladkani
2012-05-28  6:36     ` Shmulik Ladkani
2012-05-28  6:46     ` Artem Bityutskiy
2012-05-28  6:46       ` Artem Bityutskiy
2012-05-28  9:49       ` Richard Weinberger
2012-05-28  9:49         ` Richard Weinberger
  -- strict thread matches above, loose matches on Subject: below --
2012-05-21 14:01 [RFC v6] " Richard Weinberger
2012-05-21 14:01 ` [PATCH] [RFC] UBI: Implement Fastmap support Richard Weinberger
2012-05-21 14:01   ` Richard Weinberger
2012-05-22 13:43   ` Artem Bityutskiy
2012-05-22 13:43     ` Artem Bityutskiy
2012-05-22 15:01   ` Shmulik Ladkani
2012-05-22 15:01     ` Shmulik Ladkani
2012-05-22 16:55     ` Richard Weinberger
2012-05-22 16:55       ` Richard Weinberger
2012-05-22 18:18       ` Shmulik Ladkani
2012-05-22 18:18         ` Shmulik Ladkani
2012-05-22 18:57         ` Richard Weinberger
2012-05-22 18:57           ` Richard Weinberger
2012-05-23  6:18           ` Shmulik Ladkani
2012-05-23  6:18             ` Shmulik Ladkani
2012-05-23  7:43             ` Richard Weinberger
2012-05-23  7:43               ` Richard Weinberger
2012-05-22 20:11         ` Richard Weinberger
2012-05-22 20:11           ` Richard Weinberger
2012-05-24  8:19           ` Artem Bityutskiy
2012-05-24  8:19             ` Artem Bityutskiy
2012-05-24  8:26             ` Richard Weinberger
2012-05-24  8:26               ` Richard Weinberger
2012-05-24  9:21               ` Artem Bityutskiy
2012-05-24  9:21                 ` Artem Bityutskiy
2012-05-24  8:17       ` Artem Bityutskiy
2012-05-24  8:17         ` Artem Bityutskiy
2012-05-24  9:56         ` Shmulik Ladkani
2012-05-24  9:56           ` Shmulik Ladkani
2012-05-24 10:03           ` Richard Weinberger
2012-05-24 10:03             ` Richard Weinberger
2012-05-24 20:07             ` Shmulik Ladkani
2012-05-24 20:07               ` Shmulik Ladkani
2012-05-24  8:22       ` Artem Bityutskiy
2012-05-24  8:22         ` Artem Bityutskiy
2012-05-24  8:24         ` Richard Weinberger
2012-05-24  8:24           ` Richard Weinberger

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=4FC85780.9070200@intel.com \
    --to=adrian.hunter@intel.com \
    --cc=Heinz.Egger@linutronix.de \
    --cc=dedekind1@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=richard@nod.at \
    --cc=tglx@linutronix.de \
    --cc=tim.bird@am.sony.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.