Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 110042
b: refs/heads/master
c: f1ccd29
h: refs/heads/master
v: v3
  • Loading branch information
Lachlan McIlroy authored and Lachlan McIlroy committed Sep 26, 2008
1 parent 68901f3 commit edc9885
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 16 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bc173c5789e1fc6065fd378edc815914b40ee86b
refs/heads/master: f1ccd2955157e1aff992f6aaaba0944209076220
78 changes: 78 additions & 0 deletions trunk/arch/arm/include/asm/cnt32_to_63.h
Original file line number Diff line number Diff line change
@@ -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 <linux/compiler.h>
#include <asm/types.h>
#include <asm/byteorder.h>

/*
* 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
2 changes: 1 addition & 1 deletion trunk/fs/ubifs/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/ubifs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions trunk/fs/ubifs/find.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 3 additions & 11 deletions trunk/fs/ubifs/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion trunk/fs/ubifs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/ubifs/tnc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/xfs/xfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down

0 comments on commit edc9885

Please sign in to comment.