From: NeilBrown Date: Sat, 2 Oct 2010 00:42:34 +0000 (+1000) Subject: Improve handling of snapshot name. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=67bec1ca5ba78028e3da01b9b6461cb2784f3a5c;p=LaFS.git Improve handling of snapshot name. 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 --- diff --git a/inode.c b/inode.c index 88312c3..88c76d1 100644 --- a/inode.c +++ b/inode.c @@ -12,6 +12,7 @@ #include "lafs.h" #include #include +#include /* 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; } diff --git a/layout.h b/layout.h index c1e5ea2..5c6ba0e 100644 --- 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 befba49..12d5bff 100644 --- 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 */ diff --git a/snapshot.c b/snapshot.c index c509326..1bdeb97 100644 --- a/snapshot.c +++ b/snapshot.c @@ -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 239f7a7..c422cd1 100644 --- 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 d02f80b..af8b2c7 100644 --- 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;