aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVyacheslav Dubeyko <slava@dubeyko.com>2013-07-03 18:08:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 19:08:01 -0400
commitc7ef972c440fc9f1eda28b450cd30ad15c4d60cf (patch)
tree5f415ed5b082632848cae6e5798a8ac986e0ed38
parente88b815e011bcacb7066f1156ce390f6b0adc9df (diff)
nilfs2: implement calculation of free inodes count
Currently, NILFS2 returns 0 as free inodes count (f_ffree) and current used inodes count as total file nodes in file system (f_files): df -i Filesystem Inodes IUsed IFree IUse% Mounted on /dev/loop0 2 2 0 100% /mnt/nilfs2 This patch implements real calculation of free inodes count. First of all, it is calculated total file nodes in file system as (desc_blocks_count * groups_per_desc_block * entries_per_group). Then, it is calculated free inodes count as difference the total file nodes and used inodes count. As a result, we have such output for NILFS2: df -i Filesystem Inodes IUsed IFree IUse% Mounted on /dev/loop0 4194304 2114701 2079603 51% /mnt/nilfs2 Reported-by: Clemens Eisserer <linuxhippy@gmail.com> Signed-off-by: Vyacheslav Dubeyko <slava@dubeyko.com> Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Tested-by: Vyacheslav Dubeyko <slava@dubeyko.com> Cc: Joern Engel <joern@logfs.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/nilfs2/alloc.c63
-rw-r--r--fs/nilfs2/alloc.h2
-rw-r--r--fs/nilfs2/ifile.c22
-rw-r--r--fs/nilfs2/ifile.h2
-rw-r--r--fs/nilfs2/super.c25
5 files changed, 112 insertions, 2 deletions
diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c
index eed4d7b26249..741fd02e0444 100644
--- a/fs/nilfs2/alloc.c
+++ b/fs/nilfs2/alloc.c
@@ -398,6 +398,69 @@ nilfs_palloc_rest_groups_in_desc_block(const struct inode *inode,
398} 398}
399 399
400/** 400/**
401 * nilfs_palloc_count_desc_blocks - count descriptor blocks number
402 * @inode: inode of metadata file using this allocator
403 * @desc_blocks: descriptor blocks number [out]
404 */
405static int nilfs_palloc_count_desc_blocks(struct inode *inode,
406 unsigned long *desc_blocks)
407{
408 unsigned long blknum;
409 int ret;
410
411 ret = nilfs_bmap_last_key(NILFS_I(inode)->i_bmap, &blknum);
412 if (likely(!ret))
413 *desc_blocks = DIV_ROUND_UP(
414 blknum, NILFS_MDT(inode)->mi_blocks_per_desc_block);
415 return ret;
416}
417
418/**
419 * nilfs_palloc_mdt_file_can_grow - check potential opportunity for
420 * MDT file growing
421 * @inode: inode of metadata file using this allocator
422 * @desc_blocks: known current descriptor blocks count
423 */
424static inline bool nilfs_palloc_mdt_file_can_grow(struct inode *inode,
425 unsigned long desc_blocks)
426{
427 return (nilfs_palloc_groups_per_desc_block(inode) * desc_blocks) <
428 nilfs_palloc_groups_count(inode);
429}
430
431/**
432 * nilfs_palloc_count_max_entries - count max number of entries that can be
433 * described by descriptor blocks count
434 * @inode: inode of metadata file using this allocator
435 * @nused: current number of used entries
436 * @nmaxp: max number of entries [out]
437 */
438int nilfs_palloc_count_max_entries(struct inode *inode, u64 nused, u64 *nmaxp)
439{
440 unsigned long desc_blocks = 0;
441 u64 entries_per_desc_block, nmax;
442 int err;
443
444 err = nilfs_palloc_count_desc_blocks(inode, &desc_blocks);
445 if (unlikely(err))
446 return err;
447
448 entries_per_desc_block = (u64)nilfs_palloc_entries_per_group(inode) *
449 nilfs_palloc_groups_per_desc_block(inode);
450 nmax = entries_per_desc_block * desc_blocks;
451
452 if (nused == nmax &&
453 nilfs_palloc_mdt_file_can_grow(inode, desc_blocks))
454 nmax += entries_per_desc_block;
455
456 if (nused > nmax)
457 return -ERANGE;
458
459 *nmaxp = nmax;
460 return 0;
461}
462
463/**
401 * nilfs_palloc_prepare_alloc_entry - prepare to allocate a persistent object 464 * nilfs_palloc_prepare_alloc_entry - prepare to allocate a persistent object
402 * @inode: inode of metadata file using this allocator 465 * @inode: inode of metadata file using this allocator
403 * @req: nilfs_palloc_req structure exchanged for the allocation 466 * @req: nilfs_palloc_req structure exchanged for the allocation
diff --git a/fs/nilfs2/alloc.h b/fs/nilfs2/alloc.h
index fb7238100548..4bd6451b5703 100644
--- a/fs/nilfs2/alloc.h
+++ b/fs/nilfs2/alloc.h
@@ -48,6 +48,8 @@ int nilfs_palloc_get_entry_block(struct inode *, __u64, int,
48void *nilfs_palloc_block_get_entry(const struct inode *, __u64, 48void *nilfs_palloc_block_get_entry(const struct inode *, __u64,
49 const struct buffer_head *, void *); 49 const struct buffer_head *, void *);
50 50
51int nilfs_palloc_count_max_entries(struct inode *, u64, u64 *);
52
51/** 53/**
52 * nilfs_palloc_req - persistent allocator request and reply 54 * nilfs_palloc_req - persistent allocator request and reply
53 * @pr_entry_nr: entry number (vblocknr or inode number) 55 * @pr_entry_nr: entry number (vblocknr or inode number)
diff --git a/fs/nilfs2/ifile.c b/fs/nilfs2/ifile.c
index d8e65bde083c..d788a5928351 100644
--- a/fs/nilfs2/ifile.c
+++ b/fs/nilfs2/ifile.c
@@ -160,6 +160,28 @@ int nilfs_ifile_get_inode_block(struct inode *ifile, ino_t ino,
160} 160}
161 161
162/** 162/**
163 * nilfs_ifile_count_free_inodes - calculate free inodes count
164 * @ifile: ifile inode
165 * @nmaxinodes: current maximum of available inodes count [out]
166 * @nfreeinodes: free inodes count [out]
167 */
168int nilfs_ifile_count_free_inodes(struct inode *ifile,
169 u64 *nmaxinodes, u64 *nfreeinodes)
170{
171 u64 nused;
172 int err;
173
174 *nmaxinodes = 0;
175 *nfreeinodes = 0;
176
177 nused = atomic_read(&NILFS_I(ifile)->i_root->inodes_count);
178 err = nilfs_palloc_count_max_entries(ifile, nused, nmaxinodes);
179 if (likely(!err))
180 *nfreeinodes = *nmaxinodes - nused;
181 return err;
182}
183
184/**
163 * nilfs_ifile_read - read or get ifile inode 185 * nilfs_ifile_read - read or get ifile inode
164 * @sb: super block instance 186 * @sb: super block instance
165 * @root: root object 187 * @root: root object
diff --git a/fs/nilfs2/ifile.h b/fs/nilfs2/ifile.h
index 59b6f2b51df6..679674d13372 100644
--- a/fs/nilfs2/ifile.h
+++ b/fs/nilfs2/ifile.h
@@ -49,6 +49,8 @@ int nilfs_ifile_create_inode(struct inode *, ino_t *, struct buffer_head **);
49int nilfs_ifile_delete_inode(struct inode *, ino_t); 49int nilfs_ifile_delete_inode(struct inode *, ino_t);
50int nilfs_ifile_get_inode_block(struct inode *, ino_t, struct buffer_head **); 50int nilfs_ifile_get_inode_block(struct inode *, ino_t, struct buffer_head **);
51 51
52int nilfs_ifile_count_free_inodes(struct inode *, u64 *, u64 *);
53
52int nilfs_ifile_read(struct super_block *sb, struct nilfs_root *root, 54int nilfs_ifile_read(struct super_block *sb, struct nilfs_root *root,
53 size_t inode_size, struct nilfs_inode *raw_inode, 55 size_t inode_size, struct nilfs_inode *raw_inode,
54 struct inode **inodep); 56 struct inode **inodep);
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index c7d1f9f18b09..7d257e78fbad 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -609,6 +609,7 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf)
609 unsigned long overhead; 609 unsigned long overhead;
610 unsigned long nrsvblocks; 610 unsigned long nrsvblocks;
611 sector_t nfreeblocks; 611 sector_t nfreeblocks;
612 u64 nmaxinodes, nfreeinodes;
612 int err; 613 int err;
613 614
614 /* 615 /*
@@ -633,14 +634,34 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf)
633 if (unlikely(err)) 634 if (unlikely(err))
634 return err; 635 return err;
635 636
637 err = nilfs_ifile_count_free_inodes(root->ifile,
638 &nmaxinodes, &nfreeinodes);
639 if (unlikely(err)) {
640 printk(KERN_WARNING
641 "NILFS warning: fail to count free inodes: err %d.\n",
642 err);
643 if (err == -ERANGE) {
644 /*
645 * If nilfs_palloc_count_max_entries() returns
646 * -ERANGE error code then we simply treat
647 * curent inodes count as maximum possible and
648 * zero as free inodes value.
649 */
650 nmaxinodes = atomic_read(&root->inodes_count);
651 nfreeinodes = 0;
652 err = 0;
653 } else
654 return err;
655 }
656
636 buf->f_type = NILFS_SUPER_MAGIC; 657 buf->f_type = NILFS_SUPER_MAGIC;
637 buf->f_bsize = sb->s_blocksize; 658 buf->f_bsize = sb->s_blocksize;
638 buf->f_blocks = blocks - overhead; 659 buf->f_blocks = blocks - overhead;
639 buf->f_bfree = nfreeblocks; 660 buf->f_bfree = nfreeblocks;
640 buf->f_bavail = (buf->f_bfree >= nrsvblocks) ? 661 buf->f_bavail = (buf->f_bfree >= nrsvblocks) ?
641 (buf->f_bfree - nrsvblocks) : 0; 662 (buf->f_bfree - nrsvblocks) : 0;
642 buf->f_files = atomic_read(&root->inodes_count); 663 buf->f_files = nmaxinodes;
643 buf->f_ffree = 0; /* nilfs_count_free_inodes(sb); */ 664 buf->f_ffree = nfreeinodes;
644 buf->f_namelen = NILFS_NAME_LEN; 665 buf->f_namelen = NILFS_NAME_LEN;
645 buf->f_fsid.val[0] = (u32)id; 666 buf->f_fsid.val[0] = (u32)id;
646 buf->f_fsid.val[1] = (u32)(id >> 32); 667 buf->f_fsid.val[1] = (u32)(id >> 32);