From: Marko O. <d0...@us...> - 2010-03-22 08:07:30
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "kdfs". The branch, make_kdfs_compile has been updated via c1d32fe132c4e3398b8dc11cbaa88e9ed63ae824 (commit) from 220d6f49eb3796930870a04b9ec525dfcd7cd635 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit c1d32fe132c4e3398b8dc11cbaa88e9ed63ae824 Author: Marko Obrovac <mar...@in...> Date: Mon Mar 22 09:58:05 2010 +0100 Striping partially done! Currently, a file created on one node will be striped across several nodes if other nodes write to it. The extents list is being correctly imported and exported. Still, the changes to the list are not (yet) flushed to the disk so once the inode gets evicted from the cache, all extents info is lost. diff --git a/fs/kdfs/Makefile b/fs/kdfs/Makefile index f59b146..9396011 100644 --- a/fs/kdfs/Makefile +++ b/fs/kdfs/Makefile @@ -1 +1 @@ -obj-y := physical_fs.o super.o inode.o dir.o file.o address_space.o extent.o cow.o +obj-y := physical_fs.o super.o inode.o dir.o file.o address_space.o extent.o cow.o file_extent.o diff --git a/fs/kdfs/address_space.c b/fs/kdfs/address_space.c index 1d6254e..8c658b2 100644 --- a/fs/kdfs/address_space.c +++ b/fs/kdfs/address_space.c @@ -19,6 +19,7 @@ #include "super.h" #include "inode.h" +#include "file_extent.h" #include "address_space.h" #include "physical_fs.h" @@ -186,6 +187,8 @@ int __kdfs_commit_write(struct file *file, if (((loff_t)page->index * PAGE_SIZE) + _to > k_inode->inode->i_size) i_size_write(k_inode->inode, ((loff_t)page->index * PAGE_SIZE) + _to); + /* set the page's owner to this node */ + kdfs_file_extent_set_page_owner(k_inode, page->index, kerrighed_node_id); /* * From the local node point of view, we have to set DIRTY flag to the page: * set_page_dirty(page); diff --git a/fs/kdfs/file.c b/fs/kdfs/file.c index ddeb1df..45a7835 100644 --- a/fs/kdfs/file.c +++ b/fs/kdfs/file.c @@ -17,6 +17,7 @@ #include "super.h" #include "inode.h" +#include "file_extent.h" #include "address_space.h" #include "file.h" @@ -266,10 +267,11 @@ kerrighed_node_t kdfs_iol_file_default_owner (kddm_set_t *kddm_set, struct kdfs_inode *k_inode = kdfs_ilocalfind(my_data->ino); // check who's the default owner of the object !!! - ret_val = inode_linked_node(k_inode->inode->i_ino); + //ret_val = inode_linked_node(k_inode->inode->i_ino); + ret_val = kdfs_file_extent_get_page_owner(k_inode, objid); kdfs_iput(k_inode->inode->i_ino); - DEBUG(DBG_INFO, "inode_linked_node ::: %d\n", ret_val); + DEBUG(DBG_INFO, "######### /\\/\\/\\/ page owner ::: %d\n", ret_val); return ret_val; //return 2; } diff --git a/fs/kdfs/file_extent.c b/fs/kdfs/file_extent.c new file mode 100644 index 0000000..13360c5 --- /dev/null +++ b/fs/kdfs/file_extent.c @@ -0,0 +1,286 @@ +/* + * KDDM File System - striping extents management + * + * @file file_extent.c + * + * @author Marko Obrovac (2010-xxxx) + * + * Copyright (C) 2006-2007, XtreemOS Consortium. + * Copyright (C) 2008-20xx, XtreemOS Consortium, Ascola Research Group. + */ + +#include "file_extent.h" +#include "physical_fs.h" + +#include "debug_kdfs.h" +#define KDFS_PART "KDFS - Strip Extents Management" + + +void kdfs_file_extent_init(struct kdfs_inode *k_inode) +{ + DEBUG(DBG_INFO, "INIT LIST\n"); + /* initialise the extents list */ + INIT_LIST_HEAD(&k_inode->extents_list); +} + +struct kdfs_file_extent *kdfs_file_extent_alloc(pgoff_t page_start, pgoff_t page_end, kdfs_node_t owner_id) +{ + struct kdfs_file_extent *extent; + + /* Allocate the new item and populate it */ + extent = kmalloc(sizeof(struct kdfs_file_extent), GFP_KERNEL); + extent->data.page_first = page_start; + extent->data.page_last = page_end; + extent->data.extent_owner = owner_id; + + return extent; + +} + +int kdfs_file_extent_find(struct list_head *extents, pgoff_t page_no, struct kdfs_file_extent **ext_before, struct kdfs_file_extent **ext_in, struct kdfs_file_extent **ext_after) +{ + struct kdfs_file_extent *curr = NULL; + + *ext_before = *ext_in = *ext_after = NULL; + + list_for_each_entry(curr, extents, list_item) { + if (curr->data.page_first <= page_no && curr->data.page_last >= page_no) { + /* the page is inside this extent */ + *ext_in = curr; + return 1; + } + if (curr->data.page_first > page_no) { + /* the item should be inserted before the current one */ + *ext_after = curr; + return 1; + } + if (curr->data.page_last < page_no) { + /* the item should be inserted after the current one */ + *ext_before = curr; + } + } + + return 1; + +} + +int kdfs_file_extent_set_page_owner(struct kdfs_inode *k_inode, pgoff_t page_no, kdfs_node_t node_id) +{ + struct kdfs_file_extent *new_extent, *sec_new_extent; + struct kdfs_file_extent *extent_before, *extent_in, *extent_after; + struct kdfs_file_extent *curr = NULL; + int ret = 0; + + PRINT_FUNCTION_NAME; + DEBUG(DBG_INFO, "extent for ino=%lu, page_no=%lu, node=%d\n", k_inode->inode->i_ino, page_no, node_id); + + /* if the list is empty, just create a new item */ + if (list_empty(&k_inode->extents_list)) { + new_extent = kdfs_file_extent_alloc(page_no, page_no, node_id); + list_add(&new_extent->list_item, &k_inode->extents_list); + goto out; + } + + /* try to locate the page's extent */ + kdfs_file_extent_find(&k_inode->extents_list, page_no, &extent_before, &extent_in, &extent_after); + + /* do we have to add it in the middle of an existing extent? */ + if (extent_in) { + if (extent_in->data.extent_owner == node_id) { + /* same owner, so nothing to do */ + goto out; + } + if (extent_in->data.page_first < page_no && extent_in->data.page_last > page_no) { + /* extent_in has to be split in three parts */ + new_extent = kdfs_file_extent_alloc(page_no, page_no, node_id); + list_add(&new_extent->list_item, &extent_in->list_item); + sec_new_extent = kdfs_file_extent_alloc(page_no + 1, extent_in->data.page_last, extent_in->data.extent_owner); + list_add(&sec_new_extent->list_item, &new_extent->list_item); + extent_in->data.page_last = page_no - 1; + goto out; + } + /* :: border cases :: */ + if (extent_in->data.page_first == page_no) { + /* the new extent has to be put in front of extent_in */ + if (extent_in->data.page_last == page_no) { + /* this is a one-page extent, so just change the owner */ + extent_in->data.extent_owner = node_id; + goto out; + } + /* fix extent_in's border */ + extent_in->data.page_first = page_no + 1; + if (extent_before) { + if (extent_before->data.page_last == page_no - 1 && extent_before->data.extent_owner == node_id) { + /* add this page to the previous extent */ + extent_before->data.page_last = page_no; + goto out; + } + /* add a new extent between extent_before and extent_in */ + new_extent = kdfs_file_extent_alloc(page_no, page_no, node_id); + list_add(&new_extent->list_item, &extent_before->list_item); + goto out; + } + /* extent_in is the first item in the list, so add a new extent in front of it */ + new_extent = kdfs_file_extent_alloc(page_no, page_no, node_id); + list_add(&new_extent->list_item, &k_inode->extents_list); + goto out; + } + /* this page_no is the last page in extent_in but has a different owner */ + /* fix extent_in's border */ + extent_in->data.page_last = page_no - 1; + if (extent_after && extent_after->data.page_first == page_no + 1 && extent_after->data.extent_owner == node_id) { + /* we can attach this page to the next extent in the list */ + extent_after->data.page_first = page_no; + goto out; + } + /* create a new extent and place it after extent_in */ + new_extent = kdfs_file_extent_alloc(page_no, page_no, node_id); + list_add(&new_extent->list_item, &extent_in->list_item); + goto out; + } + + /* do we have to add the extent between two other extents? */ + if (extent_before && extent_after && extent_before->data.extent_owner == extent_after->data.extent_owner + && extent_before->data.extent_owner == node_id && extent_before->data.page_last == extent_after->data.page_first - 2) { + /* concatenate the two extents, encapsulating the page to be added */ + extent_before->data.page_last = extent_after->data.page_last; + /* delete extent_after, as it is part of extent_before now */ + list_del(&extent_after->list_item); + kfree(extent_after); + goto out; + } + + /* are there any extents we can attach this page to? */ + if (extent_before && extent_before->data.extent_owner == node_id && extent_before->data.page_last == page_no - 1) { + /* just append the page to extent_before */ + extent_before->data.page_last = page_no; + goto out; + } + if (extent_after && extent_after->data.extent_owner == node_id && extent_after->data.page_first == page_no + 1) { + /* add this page to extent_after */ + extent_after->data.page_first = page_no; + goto out; + } + + /* do we have to add the extent after an existing one? */ + if (extent_before) { + /* just create a new extent and place it after extent_before */ + new_extent = kdfs_file_extent_alloc(page_no, page_no, node_id); + list_add(&new_extent->list_item, &extent_before->list_item); + goto out; + } + + /* finally, add a new extent in front of extent_after */ + new_extent = kdfs_file_extent_alloc(page_no, page_no, node_id); + list_add_tail(&new_extent->list_item, &extent_after->list_item); + +out: + DEBUG(DBG_INFO, "LIST CONTENTS AFTER MANIP\n"); + list_for_each_entry(curr, &k_inode->extents_list, list_item) { + DEBUG(DBG_INFO, "#################### f=%lu, l=%lu, o=%d\n", curr->data.page_first, curr->data.page_last, curr->data.extent_owner); + } + + PRINT_FUNCTION_EXIT; + + return ret; + +} + +kdfs_node_t kdfs_file_extent_get_page_owner(struct kdfs_inode *k_inode, pgoff_t page_no) +{ + struct kdfs_file_extent *extent_before, *extent_in, *extent_after; + + kdfs_file_extent_find(&k_inode->extents_list, page_no, &extent_before, &extent_in, &extent_after); + + if (extent_in) { + return extent_in->data.extent_owner; + } + + return kerrighed_node_id; + +} + +size_t kdfs_file_extent_dump_to_file(struct kdfs_inode *k_inode, struct file *file) +{ + int list_count = 0; + int bytes_written = 0; + struct kdfs_file_extent *curr; + + ASSERT(k_inode != NULL); + + list_for_each_entry(curr, &k_inode->extents_list, list_item) { + list_count++; + } + + bytes_written += kdfs_phys_write(file, (char *) &(list_count), + sizeof(int), &file->f_pos); + + list_for_each_entry(curr, &k_inode->extents_list, list_item) { + bytes_written += kdfs_phys_write(file, + (char *) &(curr->data), sizeof(struct kdfs_file_extent_info), + &file->f_pos); + } + + return bytes_written; + +} + +size_t kdfs_file_extent_read_from_file(struct kdfs_inode *k_inode, struct file *file) +{ + /* TODO Implement*/ + return 0; + +} + +void kdfs_file_extent_net_export(struct kdfs_inode *k_inode, struct kdfs_netinode *net_inode) +{ + int list_count = 0; + struct kdfs_file_extent *curr; + + DEBUG(DBG_INFO, "Exporting the extents list for inode %lu\n", k_inode->inode->i_ino); + + list_for_each_entry(curr, &k_inode->extents_list, list_item) { + net_inode->extents[list_count].page_first = curr->data.page_first; + net_inode->extents[list_count].page_last = curr->data.page_last; + net_inode->extents[list_count].extent_owner = curr->data.extent_owner; + //DEBUG(DBG_INFO, "Exporting <%lu, %lu, %d>\n", net_inode->extents[list_count].page_first, net_inode->extents[list_count].page_last, net_inode->extents[list_count].extent_owner); + list_count++; + if (list_count == FILE_EXT_MAX_MEMBERS) { + DEBUG(DBG_ALERT, "The list is too large to export! Exporting only partially\n"); + break; + } + } + + net_inode->no_extents = list_count; + //DEBUG(DBG_INFO, "NO EXPORTED: %d\n", net_inode->no_extents); + +} + +void kdfs_file_extent_net_import(struct kdfs_inode *k_inode, struct kdfs_netinode *net_inode) +{ + int index; + struct kdfs_file_extent *new_extent, *curr; + + DEBUG(DBG_INFO, "Importing the extents list for inode %lu\n", k_inode->inode->i_ino); + + kdfs_file_extent_init(k_inode); + + //DEBUG(DBG_INFO, "NO TO IMPORT: %d\n", net_inode->no_extents); + + for(index = 0; index < net_inode->no_extents; index++) { + new_extent = kmalloc(sizeof(struct kdfs_file_extent), GFP_KERNEL); + new_extent->data.page_first = net_inode->extents[index].page_first; + new_extent->data.page_last = net_inode->extents[index].page_last; + new_extent->data.extent_owner = net_inode->extents[index].extent_owner; + DEBUG(DBG_INFO, "Importing <%lu, %lu, %d>\n", net_inode->extents[index].page_first, net_inode->extents[index].page_last, net_inode->extents[index].extent_owner); + list_add_tail(&new_extent->list_item, &k_inode->extents_list); + } + + DEBUG(DBG_INFO, "LIST CONTENTS AFTER IMPORT\n"); + list_for_each_entry(curr, &k_inode->extents_list, list_item) { + DEBUG(DBG_INFO, "#################### f=%lu, l=%lu, o=%d\n", curr->data.page_first, curr->data.page_last, curr->data.extent_owner); + } + +} + + diff --git a/fs/kdfs/file_extent.h b/fs/kdfs/file_extent.h new file mode 100644 index 0000000..1b3a7bd --- /dev/null +++ b/fs/kdfs/file_extent.h @@ -0,0 +1,38 @@ +/* + * KDDM File System - striping extents management + * + * @file file_extent.h + * + * @author Marko Obrovac (2010-xxxx) + * + * Copyright (C) 2006-2007, XtreemOS Consortium. + * Copyright (C) 2008-20xx, XtreemOS Consortium, Ascola Research Group. + */ + +#ifndef __KDFS_FILE_EXTENT__ +#define __KDFS_FILE_EXTENT__ + + +#include <linux/list.h> +#include <linux/pagemap.h> + +#include <kddm/kddm.h> + +#include "inode.h" + + +void kdfs_file_extent_init(struct kdfs_inode *k_inode); +struct kdfs_file_extent *kdfs_file_extent_alloc(pgoff_t page_start, pgoff_t page_end, kdfs_node_t owner_id); +int kdfs_file_extent_find(struct list_head *extents, pgoff_t page_no, struct kdfs_file_extent **ext_before, struct kdfs_file_extent **ext_in, struct kdfs_file_extent **ext_after); + +int kdfs_file_extent_set_page_owner(struct kdfs_inode *k_inode, pgoff_t page_no, kdfs_node_t node_id); +kdfs_node_t kdfs_file_extent_get_page_owner(struct kdfs_inode *k_inode, pgoff_t page_no); + +size_t kdfs_file_extent_dump_to_file(struct kdfs_inode *k_inode, struct file *file); +size_t kdfs_file_extent_read_from_file(struct kdfs_inode *k_inode, struct file *file); + +void kdfs_file_extent_net_export(struct kdfs_inode *k_inode, struct kdfs_netinode *net_inode); +void kdfs_file_extent_net_import(struct kdfs_inode *k_inode, struct kdfs_netinode *net_inode); + + +#endif /* __KDFS_FILE_EXTENT__ */ diff --git a/fs/kdfs/inode.c b/fs/kdfs/inode.c index 90250e2..8113b82 100644 --- a/fs/kdfs/inode.c +++ b/fs/kdfs/inode.c @@ -17,6 +17,7 @@ #include "super.h" #include "inode.h" +#include "file_extent.h" #include "dir.h" #include "file.h" #include "address_space.h" @@ -25,6 +26,7 @@ #include "debug_kdfs.h" #define KDFS_PART "KDFS - Inode Management" + /******************************** * * * SOME DEBUG FUNCTIONS * @@ -1050,6 +1052,8 @@ int kdfs_iol_inode_alloc_object (kddm_obj_t *objEntry, k_inode = kmalloc(sizeof(struct kdfs_inode), GFP_KERNEL); ASSERT(k_inode != NULL); atomic_set(&k_inode->cw_count, 0); + /* initialise the extents */ + kdfs_file_extent_init(k_inode); /* Check if the inode is locally in the cache */ /* Can happen when a content associated kddm set has been instantiated */ @@ -1126,6 +1130,8 @@ int kdfs_iol_inode_first_touch(kddm_obj_t *objEntry, k_inode = kmalloc(sizeof(struct kdfs_inode), GFP_KERNEL); ASSERT(k_inode != NULL); atomic_set(&k_inode->cw_count, 0); + /* initialise the extents */ + kdfs_file_extent_init(k_inode); if (flags & KDDM_CREATE_ON_FT) { k_inode->inode = new_inode (k_sb->sb); @@ -1192,6 +1198,9 @@ int kdfs_iol_inode_export_object(struct rpc_desc *desc, PRINT_FUNCTION_NAME; kdfs_export_kdfs_inode(&net_dest, src); + + /* export the extents part */ + kdfs_file_extent_net_export(src, &net_dest); res = rpc_pack_type(desc, net_dest); @@ -1220,6 +1229,9 @@ int kdfs_iol_inode_import_object(struct rpc_desc *desc, res = rpc_unpack_type(desc, net_src); kdfs_import_kdfs_inode(inode_dst, &net_src); + + /* import the extents part */ + kdfs_file_extent_net_import(inode_dst, &net_src); PRINT_FUNCTION_EXIT; return res; diff --git a/fs/kdfs/inode.h b/fs/kdfs/inode.h index 24e4bde..f508d46 100644 --- a/fs/kdfs/inode.h +++ b/fs/kdfs/inode.h @@ -14,6 +14,7 @@ #ifndef __KDFS_INODE__ #define __KDFS_INODE__ + /*--------------------------------------------------------------------------* * * * MACROS * @@ -28,6 +29,13 @@ #define K_INODE_DIRTY 8 #define K_INODE_TODELETE 16 +/* Max number of extent records that fit in a kddm object */ +/* if you change the kdfs_netinode or kdfs_file_extent_info + structures, please update this constant! + 124 = size of kdfs_netinode (without the extents array) + 24 = size of kdfs_file_extent_info */ +#define FILE_EXT_MAX_MEMBERS ((PAGE_SIZE - 124)/24) + /* cf <ctnr/object-server.h> */ #ifndef KDDM_CREATE_ON_FT #define KDDM_CREATE_ON_FT 0x00000100 @@ -39,6 +47,26 @@ * * *--------------------------------------------------------------------------*/ +/* COPIED FROM super.h */ +#ifndef __KDFS_SUPER__ +typedef short kdfs_node_t; /* kerrighed_node_t*/ +#endif +/* END COPY */ + +/* FILE STRIPING TYPES */ +/* the actual strip extent info */ +struct kdfs_file_extent_info { + pgoff_t page_first; /* the first page no owned by a node */ + pgoff_t page_last; /* the last page no owned by a node */ + kdfs_node_t extent_owner; /* the node holding the pages contents */ +}; +/* the extent list item */ +struct kdfs_file_extent { + struct kdfs_file_extent_info data; /* the extent data */ + struct list_head list_item; /* the list member linking it to the list */ +}; + + struct kdfs_inode { struct inode* inode; /* Local copy of the inode */ @@ -49,6 +77,10 @@ struct kdfs_inode { /* Cluster-wide count */ atomic_t cw_count; + + /* Striping extents list */ + /* TODO take care of netinode too!!! */ + struct list_head extents_list; }; /* @@ -77,6 +109,10 @@ struct kdfs_netinode { /* k_inode flags*/ char flags; + + /* File extents portion */ + size_t no_extents; + struct kdfs_file_extent_info extents[FILE_EXT_MAX_MEMBERS]; }; /*--------------------------------------------------------------------------* diff --git a/fs/kdfs/super.c b/fs/kdfs/super.c index ee51d2c..db1ebdf 100644 --- a/fs/kdfs/super.c +++ b/fs/kdfs/super.c @@ -24,6 +24,7 @@ #include "physical_fs.h" #include "super.h" #include "inode.h" +#include "file_extent.h" #include "dir.h" #include "address_space.h" @@ -1035,6 +1036,13 @@ int kdfs_write_inode(struct inode *inode) kdfs_phys_write(file, (char *) &(phys_inode), sizeof(struct kdfs_physical_inode), &file->f_pos); + /* Dump the extent's info also */ + /********************** + * #### PROBLEM #### + * it seams the kdfs_inode is locked, but we need it + * to dump the extent's info in the meta file ... + **********************/ + //kdfs_file_extent_dump_to_file(kdfs_iget(inode->i_ino), file); close_phys_file(file); } else { DEBUG (DBG_ALERT, diff --git a/fs/kdfs/super.h b/fs/kdfs/super.h index f480a74..4b615e7 100644 --- a/fs/kdfs/super.h +++ b/fs/kdfs/super.h @@ -14,7 +14,7 @@ #ifndef __KDFS_SUPER__ #define __KDFS_SUPER__ -// for PAGE_SIZE + // for PAGE_SIZE #include <asm/page.h> #include <linux/statfs.h> ----------------------------------------------------------------------- Summary of changes: fs/kdfs/Makefile | 2 +- fs/kdfs/address_space.c | 3 + fs/kdfs/file.c | 6 +- fs/kdfs/file_extent.c | 286 +++++++++++++++++++++++++++++++++++++++++++++++ fs/kdfs/file_extent.h | 38 ++++++ fs/kdfs/inode.c | 12 ++ fs/kdfs/inode.h | 36 ++++++ fs/kdfs/super.c | 8 ++ fs/kdfs/super.h | 2 +- 9 files changed, 389 insertions(+), 4 deletions(-) create mode 100644 fs/kdfs/file_extent.c create mode 100644 fs/kdfs/file_extent.h hooks/post-receive -- kdfs |