From 3510f75d5d609ebc802afafaa160ca3f08e59d38 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 6 Mar 2008 10:37:36 -0800 Subject: [PATCH] client: caps cleanup, almost --- src/TODO | 1 - src/kernel/file.c | 1 - src/kernel/inode.c | 177 +++++++++++++++++++--------------------- src/kernel/mds_client.c | 6 +- src/kernel/super.c | 9 +- src/kernel/super.h | 17 ++-- 6 files changed, 94 insertions(+), 117 deletions(-) diff --git a/src/TODO b/src/TODO index c7aab0fde9e94..a10c057daebd4 100644 --- a/src/TODO +++ b/src/TODO @@ -12,7 +12,6 @@ code cleanup kernel client - some bugs - - open path needs to call fill_trace/fill_inode such that ci->i_max_size gets filled in - caps embedded list_head's don't play nice with realloc() on cap array in ceph_add_cap() - cleanup - roll open_root_inode into fill_trace? diff --git a/src/kernel/file.c b/src/kernel/file.c index a86d0c715835c..70edaaa23a328 100644 --- a/src/kernel/file.c +++ b/src/kernel/file.c @@ -193,7 +193,6 @@ int ceph_release(struct inode *inode, struct file *file) int wanted; dout(5, "release inode %p file %p\n", inode, file); - atomic_dec(&ci->i_cap_count); /* * FIXME mystery: why is file->f_flags now different than diff --git a/src/kernel/inode.c b/src/kernel/inode.c index 7d349b882bc3c..ce47bc693c754 100644 --- a/src/kernel/inode.c +++ b/src/kernel/inode.c @@ -260,144 +260,133 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_reply_info *prinfo, struct ceph_inode_cap *ceph_find_cap(struct inode *inode, int want) { struct ceph_inode_info *ci = ceph_inode(inode); - - int i; - for (i=0; ii_nr_caps; i++) - if ((ci->i_caps[i].caps & want) == want) { - dout(40, "find_cap found i=%d cap %d want %d\n", i, ci->i_caps[i].caps, want); - return &ci->i_caps[i]; + struct ceph_inode_cap *cap; + struct list_head *p; + + list_for_each(p, &ci->i_caps) { + cap = list_entry(p, struct ceph_inode_cap, ci_caps); + if ((cap->caps & want) == want) { + dout(40, "find_cap found %p caps %d want %d\n", cap, + cap->caps, want); + return cap; } + } return 0; } static struct ceph_inode_cap *get_cap_for_mds(struct inode *inode, int mds) { struct ceph_inode_info *ci = ceph_inode(inode); - int i; - for (i=0; ii_nr_caps; i++) - if (ci->i_caps[i].mds == mds) - return &ci->i_caps[i]; + struct ceph_inode_cap *cap; + struct list_head *p; + + list_for_each(p, &ci->i_caps) { + cap = list_entry(p, struct ceph_inode_cap, ci_caps); + if (cap->mds == mds) + return cap; + } return 0; } -struct ceph_inode_cap *ceph_add_cap(struct inode *inode, struct ceph_mds_session *session, u32 cap, u32 seq) +struct ceph_inode_cap *ceph_add_cap(struct inode *inode, struct ceph_mds_session *session, u32 caps, u32 seq) { int mds = session->s_mds; struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_inode_cap *cap; int i; - dout(10, "ceph_add_cap on %p mds%d cap %d seq %d\n", inode, session->s_mds, cap, seq); - - for (i=0; ii_nr_caps; i++) - if (ci->i_caps[i].mds == mds) break; - if (i == ci->i_nr_caps) { - for (i=0; ii_nr_caps; i++) - if (ci->i_caps[i].mds < 0) break; - if (i == ci->i_max_caps) { - /* realloc */ - void *o = ci->i_caps; - ci->i_caps = kmalloc(ci->i_max_caps*2*sizeof(*ci->i_caps), GFP_KERNEL); - if (ci->i_caps == NULL) { - ci->i_caps = o; - derr(0, "add_cap enomem\n"); - return ERR_PTR(-ENOMEM); + dout(10, "ceph_add_cap on %p mds%d cap %d seq %d\n", inode, session->s_mds, caps, seq); + cap = get_cap_for_mds(inode, mds); + if (!cap) { + for (i=0; ii_static_caps[i].mds == -1) { + cap = &ci->i_static_caps[i]; + break; } - memcpy(ci->i_caps, o, ci->i_nr_caps*sizeof(*ci->i_caps)); - if (o != ci->i_caps_static) - kfree(o); - ci->i_max_caps *= 2; - } - if (i == ci->i_nr_caps) - ci->i_nr_caps++; - - ci->i_caps[i].ci = ci; - ci->i_caps[i].caps = 0; - ci->i_caps[i].mds = mds; - ci->i_caps[i].seq = 0; - ci->i_caps[i].flags = 0; + if (!cap) + cap = kmalloc(sizeof(*cap), GFP_KERNEL); + if (cap == 0) + return ERR_PTR(-ENOMEM); + + cap->caps = 0; + cap->mds = mds; + cap->seq = 0; + cap->flags = 0; + + if (list_empty(&ci->i_caps)) + igrab(inode); + cap->ci = ci; + list_add(&cap->ci_caps, &ci->i_caps); - ci->i_caps[i].session = session; + cap->session = session; spin_lock(&session->s_cap_lock); - list_add(&ci->i_caps[i].session_caps, &session->s_caps); + list_add(&cap->session_caps, &session->s_caps); session->s_nr_caps++; spin_unlock(&session->s_cap_lock); - - if (ci->i_nr_caps == 1) { - dout(10, "igrab on %p\n", inode); - igrab(inode); - } } dout(10, "add_cap inode %p (%llx) got cap %d %xh now %xh seq %d from %d\n", - inode, ceph_ino(inode), i, cap, cap|ci->i_caps[i].caps, seq, mds); - ci->i_caps[i].caps |= cap; - ci->i_caps[i].seq = seq; - return &ci->i_caps[i]; + inode, ceph_ino(inode), i, caps, caps|cap->caps, seq, mds); + cap->caps |= caps; + cap->seq = seq; + return cap; } -int ceph_get_caps(struct ceph_inode_info *ci) +int ceph_caps_issued(struct ceph_inode_info *ci) { - int i; int have = 0; - for (i=0; ii_nr_caps; i++) - have |= ci->i_caps[i].caps; + struct ceph_inode_cap *cap; + struct list_head *p; + + list_for_each(p, &ci->i_caps) { + cap = list_entry(p, struct ceph_inode_cap, ci_caps); + have |= cap->caps; + } return have; } -void __remove_cap(struct ceph_inode_cap *cap) +void __ceph_remove_cap(struct ceph_inode_cap *cap) { - /* remove from session list */ struct ceph_mds_session *session = cap->session; + struct ceph_inode_info *ci = cap->ci; + + dout(10, "__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode); + + /* remove from session list */ spin_lock(&session->s_cap_lock); list_del(&cap->session_caps); session->s_nr_caps--; cap->session = 0; spin_unlock(&session->s_cap_lock); -} -void ceph_remove_cap(struct ceph_inode_info *ci, int mds) -{ - int i; - int was = ci->i_nr_caps; - dout(10, "remove_cap on %p for mds%d\n", &ci->vfs_inode, mds); - for (i=0; ii_nr_caps; i++) { - if (ci->i_caps[i].mds != mds) - continue; - dout(10, "remove_cap removing %p\n", &ci->i_caps[i]); - __remove_cap(&ci->i_caps[i]); /* remove from list */ - if (i == ci->i_nr_caps-1) { - do { - ci->i_nr_caps--; - } while (ci->i_nr_caps && - ci->i_caps[ci->i_nr_caps-1].mds < 0); - break; - } - ci->i_caps[i].mds = -1; - ci->i_caps[i].caps = 0; - ci->i_caps[i].seq = 0; - } - if (was > 0 && ci->i_nr_caps == 0) { - dout(10, "iput on %p\n", &ci->vfs_inode); + /* remove from inode list */ + list_del(&cap->ci_caps); + if (list_empty(&ci->i_caps)) iput(&ci->vfs_inode); - } + cap->ci = 0; + + if (cap >= ci->i_static_caps && + cap < ci->i_static_caps + STATIC_CAPS) + cap->mds = -1; + else + kfree(cap); } +/*void ceph_remove_cap(struct ceph_inode_info *ci, int mds) +{ + struct ceph_inode_cap *cap = get_cap_for_mds(ci, mds); + if (cap) + __ceph_remove_cap(cap); + }*/ + void ceph_remove_caps(struct ceph_inode_info *ci) { - int i; - dout(10, "remove_caps on %p nr %d\n", &ci->vfs_inode, ci->i_nr_caps); - if (ci->i_nr_caps) { - for (i=0; ii_nr_caps; i++) - __remove_cap(&ci->i_caps[i]); - ci->i_nr_caps = 0; - if (ci->i_caps != ci->i_caps_static) { - kfree(ci->i_caps); - ci->i_caps = ci->i_caps_static; - ci->i_max_caps = STATIC_CAPS; - } - dout(10, "iput on %p\n", &ci->vfs_inode); - iput(&ci->vfs_inode); + struct ceph_inode_cap *cap; + dout(10, "remove_caps on %p\n", &ci->vfs_inode); + while (!list_empty(&ci->i_caps)) { + cap = list_entry(ci->i_caps.next, struct ceph_inode_cap, ci_caps); + __ceph_remove_cap(cap); } } diff --git a/src/kernel/mds_client.c b/src/kernel/mds_client.c index c4bf464452b9e..f3c25f4a10162 100644 --- a/src/kernel/mds_client.c +++ b/src/kernel/mds_client.c @@ -1232,12 +1232,14 @@ int ceph_mdsc_update_cap_wanted(struct ceph_inode_info *ci, int wanted) struct ceph_mds_client *mdsc = &client->mdsc; struct ceph_inode_cap *cap; struct ceph_mds_session *session; + struct list_head *p; + int i; dout(10, "update_cap_wanted %d -> %d\n", ci->i_cap_wanted, wanted); - for (i=0; ii_nr_caps; i++) { - cap = &ci->i_caps[i]; + list_for_each(p, &ci->i_caps) { + cap = list_entry(p, struct ceph_inode_cap, ci_caps); session = __get_session(mdsc, cap->mds); BUG_ON(!session); diff --git a/src/kernel/super.c b/src/kernel/super.c index 09d5f6dcb9e25..76d4e6bbc3bbe 100644 --- a/src/kernel/super.c +++ b/src/kernel/super.c @@ -114,11 +114,8 @@ static struct inode *ceph_alloc_inode(struct super_block *sb) ci->i_frag_map_nr = 0; ci->i_frag_map = ci->i_frag_map_static; - ci->i_nr_caps = 0; - ci->i_max_caps = STATIC_CAPS; - ci->i_caps = ci->i_caps_static; - atomic_set(&ci->i_cap_count, 0); - + for (i = 0; i < STATIC_CAPS; i++) + ci->i_static_caps[i].mds = -1; for (i = 0; i < 4; i++) ci->i_nr_by_mode[i] = 0; ci->i_cap_wanted = 0; @@ -139,8 +136,6 @@ static void ceph_destroy_inode(struct inode *inode) dout(30, "destroy_inode %p ino %lu=%llx\n", inode, inode->i_ino, ceph_ino(inode)); - if (ci->i_caps != ci->i_caps_static) - kfree(ci->i_caps); kfree(ci->i_symlink); kmem_cache_free(ceph_inode_cachep, ci); diff --git a/src/kernel/super.h b/src/kernel/super.h index 1ce3b887ccd1c..2b3210a818e2a 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -111,11 +111,12 @@ static inline struct ceph_client *ceph_client(struct super_block *sb) */ struct ceph_inode_cap { - int mds; + int mds; /* -1 if not used */ int caps; u64 seq; int flags; /* stale, etc.? */ struct ceph_inode_info *ci; + struct list_head ci_caps; /* per-ci caplist */ struct ceph_mds_session *session; struct list_head session_caps; /* per-session caplist */ }; @@ -144,10 +145,8 @@ struct ceph_inode_info { int i_frag_map_nr; struct ceph_inode_frag_map_item *i_frag_map, i_frag_map_static[1]; - int i_nr_caps, i_max_caps; - struct ceph_inode_cap *i_caps; - struct ceph_inode_cap i_caps_static[STATIC_CAPS]; - atomic_t i_cap_count; /* ref count (e.g. from file*) */ + struct list_head i_caps; + struct ceph_inode_cap i_static_caps[STATIC_CAPS]; int i_nr_by_mode[4]; int i_cap_wanted; @@ -193,13 +192,7 @@ static inline u64 ceph_ino(struct inode *inode) /* * caps helpers */ -static inline int ceph_caps_issued(struct ceph_inode_info *ci) -{ - int i, issued = 0; - for (i = 0; i < ci->i_nr_caps; i++) - issued |= ci->i_caps[i].caps; - return issued; -} +extern int ceph_caps_issued(struct ceph_inode_info *ci); static inline int ceph_caps_wanted(struct ceph_inode_info *ci) { -- 2.39.5