trivial: fix then -> than typos in comments and documentation
[safe/jmp/linux-2.6] / drivers / mtd / ubi / eba.c
index 85297cd..25def34 100644 (file)
  */
 
 /*
- * The UBI Eraseblock Association (EBA) unit.
+ * The UBI Eraseblock Association (EBA) sub-system.
  *
- * This unit is responsible for I/O to/from logical eraseblock.
+ * This sub-system is responsible for I/O to/from logical eraseblock.
  *
  * Although in this implementation the EBA table is fully kept and managed in
  * RAM, which assumes poor scalability, it might be (partially) maintained on
  * flash in future implementations.
  *
- * The EBA unit implements per-logical eraseblock locking. Before accessing a
- * logical eraseblock it is locked for reading or writing. The per-logical
- * eraseblock locking is implemented by means of the lock tree. The lock tree
- * is an RB-tree which refers all the currently locked logical eraseblocks. The
- * lock tree elements are &struct ubi_ltree_entry objects. They are indexed by
- * (@vol_id, @lnum) pairs.
+ * The EBA sub-system implements per-logical eraseblock locking. Before
+ * accessing a logical eraseblock it is locked for reading or writing. The
+ * per-logical eraseblock locking is implemented by means of the lock tree. The
+ * lock tree is an RB-tree which refers all the currently locked logical
+ * eraseblocks. The lock tree elements are &struct ubi_ltree_entry objects.
+ * They are indexed by (@vol_id, @lnum) pairs.
  *
  * EBA also maintains the global sequence counter which is incremented each
  * time a logical eraseblock is mapped to a physical eraseblock and it is
@@ -78,7 +78,7 @@ static unsigned long long next_sqnum(struct ubi_device *ubi)
  */
 static int ubi_get_compat(const struct ubi_device *ubi, int vol_id)
 {
-       if (vol_id == UBI_LAYOUT_VOL_ID)
+       if (vol_id == UBI_LAYOUT_VOLUME_ID)
                return UBI_LAYOUT_VOLUME_COMPAT;
        return 0;
 }
@@ -137,10 +137,12 @@ static struct ubi_ltree_entry *ltree_add_entry(struct ubi_device *ubi,
 {
        struct ubi_ltree_entry *le, *le1, *le_free;
 
-       le = kmem_cache_alloc(ubi_ltree_slab, GFP_NOFS);
+       le = kmalloc(sizeof(struct ubi_ltree_entry), GFP_NOFS);
        if (!le)
                return ERR_PTR(-ENOMEM);
 
+       le->users = 0;
+       init_rwsem(&le->mutex);
        le->vol_id = vol_id;
        le->lnum = lnum;
 
@@ -187,9 +189,7 @@ static struct ubi_ltree_entry *ltree_add_entry(struct ubi_device *ubi,
        le->users += 1;
        spin_unlock(&ubi->ltree_lock);
 
-       if (le_free)
-               kmem_cache_free(ubi_ltree_slab, le_free);
-
+       kfree(le_free);
        return le;
 }
 
@@ -221,22 +221,18 @@ static int leb_read_lock(struct ubi_device *ubi, int vol_id, int lnum)
  */
 static void leb_read_unlock(struct ubi_device *ubi, int vol_id, int lnum)
 {
-       int free = 0;
        struct ubi_ltree_entry *le;
 
        spin_lock(&ubi->ltree_lock);
        le = ltree_lookup(ubi, vol_id, lnum);
        le->users -= 1;
        ubi_assert(le->users >= 0);
+       up_read(&le->mutex);
        if (le->users == 0) {
                rb_erase(&le->rb, &ubi->ltree);
-               free = 1;
+               kfree(le);
        }
        spin_unlock(&ubi->ltree_lock);
-
-       up_read(&le->mutex);
-       if (free)
-               kmem_cache_free(ubi_ltree_slab, le);
 }
 
 /**
@@ -272,7 +268,6 @@ static int leb_write_lock(struct ubi_device *ubi, int vol_id, int lnum)
  */
 static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum)
 {
-       int free;
        struct ubi_ltree_entry *le;
 
        le = ltree_add_entry(ubi, vol_id, lnum);
@@ -287,12 +282,9 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum)
        ubi_assert(le->users >= 0);
        if (le->users == 0) {
                rb_erase(&le->rb, &ubi->ltree);
-               free = 1;
-       } else
-               free = 0;
+               kfree(le);
+       }
        spin_unlock(&ubi->ltree_lock);
-       if (free)
-               kmem_cache_free(ubi_ltree_slab, le);
 
        return 1;
 }
@@ -305,23 +297,18 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum)
  */
 static void leb_write_unlock(struct ubi_device *ubi, int vol_id, int lnum)
 {
-       int free;
        struct ubi_ltree_entry *le;
 
        spin_lock(&ubi->ltree_lock);
        le = ltree_lookup(ubi, vol_id, lnum);
        le->users -= 1;
        ubi_assert(le->users >= 0);
+       up_write(&le->mutex);
        if (le->users == 0) {
                rb_erase(&le->rb, &ubi->ltree);
-               free = 1;
-       } else
-               free = 0;
+               kfree(le);
+       }
        spin_unlock(&ubi->ltree_lock);
-
-       up_write(&le->mutex);
-       if (free)
-               kmem_cache_free(ubi_ltree_slab, le);
 }
 
 /**
@@ -339,9 +326,6 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
 {
        int err, pnum, vol_id = vol->vol_id;
 
-       ubi_assert(ubi->ref_count > 0);
-       ubi_assert(vol->ref_count > 0);
-
        if (ubi->ro_mode)
                return -EROFS;
 
@@ -390,9 +374,6 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
        struct ubi_vid_hdr *vid_hdr;
        uint32_t uninitialized_var(crc);
 
-       ubi_assert(ubi->ref_count > 0);
-       ubi_assert(vol->ref_count > 0);
-
        err = leb_read_lock(ubi, vol_id, lnum);
        if (err)
                return err;
@@ -520,16 +501,12 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
        struct ubi_vid_hdr *vid_hdr;
 
        vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
-       if (!vid_hdr) {
+       if (!vid_hdr)
                return -ENOMEM;
-       }
-
-       mutex_lock(&ubi->buf_mutex);
 
 retry:
        new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN);
        if (new_pnum < 0) {
-               mutex_unlock(&ubi->buf_mutex);
                ubi_free_vid_hdr(ubi, vid_hdr);
                return new_pnum;
        }
@@ -549,20 +526,23 @@ retry:
                goto write_error;
 
        data_size = offset + len;
+       mutex_lock(&ubi->buf_mutex);
        memset(ubi->peb_buf1 + offset, 0xFF, len);
 
        /* Read everything before the area where the write failure happened */
        if (offset > 0) {
                err = ubi_io_read_data(ubi, ubi->peb_buf1, pnum, 0, offset);
                if (err && err != UBI_IO_BITFLIPS)
-                       goto out_put;
+                       goto out_unlock;
        }
 
        memcpy(ubi->peb_buf1 + offset, buf, len);
 
        err = ubi_io_write_data(ubi, ubi->peb_buf1, new_pnum, 0, data_size);
-       if (err)
+       if (err) {
+               mutex_unlock(&ubi->buf_mutex);
                goto write_error;
+       }
 
        mutex_unlock(&ubi->buf_mutex);
        ubi_free_vid_hdr(ubi, vid_hdr);
@@ -573,8 +553,9 @@ retry:
        ubi_msg("data was successfully recovered");
        return 0;
 
-out_put:
+out_unlock:
        mutex_unlock(&ubi->buf_mutex);
+out_put:
        ubi_wl_put_peb(ubi, new_pnum, 1);
        ubi_free_vid_hdr(ubi, vid_hdr);
        return err;
@@ -587,7 +568,6 @@ write_error:
        ubi_warn("failed to write to PEB %d", new_pnum);
        ubi_wl_put_peb(ubi, new_pnum, 1);
        if (++tries > UBI_IO_RETRIES) {
-               mutex_unlock(&ubi->buf_mutex);
                ubi_free_vid_hdr(ubi, vid_hdr);
                return err;
        }
@@ -616,9 +596,6 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
        int err, pnum, tries = 0, vol_id = vol->vol_id;
        struct ubi_vid_hdr *vid_hdr;
 
-       ubi_assert(ubi->ref_count > 0);
-       ubi_assert(vol->ref_count > 0);
-
        if (ubi->ro_mode)
                return -EROFS;
 
@@ -740,7 +717,7 @@ write_error:
  * to the real data size, although the @buf buffer has to contain the
  * alignment. In all other cases, @len has to be aligned.
  *
- * It is prohibited to write more then once to logical eraseblocks of static
+ * It is prohibited to write more than once to logical eraseblocks of static
  * volumes. This function returns zero in case of success and a negative error
  * code in case of failure.
  */
@@ -752,9 +729,6 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
        struct ubi_vid_hdr *vid_hdr;
        uint32_t crc;
 
-       ubi_assert(ubi->ref_count > 0);
-       ubi_assert(vol->ref_count > 0);
-
        if (ubi->ro_mode)
                return -EROFS;
 
@@ -762,7 +736,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
                /* If this is the last LEB @len may be unaligned */
                len = ALIGN(data_size, ubi->min_io_size);
        else
-               ubi_assert(len % ubi->min_io_size == 0);
+               ubi_assert(!(len & (ubi->min_io_size - 1)));
 
        vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
        if (!vid_hdr)
@@ -869,12 +843,20 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
        struct ubi_vid_hdr *vid_hdr;
        uint32_t crc;
 
-       ubi_assert(ubi->ref_count > 0);
-       ubi_assert(vol->ref_count > 0);
-
        if (ubi->ro_mode)
                return -EROFS;
 
+       if (len == 0) {
+               /*
+                * Special case when data length is zero. In this case the LEB
+                * has to be unmapped and mapped somewhere else.
+                */
+               err = ubi_eba_unmap_leb(ubi, vol, lnum);
+               if (err)
+                       return err;
+               return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype);
+       }
+
        vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
        if (!vid_hdr)
                return -ENOMEM;
@@ -921,7 +903,7 @@ retry:
        }
 
        if (vol->eba_tbl[lnum] >= 0) {
-               err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 1);
+               err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0);
                if (err)
                        goto out_leb_unlock;
        }
@@ -967,10 +949,14 @@ write_error:
  * This function copies logical eraseblock from physical eraseblock @from to
  * physical eraseblock @to. The @vid_hdr buffer may be changed by this
  * function. Returns:
- *   o %0  in case of success;
- *   o %1 if the operation was canceled and should be tried later (e.g.,
- *     because a bit-flip was detected at the target PEB);
- *   o %2 if the volume is being deleted and this LEB should not be moved.
+ *   o %0 in case of success;
+ *   o %1 if the operation was canceled because the volume is being deleted
+ *        or because the PEB was put meanwhile;
+ *   o %2 if the operation was canceled because there was a write error to the
+ *        target PEB;
+ *   o %-EAGAIN if the operation was canceled because a bit-flip was detected
+ *     in the target PEB;
+ *   o a negative error code in case of failure.
  */
 int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
                     struct ubi_vid_hdr *vid_hdr)
@@ -996,7 +982,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
        /*
         * Note, we may race with volume deletion, which means that the volume
         * this logical eraseblock belongs to might be being deleted. Since the
-        * volume deletion unmaps all the volume's logical eraseblocks, it will
+        * volume deletion un-maps all the volume's logical eraseblocks, it will
         * be locked in 'ubi_wl_put_peb()' and wait for the WL worker to finish.
         */
        vol = ubi->volumes[idx];
@@ -1004,7 +990,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
                /* No need to do further work, cancel */
                dbg_eba("volume %d is being removed, cancel", vol_id);
                spin_unlock(&ubi->volumes_lock);
-               return 2;
+               return 1;
        }
        spin_unlock(&ubi->volumes_lock);
 
@@ -1040,8 +1026,8 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
        }
 
        /*
-        * OK, now the LEB is locked and we can safely start moving iy. Since
-        * this function utilizes thie @ubi->peb1_buf buffer which is shared
+        * OK, now the LEB is locked and we can safely start moving it. Since
+        * this function utilizes the @ubi->peb1_buf buffer which is shared
         * with some other functions, so lock the buffer by taking the
         * @ubi->buf_mutex.
         */
@@ -1086,8 +1072,11 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
        vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));
 
        err = ubi_io_write_vid_hdr(ubi, to, vid_hdr);
-       if (err)
+       if (err) {
+               if (err == -EIO)
+                       err = 2;
                goto out_unlock_buf;
+       }
 
        cond_resched();
 
@@ -1097,14 +1086,17 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
                if (err != UBI_IO_BITFLIPS)
                        ubi_warn("cannot read VID header back from PEB %d", to);
                else
-                       err = 1;
+                       err = -EAGAIN;
                goto out_unlock_buf;
        }
 
        if (data_size > 0) {
                err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size);
-               if (err)
+               if (err) {
+                       if (err == -EIO)
+                               err = 2;
                        goto out_unlock_buf;
+               }
 
                cond_resched();
 
@@ -1119,15 +1111,16 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
                                ubi_warn("cannot read data back from PEB %d",
                                         to);
                        else
-                               err = 1;
+                               err = -EAGAIN;
                        goto out_unlock_buf;
                }
 
                cond_resched();
 
                if (memcmp(ubi->peb_buf1, ubi->peb_buf2, aldata_size)) {
-                       ubi_warn("read data back from PEB %d - it is different",
-                                to);
+                       ubi_warn("read data back from PEB %d and it is "
+                                "different", to);
+                       err = -EINVAL;
                        goto out_unlock_buf;
                }
        }
@@ -1143,7 +1136,7 @@ out_unlock_leb:
 }
 
 /**
- * ubi_eba_init_scan - initialize the EBA unit using scanning information.
+ * ubi_eba_init_scan - initialize the EBA sub-system using scanning information.
  * @ubi: UBI device description object
  * @si: scanning information
  *
@@ -1158,7 +1151,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
        struct ubi_scan_leb *seb;
        struct rb_node *rb;
 
-       dbg_eba("initialize EBA unit");
+       dbg_eba("initialize EBA sub-system");
 
        spin_lock_init(&ubi->ltree_lock);
        mutex_init(&ubi->alc_mutex);
@@ -1224,7 +1217,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
                ubi->rsvd_pebs  += ubi->beb_rsvd_pebs;
        }
 
-       dbg_eba("EBA unit is initialized");
+       dbg_eba("EBA sub-system is initialized");
        return 0;
 
 out_free:
@@ -1235,20 +1228,3 @@ out_free:
        }
        return err;
 }
-
-/**
- * ubi_eba_close - close EBA unit.
- * @ubi: UBI device description object
- */
-void ubi_eba_close(const struct ubi_device *ubi)
-{
-       int i, num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT;
-
-       dbg_eba("close EBA unit");
-
-       for (i = 0; i < num_volumes; i++) {
-               if (!ubi->volumes[i])
-                       continue;
-               kfree(ubi->volumes[i]->eba_tbl);
-       }
-}