From 555706a89c94f3eff759dfb804eec60e26c8c747 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Sat, 22 Dec 2007 07:13:52 -0800 Subject: [PATCH] kernel: ceph_readpage, osd_client reply handler --- src/kernel/addr.c | 30 ++++++++++++-- src/kernel/dir.c | 91 ++++------------------------------------- src/kernel/file.c | 86 +++++++++++++++++++++++++++++++------- src/kernel/osd_client.c | 41 ++++++++++++++++--- src/kernel/osd_client.h | 5 +++ src/kernel/super.h | 4 ++ 6 files changed, 151 insertions(+), 106 deletions(-) diff --git a/src/kernel/addr.c b/src/kernel/addr.c index beae8cdbb65bd..ceb5a238674d7 100644 --- a/src/kernel/addr.c +++ b/src/kernel/addr.c @@ -1,13 +1,35 @@ +#include +#include +#include + +int ceph_debug_addr = 50; +#define DOUT_VAR ceph_debug_addr +#define DOUT_PREFIX "addr: " #include "super.h" -/* -static int ceph_vfs_readpage(struct file *filp, struct page *page) +#include "osd_client.h" + +static int ceph_readpage(struct file *filp, struct page *page) { + struct inode *inode = filp->f_dentry->d_inode; + struct ceph_osd_client *osdc = &ceph_inode_to_client(inode)->osdc; + struct ceph_inode_info *ci = ceph_inode(inode); + int err = 0; + dout(10, "ceph_readpage file %p page %p index %lu\n", filp, + page, page->index); + err = ceph_osdc_readpage(osdc, inode->i_ino, &ci->i_layout, + page->index << PAGE_SHIFT, PAGE_SIZE, page); + if (err) goto out_unlock; + + SetPageUptodate(page); +out_unlock: + unlock_page(page); + return err; } -*/ + const struct address_space_operations ceph_aops = { -// .readpage = ceph_vfs_readpage, + .readpage = ceph_readpage, }; diff --git a/src/kernel/dir.c b/src/kernel/dir.c index 3ff17f3934cd3..5dd09db63b37d 100644 --- a/src/kernel/dir.c +++ b/src/kernel/dir.c @@ -11,14 +11,14 @@ const struct file_operations ceph_dir_fops; * - no locking. * - should stop at mount root or current's CWD? */ -static int get_dentry_path(struct dentry *dn, char *buf, struct dentry *base) +int ceph_get_dentry_path(struct dentry *dn, char *buf, struct dentry *base) { int len; dout(20, "get_dentry_path in dn %p bas %p\n", dn, base); if (dn == base) return 0; - len = get_dentry_path(dn->d_parent, buf, base); + len = ceph_get_dentry_path(dn->d_parent, buf, base); dout(20, "get_dentry_path out dn %p bas %p len %d adding %s\n", dn, base, len, dn->d_name.name); @@ -29,65 +29,6 @@ static int get_dentry_path(struct dentry *dn, char *buf, struct dentry *base) return len; } -struct ceph_inode_cap *ceph_open(struct inode *inode, struct file *file, int flags) -{ - struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc; - ceph_ino_t pathbase; - char path[PATH_MAX]; - int pathlen; - struct ceph_msg *req; - struct ceph_mds_request_head *rhead; - struct ceph_mds_reply_info rinfo; - struct dentry *dentry; - int frommds; - struct ceph_inode_cap *cap; - int err; - - dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias); - - dout(5, "open inode %p dentry %p name '%s' flags %d\n", inode, dentry, dentry->d_name.name, flags); - pathbase = inode->i_sb->s_root->d_inode->i_ino; - pathlen = get_dentry_path(dentry, path, inode->i_sb->s_root); - - req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_OPEN, pathbase, path, 0, 0); - if (IS_ERR(req)) - return ERR_PTR(PTR_ERR(req)); - rhead = req->front.iov_base; - rhead->args.open.flags = cpu_to_le32(flags); - if ((err = ceph_mdsc_do_request(mdsc, req, &rinfo, -1)) < 0) - return ERR_PTR(err); - - dout(10, "open got and parsed result\n"); - frommds = rinfo.reply->hdr.src.name.num; - cap = ceph_add_cap(inode, frommds, - le32_to_cpu(rinfo.head->file_caps), - le32_to_cpu(rinfo.head->file_caps_seq)); - return cap; -} - -static int ceph_dir_open(struct inode *inode, struct file *file) -{ - struct ceph_inode_info *ci = ceph_inode(inode); - struct ceph_inode_cap *cap; - struct ceph_file_info *fi; - - dout(5, "dir_open inode %p (%lu) file %p\n", inode, inode->i_ino, file); - cap = ceph_find_cap(inode, 0); - if (!cap) { - cap = ceph_open(inode, file, O_DIRECTORY); - if (IS_ERR(cap)) - return PTR_ERR(cap); - } - - fi = kzalloc(sizeof(*fi), GFP_KERNEL); - if (fi == NULL) - return -ENOMEM; - file->private_data = fi; - - atomic_inc(&ci->i_cap_count); - dout(5, "open_dir success\n"); - return 0; -} /* * build fpos from fragment id and offset within that fragment. @@ -195,26 +136,12 @@ nextfrag: return 0; } -int ceph_dir_release(struct inode *inode, struct file *filp) -{ - struct ceph_inode_info *ci = ceph_inode(inode); - struct ceph_file_info *fi = filp->private_data; - - dout(5, "dir_release inode %p filp %p\n", inode, filp); - atomic_dec(&ci->i_cap_count); - - if (fi->rinfo.reply) - ceph_mdsc_destroy_reply_info(&fi->rinfo); - kfree(fi); - - return 0; -} const struct file_operations ceph_dir_fops = { .read = generic_read_dir, .readdir = ceph_dir_readdir, - .open = ceph_dir_open, - .release = ceph_dir_release, + .open = ceph_open, + .release = ceph_release, }; @@ -233,7 +160,7 @@ static struct dentry *ceph_dir_lookup(struct inode *dir, struct dentry *dentry, ino_t ino; dout(5, "dir_lookup inode %p dentry %p '%s'\n", dir, dentry, dentry->d_name.name); - pathlen = get_dentry_path(dentry, path, dir->i_sb->s_root); + pathlen = ceph_get_dentry_path(dentry, path, dir->i_sb->s_root); /* stat mds */ req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_STAT, @@ -269,7 +196,7 @@ static int ceph_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) int err; dout(5, "dir_mkdir dir %p dentry %p mode %d\n", dir, dentry, mode); - pathlen = get_dentry_path(dentry, path, dir->i_sb->s_root); + pathlen = ceph_get_dentry_path(dentry, path, dir->i_sb->s_root); req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_MKDIR, dir->i_sb->s_root->d_inode->i_ino, path, 0, 0); @@ -302,7 +229,7 @@ static int ceph_dir_unlink(struct inode *dir, struct dentry *dentry) int op = ((dentry->d_inode->i_mode & S_IFMT) == S_IFDIR) ? CEPH_MDS_OP_RMDIR:CEPH_MDS_OP_UNLINK; dout(5, "dir_unlink/rmdir dir %p dentry %p inode %p\n", dir, dentry, inode); - pathlen = get_dentry_path(dentry, path, dir->i_sb->s_root); + pathlen = ceph_get_dentry_path(dentry, path, dir->i_sb->s_root); req = ceph_mdsc_create_request(mdsc, op, dir->i_sb->s_root->d_inode->i_ino, path, 0, 0); @@ -333,8 +260,8 @@ static int ceph_dir_rename(struct inode *old_dir, struct dentry *old_dentry, dout(5, "dir_newname dir %p dentry %p to dir %p dentry %p\n", old_dir, old_dentry, new_dir, new_dentry); - oldpathlen = get_dentry_path(old_dentry, oldpath, root); - newpathlen = get_dentry_path(new_dentry, newpath, root); + oldpathlen = ceph_get_dentry_path(old_dentry, oldpath, root); + newpathlen = ceph_get_dentry_path(new_dentry, newpath, root); req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_RENAME, root->d_inode->i_ino, oldpath, diff --git a/src/kernel/file.c b/src/kernel/file.c index 31f44c54ca6c2..297ec9fe41d10 100644 --- a/src/kernel/file.c +++ b/src/kernel/file.c @@ -1,30 +1,86 @@ +int ceph_debug_file = 50; +#define DOUT_VAR ceph_debug_file +#define DOUT_PREFIX "file: " #include "super.h" -/* -static ssize_t -ceph_file_read(struct file *filp, char __user * data, size_t count, - loff_t * offset) +#include "mds_client.h" + +struct ceph_inode_cap *ceph_do_open(struct inode *inode, struct file *file) { -} + int flags = file->f_flags; + struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc; + ceph_ino_t pathbase; + char path[PATH_MAX]; + int pathlen; + struct ceph_msg *req; + struct ceph_mds_request_head *rhead; + struct ceph_mds_reply_info rinfo; + struct dentry *dentry; + int frommds; + struct ceph_inode_cap *cap; + int err; + dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias); -static ssize_t -ceph_file_write(struct file *filp, const char __user * data, - size_t count, loff_t * offset) -{ -} + dout(5, "open inode %p dentry %p name '%s' flags %d\n", inode, dentry, dentry->d_name.name, flags); + pathbase = inode->i_sb->s_root->d_inode->i_ino; + pathlen = ceph_get_dentry_path(dentry, path, inode->i_sb->s_root); + req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_OPEN, pathbase, path, 0, 0); + if (IS_ERR(req)) + return ERR_PTR(PTR_ERR(req)); + rhead = req->front.iov_base; + rhead->args.open.flags = cpu_to_le32(flags); + if ((err = ceph_mdsc_do_request(mdsc, req, &rinfo, -1)) < 0) + return ERR_PTR(err); + + dout(10, "open got and parsed result\n"); + frommds = rinfo.reply->hdr.src.name.num; + cap = ceph_add_cap(inode, frommds, + le32_to_cpu(rinfo.head->file_caps), + le32_to_cpu(rinfo.head->file_caps_seq)); + return cap; +} -int ceph_file_open(struct inode *inode, struct file *file) +int ceph_open(struct inode *inode, struct file *file) { -} + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_inode_cap *cap; + struct ceph_file_info *fi; + dout(5, "dir_open inode %p (%lu) file %p\n", inode, inode->i_ino, file); + cap = ceph_find_cap(inode, 0); + if (!cap) { + cap = ceph_do_open(inode, file); + if (IS_ERR(cap)) + return PTR_ERR(cap); + } + + fi = kzalloc(sizeof(*fi), GFP_KERNEL); + if (fi == NULL) + return -ENOMEM; + file->private_data = fi; -static int ceph_file_lock(struct file *filp, int cmd, struct file_lock *fl) + atomic_inc(&ci->i_cap_count); + dout(5, "open_dir success\n"); + return 0; +} + +int ceph_release(struct inode *inode, struct file *filp) { + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_file_info *fi = filp->private_data; + + dout(5, "dir_release inode %p filp %p\n", inode, filp); + atomic_dec(&ci->i_cap_count); + + if (fi->rinfo.reply) + ceph_mdsc_destroy_reply_info(&fi->rinfo); + kfree(fi); + + return 0; } -*/ const struct inode_operations ceph_file_iops = { /* .getattr = ceph_vfs_getattr, @@ -33,6 +89,8 @@ const struct inode_operations ceph_file_iops = { }; const struct file_operations ceph_file_fops = { + .open = ceph_open, + .release = ceph_release, /* .llseek = generic_file_llseek, .read = ceph_file_read, .write = ceph_file_write, diff --git a/src/kernel/osd_client.c b/src/kernel/osd_client.c index 08d30715e5bcc..68c5a73ae68ef 100644 --- a/src/kernel/osd_client.c +++ b/src/kernel/osd_client.c @@ -109,12 +109,6 @@ bad: -void ceph_osdc_handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg) -{ - dout(5, "handle_reply\n"); -} - - /* * requests */ @@ -220,6 +214,41 @@ static void unregister_request(struct ceph_osd_client *osdc, put_request(req); } +/* + * handle osd op reply + */ +void ceph_osdc_handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg) +{ + struct ceph_osd_reply_head *rhead = msg->front.iov_base; + struct ceph_osd_request *req; + ceph_tid_t tid; + + dout(10, "handle_reply %p tid %llu\n", msg, le64_to_cpu(rhead->tid)); + + /* lookup */ + tid = le64_to_cpu(rhead->tid); + spin_lock(&osdc->lock); + req = radix_tree_lookup(&osdc->request_tree, tid); + if (req == NULL) { + dout(10, "handle_reply tid %llu dne\n", tid); + spin_unlock(&osdc->lock); + return; + } + get_request(req); + + if (req->r_reply == NULL) { + dout(10, "handle_reply tid %llu saving reply\n", tid); + ceph_msg_get(msg); + req->r_reply = msg; + } else { + dout(10, "handle_reply tid %llu already had a reply\n", tid); + } + dout(10, "handle_reply tid %llu flags %d |= %d\n", tid, req->r_flags, rhead->flags); + req->r_flags |= rhead->flags; + spin_unlock(&osdc->lock); + complete(&req->r_completion); + put_request(req); +} /* diff --git a/src/kernel/osd_client.h b/src/kernel/osd_client.h index 51c133d5e45e4..3ca8ebbf0f340 100644 --- a/src/kernel/osd_client.h +++ b/src/kernel/osd_client.h @@ -58,5 +58,10 @@ extern void ceph_osdc_handle_reply(struct ceph_osd_client *osdc, struct ceph_msg extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg); extern int ceph_osdc_prepare_pages(void *p, struct ceph_msg *m, int want); +extern int ceph_osdc_readpage(struct ceph_osd_client *osdc, ceph_ino_t ino, + struct ceph_file_layout *layout, + loff_t off, loff_t len, + struct page *page); + #endif diff --git a/src/kernel/super.h b/src/kernel/super.h index 8a7c647f26277..55d9a5763469f 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -140,9 +140,13 @@ extern const struct address_space_operations ceph_aops; extern const struct inode_operations ceph_file_iops; extern const struct file_operations ceph_file_fops; extern const struct address_space_operations ceph_aops; +extern int ceph_open(struct inode *inode, struct file *file); +extern int ceph_release(struct inode *inode, struct file *filp); /* dir.c */ extern const struct inode_operations ceph_dir_iops; extern const struct file_operations ceph_dir_fops; +extern int ceph_get_dentry_path(struct dentry *dn, char *buf, struct dentry *base); /* move me */ + #endif /* _FS_CEPH_CEPH_H */ -- 2.39.5