[PATCH 3/6] nilfs2: keep zero value in i_cno except for gc-inodes

2010-08-22 Thread Ryusuke Konishi
On-memory inode structures of nilfs have a member i_cno which stores
a checkpoint number related to the inode.  For gc-inodes, this field
indicates version of data each gc-inode caches for GC.  Log writer
temporarily uses i_cno to transfer the latest checkpoint number.

This stops the latter use and lets only gc-inodes use it.

The purpose of this patch is to allow the successive change use
i_cno for inode lookup.

Signed-off-by: Ryusuke Konishi konishi.ryus...@lab.ntt.co.jp
---
 fs/nilfs2/segment.c   |   29 ++---
 fs/nilfs2/segment.h   |3 ++-
 include/linux/nilfs2_fs.h |8 
 3 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 9fd051a..eee4b22 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -366,8 +366,7 @@ static int nilfs_segctor_reset_segment_buffer(struct 
nilfs_sc_info *sci)
 
if (nilfs_doing_gc())
flags = NILFS_SS_GC;
-   err = nilfs_segbuf_reset(segbuf, flags, sci-sc_seg_ctime,
-sci-sc_sbi-s_nilfs-ns_cno);
+   err = nilfs_segbuf_reset(segbuf, flags, sci-sc_seg_ctime, sci-sc_cno);
if (unlikely(err))
return err;
 
@@ -440,17 +439,26 @@ static void nilfs_segctor_end_finfo(struct nilfs_sc_info 
*sci,
struct nilfs_finfo *finfo;
struct nilfs_inode_info *ii;
struct nilfs_segment_buffer *segbuf;
+   __u64 cno;
 
if (sci-sc_blk_cnt == 0)
return;
 
ii = NILFS_I(inode);
+
+   if (test_bit(NILFS_I_GCINODE, ii-i_state))
+   cno = ii-i_cno;
+   else if (NILFS_ROOT_METADATA_FILE(inode-i_ino))
+   cno = 0;
+   else
+   cno = sci-sc_cno;
+
finfo = nilfs_segctor_map_segsum_entry(sci, sci-sc_finfo_ptr,
 sizeof(*finfo));
finfo-fi_ino = cpu_to_le64(inode-i_ino);
finfo-fi_nblocks = cpu_to_le32(sci-sc_blk_cnt);
finfo-fi_ndatablk = cpu_to_le32(sci-sc_datablk_cnt);
-   finfo-fi_cno = cpu_to_le64(ii-i_cno);
+   finfo-fi_cno = cpu_to_le64(cno);
 
segbuf = sci-sc_curseg;
segbuf-sb_sum.sumbytes = sci-sc_binfo_ptr.offset +
@@ -1976,7 +1984,6 @@ static int nilfs_segctor_check_in_files(struct 
nilfs_sc_info *sci,
struct nilfs_sb_info *sbi)
 {
struct nilfs_inode_info *ii, *n;
-   __u64 cno = sbi-s_nilfs-ns_cno;
 
spin_lock(sbi-s_inode_lock);
  retry:
@@ -2002,7 +2009,6 @@ static int nilfs_segctor_check_in_files(struct 
nilfs_sc_info *sci,
brelse(ibh);
goto retry;
}
-   ii-i_cno = cno;
 
clear_bit(NILFS_I_QUEUED, ii-i_state);
set_bit(NILFS_I_BUSY, ii-i_state);
@@ -2011,8 +2017,6 @@ static int nilfs_segctor_check_in_files(struct 
nilfs_sc_info *sci,
}
spin_unlock(sbi-s_inode_lock);
 
-   NILFS_I(sbi-s_ifile)-i_cno = cno;
-
return 0;
 }
 
@@ -2021,19 +2025,13 @@ static void nilfs_segctor_check_out_files(struct 
nilfs_sc_info *sci,
 {
struct nilfs_transaction_info *ti = current-journal_info;
struct nilfs_inode_info *ii, *n;
-   __u64 cno = sbi-s_nilfs-ns_cno;
 
spin_lock(sbi-s_inode_lock);
list_for_each_entry_safe(ii, n, sci-sc_dirty_files, i_dirty) {
if (!test_and_clear_bit(NILFS_I_UPDATED, ii-i_state) ||
-   test_bit(NILFS_I_DIRTY, ii-i_state)) {
-   /* The current checkpoint number (=nilfs-ns_cno) is
-  changed between check-in and check-out only if the
-  super root is written out.  So, we can update i_cno
-  for the inodes that remain in the dirty list. */
-   ii-i_cno = cno;
+   test_bit(NILFS_I_DIRTY, ii-i_state))
continue;
-   }
+
clear_bit(NILFS_I_BUSY, ii-i_state);
brelse(ii-i_bh);
ii-i_bh = NULL;
@@ -2054,6 +2052,7 @@ static int nilfs_segctor_do_construct(struct 
nilfs_sc_info *sci, int mode)
int err;
 
sci-sc_stage.scnt = NILFS_ST_INIT;
+   sci-sc_cno = nilfs-ns_cno;
 
err = nilfs_segctor_check_in_files(sci, sbi);
if (unlikely(err))
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h
index 17c487b..675d932 100644
--- a/fs/nilfs2/segment.h
+++ b/fs/nilfs2/segment.h
@@ -107,6 +107,7 @@ struct nilfs_segsum_pointer {
  * @sc_datablk_cnt: Data block count of a file
  * @sc_nblk_this_inc: Number of blocks included in the current logical segment
  * @sc_seg_ctime: Creation time
+ * @sc_cno: checkpoint number of current log
  * @sc_flags: Internal flags
  * @sc_state_lock: spinlock for sc_state and so on
  * @sc_state: Segctord state flags
@@ -156,7 +157,7 @@ struct nilfs_sc_info {
unsigned long  

[PATCH 0/6] nilfs2: remove own inode hash table

2010-08-22 Thread Ryusuke Konishi
This is a patchset to remove own inode hash table from nilfs.

The current version of nilfs uses inode not only to manage regular
files, directories, symlinks but also for some types of metadata and
for caching file blocks relocated by GC.

The last type of inodes is called gc-inodes, and nilfs keeps them with
an own hash table.

With this patchset, the gc-inodes will be stored in vfs inode cache
like regular inodes, and the own inode hash is deleted.

I hope this would be helpful for the vfs scalability work.

The patchset is also available from remove-own-inode-hash branch on:

 git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2.git


My next goal is to remove own inode allocator used to manage metadata
as files, but it still looks to need more effort.

I'd like to queue this for the next merge window if there are no
objections.

Thanks,
Ryusuke Konishi
--
Ryusuke Konishi (6):
  nilfs2: allow nilfs_destroy_inode to destroy metadata file inodes
  nilfs2: allow nilfs_dirty_inode to mark metadata file inodes dirty
  nilfs2: keep zero value in i_cno except for gc-inodes
  nilfs2: use iget5_locked to get inode
  nilfs2: separate initializer of metadata file inode
  nilfs2: remove own inode hash used for GC

 fs/nilfs2/gcinode.c   |  136 
 fs/nilfs2/inode.c |   64 -
 fs/nilfs2/ioctl.c |   17 +++--
 fs/nilfs2/mdt.c   |   46 +--
 fs/nilfs2/mdt.h   |4 +-
 fs/nilfs2/nilfs.h |9 +--
 fs/nilfs2/segment.c   |   32 +--
 fs/nilfs2/segment.h   |3 +-
 fs/nilfs2/super.c |7 ++
 fs/nilfs2/the_nilfs.c |8 +--
 fs/nilfs2/the_nilfs.h |7 +--
 include/linux/nilfs2_fs.h |8 +++
 12 files changed, 164 insertions(+), 177 deletions(-)


--
To unsubscribe from this list: send the line unsubscribe linux-nilfs in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/6] nilfs2: remove own inode hash used for GC

2010-08-22 Thread Ryusuke Konishi
This uses inode hash function that vfs provides instead of the own
hash table for caching gc inodes.  This finally removes the own inode
hash from nilfs.

Signed-off-by: Ryusuke Konishi konishi.ryus...@lab.ntt.co.jp
---
 fs/nilfs2/gcinode.c   |  140 +
 fs/nilfs2/inode.c |   22 
 fs/nilfs2/ioctl.c |   17 ---
 fs/nilfs2/nilfs.h |9 ++--
 fs/nilfs2/segment.c   |3 +-
 fs/nilfs2/the_nilfs.c |8 +---
 fs/nilfs2/the_nilfs.h |7 +--
 7 files changed, 64 insertions(+), 142 deletions(-)

diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c
index cd19a37..34f8f84 100644
--- a/fs/nilfs2/gcinode.c
+++ b/fs/nilfs2/gcinode.c
@@ -28,13 +28,6 @@
  * gcinodes), and this file provides lookup function of the dummy
  * inodes and their buffer read function.
  *
- * Since NILFS2 keeps up multiple checkpoints/snapshots across GC, it
- * has to treat blocks that belong to a same file but have different
- * checkpoint numbers.  To avoid interference among generations, dummy
- * inodes are managed separately from actual inodes, and their lookup
- * function (nilfs_gc_iget) is designed to be specified with a
- * checkpoint number argument as well as an inode number.
- *
  * Buffers and pages held by the dummy inodes will be released each
  * time after they are copied to a new log.  Dirty blocks made on the
  * current generation and the blocks to be moved by GC never overlap
@@ -180,124 +173,41 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head 
*bh)
return 0;
 }
 
-/*
- * nilfs_init_gccache() - allocate and initialize gc_inode hash table
- * @nilfs - the_nilfs
- *
- * Return Value: On success, 0.
- * On error, a negative error code is returned.
- */
-int nilfs_init_gccache(struct the_nilfs *nilfs)
-{
-   int loop;
-
-   BUG_ON(nilfs-ns_gc_inodes_h);
-
-   INIT_LIST_HEAD(nilfs-ns_gc_inodes);
-
-   nilfs-ns_gc_inodes_h =
-   kmalloc(sizeof(struct hlist_head) * NILFS_GCINODE_HASH_SIZE,
-   GFP_NOFS);
-   if (nilfs-ns_gc_inodes_h == NULL)
-   return -ENOMEM;
-
-   for (loop = 0; loop  NILFS_GCINODE_HASH_SIZE; loop++)
-   INIT_HLIST_HEAD(nilfs-ns_gc_inodes_h[loop]);
-   return 0;
-}
-
-/*
- * nilfs_destroy_gccache() - free gc_inode hash table
- * @nilfs - the nilfs
- */
-void nilfs_destroy_gccache(struct the_nilfs *nilfs)
+int nilfs_init_gcinode(struct inode *inode)
 {
-   if (nilfs-ns_gc_inodes_h) {
-   nilfs_remove_all_gcinode(nilfs);
-   kfree(nilfs-ns_gc_inodes_h);
-   nilfs-ns_gc_inodes_h = NULL;
-   }
-}
-
-static struct inode *alloc_gcinode(struct the_nilfs *nilfs, ino_t ino,
-  __u64 cno)
-{
-   struct inode *inode;
-   struct nilfs_inode_info *ii;
-
-   inode = nilfs_mdt_new_common(nilfs, NULL, ino);
-   if (!inode)
-   return NULL;
-
-   if (nilfs_mdt_init(inode, nilfs, GFP_NOFS, 0)  0) {
-   nilfs_destroy_inode(inode);
-   return NULL;
-   }
-   inode-i_op = NULL;
-   inode-i_fop = NULL;
-   inode-i_mapping-a_ops = def_gcinode_aops;
-
-   ii = NILFS_I(inode);
-   ii-i_cno = cno;
-   ii-i_flags = 0;
-   ii-i_state = 1  NILFS_I_GCINODE;
-   ii-i_bh = NULL;
-   nilfs_bmap_init_gc(ii-i_bmap);
+   struct nilfs_inode_info *ii = NILFS_I(inode);
+   struct the_nilfs *nilfs = NILFS_SB(inode-i_sb)-s_nilfs;
+   int ret;
 
-   return inode;
-}
+   ret = nilfs_mdt_init(inode, nilfs, GFP_NOFS, 0);
+   if (!ret) {
+   inode-i_mapping-a_ops = def_gcinode_aops;
 
-static unsigned long ihash(ino_t ino, __u64 cno)
-{
-   return hash_long((unsigned long)((ino  2) + cno),
-NILFS_GCINODE_HASH_BITS);
-}
+   ii-i_flags = 0;
+   nilfs_bmap_init_gc(ii-i_bmap);
 
-/*
- * nilfs_gc_iget() - find or create gc inode with specified (ino,cno)
- */
-struct inode *nilfs_gc_iget(struct the_nilfs *nilfs, ino_t ino, __u64 cno)
-{
-   struct hlist_head *head = nilfs-ns_gc_inodes_h + ihash(ino, cno);
-   struct hlist_node *node;
-   struct inode *inode;
-
-   hlist_for_each_entry(inode, node, head, i_hash) {
-   if (inode-i_ino == ino  NILFS_I(inode)-i_cno == cno)
-   return inode;
-   }
-
-   inode = alloc_gcinode(nilfs, ino, cno);
-   if (likely(inode)) {
-   hlist_add_head(inode-i_hash, head);
+   /*
+* Add the inode to GC inode list. Garbage Collection
+* is serialized and no two processes manipulate the
+* list simultaneously.
+*/
+   igrab(inode);
list_add(NILFS_I(inode)-i_dirty, nilfs-ns_gc_inodes);
}
-   return inode;
-}
-
-/*
- * nilfs_clear_gcinode() - clear and free a gc inode
- */
-void nilfs_clear_gcinode(struct inode *inode)

[GIT PULL] nilfs2 additional fix

2010-08-22 Thread Ryusuke Konishi
Hi Linus,

please pull:

  git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2.git for-linus

to grab the following fix, which corrects sync failure of discard in
nilfs that Christoph noticed me recently.

Thanks!

Ryusuke Konishi
--
The following changes since commit 3b89f56783a4ef796190ef1192c25e72e0b986b6:
  Linus Torvalds (1):
Merge branch 'for-linus' of 
git://git.kernel.org/.../jmorris/security-testing-2.6

Ryusuke Konishi (1):
  nilfs2: wait for discard to finish

 fs/nilfs2/the_nilfs.c |4 +++-

diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 6af1c00..4317f17 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -775,6 +775,7 @@ int nilfs_discard_segments(struct the_nilfs *nilfs, __u64 
*segnump,
   start * sects_per_block,
   nblocks * sects_per_block,
   GFP_NOFS,
+  BLKDEV_IFL_WAIT |
   BLKDEV_IFL_BARRIER);
if (ret  0)
return ret;
@@ -785,7 +786,8 @@ int nilfs_discard_segments(struct the_nilfs *nilfs, __u64 
*segnump,
ret = blkdev_issue_discard(nilfs-ns_bdev,
   start * sects_per_block,
   nblocks * sects_per_block,
-  GFP_NOFS, BLKDEV_IFL_BARRIER);
+  GFP_NOFS,
+ BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER);
return ret;
 }
 
--
To unsubscribe from this list: send the line unsubscribe linux-nilfs in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html