aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>2013-01-15 01:43:51 +0900
committerDaniel Phillips <daniel@tux3.org>2013-01-15 01:43:51 +0900
commitd67d209e9e543a78e636fd2093179d41e48d679f (patch)
tree399bc674b923e2cb69bb59a24fffabbead9ca5ba
parente1294ea71fa3b9111eb884d23e96d9ef937b9f6c (diff)
downloadlinux-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.c5
-rw-r--r--fs/tux3/inode.c44
-rw-r--r--fs/tux3/super.c4
-rw-r--r--fs/tux3/tux3.h14
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 */