Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/ryusuke/nilfs2

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2: (49 commits)
  nilfs2: separate wait function from nilfs_segctor_write
  nilfs2: add iterator for segment buffers
  nilfs2: hide nilfs_write_info struct in segment buffer code
  nilfs2: relocate io status variables to segment buffer
  nilfs2: do not return io error for bio allocation failure
  nilfs2: use list_splice_tail or list_splice_tail_init
  nilfs2: replace mark_inode_dirty as nilfs_mark_inode_dirty
  nilfs2: delete mark_inode_dirty in nilfs_delete_entry
  nilfs2: delete mark_inode_dirty in nilfs_commit_chunk
  nilfs2: change return type of nilfs_commit_chunk
  nilfs2: split nilfs_unlink as nilfs_do_unlink and nilfs_unlink
  nilfs2: delete redundant mark_inode_dirty
  nilfs2: expand inode_inc_link_count and inode_dec_link_count
  nilfs2: delete mark_inode_dirty from nilfs_set_link
  nilfs2: delete mark_inode_dirty in nilfs_new_inode
  nilfs2: add norecovery mount option
  nilfs2: add helper to get if volume is in a valid state
  nilfs2: move recovery completion into load_nilfs function
  nilfs2: apply readahead for recovery on mount
  nilfs2: clean up get/put function of a segment usage
  ...
  • Loading branch information
Linus Torvalds committed Dec 11, 2009
2 parents 3ef884b + a694291 commit 4e2ccdb
Show file tree
Hide file tree
Showing 32 changed files with 1,025 additions and 787 deletions.
7 changes: 5 additions & 2 deletions Documentation/filesystems/nilfs2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ Mount options
NILFS2 supports the following mount options:
(*) == default

barrier=on(*) This enables/disables barriers. barrier=off disables
it, barrier=on enables it.
nobarrier Disables barriers.
errors=continue(*) Keep going on a filesystem error.
errors=remount-ro Remount the filesystem read-only on an error.
errors=panic Panic and halt the machine if an error occurs.
Expand All @@ -71,6 +70,10 @@ order=strict Apply strict in-order semantics that preserves sequence
blocks. That means, it is guaranteed that no
overtaking of events occurs in the recovered file
system after a crash.
norecovery Disable recovery of the filesystem on mount.
This disables every write access on the device for
read-only mounts or snapshots. This option will fail
for r/w mounts on an unclean volume.

NILFS2 usage
============
Expand Down
108 changes: 85 additions & 23 deletions fs/nilfs2/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,29 +142,75 @@ static void nilfs_palloc_desc_block_init(struct inode *inode,
}
}

static int nilfs_palloc_get_block(struct inode *inode, unsigned long blkoff,
int create,
void (*init_block)(struct inode *,
struct buffer_head *,
void *),
struct buffer_head **bhp,
struct nilfs_bh_assoc *prev,
spinlock_t *lock)
{
int ret;

spin_lock(lock);
if (prev->bh && blkoff == prev->blkoff) {
get_bh(prev->bh);
*bhp = prev->bh;
spin_unlock(lock);
return 0;
}
spin_unlock(lock);

ret = nilfs_mdt_get_block(inode, blkoff, create, init_block, bhp);
if (!ret) {
spin_lock(lock);
/*
* The following code must be safe for change of the
* cache contents during the get block call.
*/
brelse(prev->bh);
get_bh(*bhp);
prev->bh = *bhp;
prev->blkoff = blkoff;
spin_unlock(lock);
}
return ret;
}

static int nilfs_palloc_get_desc_block(struct inode *inode,
unsigned long group,
int create, struct buffer_head **bhp)
{
return nilfs_mdt_get_block(inode,
nilfs_palloc_desc_blkoff(inode, group),
create, nilfs_palloc_desc_block_init, bhp);
struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;

return nilfs_palloc_get_block(inode,
nilfs_palloc_desc_blkoff(inode, group),
create, nilfs_palloc_desc_block_init,
bhp, &cache->prev_desc, &cache->lock);
}

static int nilfs_palloc_get_bitmap_block(struct inode *inode,
unsigned long group,
int create, struct buffer_head **bhp)
{
return nilfs_mdt_get_block(inode,
nilfs_palloc_bitmap_blkoff(inode, group),
create, NULL, bhp);
struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;

return nilfs_palloc_get_block(inode,
nilfs_palloc_bitmap_blkoff(inode, group),
create, NULL, bhp,
&cache->prev_bitmap, &cache->lock);
}

int nilfs_palloc_get_entry_block(struct inode *inode, __u64 nr,
int create, struct buffer_head **bhp)
{
return nilfs_mdt_get_block(inode, nilfs_palloc_entry_blkoff(inode, nr),
create, NULL, bhp);
struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;

return nilfs_palloc_get_block(inode,
nilfs_palloc_entry_blkoff(inode, nr),
create, NULL, bhp,
&cache->prev_entry, &cache->lock);
}

static struct nilfs_palloc_group_desc *
Expand All @@ -176,13 +222,6 @@ nilfs_palloc_block_get_group_desc(const struct inode *inode,
group % nilfs_palloc_groups_per_desc_block(inode);
}

static unsigned char *
nilfs_palloc_block_get_bitmap(const struct inode *inode,
const struct buffer_head *bh, void *kaddr)
{
return (unsigned char *)(kaddr + bh_offset(bh));
}

void *nilfs_palloc_block_get_entry(const struct inode *inode, __u64 nr,
const struct buffer_head *bh, void *kaddr)
{
Expand Down Expand Up @@ -289,8 +328,7 @@ int nilfs_palloc_prepare_alloc_entry(struct inode *inode,
if (ret < 0)
goto out_desc;
bitmap_kaddr = kmap(bitmap_bh->b_page);
bitmap = nilfs_palloc_block_get_bitmap(
inode, bitmap_bh, bitmap_kaddr);
bitmap = bitmap_kaddr + bh_offset(bitmap_bh);
pos = nilfs_palloc_find_available_slot(
inode, group, group_offset, bitmap,
entries_per_group);
Expand Down Expand Up @@ -351,8 +389,7 @@ void nilfs_palloc_commit_free_entry(struct inode *inode,
desc = nilfs_palloc_block_get_group_desc(inode, group,
req->pr_desc_bh, desc_kaddr);
bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page);
bitmap = nilfs_palloc_block_get_bitmap(inode, req->pr_bitmap_bh,
bitmap_kaddr);
bitmap = bitmap_kaddr + bh_offset(req->pr_bitmap_bh);

if (!nilfs_clear_bit_atomic(nilfs_mdt_bgl_lock(inode, group),
group_offset, bitmap))
Expand Down Expand Up @@ -385,8 +422,7 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode,
desc = nilfs_palloc_block_get_group_desc(inode, group,
req->pr_desc_bh, desc_kaddr);
bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page);
bitmap = nilfs_palloc_block_get_bitmap(inode, req->pr_bitmap_bh,
bitmap_kaddr);
bitmap = bitmap_kaddr + bh_offset(req->pr_bitmap_bh);
if (!nilfs_clear_bit_atomic(nilfs_mdt_bgl_lock(inode, group),
group_offset, bitmap))
printk(KERN_WARNING "%s: entry numer %llu already freed\n",
Expand Down Expand Up @@ -472,8 +508,7 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
desc = nilfs_palloc_block_get_group_desc(
inode, group, desc_bh, desc_kaddr);
bitmap_kaddr = kmap(bitmap_bh->b_page);
bitmap = nilfs_palloc_block_get_bitmap(
inode, bitmap_bh, bitmap_kaddr);
bitmap = bitmap_kaddr + bh_offset(bitmap_bh);
for (j = i, n = 0;
(j < nitems) && nilfs_palloc_group_is_in(inode, group,
entry_nrs[j]);
Expand Down Expand Up @@ -502,3 +537,30 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
}
return 0;
}

void nilfs_palloc_setup_cache(struct inode *inode,
struct nilfs_palloc_cache *cache)
{
NILFS_MDT(inode)->mi_palloc_cache = cache;
spin_lock_init(&cache->lock);
}

void nilfs_palloc_clear_cache(struct inode *inode)
{
struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;

spin_lock(&cache->lock);
brelse(cache->prev_desc.bh);
brelse(cache->prev_bitmap.bh);
brelse(cache->prev_entry.bh);
cache->prev_desc.bh = NULL;
cache->prev_bitmap.bh = NULL;
cache->prev_entry.bh = NULL;
spin_unlock(&cache->lock);
}

void nilfs_palloc_destroy_cache(struct inode *inode)
{
nilfs_palloc_clear_cache(inode);
NILFS_MDT(inode)->mi_palloc_cache = NULL;
}
21 changes: 21 additions & 0 deletions fs/nilfs2/alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,25 @@ int nilfs_palloc_freev(struct inode *, __u64 *, size_t);
#define nilfs_clear_bit_atomic ext2_clear_bit_atomic
#define nilfs_find_next_zero_bit ext2_find_next_zero_bit

/*
* persistent object allocator cache
*/

struct nilfs_bh_assoc {
unsigned long blkoff;
struct buffer_head *bh;
};

struct nilfs_palloc_cache {
spinlock_t lock;
struct nilfs_bh_assoc prev_desc;
struct nilfs_bh_assoc prev_bitmap;
struct nilfs_bh_assoc prev_entry;
};

void nilfs_palloc_setup_cache(struct inode *inode,
struct nilfs_palloc_cache *cache);
void nilfs_palloc_clear_cache(struct inode *inode);
void nilfs_palloc_destroy_cache(struct inode *inode);

#endif /* _NILFS_ALLOC_H */
8 changes: 0 additions & 8 deletions fs/nilfs2/bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,19 +402,11 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap)
void nilfs_bmap_add_blocks(const struct nilfs_bmap *bmap, int n)
{
inode_add_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n);
if (NILFS_MDT(bmap->b_inode))
nilfs_mdt_mark_dirty(bmap->b_inode);
else
mark_inode_dirty(bmap->b_inode);
}

void nilfs_bmap_sub_blocks(const struct nilfs_bmap *bmap, int n)
{
inode_sub_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n);
if (NILFS_MDT(bmap->b_inode))
nilfs_mdt_mark_dirty(bmap->b_inode);
else
mark_inode_dirty(bmap->b_inode);
}

__u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap,
Expand Down
76 changes: 34 additions & 42 deletions fs/nilfs2/btnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,34 @@ void nilfs_btnode_cache_clear(struct address_space *btnc)
truncate_inode_pages(btnc, 0);
}

struct buffer_head *
nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr)
{
struct inode *inode = NILFS_BTNC_I(btnc);
struct buffer_head *bh;

bh = nilfs_grab_buffer(inode, btnc, blocknr, 1 << BH_NILFS_Node);
if (unlikely(!bh))
return NULL;

if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) ||
buffer_dirty(bh))) {
brelse(bh);
BUG();
}
memset(bh->b_data, 0, 1 << inode->i_blkbits);
bh->b_bdev = NILFS_I_NILFS(inode)->ns_bdev;
bh->b_blocknr = blocknr;
set_buffer_mapped(bh);
set_buffer_uptodate(bh);

unlock_page(bh->b_page);
page_cache_release(bh->b_page);
return bh;
}

int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
sector_t pblocknr, struct buffer_head **pbh,
int newblk)
sector_t pblocknr, struct buffer_head **pbh)
{
struct buffer_head *bh;
struct inode *inode = NILFS_BTNC_I(btnc);
Expand All @@ -81,19 +106,6 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
return -ENOMEM;

err = -EEXIST; /* internal code */
if (newblk) {
if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) ||
buffer_dirty(bh))) {
brelse(bh);
BUG();
}
memset(bh->b_data, 0, 1 << inode->i_blkbits);
bh->b_bdev = NILFS_I_NILFS(inode)->ns_bdev;
bh->b_blocknr = blocknr;
set_buffer_mapped(bh);
set_buffer_uptodate(bh);
goto found;
}

if (buffer_uptodate(bh) || buffer_dirty(bh))
goto found;
Expand Down Expand Up @@ -135,27 +147,6 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
return err;
}

int nilfs_btnode_get(struct address_space *btnc, __u64 blocknr,
sector_t pblocknr, struct buffer_head **pbh, int newblk)
{
struct buffer_head *bh;
int err;

err = nilfs_btnode_submit_block(btnc, blocknr, pblocknr, pbh, newblk);
if (err == -EEXIST) /* internal code (cache hit) */
return 0;
if (unlikely(err))
return err;

bh = *pbh;
wait_on_buffer(bh);
if (!buffer_uptodate(bh)) {
brelse(bh);
return -EIO;
}
return 0;
}

/**
* nilfs_btnode_delete - delete B-tree node buffer
* @bh: buffer to be deleted
Expand Down Expand Up @@ -244,12 +235,13 @@ int nilfs_btnode_prepare_change_key(struct address_space *btnc,
unlock_page(obh->b_page);
}

err = nilfs_btnode_get(btnc, newkey, 0, &nbh, 1);
if (likely(!err)) {
BUG_ON(nbh == obh);
ctxt->newbh = nbh;
}
return err;
nbh = nilfs_btnode_create_block(btnc, newkey);
if (!nbh)
return -ENOMEM;

BUG_ON(nbh == obh);
ctxt->newbh = nbh;
return 0;

failed_unlock:
unlock_page(obh->b_page);
Expand Down
6 changes: 3 additions & 3 deletions fs/nilfs2/btnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ struct nilfs_btnode_chkey_ctxt {
void nilfs_btnode_cache_init_once(struct address_space *);
void nilfs_btnode_cache_init(struct address_space *, struct backing_dev_info *);
void nilfs_btnode_cache_clear(struct address_space *);
struct buffer_head *nilfs_btnode_create_block(struct address_space *btnc,
__u64 blocknr);
int nilfs_btnode_submit_block(struct address_space *, __u64, sector_t,
struct buffer_head **, int);
int nilfs_btnode_get(struct address_space *, __u64, sector_t,
struct buffer_head **, int);
struct buffer_head **);
void nilfs_btnode_delete(struct buffer_head *);
int nilfs_btnode_prepare_change_key(struct address_space *,
struct nilfs_btnode_chkey_ctxt *);
Expand Down
Loading

0 comments on commit 4e2ccdb

Please sign in to comment.