]> git.neil.brown.name Git - LaFS.git/commitdiff
Improve handling of snapshot name.
authorNeilBrown <neilb@suse.de>
Sat, 2 Oct 2010 00:42:34 +0000 (10:42 +1000)
committerNeilBrown <neilb@suse.de>
Sat, 2 Oct 2010 00:42:34 +0000 (10:42 +1000)
Name stored in fileset inode is now variable length and empty
on subordinate filesets.  Snapshots have space for a name depending
on how much space was allocated when fs was created.

Name is only used for snapshots.

Signed-off-by: NeilBrown <neilb@suse.de>
inode.c
layout.h
roll.c
snapshot.c
state.h
super.c

diff --git a/inode.c b/inode.c
index 88312c3620e579c06cc02fc923212ecd0714ab8b..88c76d1d221c628c031d5fba5ab4d49c2bbbf0a5 100644 (file)
--- a/inode.c
+++ b/inode.c
@@ -12,6 +12,7 @@
 #include       "lafs.h"
 #include <linux/random.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
 
 /* Supporting an async 'iget' - as required by the cleaner -
  * is slightly non-trivial.
@@ -281,6 +282,8 @@ lafs_import_inode(struct inode *ino, struct datablock *b)
        {
                struct fs_md *i = &li->md.fs;
                struct fs_metadata *l = &lai->metadata[0].fs;
+               int nlen;
+
                i->usagetable = le16_to_cpu(l->snapshot_usage_table);
                decode_time(&ino->i_mtime, le64_to_cpu(l->update_time));
                i->cblocks_used = le64_to_cpu(l->blocks_used);
@@ -294,9 +297,25 @@ lafs_import_inode(struct inode *ino, struct datablock *b)
                i->quota_inums[2] = le32_to_cpu(l->quota_inodes[2]);
                i->quota_inodes[0] = i->quota_inodes[1]
                        = i->quota_inodes[2] = NULL;
-               memcpy(i->name, l->name, 64);
-               i->name[64] = 0;
+               nlen = li->metadata_size - offsetof(struct la_inode,
+                                                   metadata[0].fs.name);
+               if (nlen == 0)
+                       i->name = NULL;
+               else {
+                       /* Need to unmap the dblock to kmalloc because
+                        * the mapping makes us 'atomic'
+                        */
+                       unmap_dblock(b, lai);
+                       i->name = kmalloc(nlen+1, GFP_KERNEL);
+                       lai = map_dblock(b);
+                       l = &lai->metadata[0].fs;
 
+                       err = -ENOMEM;
+                       if (!i->name)
+                               goto out;
+                       memcpy(i->name, l->name, nlen);
+                       i->name[nlen] = 0;
+               }
                /* Make this look like a directory */
                ino->i_mode = S_IFDIR;
                ino->i_uid = 0;
@@ -551,9 +570,7 @@ void lafs_inode_init(struct datablock *b, int type, int mode, struct inode *dir)
                l->quota_inodes[2] = 0;
                l->snapshot_usage_table = 0;
                l->pad = 0;
-               memset(l->name, 0, sizeof(l->name));
-               /* FIXME real name?? */
-               strlcpy(l->name, "Secondary", sizeof(l->name));
+               /* name will be zero length and not used */
                break;
        }
        case TypeInodeMap:
@@ -1181,6 +1198,8 @@ void lafs_inode_fillblock(struct inode *ino)
        {
                struct fs_md *i = &li->md.fs;
                struct fs_metadata *l = &lai->metadata[0].fs;
+               int nlen;
+
                l->snapshot_usage_table = cpu_to_le16(i->usagetable);
                l->update_time = cpu_to_le64(encode_time(&ino->i_mtime));
                l->blocks_used = cpu_to_le64(i->cblocks_used);
@@ -1190,7 +1209,14 @@ void lafs_inode_fillblock(struct inode *ino)
                l->quota_inodes[0] = cpu_to_le32(i->quota_inums[0]);
                l->quota_inodes[1] = cpu_to_le32(i->quota_inums[1]);
                l->quota_inodes[2] = cpu_to_le32(i->quota_inums[2]);
-               memcpy(l->name, i->name, 64);
+               nlen = lai->metadata_size - offsetof(struct la_inode,
+                                                    metadata[0].fs.name);
+               memset(l->name, 0, nlen);
+               if (i->name == NULL)
+                       nlen = 0;
+               else if (strlen(i->name) < nlen)
+                       nlen = strlen(i->name);
+               memcpy(l->name, i->name, nlen);
                break;
        }
 
index c1e5ea22caccdc8c716cffa9d00b15053e13bde2..5c6ba0eb7e8d94a465cb6981e67f067d685005d8 100644 (file)
--- a/layout.h
+++ b/layout.h
@@ -130,7 +130,7 @@ struct la_inode {
 #define        File_nonlogged  1
        union {
                struct fs_metadata {
-                       /* 116 bytes */
+                       /* 52 bytes plus name. */
                        u64     update_time;
                        u64     blocks_used; /* data+index */
                        u64     blocks_allowed;
@@ -139,7 +139,8 @@ struct la_inode {
                        u32     quota_inodes[3];
                        u16     snapshot_usage_table;
                        u16     pad;
-                       char    name[64];
+                       char    name[0]; /* variable size, nul padded, but
+                                         * not necessarily nul terminated */
                } fs;
                struct inodemap_metadata {
                        u32     size;
diff --git a/roll.c b/roll.c
index befba49a4906ab5a4fa178c3bec9da6475a28770..12d5bffaf17fcca9608a036a14453987150b9bce 100644 (file)
--- a/roll.c
+++ b/roll.c
@@ -600,7 +600,6 @@ lafs_mount(struct fs *fs)
                goto err;
        putdref(b, MKREF(mount));
        b = NULL;
-       dprintk("name is %s\n", LAFSI(root)->md.fs.name);
 
        unlock_new_inode(root);
        /* FIXME lots of error checking */
index c50932664249a095b27ffbe82d9f6316932338fa..1bdeb976063a97408b109170d3c1997d0ba13228 100644 (file)
@@ -114,11 +114,14 @@ lafs_snap_get_sb(struct file_system_type *fstype,
        fs = fs_from_sb(sb);
 
        for (s = 1; s < fs->maxsnapshot; s++) {
+               int nlen;
+
                if (fs->ss[s].root_addr == 0)
                        continue;
                if (fs->ss[s].root) {
                        struct lafs_inode *li = LAFSI(fs->ss[s].root);
-                       if (strcmp(li->md.fs.name, op.snapshot) == 0)
+                       if (li->md.fs.name &&
+                           strcmp(li->md.fs.name, op.snapshot) == 0)
                                /* found it */
                                break;
                }
@@ -126,8 +129,10 @@ lafs_snap_get_sb(struct file_system_type *fstype,
                if (err)
                        continue;
                lai = (struct la_inode *)page_address(p);
-               printk("ss %d is %.64s\n", s, lai->metadata[0].fs.name);
-               if (strncmp(lai->metadata[0].fs.name, op.snapshot, 64) != 0)
+               nlen = le16_to_cpu(lai->metadata_size) -
+                       offsetof(struct la_inode, metadata[0].fs.name);
+               printk("ss %d is %.*s\n", s, nlen, lai->metadata[0].fs.name);
+               if (strncmp(lai->metadata[0].fs.name, op.snapshot, nlen) != 0)
                        continue;
                /* FIXME more checks? */
                /* Found it */
diff --git a/state.h b/state.h
index 239f7a70059cc295043b8c232232185f46b39205..c422cd12e22678204c1003ec3c9d051186c1c671 100644 (file)
--- a/state.h
+++ b/state.h
@@ -593,7 +593,7 @@ struct lafs_inode {
                        u32     inodes_used;
                        u32     quota_inums[3];
                        struct inode *quota_inodes[3];
-                       char    name[65];
+                       char    *name;
                } fs;
                struct inodemap_md {
                        u32     size;
diff --git a/super.c b/super.c
index d02f80b8a3c7295c1c4a31f4368cfd61ff209831..af8b2c7d3490b813f6a550ff8f1e758e88bfc3eb 100644 (file)
--- a/super.c
+++ b/super.c
@@ -1036,7 +1036,7 @@ lafs_get_subset(struct file_system_type *fs_type,
                        md->quota_inodes[0] = NULL;
                        md->quota_inodes[1] = NULL;
                        md->quota_inodes[2] = NULL;
-                       md->name[0] = '\0';
+                       md->name = NULL;
                        lafs_dirty_dblock(inodb);
                        lafs_dirty_inode(ino);
                        /* We use a checkpoint to commit this change,
@@ -1231,8 +1231,11 @@ static void kfree_inode(struct rcu_head *head)
 {
        struct lafs_inode *lai = container_of(head, struct lafs_inode,
                                              md.rcu);
+       if (lai->type == TypeInodeFile)
+               kfree(lai->md.fs.name);
        kfree(lai);
 }
+
 void lafs_destroy_inode(struct inode *inode)
 {
        struct datablock *db;