]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
atomic lookup+open
authorYehuda Sadeh-Weinraub <yehuda@yehuda.infit.com>
Tue, 22 Jan 2008 21:23:45 +0000 (23:23 +0200)
committerYehuda Sadeh-Weinraub <yehuda@yehuda.infit.com>
Tue, 22 Jan 2008 21:23:45 +0000 (23:23 +0200)
src/kernel/dir.c
src/kernel/file.c

index 4da456d5dff684f2663752f8d3bf2ab9414ca31c..d5c5759331b78ee6210994e39af624544c7d9c18 100644 (file)
@@ -252,10 +252,8 @@ static struct dentry *ceph_dir_lookup(struct inode *dir, struct dentry *dentry,
        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);
index c87caec05a91eded705b49cd88cac8c5b2fe49f5..21ff61669c717b4b6570153e5d90b6505632067c 100644 (file)
@@ -9,24 +9,17 @@ int ceph_debug_file = 50;
 /*
  * if err==0, caller is responsible for a put_session on *psession
  */
-int do_open_request(struct dentry *dentry, int flags, int create_mode,
-                   struct ceph_mds_session **psession, struct ceph_mds_reply_info *rinfo)
+int do_open_request(struct super_block *sb, struct dentry *dentry, char *path, ceph_ino_t pathbase, int flags,
+                   int create_mode, struct ceph_mds_session **psession, struct ceph_mds_reply_info *rinfo)
 {
-       struct ceph_mds_client *mdsc = &ceph_inode_to_client(dentry->d_inode)->mdsc;
-       ceph_ino_t pathbase;
-       char *path;
-       int pathlen;
+       struct ceph_client *client = sb->s_fs_info;
+       struct ceph_mds_client *mdsc = &client->mdsc;
        struct ceph_msg *req;
        struct ceph_mds_request_head *rhead;
        int err;
 
        dout(5, "open dentry %p name '%s' flags %d\n", dentry, dentry->d_name.name, flags);
-       pathbase = dentry->d_inode->i_sb->s_root->d_inode->i_ino;
-       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, pathbase, path, 0, 0);
-       kfree(path);
        if (IS_ERR(req)) 
                return PTR_ERR(req);
        rhead = req->front.iov_base;
@@ -61,26 +54,61 @@ int proc_open_reply(struct inode *inode, struct file *file,
        return 0;
 }
 
-int ceph_open(struct inode *inode, struct file *file)
+static int ceph_open_init_private_data(struct inode *inode, struct file *file)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_file_info *cf;
+       int mode;
+       int wanted;
+
+       cf = kzalloc(sizeof(*cf), GFP_KERNEL);
+       if (cf == NULL)
+               return -ENOMEM;
+       file->private_data = cf;
+
+       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 */
+
+       return 0;
+}
+
+int ceph_open(struct inode *inode, struct file *file)
+{
        struct dentry *dentry;
+       char *path;
+       int pathlen;
+       ceph_ino_t pathbase;
        struct ceph_mds_reply_info rinfo;
        struct ceph_mds_session *session;
        struct ceph_inode_cap *cap = 0;
-       struct ceph_file_info *cf;
+       struct ceph_file_info *cf = file->private_data;
        int err;
-       int mode;
-       int wanted;
 
        dout(5, "ceph_open inode %p (%lu) file %p\n", inode, inode->i_ino, file);
+
+       if (cf) {
+               /* the file is already opened */
+               return 0;
+       }
+       
        /*
        if (file->f_flags == O_DIRECTORY && ... ) 
                cap = ceph_find_cap(inode, 0);
        */
        if (!cap) {
                dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);
-               err = do_open_request(dentry, file->f_flags, 0, &session, &rinfo);
+
+               pathbase = dentry->d_inode->i_sb->s_root->d_inode->i_ino;
+               path = ceph_build_dentry_path(dentry, &pathlen);
+               if (IS_ERR(path)) 
+                       return PTR_ERR(path);
+
+               err = do_open_request(inode->i_sb, dentry, path, pathbase, file->f_flags, 0, &session, &rinfo);
+
+               kfree(path);
+
                if (err < 0) 
                        return err;
                err = proc_open_reply(inode, file, session, &rinfo);
@@ -88,35 +116,48 @@ int ceph_open(struct inode *inode, struct file *file)
                if (err < 0)
                        return err;
        }
-       
-       cf = kzalloc(sizeof(*cf), GFP_KERNEL);
-       if (cf == NULL)
-               return -ENOMEM;
-       file->private_data = cf;
 
-       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 */
+       err = ceph_open_init_private_data(inode, file);
 
+       if (err < 0) {
+               return err;
+       }
+       
        dout(5, "ceph_open success, %lx\n", inode->i_ino);
        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;
        struct ceph_mds_reply_info rinfo;
        struct ceph_mds_session *session;
        struct file *file = nd->intent.open.file;
+       struct inode *inode;
+       struct dentry *dir_dentry;
+       char *path, *dirpath;
+       int pathlen;
+       ceph_ino_t pathbase;
        ino_t ino;
        int found = 0;
+       int err;
 
        dout(5, "ceph_lookup_open in dir %p dentry %p '%s'\n", dir, dentry, dentry->d_name.name);
 
-       err = do_open_request(dentry, nd->intent.open.flags, nd->intent.open.create_mode,
+       pathbase = dir->i_sb->s_root->d_inode->i_ino;
+
+       dir_dentry = list_entry(dir->i_dentry.next, struct dentry, d_alias);
+
+       pathbase = dir_dentry->d_inode->i_sb->s_root->d_inode->i_ino;
+       dirpath = ceph_build_dentry_path(dir_dentry, &pathlen);
+
+       path = kmalloc(pathlen+dentry->d_name.len+2, GFP_KERNEL);
+       strncpy(path, dirpath, pathlen);
+       kfree(dirpath);
+       path[pathlen]='/';
+       strncpy(&path[pathlen+1], dentry->d_name.name, dentry->d_name.len);
+       path[pathlen+dentry->d_name.len+1]=0;
+
+       err = do_open_request(dir->i_sb, dentry, path, pathbase, nd->intent.open.flags, nd->intent.open.create_mode,
                              &session, &rinfo);
        if (err < 0)
                return err;
@@ -156,18 +197,14 @@ int ceph_lookup_open(struct inode *dir, struct dentry *dentry, struct nameidata
                iput(inode);
 
        /* finish the open */
-       err = proc_open_reply(inode, file);
+       err = proc_open_reply(inode, file, session, &rinfo);
        if (err == 0) {
-               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 */
+               err = ceph_open_init_private_data(inode, file);
        }
 out:
        ceph_mdsc_put_session(session);
        return err;
 }
-#endif
 
 int ceph_release(struct inode *inode, struct file *file)
 {