On Wed, 29 May 2013 13:26:16 +0400, Vyacheslav Dubeyko wrote:
> From: Vyacheslav Dubeyko <[email protected]>
> Subject: [PATCH v6 1/2] 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 <[email protected]>
> Signed-off-by: Vyacheslav Dubeyko <[email protected]>
> Signed-off-by: Ryusuke Konishi <[email protected]>
> Tested-by: Vyacheslav Dubeyko <[email protected]>
This patch looks ok, too.
Thanks,
Ryusuke Konishi
> ---
> fs/nilfs2/alloc.c | 63
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
> fs/nilfs2/alloc.h | 2 ++
> fs/nilfs2/ifile.c | 22 +++++++++++++++++++
> fs/nilfs2/ifile.h | 2 ++
> fs/nilfs2/super.c | 25 +++++++++++++++++++--
> 5 files changed, 112 insertions(+), 2 deletions(-)
>
> diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c
> index eed4d7b..741fd02 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,
> }
>
> /**
> + * nilfs_palloc_count_desc_blocks - count descriptor blocks number
> + * @inode: inode of metadata file using this allocator
> + * @desc_blocks: descriptor blocks number [out]
> + */
> +static int nilfs_palloc_count_desc_blocks(struct inode *inode,
> + unsigned long *desc_blocks)
> +{
> + unsigned long blknum;
> + int ret;
> +
> + ret = nilfs_bmap_last_key(NILFS_I(inode)->i_bmap, &blknum);
> + if (likely(!ret))
> + *desc_blocks = DIV_ROUND_UP(
> + blknum, NILFS_MDT(inode)->mi_blocks_per_desc_block);
> + return ret;
> +}
> +
> +/**
> + * nilfs_palloc_mdt_file_can_grow - check potential opportunity for
> + * MDT file growing
> + * @inode: inode of metadata file using this allocator
> + * @desc_blocks: known current descriptor blocks count
> + */
> +static inline bool nilfs_palloc_mdt_file_can_grow(struct inode *inode,
> + unsigned long desc_blocks)
> +{
> + return (nilfs_palloc_groups_per_desc_block(inode) * desc_blocks) <
> + nilfs_palloc_groups_count(inode);
> +}
> +
> +/**
> + * nilfs_palloc_count_max_entries - count max number of entries that can be
> + * described by descriptor blocks count
> + * @inode: inode of metadata file using this allocator
> + * @nused: current number of used entries
> + * @nmaxp: max number of entries [out]
> + */
> +int nilfs_palloc_count_max_entries(struct inode *inode, u64 nused, u64
> *nmaxp)
> +{
> + unsigned long desc_blocks = 0;
> + u64 entries_per_desc_block, nmax;
> + int err;
> +
> + err = nilfs_palloc_count_desc_blocks(inode, &desc_blocks);
> + if (unlikely(err))
> + return err;
> +
> + entries_per_desc_block = (u64)nilfs_palloc_entries_per_group(inode) *
> + nilfs_palloc_groups_per_desc_block(inode);
> + nmax = entries_per_desc_block * desc_blocks;
> +
> + if (nused == nmax &&
> + nilfs_palloc_mdt_file_can_grow(inode, desc_blocks))
> + nmax += entries_per_desc_block;
> +
> + if (nused > nmax)
> + return -ERANGE;
> +
> + *nmaxp = nmax;
> + return 0;
> +}
> +
> +/**
> * nilfs_palloc_prepare_alloc_entry - prepare to allocate a persistent object
> * @inode: inode of metadata file using this allocator
> * @req: nilfs_palloc_req structure exchanged for the allocation
> diff --git a/fs/nilfs2/alloc.h b/fs/nilfs2/alloc.h
> index fb72381..4bd6451 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,
> void *nilfs_palloc_block_get_entry(const struct inode *, __u64,
> const struct buffer_head *, void *);
>
> +int nilfs_palloc_count_max_entries(struct inode *, u64, u64 *);
> +
> /**
> * nilfs_palloc_req - persistent allocator request and reply
> * @pr_entry_nr: entry number (vblocknr or inode number)
> diff --git a/fs/nilfs2/ifile.c b/fs/nilfs2/ifile.c
> index d8e65bd..d788a59 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,
> }
>
> /**
> + * nilfs_ifile_count_free_inodes - calculate free inodes count
> + * @ifile: ifile inode
> + * @nmaxinodes: current maximum of available inodes count [out]
> + * @nfreeinodes: free inodes count [out]
> + */
> +int nilfs_ifile_count_free_inodes(struct inode *ifile,
> + u64 *nmaxinodes, u64 *nfreeinodes)
> +{
> + u64 nused;
> + int err;
> +
> + *nmaxinodes = 0;
> + *nfreeinodes = 0;
> +
> + nused = atomic_read(&NILFS_I(ifile)->i_root->inodes_count);
> + err = nilfs_palloc_count_max_entries(ifile, nused, nmaxinodes);
> + if (likely(!err))
> + *nfreeinodes = *nmaxinodes - nused;
> + return err;
> +}
> +
> +/**
> * nilfs_ifile_read - read or get ifile inode
> * @sb: super block instance
> * @root: root object
> diff --git a/fs/nilfs2/ifile.h b/fs/nilfs2/ifile.h
> index 59b6f2b..679674d 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 **);
> int nilfs_ifile_delete_inode(struct inode *, ino_t);
> int nilfs_ifile_get_inode_block(struct inode *, ino_t, struct buffer_head
> **);
>
> +int nilfs_ifile_count_free_inodes(struct inode *, u64 *, u64 *);
> +
> int nilfs_ifile_read(struct super_block *sb, struct nilfs_root *root,
> size_t inode_size, struct nilfs_inode *raw_inode,
> struct inode **inodep);
> diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
> index c7d1f9f..7d257e7 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)
> unsigned long overhead;
> unsigned long nrsvblocks;
> sector_t nfreeblocks;
> + u64 nmaxinodes, nfreeinodes;
> int err;
>
> /*
> @@ -633,14 +634,34 @@ static int nilfs_statfs(struct dentry *dentry, struct
> kstatfs *buf)
> if (unlikely(err))
> return err;
>
> + err = nilfs_ifile_count_free_inodes(root->ifile,
> + &nmaxinodes, &nfreeinodes);
> + if (unlikely(err)) {
> + printk(KERN_WARNING
> + "NILFS warning: fail to count free inodes: err %d.\n",
> + err);
> + if (err == -ERANGE) {
> + /*
> + * If nilfs_palloc_count_max_entries() returns
> + * -ERANGE error code then we simply treat
> + * curent inodes count as maximum possible and
> + * zero as free inodes value.
> + */
> + nmaxinodes = atomic_read(&root->inodes_count);
> + nfreeinodes = 0;
> + err = 0;
> + } else
> + return err;
> + }
> +
> buf->f_type = NILFS_SUPER_MAGIC;
> buf->f_bsize = sb->s_blocksize;
> buf->f_blocks = blocks - overhead;
> buf->f_bfree = nfreeblocks;
> buf->f_bavail = (buf->f_bfree >= nrsvblocks) ?
> (buf->f_bfree - nrsvblocks) : 0;
> - buf->f_files = atomic_read(&root->inodes_count);
> - buf->f_ffree = 0; /* nilfs_count_free_inodes(sb); */
> + buf->f_files = nmaxinodes;
> + buf->f_ffree = nfreeinodes;
> buf->f_namelen = NILFS_NAME_LEN;
> buf->f_fsid.val[0] = (u32)id;
> buf->f_fsid.val[1] = (u32)(id >> 32);
> --
> 1.7.9.5
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html