From 3764e1cbcf740df1143a8f13370b2ec0c3659bb7 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 22 Jan 2008 11:32:43 -0800 Subject: [PATCH] refactor open a bit; initial pass at ceph_lookup_open --- src/kernel/dir.c | 10 ++- src/kernel/file.c | 147 ++++++++++++++++++++++++++++++++++++++------- src/kernel/super.h | 1 + 3 files changed, 135 insertions(+), 23 deletions(-) diff --git a/src/kernel/dir.c b/src/kernel/dir.c index f0a76a20eceea..4da456d5dff68 100644 --- a/src/kernel/dir.c +++ b/src/kernel/dir.c @@ -236,7 +236,7 @@ const struct file_operations ceph_dir_fops = { static struct dentry *ceph_dir_lookup(struct inode *dir, struct dentry *dentry, - struct nameidata *nameidata) + struct nameidata *nd) { struct ceph_client *client = dir->i_sb->s_fs_info; struct ceph_mds_client *mdsc = &client->mdsc; @@ -250,6 +250,14 @@ static struct dentry *ceph_dir_lookup(struct inode *dir, struct dentry *dentry, int found = 0; dout(5, "dir_lookup in dir %p dentry %p '%s'\n", dir, dentry, dentry->d_name.name); + + /* open(|create) intent? */ + /* + if (nd->flags & LOOKUP_OPEN) + return ceph_lookup_open(dir, dentry, nd); + */ + + /* regular lookup */ path = ceph_build_dentry_path(dentry, &pathlen); if (IS_ERR(path)) return ERR_PTR(PTR_ERR(path)); diff --git a/src/kernel/file.c b/src/kernel/file.c index b377fac1fa19e..66c857592f1fe 100644 --- a/src/kernel/file.c +++ b/src/kernel/file.c @@ -6,20 +6,16 @@ int ceph_debug_file = 50; #include "mds_client.h" -struct ceph_inode_cap *ceph_do_open(struct inode *inode, struct file *file) +int do_open_request(struct inode *inode, int flags, int create_mode, + struct ceph_mds_session **psession, struct ceph_mds_reply_info *rinfo) { - int flags = file->f_flags; struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc; ceph_ino_t pathbase; char *path; int pathlen; struct ceph_msg *req; struct ceph_mds_request_head *rhead; - struct ceph_mds_reply_info rinfo; - struct ceph_mds_session *session; struct dentry *dentry; - int frommds; - struct ceph_inode_cap *cap; int err; dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias); @@ -28,30 +24,47 @@ struct ceph_inode_cap *ceph_do_open(struct inode *inode, struct file *file) pathbase = inode->i_sb->s_root->d_inode->i_ino; path = ceph_build_dentry_path(dentry, &pathlen); if (IS_ERR(path)) - return ERR_PTR(PTR_ERR(path)); + return PTR_ERR(path); req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_OPEN, pathbase, path, 0, 0); kfree(path); if (IS_ERR(req)) - return ERR_PTR(PTR_ERR(req)); + return 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, &session)) < 0) - return ERR_PTR(err); - - dout(10, "open got and parsed result\n"); - frommds = rinfo.reply->hdr.src.name.num; + rhead->args.open.mode = cpu_to_le32(create_mode); + if ((err = ceph_mdsc_do_request(mdsc, req, rinfo, psession)) < 0) + return err; + return 0; +} + +int proc_open_reply(struct inode *inode, struct file *file, + struct ceph_mds_session *session, struct ceph_mds_reply_info *rinfo) +{ + struct ceph_inode_cap *cap; + struct ceph_file_info *cf; + cap = ceph_add_cap(inode, session, - le32_to_cpu(rinfo.head->file_caps), - le32_to_cpu(rinfo.head->file_caps_seq)); - ceph_mdsc_put_session(session); - return cap; + le32_to_cpu(rinfo->head->file_caps), + le32_to_cpu(rinfo->head->file_caps_seq)); + + if (file->f_flags & O_DIRECTORY) { + cf = kzalloc(sizeof(*cf), GFP_KERNEL); + if (cf == NULL) + return -ENOMEM; + file->private_data = cf; + } + + return 0; } int ceph_open(struct inode *inode, struct file *file) { struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_mds_reply_info rinfo; + struct ceph_mds_session *session; struct ceph_inode_cap *cap = 0; struct ceph_file_info *cf; + int err; int mode; int wanted; @@ -61,9 +74,13 @@ int ceph_open(struct inode *inode, struct file *file) cap = ceph_find_cap(inode, 0); */ if (!cap) { - cap = ceph_do_open(inode, file); - if (IS_ERR(cap)) - return PTR_ERR(cap); + err = do_open_request(inode, file->f_flags, 0, &session, &rinfo); + if (err < 0) + return err; + err = proc_open_reply(inode, file, session, &rinfo); + ceph_mdsc_put_session(session); + if (err < 0) + return err; } cf = kzalloc(sizeof(*cf), GFP_KERNEL); @@ -71,8 +88,6 @@ int ceph_open(struct inode *inode, struct file *file) return -ENOMEM; file->private_data = cf; - atomic_inc(&ci->i_cap_count); - mode = ceph_file_mode(file->f_flags); ci->i_nr_by_mode[mode]++; wanted = ceph_caps_wanted(ci); @@ -82,6 +97,94 @@ int ceph_open(struct inode *inode, struct file *file) return 0; } +#if 0 +int ceph_lookup_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) +{ + struct ceph_client *client = dir->i_sb->s_fs_info; + struct ceph_mds_client *mdsc = &client->mdsc; + char *path; + int pathlen; + struct ceph_msg *req; + struct ceph_mds_request_head *rhead; + struct ceph_mds_reply_info rinfo; + struct ceph_mds_session *session; + struct file *file = nd->intent.open.file; + ino_t ino; + int found = 0; + + dout(5, "ceph_lookup_open in dir %p dentry %p '%s'\n", dir, dentry, dentry->d_name.name); + + /* do request */ + path = ceph_build_dentry_path(dentry, &pathlen); + if (IS_ERR(path)) + return PTR_ERR(path); + req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_OPEN, + dir->i_sb->s_root->d_inode->i_ino, path, 0, 0); + kfree(path); + if (IS_ERR(req)) + return PTR_ERR(req); + rhead = req->front.iov_base; + rhead->args.open.flags = cpu_to_le32(nd->intent.open.flags); + rhead->args.open.mode = cpu_to_le32(nd->intent.open.create_mode); + if ((err = ceph_mdsc_do_request(mdsc, req, &rinfo, &session)) < 0) + return err; + err = le32_to_cpu(rinfo.head->result); + dout(20, "ceph_lookup_open result=%d\n", err); + + /* if there was a previous inode associated with this dentry, now there isn't one */ + if (err == -ENOENT) + d_add(dentry, NULL); + if (err < 0) + goto out; + if (rinfo.trace_nr == 0) { + derr(0, "wtf, no trace from mds\n"); + err = -EIO; + goto out; + } + + /* create the inode */ + ino = le64_to_cpu(rinfo.trace_in[rinfo.trace_nr-1].in->ino); + dout(10, "got and parsed stat result, ino %lu\n", ino); + inode = ilookup(dir->i_sb, ino); + if (!inode) + inode = new_inode(dir->i_sb); + else + found++; + if (!inode) { + err = -EACCES; + goto out; + } + + if ((err = ceph_fill_inode(inode, rinfo.trace_in[rinfo.trace_nr-1].in)) < 0) + goto out; + d_add(dentry, inode); + + if (found) + iput(inode); + + /* do the open */ + cap = ceph_add_cap(inode, session, + le32_to_cpu(rinfo.head->file_caps), + le32_to_cpu(rinfo.head->file_caps_seq)); + + cf = kzalloc(sizeof(*cf), GFP_KERNEL); + if (cf == NULL) + return -ENOMEM; + file->private_data = cf; + + atomic_inc(&ci->i_cap_count); + + mode = ceph_file_mode(file->f_flags); + ci->i_nr_by_mode[mode]++; + wanted = ceph_caps_wanted(ci); + ci->i_cap_wanted |= wanted; /* FIXME this isn't quite right */ + +out: + ceph_mdsc_put_session(session); + return err; +} +#endif + int ceph_release(struct inode *inode, struct file *file) { struct ceph_inode_info *ci = ceph_inode(inode); diff --git a/src/kernel/super.h b/src/kernel/super.h index c42853f2d09e6..5db9497baa563 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -238,6 +238,7 @@ 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_lookup_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd); extern int ceph_release(struct inode *inode, struct file *filp); /* dir.c */ -- 2.39.5