Commit 4e2ccdb0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
  ...
parents 3ef884b4 a694291a
Loading
Loading
Loading
Loading
+5 −2
Original line number Original line Diff line number Diff line
@@ -49,8 +49,7 @@ Mount options
NILFS2 supports the following mount options:
NILFS2 supports the following mount options:
(*) == default
(*) == default


barrier=on(*)		This enables/disables barriers. barrier=off disables
nobarrier		Disables barriers.
			it, barrier=on enables it.
errors=continue(*)	Keep going on a filesystem error.
errors=continue(*)	Keep going on a filesystem error.
errors=remount-ro	Remount the filesystem read-only on an error.
errors=remount-ro	Remount the filesystem read-only on an error.
errors=panic		Panic and halt the machine if an error occurs.
errors=panic		Panic and halt the machine if an error occurs.
@@ -71,6 +70,10 @@ order=strict Apply strict in-order semantics that preserves sequence
			blocks.  That means, it is guaranteed that no
			blocks.  That means, it is guaranteed that no
			overtaking of events occurs in the recovered file
			overtaking of events occurs in the recovered file
			system after a crash.
			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
NILFS2 usage
============
============
+85 −23
Original line number Original line Diff line number Diff line
@@ -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,
static int nilfs_palloc_get_desc_block(struct inode *inode,
				       unsigned long group,
				       unsigned long group,
				       int create, struct buffer_head **bhp)
				       int create, struct buffer_head **bhp)
{
{
	return nilfs_mdt_get_block(inode,
	struct nilfs_palloc_cache *cache = NILFS_MDT(inode)->mi_palloc_cache;

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


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

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


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

	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 *
static struct nilfs_palloc_group_desc *
@@ -176,13 +222,6 @@ nilfs_palloc_block_get_group_desc(const struct inode *inode,
		group % nilfs_palloc_groups_per_desc_block(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,
void *nilfs_palloc_block_get_entry(const struct inode *inode, __u64 nr,
				   const struct buffer_head *bh, void *kaddr)
				   const struct buffer_head *bh, void *kaddr)
{
{
@@ -289,8 +328,7 @@ int nilfs_palloc_prepare_alloc_entry(struct inode *inode,
				if (ret < 0)
				if (ret < 0)
					goto out_desc;
					goto out_desc;
				bitmap_kaddr = kmap(bitmap_bh->b_page);
				bitmap_kaddr = kmap(bitmap_bh->b_page);
				bitmap = nilfs_palloc_block_get_bitmap(
				bitmap = bitmap_kaddr + bh_offset(bitmap_bh);
					inode, bitmap_bh, bitmap_kaddr);
				pos = nilfs_palloc_find_available_slot(
				pos = nilfs_palloc_find_available_slot(
					inode, group, group_offset, bitmap,
					inode, group, group_offset, bitmap,
					entries_per_group);
					entries_per_group);
@@ -351,8 +389,7 @@ void nilfs_palloc_commit_free_entry(struct inode *inode,
	desc = nilfs_palloc_block_get_group_desc(inode, group,
	desc = nilfs_palloc_block_get_group_desc(inode, group,
						 req->pr_desc_bh, desc_kaddr);
						 req->pr_desc_bh, desc_kaddr);
	bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page);
	bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page);
	bitmap = nilfs_palloc_block_get_bitmap(inode, req->pr_bitmap_bh,
	bitmap = bitmap_kaddr + bh_offset(req->pr_bitmap_bh);
					       bitmap_kaddr);


	if (!nilfs_clear_bit_atomic(nilfs_mdt_bgl_lock(inode, group),
	if (!nilfs_clear_bit_atomic(nilfs_mdt_bgl_lock(inode, group),
				    group_offset, bitmap))
				    group_offset, bitmap))
@@ -385,8 +422,7 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode,
	desc = nilfs_palloc_block_get_group_desc(inode, group,
	desc = nilfs_palloc_block_get_group_desc(inode, group,
						 req->pr_desc_bh, desc_kaddr);
						 req->pr_desc_bh, desc_kaddr);
	bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page);
	bitmap_kaddr = kmap(req->pr_bitmap_bh->b_page);
	bitmap = nilfs_palloc_block_get_bitmap(inode, req->pr_bitmap_bh,
	bitmap = bitmap_kaddr + bh_offset(req->pr_bitmap_bh);
					       bitmap_kaddr);
	if (!nilfs_clear_bit_atomic(nilfs_mdt_bgl_lock(inode, group),
	if (!nilfs_clear_bit_atomic(nilfs_mdt_bgl_lock(inode, group),
				    group_offset, bitmap))
				    group_offset, bitmap))
		printk(KERN_WARNING "%s: entry numer %llu already freed\n",
		printk(KERN_WARNING "%s: entry numer %llu already freed\n",
@@ -472,8 +508,7 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
		desc = nilfs_palloc_block_get_group_desc(
		desc = nilfs_palloc_block_get_group_desc(
			inode, group, desc_bh, desc_kaddr);
			inode, group, desc_bh, desc_kaddr);
		bitmap_kaddr = kmap(bitmap_bh->b_page);
		bitmap_kaddr = kmap(bitmap_bh->b_page);
		bitmap = nilfs_palloc_block_get_bitmap(
		bitmap = bitmap_kaddr + bh_offset(bitmap_bh);
			inode, bitmap_bh, bitmap_kaddr);
		for (j = i, n = 0;
		for (j = i, n = 0;
		     (j < nitems) && nilfs_palloc_group_is_in(inode, group,
		     (j < nitems) && nilfs_palloc_group_is_in(inode, group,
							      entry_nrs[j]);
							      entry_nrs[j]);
@@ -502,3 +537,30 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
	}
	}
	return 0;
	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 −0
Original line number Original line Diff line number Diff line
@@ -69,4 +69,25 @@ int nilfs_palloc_freev(struct inode *, __u64 *, size_t);
#define nilfs_clear_bit_atomic		ext2_clear_bit_atomic
#define nilfs_clear_bit_atomic		ext2_clear_bit_atomic
#define nilfs_find_next_zero_bit	ext2_find_next_zero_bit
#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 */
#endif	/* _NILFS_ALLOC_H */
+0 −8
Original line number Original line Diff line number Diff line
@@ -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)
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);
	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)
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);
	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,
__u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap,
+34 −42
Original line number Original line Diff line number Diff line
@@ -68,20 +68,16 @@ void nilfs_btnode_cache_clear(struct address_space *btnc)
	truncate_inode_pages(btnc, 0);
	truncate_inode_pages(btnc, 0);
}
}


int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
struct buffer_head *
			      sector_t pblocknr, struct buffer_head **pbh,
nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr)
			      int newblk)
{
{
	struct buffer_head *bh;
	struct inode *inode = NILFS_BTNC_I(btnc);
	struct inode *inode = NILFS_BTNC_I(btnc);
	int err;
	struct buffer_head *bh;


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


	err = -EEXIST; /* internal code */
	if (newblk) {
	if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) ||
	if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) ||
		     buffer_dirty(bh))) {
		     buffer_dirty(bh))) {
		brelse(bh);
		brelse(bh);
@@ -92,9 +88,25 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
	bh->b_blocknr = blocknr;
	bh->b_blocknr = blocknr;
	set_buffer_mapped(bh);
	set_buffer_mapped(bh);
	set_buffer_uptodate(bh);
	set_buffer_uptodate(bh);
		goto found;

	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)
{
	struct buffer_head *bh;
	struct inode *inode = NILFS_BTNC_I(btnc);
	int err;

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

	err = -EEXIST; /* internal code */

	if (buffer_uptodate(bh) || buffer_dirty(bh))
	if (buffer_uptodate(bh) || buffer_dirty(bh))
		goto found;
		goto found;


@@ -135,27 +147,6 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
	return err;
	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
 * nilfs_btnode_delete - delete B-tree node buffer
 * @bh: buffer to be deleted
 * @bh: buffer to be deleted
@@ -244,12 +235,13 @@ int nilfs_btnode_prepare_change_key(struct address_space *btnc,
		unlock_page(obh->b_page);
		unlock_page(obh->b_page);
	}
	}


	err = nilfs_btnode_get(btnc, newkey, 0, &nbh, 1);
	nbh = nilfs_btnode_create_block(btnc, newkey);
	if (likely(!err)) {
	if (!nbh)
		return -ENOMEM;

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


 failed_unlock:
 failed_unlock:
	unlock_page(obh->b_page);
	unlock_page(obh->b_page);
Loading