]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: add dentry lru
authorYehuda Sadeh <yehuda@hq.newdream.net>
Tue, 31 Mar 2009 21:44:42 +0000 (14:44 -0700)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Tue, 31 Mar 2009 21:45:06 +0000 (14:45 -0700)
src/kernel/debugfs.c
src/kernel/dir.c
src/kernel/inode.c
src/kernel/mds_client.c
src/kernel/mds_client.h
src/kernel/super.h

index de664447cc6c5982caa4523a879f3d2d6b390705..5f811081131015db20751742409691b363e71683 100644 (file)
@@ -367,6 +367,26 @@ static int osdc_show(struct seq_file *s, void *p)
        return 0;
 }
 
+static int dentry_lru_show(struct seq_file *s, void *ptr)
+{
+       struct ceph_client *client = s->private;
+       struct ceph_mds_client *mdsc = &client->mdsc;
+       struct list_head *p;
+       struct ceph_dentry_info *di;
+
+       spin_lock(&mdsc->dentry_lru_lock);
+       list_for_each(p, &mdsc->dentry_lru) {
+               struct dentry *dentry;
+               di = list_entry(p, struct ceph_dentry_info, lru);
+               dentry = di->dentry;
+               seq_printf(s, "%p %p\t%.*s\n",
+                       di, dentry, dentry->d_name.len, dentry->d_name.name);
+       }
+       spin_unlock(&mdsc->dentry_lru_lock);
+
+       return 0;
+}
+
 #define DEFINE_SHOW_FUNC(name)                                                 \
 static int name##_open(struct inode *inode, struct file *file)         \
 {                                                                      \
@@ -393,6 +413,7 @@ DEFINE_SHOW_FUNC(osdmap_show)
 DEFINE_SHOW_FUNC(monc_show)
 DEFINE_SHOW_FUNC(mdsc_show)
 DEFINE_SHOW_FUNC(osdc_show)
+DEFINE_SHOW_FUNC(dentry_lru_show)
 
 #ifdef CONFIG_CEPH_BOOKKEEPER
 static int debugfs_bookkeeper_set(void *data, u64 val)
@@ -545,6 +566,14 @@ int ceph_debugfs_client_init(struct ceph_client *client)
        if (!client->debugfs_osdmap)
                goto out;
 
+       client->debugfs_dentry_lru = debugfs_create_file("dentry_lru",
+                                       0600,
+                                       client->debugfs_dir,
+                                       client,
+                                       &dentry_lru_show_fops);
+       if (!client->debugfs_osdmap)
+               goto out;
+
        return 0;
 
 out:
@@ -557,6 +586,7 @@ void ceph_debugfs_client_cleanup(struct ceph_client *client)
        debugfs_remove(client->monc.debugfs_file);
        debugfs_remove(client->mdsc.debugfs_file);
        debugfs_remove(client->osdc.debugfs_file);
+       debugfs_remove(client->debugfs_dentry_lru);
        debugfs_remove(client->debugfs_monmap);
        debugfs_remove(client->debugfs_mdsmap);
        debugfs_remove(client->debugfs_osdmap);
index c6d29f5e92a4abc415a344e9cf7d518dbe87c78e..d70564b8fbfdbf64ffd65026079713af1723c89a 100644 (file)
@@ -617,7 +617,7 @@ static int dentry_lease_is_valid(struct dentry *dentry)
 
        spin_lock(&dentry->d_lock);
        di = ceph_dentry(dentry);
-       if (di) {
+       if (di && di->lease_session) {
                s = di->lease_session;
                spin_lock(&s->s_cap_lock);
                gen = s->s_cap_gen;
@@ -683,20 +683,23 @@ static int ceph_dentry_revalidate(struct dentry *dentry, struct nameidata *nd)
        if (ceph_snap(dir) != CEPH_NOSNAP) {
                dout(10, "d_revalidate %p '%.*s' inode %p is SNAPPED\n", dentry,
                     dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
-               return 1;
+               goto out_touch;
        }
 
        if (dentry_lease_is_valid(dentry))
-               return 1;
+               goto out_touch;
 
        if (dir_lease_is_valid(dir, dentry))
-               return 1;
+               goto out_touch;
 
        dout(20, "dentry_revalidate %p invalid, clearing %p complete\n",
             dentry, dir);
        ceph_i_clear(dir, CEPH_I_COMPLETE|CEPH_I_READDIR);
        d_drop(dentry);
        return 0;
+out_touch:
+       ceph_dentry_lru_touch(dentry);
+       return 1;
 }
 
 static void ceph_dentry_release(struct dentry *dentry)
@@ -705,7 +708,9 @@ static void ceph_dentry_release(struct dentry *dentry)
        struct inode *parent_inode = dentry->d_parent->d_inode;
 
        if (di) {
-               ceph_put_mds_session(di->lease_session);
+               ceph_dentry_lru_del(dentry);
+               if (di->lease_session)
+                       ceph_put_mds_session(di->lease_session);
                kfree(di);
                dentry->d_fsdata = NULL;
        }
@@ -824,6 +829,49 @@ out:
        return ret;
 }
 
+void ceph_dentry_lru_add(struct dentry *dn)
+{
+       struct ceph_dentry_info *di = ceph_dentry(dn);
+       struct ceph_mds_client *mdsc;
+       dout(30, "dentry_lru_add %p %p\t%.*s\n",
+                       di, dn, dn->d_name.len, dn->d_name.name);
+
+       if (di) {
+               mdsc = &ceph_client(dn->d_sb)->mdsc;
+               spin_lock(&mdsc->dentry_lru_lock);
+               list_add_tail(&di->lru, &mdsc->dentry_lru);
+               mdsc->num_dentry++;
+               spin_unlock(&mdsc->dentry_lru_lock);
+       }
+}
+
+void ceph_dentry_lru_touch(struct dentry *dn)
+{
+       struct ceph_dentry_info *di = ceph_dentry(dn);
+       struct ceph_mds_client *mdsc;
+
+       if (di) {
+               mdsc = &ceph_client(dn->d_sb)->mdsc;
+               spin_lock(&mdsc->dentry_lru_lock);
+               list_move_tail(&di->lru, &mdsc->dentry_lru);
+               spin_unlock(&mdsc->dentry_lru_lock);
+       }
+}
+
+void ceph_dentry_lru_del(struct dentry *dn)
+{
+       struct ceph_dentry_info *di = ceph_dentry(dn);
+       struct ceph_mds_client *mdsc;
+
+       if (di) {
+               mdsc = &ceph_client(dn->d_sb)->mdsc;
+               spin_lock(&mdsc->dentry_lru_lock);
+               list_del_init(&di->lru);
+               mdsc->num_dentry--;
+               spin_unlock(&mdsc->dentry_lru_lock);
+       }
+}
+
 const struct file_operations ceph_dir_fops = {
        .read = ceph_read_dir,
        .readdir = ceph_readdir,
index ce5e770840b197fa045949b96b005c14fc57d425..1eba5000a2542da0b7289a7fefd5fd6260b39ac5 100644 (file)
@@ -647,6 +647,32 @@ out:
        return err;
 }
 
+static int __init_ceph_dentry(struct dentry *dentry, int locked)
+{
+       struct ceph_dentry_info *di;
+
+       if (locked)
+               spin_unlock(&dentry->d_lock);
+       di = kmalloc(sizeof(struct ceph_dentry_info),
+                    GFP_NOFS);
+
+       if (locked)
+               spin_lock(&dentry->d_lock);
+       if (!di)
+               return -ENOMEM;          /* oh well */
+
+       if (dentry->d_fsdata) {
+               kfree(di);   /* lost a race! */
+               return 0;
+       }
+       dentry->d_fsdata = di;
+       di->dentry = dentry;
+       di->lease_session = NULL;
+       ceph_dentry_lru_add(dentry);
+
+       return 0;
+}
+
 /*
  * caller should hold session s_mutex.
  */
@@ -656,7 +682,6 @@ static void update_dentry_lease(struct dentry *dentry,
                                unsigned long from_time)
 {
        struct ceph_dentry_info *di;
-       int is_new = 0;
        long unsigned duration = le32_to_cpu(lease->duration_ms);
        long unsigned ttl = from_time + (duration * HZ) / 1000;
        long unsigned half_ttl = from_time + (duration * HZ / 2) / 1000;
@@ -688,23 +713,18 @@ static void update_dentry_lease(struct dentry *dentry,
                goto out_unlock;  /* we already have a newer lease. */
 
        if (!di) {
-               spin_unlock(&dentry->d_lock);
-               di = kmalloc(sizeof(struct ceph_dentry_info),
-                            GFP_NOFS);
+               __init_ceph_dentry(dentry, 1);
+               di = ceph_dentry(dentry);
                if (!di)
-                       return;          /* oh well */
-               spin_lock(&dentry->d_lock);
-               if (dentry->d_fsdata) {
-                       kfree(di);   /* lost a race! */
                        goto out_unlock;
-               }
-               dentry->d_fsdata = di;
-               di->lease_session = ceph_get_mds_session(session);
-               di->lease_gen = session->s_cap_gen;
-               di->lease_seq = le32_to_cpu(lease->seq);
-               is_new = 1;
-       } else if (di->lease_session != session)
+       } else if (di->lease_session != session) {
                goto out_unlock;
+       } else {
+               ceph_dentry_lru_touch(dentry);
+       }
+       di->lease_session = ceph_get_mds_session(session);
+       di->lease_gen = session->s_cap_gen;
+       di->lease_seq = le32_to_cpu(lease->seq);
        di->lease_renew_after = half_ttl;
        di->lease_renew_from = 0;
        dentry->d_time = ttl;
@@ -746,6 +766,7 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in,
                dput(dn);
                dn = realdn;
                ceph_init_dentry(dn);
+               __init_ceph_dentry(dn, 0);
        } else {
                dout(10, "dn %p attached to %p ino %llx.%llx\n",
                     dn, dn->d_inode, ceph_vinop(dn->d_inode));
index 7ac8eb7455a998a421d62d368b5352c5674e8c5e..e37ee62937674233852218d548747847cb300550 100644 (file)
@@ -1880,6 +1880,7 @@ void __ceph_mdsc_drop_dentry_lease(struct dentry *dentry)
        struct ceph_dentry_info *di = ceph_dentry(dentry);
 
        ceph_put_mds_session(di->lease_session);
+       ceph_dentry_lru_del(dentry);
        kfree(di);
        dentry->d_fsdata = NULL;
 }
@@ -2172,6 +2173,8 @@ void ceph_mdsc_init(struct ceph_mds_client *mdsc, struct ceph_client *client)
        spin_lock_init(&mdsc->cap_delay_lock);
        INIT_LIST_HEAD(&mdsc->snap_flush_list);
        spin_lock_init(&mdsc->snap_flush_lock);
+       spin_lock_init(&mdsc->dentry_lru_lock);
+       INIT_LIST_HEAD(&mdsc->dentry_lru);
 }
 
 /*
index 5104b907de11efd1a3b79ea367f86d22ff4dc04a..811607e7db5d1115e24aeca324d091d3f12b9902 100644 (file)
@@ -238,6 +238,10 @@ struct ceph_mds_client {
        spinlock_t       snap_flush_lock;
 
        struct dentry           *debugfs_file;
+
+       spinlock_t              dentry_lru_lock;
+       struct list_head        dentry_lru;
+       int                     num_dentry;
 };
 
 extern const char *ceph_mds_op_name(int op);
index d076203f1c32ecef23d93d5cfde600d35ac91f3b..5c95cca0ec98a2d1f2b87aee0a98c38038c915c6 100644 (file)
@@ -98,7 +98,7 @@ struct ceph_client {
        struct ceph_client_attr k_fsid, k_monmap, k_mdsmap, k_osdmap;
        struct dentry *debugfs_fsid, *debugfs_monmap;
        struct dentry *debugfs_mdsmap, *debugfs_osdmap;
-       struct dentry *debugfs_dir;
+       struct dentry *debugfs_dir, *debugfs_dentry_lru;
 
        struct mutex mount_mutex;       /* serialize mount attempts */
        struct ceph_mount_args mount_args;
@@ -376,6 +376,8 @@ struct ceph_dentry_info {
        u32 lease_gen;
        u32 lease_seq;
        unsigned long lease_renew_after, lease_renew_from;
+       struct list_head lru;
+       struct dentry *dentry;
 };
 
 static inline struct ceph_dentry_info *ceph_dentry(struct dentry *dentry)
@@ -784,6 +786,10 @@ extern struct dentry_operations ceph_dentry_ops, ceph_snap_dentry_ops,
 extern struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
                                         struct dentry *dentry, int err);
 
+extern void ceph_dentry_lru_add(struct dentry *dn);
+extern void ceph_dentry_lru_touch(struct dentry *dn);
+extern void ceph_dentry_lru_del(struct dentry *dn);
+
 /*
  * our d_ops vary depending on whether the inode is live,
  * snapshotted (read-only), or a virtual ".snap" directory.