diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2013-01-15 01:43:51 +0900 |
---|---|---|
committer | Daniel Phillips <daniel@tux3.org> | 2013-01-15 01:43:51 +0900 |
commit | d67d209e9e543a78e636fd2093179d41e48d679f (patch) | |
tree | 399bc674b923e2cb69bb59a24fffabbead9ca5ba | |
parent | e1294ea71fa3b9111eb884d23e96d9ef937b9f6c (diff) | |
download | linux-tux3-d67d209e9e543a78e636fd2093179d41e48d679f.tar.gz |
tux3: Implement statfs->f_{files,ffree}
To keep track the free inodes, this adds sb->freeinodes.
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
-rw-r--r-- | fs/tux3/commit.c | 5 | ||||
-rw-r--r-- | fs/tux3/inode.c | 44 | ||||
-rw-r--r-- | fs/tux3/super.c | 4 | ||||
-rw-r--r-- | fs/tux3/tux3.h | 14 |
4 files changed, 60 insertions, 7 deletions
diff --git a/fs/tux3/commit.c b/fs/tux3/commit.c index 6160994a062d6b..3f3846bafc3be4 100644 --- a/fs/tux3/commit.c +++ b/fs/tux3/commit.c @@ -92,6 +92,7 @@ static void __setup_sb(struct sb *sb, struct disksuper *super) vfs_sb(sb)->s_maxbytes = calc_maxbytes(sb->blocksize); /* Probably does not belong here (maybe metablock) */ + sb->freeinodes = MAX_INODES - be64_to_cpu(super->usedinodes); sb->freeblocks = sb->volblocks; sb->nextalloc = be64_to_cpu(super->nextalloc); sb->atomdictsize = be64_to_cpu(super->atomdictsize); @@ -100,8 +101,8 @@ static void __setup_sb(struct sb *sb, struct disksuper *super) /* logchain and logcount are read from super directly */ trace("blocksize %u, blockbits %u, blockmask %08x", sb->blocksize, sb->blockbits, sb->blockmask); - trace("volblocks %Lu, freeblocks %Lu, nextalloc %Lu", - sb->volblocks, sb->freeblocks, sb->nextalloc); + trace("volblocks %Lu, freeblocks %Lu, freeinodes %Lu, nextalloc %Lu", + sb->volblocks, sb->freeblocks, sb->freeinodes, sb->nextalloc); trace("atom_dictsize %Lu, freeatom %u, atomgen %u", (s64)sb->atomdictsize, sb->freeatom, sb->atomgen); trace("logchain %Lu, logcount %u", diff --git a/fs/tux3/inode.c b/fs/tux3/inode.c index 31ce97bfbed030..d99807ad936948 100644 --- a/fs/tux3/inode.c +++ b/fs/tux3/inode.c @@ -257,6 +257,17 @@ static int alloc_inum(struct inode *inode, inum_t goal) add_defer_alloc_inum(inode); + /* + * If inum is not reserved area, account it. If inum is + * reserved area, inode might not be written into itable. So, + * we don't include the reserved area into dynamic accounting. + * FIXME: what happen if snapshot was introduced? + */ + if (goal >= TUX_NORMAL_INO) { + assert(sb->freeinodes > TUX_NORMAL_INO); + sb->freeinodes--; + } + error: up_write(&cursor->btree->lock); free_cursor(cursor); @@ -458,6 +469,15 @@ static int save_inode(struct inode *inode, struct tux3_iattr_data *idata, if (err) goto error_release; + /* + * If inode is newly added into itable, account to on-disk usedinodes. + * ->usedinodes is used only by backend, no need lock. + * FIXME: what happen if snapshot was introduced? + */ + if (is_defer_alloc_inum(inode) && inum >= TUX_NORMAL_INO) { + assert(be64_to_cpu(sb->super.usedinodes) < MAX_INODES); + be64_add_cpu(&sb->super.usedinodes, 1); + } del_defer_alloc_inum(inode); error_release: @@ -539,9 +559,21 @@ error: /* Remove inode from itable */ static int purge_inode(struct inode *inode) { - struct btree *itable = itable_btree(tux_sb(inode->i_sb)); + struct sb *sb = tux_sb(inode->i_sb); + struct btree *itable = itable_btree(sb); + int reserved_inum = tux_inode(inode)->inum < TUX_NORMAL_INO; down_write(&itable->lock); /* FIXME: spinlock is enough? */ + + /* + * If inum is not reserved area, account it. + * FIXME: what happen if snapshot was introduced? + */ + if (!reserved_inum) { + assert(sb->freeinodes < MAX_INODES); + sb->freeinodes++; + } + if (is_defer_alloc_inum(inode)) { del_defer_alloc_inum(inode); up_write(&itable->lock); @@ -549,6 +581,16 @@ static int purge_inode(struct inode *inode) } up_write(&itable->lock); + /* + * If inode is deleted from itable, account to on-disk usedinodes. + * ->usedinodes is used only by backend, no need lock. + * FIXME: what happen if snapshot was introduced? + */ + if (!reserved_inum) { + assert(be64_to_cpu(sb->super.usedinodes) > TUX_NORMAL_INO); + be64_add_cpu(&sb->super.usedinodes, -1); + } + /* Remove inum from inode btree */ return btree_chop(itable, tux_inode(inode)->inum, 1); } diff --git a/fs/tux3/super.c b/fs/tux3/super.c index 6a1614eccc0bde..428b19742226a4 100644 --- a/fs/tux3/super.c +++ b/fs/tux3/super.c @@ -357,9 +357,9 @@ static int tux3_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_blocks = sbi->volblocks; buf->f_bfree = sbi->freeblocks; buf->f_bavail = sbi->freeblocks; + buf->f_files = MAX_INODES; + buf->f_ffree = sbi->freeinodes; #if 0 - buf->f_files = buf->f_blocks << (sbi->clus_bits - EXFAT_CHUNK_BITS) / 3; - buf->f_ffree = buf->f_blocks << (sbi->clus_bits - EXFAT_CHUNK_BITS) / 3; buf->f_fsid.val[0] = sbi->serial_number; /*buf->f_fsid.val[1];*/ #endif diff --git a/fs/tux3/tux3.h b/fs/tux3/tux3.h index 1ffee11312c040..c15b01fab76dec 100644 --- a/fs/tux3/tux3.h +++ b/fs/tux3/tux3.h @@ -85,7 +85,7 @@ static inline void *decode48(void *at, u64 *val) /* Tux3 disk format */ -#define TUX3_MAGIC "tux3" "\x20\x12\x07\x02" +#define TUX3_MAGIC "tux3" "\x20\x12\x12\x20" /* * TUX3_LABEL includes the date of the last incompatible disk format change * NOTE: Always update this history for each incompatible change! @@ -108,9 +108,12 @@ static inline void *decode48(void *at, u64 *val) #define TUX3_MAGIC_ILEAF 0x90de #define TUX3_MAGIC_OLEAF 0x6eaf +/* Number of available inum ("0" - "((1 << 48) - 1)") */ #define MAX_INODES_BITS 48 +#define MAX_INODES ((u64)1 << MAX_INODES_BITS) +/* Maximum number of block address ("0" - "((1 << 48) - 1)") */ #define MAX_BLOCKS_BITS 48 -#define MAX_BLOCKS ((block_t)1 << 48) +#define MAX_BLOCKS ((block_t)1 << MAX_BLOCKS_BITS) #define MAX_EXTENT (1 << 6) #define SB_LOC (1 << 12) @@ -141,6 +144,11 @@ struct disksuper { /* The rest should be moved to a "metablock" that is updated frequently */ __be64 iroot; /* Root of the inode table btree */ __be64 oroot; /* Root of the orphan table btree */ + __be64 usedinodes; /* Number of using inode numbers. (Instead of + * free inode numbers). With this, we can + * change the maximum inodes without changing + * usedinodes on disk. + */ __be64 nextalloc; /* Get rid of this when we have a real allocation policy */ __be64 atomdictsize; /* * Size of the atom dictionary instead of i_size @@ -248,6 +256,8 @@ struct sb { struct inode *atable; /* xattr atom special file */ unsigned blocksize, blockbits, blockmask; + u64 freeinodes; /* Number of free inode numbers. This is + * including the deferred allocated inodes */ block_t volblocks, freeblocks, nextalloc; unsigned entries_per_node; /* must be per-btree type, get rid of this */ unsigned version; /* Currently mounted volume version view */ |