From 8fba1ecdaa0757ac024c26ae6bb3cacf129e3166 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Wed, 23 Nov 2011 21:02:45 +0400 Subject: [PATCH] Switched directory structure to sstable2 --- fs/pohmelfs/dir.c | 167 +++++++++++++++++++++--------------------------------- 1 file changed, 64 insertions(+), 103 deletions(-) diff --git a/fs/pohmelfs/dir.c b/fs/pohmelfs/dir.c index 89bb12966d6..b2ae607eadb 100644 --- a/fs/pohmelfs/dir.c +++ b/fs/pohmelfs/dir.c @@ -262,23 +262,41 @@ struct pohmelfs_readdir_chunk { struct pohmelfs_readdir_header { char magic[8]; - short version; - short payload_size; - int offset_num; + unsigned short version; + unsigned short chunk_size; + unsigned int chunk_num; } __attribute__((packed)); static void pohmelfs_convert_readdir_header(struct pohmelfs_readdir_header *h) { h->version = dnet_bswap16(h->version); + h->chunk_size = dnet_bswap16(h->chunk_size); + h->chunk_num = dnet_bswap32(h->chunk_num); +} + +struct pohmelfs_readdir_chunk_header { + unsigned short length; + unsigned short num; + unsigned short key_size; + unsigned short payload_size; +} __attribute__((packed)); + +static void pohmelfs_convert_readdir_chunk_header(struct pohmelfs_readdir_chunk_header *h) +{ + h->length = dnet_bswap16(h->length); + h->num = dnet_bswap16(h->num); + h->key_size = dnet_bswap16(h->key_size); h->payload_size = dnet_bswap16(h->payload_size); - h->offset_num = dnet_bswap32(h->offset_num); } +/* Chunk size = maximum file name length + sizeof header + sizeof pohmelfs_inode_info + * It allows to store whole file entry on 1 chunk + */ +#define POHMELFS_CHUNK_SIZE (NAME_MAX + 1 + sizeof(struct pohmelfs_inode_info) + sizeof(struct pohmelfs_readdir_chunk_header)) + enum pohmelfs_readdir_states { POHMELFS_READDIR_WANT_HEADER = 1, - POHMELFS_READDIR_WANT_NEW_CHUNK, POHMELFS_READDIR_WANT_RECV_CHUNK, - POHMELFS_READDIR_WANT_RECV_INODES, }; struct pohmelfs_readdir_priv { @@ -286,29 +304,18 @@ struct pohmelfs_readdir_priv { struct kref refcnt; - struct list_head chunk_list; - struct pohmelfs_readdir_header header; int state; int read_total; /* number of inode offsets read or processed total (in all chunks summed) */ - int read_in_last_chunk; /* number of inode offsets read or processed in last or current chunk */ int read_in_inode; /* offset of name+pohmelfs_inode_info read in below buffer */ - int prev_offset; /* offset we just read data from */ - char data[NAME_MAX + 1 + sizeof(struct pohmelfs_inode_info)]; + char chunk[POHMELFS_CHUNK_SIZE]; }; static void pohmelfs_readdir_free(struct kref *kref) { struct pohmelfs_readdir_priv *priv = container_of(kref, struct pohmelfs_readdir_priv, refcnt); - struct pohmelfs_readdir_chunk *c, *tmp; - - list_for_each_entry_safe(c, tmp, &priv->chunk_list, chunk_entry) { - list_del(&c->chunk_entry); - - kfree(c); - } if (priv->wait) pohmelfs_wait_put(priv->wait); @@ -435,10 +442,8 @@ static int pohmelfs_readdir_recv_reply(struct pohmelfs_trans *t, struct pohmelfs { struct pohmelfs_readdir_priv *priv = t->priv; struct dnet_cmd *cmd = &recv->cmd; - struct pohmelfs_readdir_chunk *c; int attr_size = sizeof(struct dnet_attr) + sizeof(struct dnet_io_attr); long old_recv_offset; - int offset_num; void *data; int size; int err = 0; @@ -475,112 +480,69 @@ static int pohmelfs_readdir_recv_reply(struct pohmelfs_trans *t, struct pohmelfs goto err_out_exit; pohmelfs_convert_readdir_header(&priv->header); - priv->state = POHMELFS_READDIR_WANT_NEW_CHUNK; - - priv->header.offset_num++; + priv->read_total = 0; + priv->read_in_inode = 0; + priv->state = POHMELFS_READDIR_WANT_RECV_CHUNK; - pohmelfs_print_addr(&recv->sa, "%s: header: header size: %d, version: %hd, payload_size: %hd, offset num: %d\n", + pohmelfs_print_addr(&recv->sa, "%s: header: header size: %d, version: %hd, chunk_size: %hd, chunk_num: %d\n", pohmelfs_dump_id(cmd->id.id), header_size_to_read, - priv->header.version, priv->header.payload_size, priv->header.offset_num); - } + priv->header.version, priv->header.chunk_size, priv->header.chunk_num); -get_new_chunk: - if (priv->state == POHMELFS_READDIR_WANT_NEW_CHUNK) { - if ((priv->header.offset_num - priv->read_total) * 4 < PAGE_SIZE - sizeof(struct pohmelfs_readdir_chunk)) { - c = kmalloc(sizeof(struct pohmelfs_readdir_chunk) + priv->header.offset_num * 4, GFP_NOIO); - offset_num = priv->header.offset_num - priv->read_total; - } else { - c = kmalloc(PAGE_SIZE, GFP_NOIO); - offset_num = (PAGE_SIZE - sizeof(struct pohmelfs_readdir_chunk)) / 4; - } - if (!c) { - err = -ENOMEM; + if (priv->header.chunk_size > POHMELFS_CHUNK_SIZE) { + err = -E2BIG; goto err_out_exit; } - - c->offset_num = offset_num; - list_add_tail(&c->chunk_entry, &priv->chunk_list); - - priv->state = POHMELFS_READDIR_WANT_RECV_CHUNK; - priv->read_in_last_chunk = 0; } +get_new_chunk: if (priv->state == POHMELFS_READDIR_WANT_RECV_CHUNK) { - old_recv_offset = t->recv_offset; - - c = list_entry(priv->chunk_list.prev, struct pohmelfs_readdir_chunk, chunk_entry); + data = priv->chunk + priv->read_in_inode; + size = POHMELFS_CHUNK_SIZE - priv->read_in_inode; - data = &c->offset[priv->read_in_last_chunk]; - size = (c->offset_num - priv->read_in_last_chunk) * 4; + old_recv_offset = t->recv_offset; err = pohmelfs_recv(t, recv, data, size); if (err < 0) goto err_out_exit; - offset_num = (t->recv_offset - old_recv_offset) / 4; - priv->read_in_last_chunk += offset_num; - priv->read_total += offset_num; - - if (priv->read_total == priv->header.offset_num) { - priv->state = POHMELFS_READDIR_WANT_RECV_INODES; - priv->read_total = 0; - priv->read_in_inode = 0; - priv->read_in_last_chunk = 1; /* we skip first record, it is zero */ - } else if (priv->read_in_last_chunk == c->offset_num) { - priv->state = POHMELFS_READDIR_WANT_NEW_CHUNK; - priv->read_in_last_chunk = 0; - goto get_new_chunk; - } - } - - if (priv->state == POHMELFS_READDIR_WANT_RECV_INODES) { - int i, read_count = 0; - - list_for_each_entry(c, &priv->chunk_list, chunk_entry) { - if (priv->read_total > read_count + c->offset_num) { - read_count += c->offset_num; - continue; - } + priv->read_in_inode += t->recv_offset - old_recv_offset; - for (i = priv->read_in_last_chunk; i < c->offset_num; ++i) { - int isize = le32_to_cpu(c->offset[i]) - priv->prev_offset; - - data = priv->data + priv->read_in_inode; - size = isize - priv->read_in_inode; - - old_recv_offset = t->recv_offset; + if (priv->read_in_inode == POHMELFS_CHUNK_SIZE) { + struct pohmelfs_readdir_chunk_header *chunk_header; + struct pohmelfs_inode_info *info; + char *filename; - err = pohmelfs_recv(t, recv, data, size); - if (err < 0) - goto err_out_exit; + priv->read_in_inode = 0; + priv->read_total++; - priv->read_in_inode += t->recv_offset - old_recv_offset; - if (priv->read_in_inode == isize) { - struct pohmelfs_inode_info *info; + chunk_header = (struct pohmelfs_readdir_chunk_header *)priv->chunk; + pohmelfs_convert_readdir_chunk_header(chunk_header); - priv->prev_offset = le32_to_cpu(c->offset[i]); - priv->read_in_inode = 0; - priv->read_in_last_chunk++; - priv->read_total++; + /* + * Here we assume that record always fits in 1 chunk. + * In future this code should be changed to read several chunks + * and concatenate it to build continous buffer for + * file name and pohmelfs_inode_info structure + */ - info = (struct pohmelfs_inode_info *)(priv->data + isize - sizeof(struct pohmelfs_inode_info)); - pohmelfs_convert_inode_info(info); + info = (struct pohmelfs_inode_info *)(priv->chunk + sizeof(struct pohmelfs_readdir_chunk_header) + chunk_header->key_size); + pohmelfs_convert_inode_info(info); - pohmelfs_print_addr(&recv->sa, "%s: inode: %llu, namelen: %d, name: %.*s\n", - pohmelfs_dump_id(info->id.id), (unsigned long long)info->ino, - info->namelen, info->namelen, priv->data); + filename = (char *)(priv->chunk + sizeof(struct pohmelfs_readdir_chunk_header)); - pohmelfs_update_inode(priv->wait->pi, info, priv->data); - } else { - err = -EAGAIN; - goto err_out_exit; - } - } + pohmelfs_print_addr(&recv->sa, "%s: inode: %llu, namelen: %d, name: %.*s\n", + pohmelfs_dump_id(info->id.id), (unsigned long long)info->ino, + info->namelen, info->namelen, filename); - read_count += priv->read_in_last_chunk; - priv->read_in_last_chunk = 0; + pohmelfs_update_inode(priv->wait->pi, info, filename); + } else { + err = -EAGAIN; + goto err_out_exit; } + + if ((priv->read_total < priv->header.chunk_num) && (t->recv_offset < cmd->size)) + goto get_new_chunk; } return 0; @@ -619,7 +581,6 @@ static int pohmelfs_warm_dir_group(struct inode *dir, int group_id) goto err_out_free; } - INIT_LIST_HEAD(&priv->chunk_list); kref_init(&priv->refcnt); wait = pohmelfs_wait_alloc(parent); -- 2.11.4.GIT