]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: atomically handle fmode refcounts (untested)
authorSage Weil <sage@newdream.net>
Wed, 16 Apr 2008 14:38:36 +0000 (07:38 -0700)
committerSage Weil <sage@newdream.net>
Wed, 16 Apr 2008 14:38:36 +0000 (07:38 -0700)
src/TODO
src/kernel/dir.c
src/kernel/file.c
src/kernel/inode.c
src/kernel/mds_client.c
src/kernel/mds_client.h
src/kernel/super.h
src/start.sh

index 7f73178a678bdd80d7cef286c3a333c123b6439c..e5505b548146dbefa968e51db04b6289dc744a88 100644 (file)
--- a/src/TODO
+++ b/src/TODO
@@ -20,7 +20,6 @@ yehuda:
 - apply_truncate needs to truncate page cache, or something?
 
 kernel client
-- take file_mode refs on inode safely/atomically on open
 - fix session close seq interaction with mds (sessions don't currently close all the way)
 - file_data_version stuff!
 - deal with CAP_RDCACHE properly: invalidate cache pages?
index d5e5a90ca267149e71555526697a41502db3c130..ed79d37b500a16f0fda7a83c51f7dbdb91b2b282 100644 (file)
@@ -190,15 +190,6 @@ nextfrag:
        return 0;
 }
 
-
-const struct file_operations ceph_dir_fops = {
-       .read = generic_read_dir,
-       .readdir = ceph_dir_readdir,
-       .open = ceph_open,
-       .release = ceph_release,
-};
-
-
 int ceph_do_lookup(struct super_block *sb, struct dentry *dentry, int mask)
 {
        struct ceph_client *client = ceph_sb_to_client(sb);
@@ -538,6 +529,12 @@ static void ceph_dentry_release(struct dentry *dentry)
        }
 }
 
+const struct file_operations ceph_dir_fops = {
+       .read = generic_read_dir,
+       .readdir = ceph_dir_readdir,
+       .open = ceph_open,
+       .release = ceph_release,
+};
 
 const struct inode_operations ceph_dir_iops = {
        .lookup = ceph_dir_lookup,
index 59411729d7a53aa85021c2d90f3071c72d4cd9e1..a01678d7c84624f088f6a9edbad39753de9c86a8 100644 (file)
@@ -15,7 +15,7 @@ int ceph_debug_file = -1;
 /*
  * if err==0, caller is responsible for a put_session on *psession
  */
-struct ceph_mds_request *
+static struct ceph_mds_request *
 prepare_open_request(struct super_block *sb, struct dentry *dentry,
                     int flags, int create_mode)
 {
@@ -36,6 +36,7 @@ prepare_open_request(struct super_block *sb, struct dentry *dentry,
        req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_OPEN, pathbase, path,
                                       0, 0);
        req->r_expects_cap = 1;
+       req->r_fmode = ceph_file_mode(flags);
        kfree(path);
        if (!IS_ERR(req)) {
                rhead = req->r_request->front.iov_base;
@@ -45,20 +46,21 @@ prepare_open_request(struct super_block *sb, struct dentry *dentry,
        return req;
 }
 
-
-static int ceph_init_file(struct inode *inode, struct file *file, int flags)
+/*
+ * initialize private struct file data.
+ * if we fail, clean up by dropping fmode reference on the ceph_inode
+ */
+static int ceph_init_file(struct inode *inode, struct file *file, int fmode)
 {
-       struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_file_info *cf;
-       int fmode = ceph_file_mode(flags);
 
        cf = kzalloc(sizeof(*cf), GFP_KERNEL);
-       if (cf == NULL)
+       if (cf == NULL) {
+               ceph_put_fmode(ceph_inode(inode), fmode);  /* clean up */
                return -ENOMEM;
+       }
        file->private_data = cf;
-
        cf->mode = fmode;
-       ceph_get_mode(ci, fmode);
        return 0;
 }
 
@@ -94,10 +96,9 @@ int ceph_open(struct inode *inode, struct file *file)
        if ((__ceph_caps_issued(ci) & wantcaps) == wantcaps) {
                dout(10, "open fmode %d caps %d using existing on %p\n", 
                     fmode, wantcaps, inode);
+               __ceph_get_fmode(ci, fmode);
                spin_unlock(&inode->i_lock);
-               err = ceph_init_file(inode, file, flags);
-               BUG_ON(err); /* fixme */
-               return 0;
+               return ceph_init_file(inode, file, fmode);
        } 
        spin_unlock(&inode->i_lock);
        dout(10, "open mode %d, don't have caps %d\n", fmode, wantcaps);
@@ -106,8 +107,8 @@ int ceph_open(struct inode *inode, struct file *file)
        if (IS_ERR(req))
                return PTR_ERR(req);
        err = ceph_mdsc_do_request(mdsc, req);
-       if (err == 0) 
-               err = ceph_init_file(inode, file, flags);
+       if (err == 0)
+               err = ceph_init_file(inode, file, req->r_fmode);
        ceph_mdsc_put_request(req);
        dout(5, "ceph_open result=%d on %llx\n", err, ceph_ino(inode));
        return err;
@@ -146,7 +147,7 @@ int ceph_lookup_open(struct inode *dir, struct dentry *dentry,
        req->r_last_dentry = dentry; /* use this dentry in fill_trace */
        err = ceph_mdsc_do_request(mdsc, req);
        if (err == 0)
-               err = ceph_init_file(req->r_last_inode, file, flags);
+               err = ceph_init_file(req->r_last_inode, file, req->r_fmode);
        else if (err == -ENOENT) {
                ceph_init_dentry(dentry);
                d_add(dentry, NULL);
@@ -173,7 +174,7 @@ int ceph_release(struct inode *inode, struct file *file)
         * for now, store the open mode in ceph_file_info.
         */
 
-       ceph_put_mode(ci, cf->mode);
+       ceph_put_fmode(ci, cf->mode);
        if (cf->last_readdir)
                ceph_mdsc_put_request(cf->last_readdir);
        kfree(cf);
index 0c3905ddb42ef73746fd1d9773dcf53c02105bb9..065815aae45a900a1db05387db0dce24a71432f5 100644 (file)
@@ -651,6 +651,7 @@ static struct ceph_inode_cap *__get_cap_for_mds(struct inode *inode, int mds)
  */
 struct ceph_inode_cap *ceph_add_cap(struct inode *inode,
                                    struct ceph_mds_session *session, 
+                                   int fmode,
                                    u32 issued, u32 seq)
 {
        int mds = session->s_mds;
@@ -701,6 +702,7 @@ struct ceph_inode_cap *ceph_add_cap(struct inode *inode,
        cap->issued |= issued;
        cap->implemented |= issued;
        cap->seq = seq;
+       __ceph_get_fmode(ci, fmode);
        spin_unlock(&inode->i_lock);
        if (is_new)
                igrab(inode);
@@ -929,25 +931,14 @@ void ceph_inode_set_size(struct inode *inode, loff_t size)
                spin_unlock(&inode->i_lock);
 }
 
-/*
- * called on struct file init and release, to safely track which
- * capabilities we want due to currently open files
- */
-void ceph_get_mode(struct ceph_inode_info *ci, int mode)
-{
-       spin_lock(&ci->vfs_inode.i_lock);
-       ci->i_nr_by_mode[mode]++;
-       spin_unlock(&ci->vfs_inode.i_lock);
-}
-
-void ceph_put_mode(struct ceph_inode_info *ci, int mode)
+void ceph_put_fmode(struct ceph_inode_info *ci, int fmode)
 {
        int last = 0;
 
        spin_lock(&ci->vfs_inode.i_lock);
-       dout(20, "put_mode %p mode %d %d -> %d\n", &ci->vfs_inode, mode,
-            ci->i_nr_by_mode[mode], ci->i_nr_by_mode[mode]-1);
-       if (--ci->i_nr_by_mode[mode] == 0)
+       dout(20, "put_mode %p fmode %d %d -> %d\n", &ci->vfs_inode, fmode,
+            ci->i_nr_by_mode[fmode], ci->i_nr_by_mode[fmode]-1);
+       if (--ci->i_nr_by_mode[fmode] == 0)
                last++;
        spin_unlock(&ci->vfs_inode.i_lock);
 
index 3403b56689bbda91d7c0ca89a87e594099a98fc2..e1b95968e42883d4cf0c6302b31d57da98f9cabe 100644 (file)
@@ -406,6 +406,7 @@ static struct ceph_mds_request *new_request(struct ceph_msg *msg)
        req->r_last_dentry = 0;
        req->r_old_dentry = 0;
        req->r_expects_cap = 0;
+       req->r_fmode = 0;
        req->r_cap = 0;
        req->r_session = 0;
        req->r_num_mds = 0;
@@ -930,6 +931,7 @@ void ceph_mdsc_handle_reply(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
                        capseq = le32_to_cpu(rinfo->head->file_caps_seq);
                        req->r_cap = ceph_add_cap(req->r_last_inode,
                                                  req->r_session,
+                                                 req->r_fmode,
                                                  cap, capseq);
                        if (IS_ERR(req->r_cap)) {
                                err = PTR_ERR(req->r_cap);
index 1b57c5de1cc9f0c08a50d03b1e38d36cbdd5004b..50a83036338a5950ab947038f6e59b9e65747bb2 100644 (file)
@@ -76,6 +76,7 @@ struct ceph_mds_request {
        struct dentry    *r_last_dentry;
        struct dentry    *r_old_dentry;   /* for rename */
        int                     r_expects_cap;
+       int                     r_fmode;  /* if expecting cap */
        unsigned long           r_from_time;
        struct ceph_inode_cap  *r_cap;
        struct ceph_mds_session *r_session;
index 285efba53b4e6ff8d92bc33e4cafcc6ad3304bdd..2f45705e326cf9da25d131c5295b4a56d14cfec9 100644 (file)
@@ -326,6 +326,12 @@ static inline int ceph_file_mode(int flags)
        return FILE_MODE_RDWR;  /* not -EINVAL under Linux, strangely */
 }
 
+static inline void __ceph_get_fmode(struct ceph_inode_info *ci, int mode) 
+{
+       ci->i_nr_by_mode[mode]++;
+}
+extern void ceph_put_fmode(struct ceph_inode_info *ci, int mode);
+
 static inline struct ceph_client *ceph_inode_to_client(struct inode *inode)
 {
        return (struct ceph_client *)inode->i_sb->s_fs_info;
@@ -399,6 +405,7 @@ extern int ceph_dentry_lease_valid(struct dentry *dentry);
 
 extern struct ceph_inode_cap *ceph_add_cap(struct inode *inode,
                                           struct ceph_mds_session *session,
+                                          int fmode,
                                           u32 cap, u32 seq);
 extern void ceph_remove_cap(struct ceph_inode_cap *cap);
 extern void ceph_remove_all_caps(struct ceph_inode_info *ci);
@@ -414,8 +421,6 @@ extern void ceph_put_cap_refs(struct ceph_inode_info *ci, int had);
 extern void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr);
 extern void ceph_cap_delayed_work(struct work_struct *work);
 extern void ceph_check_caps(struct ceph_inode_info *ci, int was_last);
-extern void ceph_get_mode(struct ceph_inode_info *ci, int mode);
-extern void ceph_put_mode(struct ceph_inode_info *ci, int mode);
 extern void ceph_inode_set_size(struct inode *inode, loff_t size);
 extern void ceph_inode_writeback(struct work_struct *work);
 
index d6d25b509f77d388d416cc2edfa1a43886938b7d..dbfe81f390887ea9d557811a66f8ee088f3ad31c 100755 (executable)
@@ -43,7 +43,7 @@ do
 done
 
 # mds
-$CEPH_BIN/cmds $ARGS --debug_mds 20 --debug_ms 1
+$CEPH_BIN/cmds $ARGS --debug_mds 20 --debug_ms 20
 
 echo "started.  stop.sh to stop.  see out/* (e.g. 'tail -f out/????') for debug output."