Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 217804
b: refs/heads/master
c: f991bd2
h: refs/heads/master
v: v3
  • Loading branch information
Eric Dumazet authored and Al Viro committed Oct 26, 2010
1 parent 863bdc7 commit dee4cbb
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 8 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: 7de9c6ee3ecffd99e1628e81a5ea5468f7581a1f
refs/heads/master: f991bd2e14210fb93d722cb23e54991de20e8a3d
45 changes: 38 additions & 7 deletions trunk/fs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,43 @@ static struct inode *find_inode_fast(struct super_block *sb,
return NULL;
}

/*
* Each cpu owns a range of LAST_INO_BATCH numbers.
* 'shared_last_ino' is dirtied only once out of LAST_INO_BATCH allocations,
* to renew the exhausted range.
*
* This does not significantly increase overflow rate because every CPU can
* consume at most LAST_INO_BATCH-1 unused inode numbers. So there is
* NR_CPUS*(LAST_INO_BATCH-1) wastage. At 4096 and 1024, this is ~0.1% of the
* 2^32 range, and is a worst-case. Even a 50% wastage would only increase
* overflow rate by 2x, which does not seem too significant.
*
* On a 32bit, non LFS stat() call, glibc will generate an EOVERFLOW
* error if st_ino won't fit in target struct field. Use 32bit counter
* here to attempt to avoid that.
*/
#define LAST_INO_BATCH 1024
static DEFINE_PER_CPU(unsigned int, last_ino);

static unsigned int get_next_ino(void)
{
unsigned int *p = &get_cpu_var(last_ino);
unsigned int res = *p;

#ifdef CONFIG_SMP
if (unlikely((res & (LAST_INO_BATCH-1)) == 0)) {
static atomic_t shared_last_ino;
int next = atomic_add_return(LAST_INO_BATCH, &shared_last_ino);

res = next - LAST_INO_BATCH;
}
#endif

*p = ++res;
put_cpu_var(last_ino);
return res;
}

/**
* new_inode - obtain an inode
* @sb: superblock
Expand All @@ -731,12 +768,6 @@ static struct inode *find_inode_fast(struct super_block *sb,
*/
struct inode *new_inode(struct super_block *sb)
{
/*
* On a 32bit, non LFS stat() call, glibc will generate an EOVERFLOW
* error if st_ino won't fit in target struct field. Use 32bit counter
* here to attempt to avoid that.
*/
static unsigned int last_ino;
struct inode *inode;

spin_lock_prefetch(&inode_lock);
Expand All @@ -745,7 +776,7 @@ struct inode *new_inode(struct super_block *sb)
if (inode) {
spin_lock(&inode_lock);
__inode_sb_list_add(inode);
inode->i_ino = ++last_ino;
inode->i_ino = get_next_ino();
inode->i_state = 0;
spin_unlock(&inode_lock);
}
Expand Down

0 comments on commit dee4cbb

Please sign in to comment.