From e74dd97bb2530b1a5133e7252f3342781167a24c Mon Sep 17 00:00:00 2001 From: sageweil Date: Sat, 10 Nov 2007 01:28:46 +0000 Subject: [PATCH] super/inode reorg. getting started on mount related code git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@2043 29311d96-e01e-0410-9327-a35deaab8ce9 --- trunk/ceph/include/ceph_fs.h | 13 ++ trunk/ceph/kernel/Makefile | 2 +- trunk/ceph/kernel/client.c | 105 +++++++++++++ trunk/ceph/kernel/client.h | 41 +++++ trunk/ceph/kernel/inode.c | 126 --------------- trunk/ceph/kernel/super.c | 297 +++++++++++++++++++++++++++++++---- trunk/ceph/kernel/super.h | 60 +++---- 7 files changed, 446 insertions(+), 198 deletions(-) create mode 100644 trunk/ceph/kernel/client.c create mode 100644 trunk/ceph/kernel/client.h diff --git a/trunk/ceph/include/ceph_fs.h b/trunk/ceph/include/ceph_fs.h index ba7bc37253600..e827d12f99590 100644 --- a/trunk/ceph/include/ceph_fs.h +++ b/trunk/ceph/include/ceph_fs.h @@ -21,6 +21,19 @@ extern int ceph_debug; # define derr(x, args...) do { if (x >= ceph_debug) printk(KERN_ERR "ceph: " args); } while (0); #endif +/** + * fs id + */ +struct ceph_fsid { + __u64 major; + __u64 minor; +}; +typedef struct ceph_fsid ceph_fsid_t; + +static inline int ceph_fsid_equal(const ceph_fsid_t *a, const ceph_fsid_t *b) { + return a->major == b->major && a->minor == b->minor; +} + /** * object id diff --git a/trunk/ceph/kernel/Makefile b/trunk/ceph/kernel/Makefile index 6defa37ec3662..638aae392a1ae 100644 --- a/trunk/ceph/kernel/Makefile +++ b/trunk/ceph/kernel/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_CEPH_FS) += ceph.o -ceph-objs := inode.o bufferlist.o ktcp.o super.o messenger.o mds_client.o osd_client.o +ceph-objs := inode.o bufferlist.o ktcp.o super.o messenger.o poll.o mds_client.o osd_client.o diff --git a/trunk/ceph/kernel/client.c b/trunk/ceph/kernel/client.c new file mode 100644 index 0000000000000..42da02161f4f6 --- /dev/null +++ b/trunk/ceph/kernel/client.c @@ -0,0 +1,105 @@ + +#include "client.h" +#include "super.h" +#include + + +/* debug level; defined in include/ceph_fs.h */ +int ceph_debug = 10; + +/* + * dispatch -- called with incoming messages. + * + * should be fast and non-blocking, as it is called with locks held. + */ +static void dispatch(struct ceph_client *client, struct ceph_message *msg) +{ + dout(5, "dispatch %p type %d\n", (void*)msg, msg->hdr.type); + + /* deliver the message */ + switch (msg->hdr.type) { + /* mds client */ + case CEPH_MSG_MDS_MAP: + ceph_mdsc_handle_map(&client->mds_client, msg); + break; + case CEPH_MSG_CLIENT_REPLY: + ceph_mdsc_handle_reply(&client->mds_client, msg); + break; + case CEPH_MSG_CLIENT_REQUEST_FORWARD: + ceph_mdsc_handle_forward(&client->mds_client, msg); + break; + + /* osd client */ + case CEPH_MSG_OSD_MAP: + ceph_osdc_handle_map(&client->osd_client, msg); + break; + case CEPH_MSG_OSD_OPREPLY: + ceph_osdc_handle_reply(&client->osd_client, msg); + break; + + default: + derr(1, "dispatch unknown message type %d\n", msg->hdr.type); + ceph_put_msg(msg); + } +} + + + + + + + +/* + * directory of filesystems mounted by this host + * + * key: fsid.major ^ fsid.minor + * value: struct ceph_client.fsid_item + */ +RADIX_TREE(ceph_clients, GFP_KERNEL); + +struct ceph_client *ceph_get_client(ceph_mount_args *args) +{ + struct ceph_client *client = 0; + struct sockaddr_in monaddr; + struct ceph_message *mount_msg; + int which; + + /* existing, by fsid? */ + if (args->flags & CEPH_MOUNT_FSID) + client = ceph_get_client_fsid(&args->fsid); + if (client) + return client; + + /* existing, by monitors? */ + /* write me. */ + + /* create new client */ + client = create_client(); + if (IS_ERR(client)) + return PTR_ERR(client); + + /* send mount request */ + mount_msg = prepare_mount_request(client); + ceph_get_msg(mount_msg); /* grab ref; we may retry */ + which = 0; +trymount: + ceph_msgr_send(client->msgr, mount_msg, args->mon_addr[which]); + + /* ... wait ... */ + + + + + + +} + +void ceph_put_client(struct ceph_client *cl) +{ + +} + + + + + diff --git a/trunk/ceph/kernel/client.h b/trunk/ceph/kernel/client.h new file mode 100644 index 0000000000000..8f106abc5f142 --- /dev/null +++ b/trunk/ceph/kernel/client.h @@ -0,0 +1,41 @@ +/* + * client.h + * + * ceph client instance. may be shared by multiple supers (mount points), + * if we are mounting the same cluster multiple times (e.g. at different + * offsets) + */ + +#include + +#include "messenger.h" +#include "monmap.h" + +#include "mon_client.h" +#include "mds_client.h" +#include "osd_client.h" + +struct ceph_mount_args; + +/* + * CEPH per-filesystem client state + * + * possibly shared by multiple mount points, if they are + * mounting the same ceph filesystem/cluster. + */ +struct ceph_client { + __u32 s_whoami; /* my client number */ + struct ceph_messenger *msgr; /* messenger instance */ + + struct ceph_monmap *monmap; /* monitor map */ + + struct ceph_mon_client mon_client; + struct ceph_mds_client mds_client; + struct ceph_osd_client osd_client; + + int s_ref; /* reference count (for each sb_info that points to me) */ + struct list_head fsid_item; +}; + +extern struct ceph_client *ceph_get_client(ceph_mount_args *args); +extern void ceph_put_client(struct ceph_client *cl); diff --git a/trunk/ceph/kernel/inode.c b/trunk/ceph/kernel/inode.c index dee289bbcfb42..7150d3b39c8a2 100644 --- a/trunk/ceph/kernel/inode.c +++ b/trunk/ceph/kernel/inode.c @@ -11,129 +11,3 @@ MODULE_AUTHOR("Patience Warnick "); MODULE_DESCRIPTION("Ceph filesystem for Linux"); MODULE_LICENSE("GPL"); - -static void ceph_read_inode(struct inode * inode) -{ - return; -} - -static int ceph_write_inode(struct inode * inode, int unused) -{ - lock_kernel(); - unlock_kernel(); - return 0; -} - -static void ceph_delete_inode(struct inode * inode) -{ - return; -} - -static void ceph_put_super(struct super_block *s) -{ - return; -} - -static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf) -{ - return 0; -} - -static void ceph_write_super(struct super_block *s) -{ - lock_kernel(); - unlock_kernel(); - return; -} - -static struct kmem_cache *ceph_inode_cachep; - -static struct inode *ceph_alloc_inode(struct super_block *sb) -{ - struct ceph_inode_info *ci; - ci = kmem_cache_alloc(ceph_inode_cachep, GFP_KERNEL); - if (!ci) - return NULL; - return &ci->vfs_inode; -} - -static void ceph_destroy_inode(struct inode *inode) -{ - kmem_cache_free(ceph_inode_cachep, CEPH_I(inode)); -} - -static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) -{ - struct ceph_inode_info *ci = (struct ceph_inode_info *) foo; - - if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == - SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ci->vfs_inode); -} - -static int init_inodecache(void) -{ - ceph_inode_cachep = kmem_cache_create("ceph_inode_cache", - sizeof(struct ceph_inode_info), - 0, (SLAB_RECLAIM_ACCOUNT| - SLAB_MEM_SPREAD), - init_once, NULL); - if (ceph_inode_cachep == NULL) - return -ENOMEM; - return 0; -} - -static void destroy_inodecache(void) -{ - kmem_cache_destroy(ceph_inode_cachep); -} - -static const struct super_operations ceph_sops = { - .alloc_inode = ceph_alloc_inode, - .destroy_inode = ceph_destroy_inode, - .read_inode = ceph_read_inode, - .write_inode = ceph_write_inode, - .delete_inode = ceph_delete_inode, - .put_super = ceph_put_super, - .write_super = ceph_write_super, - .statfs = ceph_statfs, -}; - -static int ceph_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data, struct vfsmount *mnt) -{ - printk(KERN_INFO "entered ceph_get_sb\n"); - return 0; -} - -static struct file_system_type ceph_fs_type = { - .owner = THIS_MODULE, - .name = "ceph", - .get_sb = ceph_get_sb, - .kill_sb = kill_block_super, -/* .fs_flags = */ -}; - -static int __init init_ceph(void) -{ - int ret = 0; - - printk(KERN_INFO "ceph init\n"); - if (!(ret = init_inodecache())) { - if ((ret = register_filesystem(&ceph_fs_type))) { - destroy_inodecache(); - } - } - return ret; -} - -static void __exit exit_ceph(void) -{ - printk(KERN_INFO "ceph exit\n"); - - unregister_filesystem(&ceph_fs_type); -} - - -module_init(init_ceph); -module_exit(exit_ceph); diff --git a/trunk/ceph/kernel/super.c b/trunk/ceph/kernel/super.c index b7077fa8f85de..51927cc1bf7d4 100644 --- a/trunk/ceph/kernel/super.c +++ b/trunk/ceph/kernel/super.c @@ -1,43 +1,272 @@ -#include #include "super.h" -/* debug level */ -int ceph_debug = 10; /* - * dispatch -- called with incoming messages. - * - * should be fast and non-blocking, as it is called with locks held. + * super ops */ -void dispatch(struct ceph_client *client, struct ceph_message *msg) -{ - dout(5, "dispatch %p type %d\n", (void*)msg, msg->hdr.type); - - /* deliver the message */ - switch (msg->hdr.type) { - /* mds client */ - case CEPH_MSG_MDS_MAP: - ceph_mdsc_handle_map(&client->mds_client, msg); - break; - case CEPH_MSG_CLIENT_REPLY: - ceph_mdsc_handle_reply(&client->mds_client, msg); - break; - case CEPH_MSG_CLIENT_REQUEST_FORWARD: - ceph_mdsc_handle_forward(&client->mds_client, msg); - break; - - /* osd client */ - case CEPH_MSG_OSD_MAP: - ceph_osdc_handle_map(&client->osd_client, msg); - break; - case CEPH_MSG_OSD_OPREPLY: - ceph_osdc_handle_reply(&client->osd_client, msg); - break; - - default: - derr(1, "dispatch unknown message type %d\n", msg->hdr.type); - ceph_put_msg(msg); + +static void ceph_read_inode(struct inode * inode) +{ + return; +} + +static int ceph_write_inode(struct inode * inode, int unused) +{ + lock_kernel(); + unlock_kernel(); + return 0; +} + +static void ceph_delete_inode(struct inode * inode) +{ + return; +} + +static void ceph_clear_inode(struct inode * inode, int unused) +{ + +} + +static void ceph_put_super(struct super_block *s) +{ + return; +} + +static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + return 0; +} + +static void ceph_write_super(struct super_block *s) +{ + return; +} + + +/* + * inode cache + */ +static struct kmem_cache *ceph_inode_cachep; + +static struct inode *ceph_alloc_inode(struct super_block *sb) +{ + struct ceph_inode_info *ci; + ci = kmem_cache_alloc(ceph_inode_cachep, GFP_KERNEL); + if (!ci) + return NULL; + return &ci->vfs_inode; +} + +static void ceph_destroy_inode(struct inode *inode) +{ + kmem_cache_free(ceph_inode_cachep, CEPH_I(inode)); +} + +static void ceph_icache_init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) +{ + struct ceph_inode_info *ci = (struct ceph_inode_info *) foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == + SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ci->vfs_inode); +} + +static int init_inodecache(void) +{ + ceph_inode_cachep = kmem_cache_create("ceph_inode_cache", + sizeof(struct ceph_inode_info), + 0, (SLAB_RECLAIM_ACCOUNT| + SLAB_MEM_SPREAD), + ceph_icache_init_once, NULL); + if (ceph_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + +static void destroy_inodecache(void) +{ + kmem_cache_destroy(ceph_inode_cachep); +} + +static const struct super_operations ceph_sops = { + .alloc_inode = ceph_alloc_inode, + .destroy_inode = ceph_destroy_inode, + .read_inode = ceph_read_inode, + .write_inode = ceph_write_inode, + .clear_inode = ceph_clear_inode, + .delete_inode = ceph_delete_inode, + .put_super = ceph_put_super, + .write_super = ceph_write_super, + .statfs = ceph_statfs, +}; + +static int ceph_set_super(struct super_block *s, void *data) +{ + struct ceph_mount_args *args = data; + struct ceph_super_info *sbinfo; + + s->s_flags = args->mntflags; + + sbinfo = kmalloc(sizeof(struct ceph_super_info), GFP_KERNEL); + if (!sbinfo) + return -ENOMEM; + memset(sbinfo, 0, sizeof(*sbinfo)); + s->s_fs_info = sbinfo; + + memcpy(sbinfo->mount_args, args, sizeof(*args)); + + ret = set_anon_super(s, 0); /* what is the second arg for? */ + if (ret != 0) + goto out; + + return ret; + +out: + kfree(s->s_fs_info); + s->s_fs_info = 0; + return ret; +} + +/* + * share superblock if same fs AND path AND options + */ +static int ceph_compare_super(struct super_block *sb, void *data) +{ + struct ceph_mount_args *args = (struct ceph_mount_args*)data; + struct ceph_super_info *other = ceph_sbinfo(sb); + + /* either compare fsid, or specified mon_hostname */ + if (args->flags & CEPH_MOUNT_FSID) { + if (!ceph_fsid_equal(&args->fsid, other->sb_client->fsid)) + return 1; + } else { + if (strcmp(args->mon_hostname, other->mount_args.mon_hostname) != 0) + return 1; + } + if (strcmp(args->path, other->mount_args.path) != 0) + return 1; + if (args->mntflags != other->mount_args.mntflags) + return 1; + return 0; +} + + +static int parse_mount_args(int flags, void *data, char *dev_name, struct ceph_mount_args *args) +{ + char *c; + int len; + + dout(1, "parse_mount_args dev_name %s\n", dev_name); + + args->mntflags = flags; + args->flags = 0; + + /* get mon hostname, relative path */ + c = strchr(dev_name, ":"); + if (c == NULL) + return -EINVAL; + len = c - dev_name; + if (len >= sizeof(args->mon_hostname)) + return -ENAMETOOLONG; + strncpy(args->mon_hostname, dev_name, len); + + c++; + if (strlen(c) >= sizeof(data->path)) + return -ENAMETOOLONG; + strcpy(args.path, c); + + dout(1, "mon %s, path %s\n", args->mon_hostname, args->path); + + /* FIXME parse mount options too? */ + + return 0; +} + + +static int ceph_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) +{ + struct super_block *s; + struct ceph_mount_args mount_args; + struct ceph_super_info *sbinfo; + int ret; + int (*compare_super)(struct super_block *, void *) = ceph_compare_super; + + dout(1, "ceph_get_sb\n"); + + error = parse_mount_args(data, dev_name, &mount_args); + if (error < 0) + goto out; + + if (mount_args.flags & CEPH_MOUNT_NOSHARE) + compare_super = 0; + + /* superblock */ + s = sget(fs_type, compare_super, ceph_set_super, &mount_args); + if (IS_ERR(s)) { + error = PTR_ERR(s); + goto out; + } + sbinfo = ceph_sbinfo(s); + + /* client */ + if (!sbinfo->sb_client) { + sbinfo->sb_client = ceph_get_client(&mount_args); + if (PTR_ERR(!sbinfo->sb_client)) { + error = PTR_ERR(sbinfo->sb_client); + goto out_splat; + } } + return 0; + +out_splat: + up_write(&s->s_umount); + deactivate_super(s); +out: + kfree(data); + return error; +} + +static void ceph_kill_sb(struct super_block *s) +{ + struct ceph_super_info *sbinfo = ceph_sbinfo(s); + dout(1, "ceph_kill_sb\n"); + ceph_put_client(sbinfo->sb_client); + kfree(sbinfo); +} + + +/************************************/ + +static struct file_system_type ceph_fs_type = { + .owner = THIS_MODULE, + .name = "ceph", + .get_sb = ceph_get_sb, + .kill_sb = ceph_kill_sb, +/* .fs_flags = */ +}; + +static int __init init_ceph(void) +{ + int ret = 0; + + dout(1, "init_ceph\n"); + if (!(ret = init_inodecache())) { + if ((ret = register_filesystem(&ceph_fs_type))) { + destroy_inodecache(); + } + } + return ret; } +static void __exit exit_ceph(void) +{ + dout(1, "exit_ceph\n"); + + unregister_filesystem(&ceph_fs_type); +} + + +module_init(init_ceph); +module_exit(exit_ceph); diff --git a/trunk/ceph/kernel/super.h b/trunk/ceph/kernel/super.h index e6f5ce2af34fc..9f2339e1e5f0a 100644 --- a/trunk/ceph/kernel/super.h +++ b/trunk/ceph/kernel/super.h @@ -4,55 +4,40 @@ #include #include -#include "messenger.h" -#include "monmap.h" - -#include "mon_client.h" -#include "mds_client.h" -#include "osd_client.h" - - - -/* - * CEPH per-filesystem client state - * - * possibly shared by multiple mount points, if they are - * mounting the same ceph filesystem/cluster. - */ -struct ceph_client { - __u64 s_fsid; /* hmm this should be part of the monmap? */ - - __u32 s_whoami; /* my client number */ - struct ceph_messenger *msgr; /* messenger instance */ - - struct ceph_monmap *monmap; /* monitor map */ - - struct ceph_mon_client mon_client; - struct ceph_mds_client mds_client; - struct ceph_osd_client osd_client; - - int s_ref; /* reference count (for each sb_info that points to me) */ -}; +#include "client.h" /* - * directory of filesystems mounted by this host - * - * key: fsid? ipquad of monitor? hmm! - * value: struct ceph_fs_client* + * mount options */ -extern struct radix_tree ceph_fs_clients; +#define CEPH_MOUNT_FSID 1 +#define CEPH_MOUNT_NOSHARE 2 /* don't share client with other mounts */ + +struct ceph_mount_args { + int mntflags; + int flags; + struct ceph_fsid fsid; + int num_mon; + struct ceph_entity_addr mon_addr[5]; + char path[100]; +}; /* * CEPH per-mount superblock info */ -struct ceph_sb_info { +struct ceph_super_info { + struct ceph_mount_args mount_args; struct ceph_client *sb_client; - /* FIXME: add my relative offset into the filesystem, - so we can appropriately mangle/adjust path names in requests, etc. */ + /* FIXME: ptr to inode of my relative offset into the filesystem, + so we can appropriately mangle/adjust path names in requests, etc...? */ }; +static inline struct ceph_super_info *ceph_sbinfo(struct super_block *sb) +{ + return sb->s_fs_info; +} + /* * CEPH file system in-core inode info */ @@ -68,6 +53,7 @@ static inline struct ceph_inode_info *CEPH_I(struct inode *inode) } + /* file.c */ extern const struct inode_operations ceph_file_inops; extern const struct file_operations ceph_file_operations; -- 2.39.5