diff --git a/[refs] b/[refs] index 6adedd82469c..a59b3a141ce7 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: bc173c5789e1fc6065fd378edc815914b40ee86b +refs/heads/master: f1ccd2955157e1aff992f6aaaba0944209076220 diff --git a/trunk/arch/arm/include/asm/cnt32_to_63.h b/trunk/arch/arm/include/asm/cnt32_to_63.h new file mode 100644 index 000000000000..480c873fa746 --- /dev/null +++ b/trunk/arch/arm/include/asm/cnt32_to_63.h @@ -0,0 +1,78 @@ +/* + * include/asm/cnt32_to_63.h -- extend a 32-bit counter to 63 bits + * + * Author: Nicolas Pitre + * Created: December 3, 2006 + * Copyright: MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + */ + +#ifndef __INCLUDE_CNT32_TO_63_H__ +#define __INCLUDE_CNT32_TO_63_H__ + +#include +#include +#include + +/* + * Prototype: u64 cnt32_to_63(u32 cnt) + * Many hardware clock counters are only 32 bits wide and therefore have + * a relatively short period making wrap-arounds rather frequent. This + * is a problem when implementing sched_clock() for example, where a 64-bit + * non-wrapping monotonic value is expected to be returned. + * + * To overcome that limitation, let's extend a 32-bit counter to 63 bits + * in a completely lock free fashion. Bits 0 to 31 of the clock are provided + * by the hardware while bits 32 to 62 are stored in memory. The top bit in + * memory is used to synchronize with the hardware clock half-period. When + * the top bit of both counters (hardware and in memory) differ then the + * memory is updated with a new value, incrementing it when the hardware + * counter wraps around. + * + * Because a word store in memory is atomic then the incremented value will + * always be in synch with the top bit indicating to any potential concurrent + * reader if the value in memory is up to date or not with regards to the + * needed increment. And any race in updating the value in memory is harmless + * as the same value would simply be stored more than once. + * + * The only restriction for the algorithm to work properly is that this + * code must be executed at least once per each half period of the 32-bit + * counter to properly update the state bit in memory. This is usually not a + * problem in practice, but if it is then a kernel timer could be scheduled + * to manage for this code to be executed often enough. + * + * Note that the top bit (bit 63) in the returned value should be considered + * as garbage. It is not cleared here because callers are likely to use a + * multiplier on the returned value which can get rid of the top bit + * implicitly by making the multiplier even, therefore saving on a runtime + * clear-bit instruction. Otherwise caller must remember to clear the top + * bit explicitly. + */ + +/* this is used only to give gcc a clue about good code generation */ +typedef union { + struct { +#if defined(__LITTLE_ENDIAN) + u32 lo, hi; +#elif defined(__BIG_ENDIAN) + u32 hi, lo; +#endif + }; + u64 val; +} cnt32_to_63_t; + +#define cnt32_to_63(cnt_lo) \ +({ \ + static volatile u32 __m_cnt_hi = 0; \ + cnt32_to_63_t __x; \ + __x.hi = __m_cnt_hi; \ + __x.lo = (cnt_lo); \ + if (unlikely((s32)(__x.hi ^ __x.lo) < 0)) \ + __m_cnt_hi = __x.hi = (__x.hi ^ 0x80000000) + (__x.hi >> 31); \ + __x.val; \ +}) + +#endif diff --git a/trunk/fs/ubifs/debug.c b/trunk/fs/ubifs/debug.c index d7f7645779f2..b9cb77473758 100644 --- a/trunk/fs/ubifs/debug.c +++ b/trunk/fs/ubifs/debug.c @@ -538,7 +538,7 @@ void dbg_dump_node(const struct ubifs_info *c, const void *node) printk(KERN_DEBUG "\t%d orphan inode numbers:\n", n); for (i = 0; i < n; i++) printk(KERN_DEBUG "\t ino %llu\n", - (unsigned long long)le64_to_cpu(orph->inos[i])); + le64_to_cpu(orph->inos[i])); break; } default: diff --git a/trunk/fs/ubifs/dir.c b/trunk/fs/ubifs/dir.c index 526c01ec8003..2b267c9a1806 100644 --- a/trunk/fs/ubifs/dir.c +++ b/trunk/fs/ubifs/dir.c @@ -426,7 +426,7 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) while (1) { dbg_gen("feed '%s', ino %llu, new f_pos %#x", - dent->name, (unsigned long long)le64_to_cpu(dent->inum), + dent->name, le64_to_cpu(dent->inum), key_hash_flash(c, &dent->key)); ubifs_assert(dent->ch.sqnum > ubifs_inode(dir)->creat_sqnum); diff --git a/trunk/fs/ubifs/find.c b/trunk/fs/ubifs/find.c index 47814cde2407..e045c8b55423 100644 --- a/trunk/fs/ubifs/find.c +++ b/trunk/fs/ubifs/find.c @@ -507,6 +507,7 @@ int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *free, rsvd_idx_lebs = 0; lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - c->lst.taken_empty_lebs; + ubifs_assert(lebs + c->lst.idx_lebs >= c->min_idx_lebs); if (rsvd_idx_lebs < lebs) /* * OK to allocate an empty LEB, but we still don't want to go diff --git a/trunk/fs/ubifs/gc.c b/trunk/fs/ubifs/gc.c index 02aba36fe3d4..13f1019c859f 100644 --- a/trunk/fs/ubifs/gc.c +++ b/trunk/fs/ubifs/gc.c @@ -334,15 +334,15 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) err = move_nodes(c, sleb); if (err) - goto out_inc_seq; + goto out; err = gc_sync_wbufs(c); if (err) - goto out_inc_seq; + goto out; err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0, 0, 0); if (err) - goto out_inc_seq; + goto out; /* Allow for races with TNC */ c->gced_lnum = lnum; @@ -369,14 +369,6 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) out: ubifs_scan_destroy(sleb); return err; - -out_inc_seq: - /* We may have moved at least some nodes so allow for races with TNC */ - c->gced_lnum = lnum; - smp_wmb(); - c->gc_seq += 1; - smp_wmb(); - goto out; } /** diff --git a/trunk/fs/ubifs/super.c b/trunk/fs/ubifs/super.c index 3f4902060c7a..7562464ac83f 100644 --- a/trunk/fs/ubifs/super.c +++ b/trunk/fs/ubifs/super.c @@ -1024,13 +1024,14 @@ static int mount_ubifs(struct ubifs_info *c) goto out_dereg; } - sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id); if (!mounted_read_only) { err = alloc_wbufs(c); if (err) goto out_cbuf; /* Create background thread */ + sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, + c->vi.vol_id); c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name); if (!c->bgt) c->bgt = ERR_PTR(-EINVAL); diff --git a/trunk/fs/ubifs/tnc.c b/trunk/fs/ubifs/tnc.c index 7634c5970887..7da209ab9378 100644 --- a/trunk/fs/ubifs/tnc.c +++ b/trunk/fs/ubifs/tnc.c @@ -1476,7 +1476,7 @@ int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, } err = fallible_read_node(c, key, &zbr, node); - if (err <= 0 || maybe_leb_gced(c, zbr.lnum, gc_seq1)) { + if (maybe_leb_gced(c, zbr.lnum, gc_seq1)) { /* * The node may have been GC'ed out from under us so try again * while keeping the TNC mutex locked. diff --git a/trunk/fs/xfs/xfs_inode.c b/trunk/fs/xfs/xfs_inode.c index 00e80df9dd9d..419cfc2eacb3 100644 --- a/trunk/fs/xfs/xfs_inode.c +++ b/trunk/fs/xfs/xfs_inode.c @@ -4584,6 +4584,7 @@ xfs_iext_irec_compact_full( (XFS_LINEAR_EXTS - erp_next->er_extcount) * sizeof(xfs_bmbt_rec_t)); + erp_next->er_extoff += ext_diff; } }