mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-12 09:24:17 +00:00
ceph: delete stale dentry when last reference is dropped
introduce ceph_d_delete(), which checks if dentry has valid lease. Signed-off-by: "Yan, Zheng" <zyan@redhat.com> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
8d9c0906ac
commit
1e9c2eb681
4 changed files with 104 additions and 32 deletions
130
fs/ceph/dir.c
130
fs/ceph/dir.c
|
@ -1139,45 +1139,59 @@ void ceph_invalidate_dentry_lease(struct dentry *dentry)
|
||||||
* Check if dentry lease is valid. If not, delete the lease. Try to
|
* Check if dentry lease is valid. If not, delete the lease. Try to
|
||||||
* renew if the least is more than half up.
|
* renew if the least is more than half up.
|
||||||
*/
|
*/
|
||||||
|
static bool __dentry_lease_is_valid(struct ceph_dentry_info *di)
|
||||||
|
{
|
||||||
|
struct ceph_mds_session *session;
|
||||||
|
|
||||||
|
if (!di->lease_gen)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
session = di->lease_session;
|
||||||
|
if (session) {
|
||||||
|
u32 gen;
|
||||||
|
unsigned long ttl;
|
||||||
|
|
||||||
|
spin_lock(&session->s_gen_ttl_lock);
|
||||||
|
gen = session->s_cap_gen;
|
||||||
|
ttl = session->s_cap_ttl;
|
||||||
|
spin_unlock(&session->s_gen_ttl_lock);
|
||||||
|
|
||||||
|
if (di->lease_gen == gen &&
|
||||||
|
time_before(jiffies, ttl) &&
|
||||||
|
time_before(jiffies, di->time))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
di->lease_gen = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int dentry_lease_is_valid(struct dentry *dentry, unsigned int flags,
|
static int dentry_lease_is_valid(struct dentry *dentry, unsigned int flags,
|
||||||
struct inode *dir)
|
struct inode *dir)
|
||||||
{
|
{
|
||||||
struct ceph_dentry_info *di;
|
struct ceph_dentry_info *di;
|
||||||
struct ceph_mds_session *s;
|
|
||||||
int valid = 0;
|
|
||||||
u32 gen;
|
|
||||||
unsigned long ttl;
|
|
||||||
struct ceph_mds_session *session = NULL;
|
struct ceph_mds_session *session = NULL;
|
||||||
u32 seq = 0;
|
u32 seq = 0;
|
||||||
|
int valid = 0;
|
||||||
|
|
||||||
spin_lock(&dentry->d_lock);
|
spin_lock(&dentry->d_lock);
|
||||||
di = ceph_dentry(dentry);
|
di = ceph_dentry(dentry);
|
||||||
if (di && di->lease_session) {
|
if (di && __dentry_lease_is_valid(di)) {
|
||||||
s = di->lease_session;
|
valid = 1;
|
||||||
spin_lock(&s->s_gen_ttl_lock);
|
|
||||||
gen = s->s_cap_gen;
|
|
||||||
ttl = s->s_cap_ttl;
|
|
||||||
spin_unlock(&s->s_gen_ttl_lock);
|
|
||||||
|
|
||||||
if (di->lease_gen == gen &&
|
if (di->lease_renew_after &&
|
||||||
time_before(jiffies, di->time) &&
|
time_after(jiffies, di->lease_renew_after)) {
|
||||||
time_before(jiffies, ttl)) {
|
/*
|
||||||
valid = 1;
|
* We should renew. If we're in RCU walk mode
|
||||||
if (di->lease_renew_after &&
|
* though, we can't do that so just return
|
||||||
time_after(jiffies, di->lease_renew_after)) {
|
* -ECHILD.
|
||||||
/*
|
*/
|
||||||
* We should renew. If we're in RCU walk mode
|
if (flags & LOOKUP_RCU) {
|
||||||
* though, we can't do that so just return
|
valid = -ECHILD;
|
||||||
* -ECHILD.
|
} else {
|
||||||
*/
|
session = ceph_get_mds_session(di->lease_session);
|
||||||
if (flags & LOOKUP_RCU) {
|
seq = di->lease_seq;
|
||||||
valid = -ECHILD;
|
di->lease_renew_after = 0;
|
||||||
} else {
|
di->lease_renew_from = jiffies;
|
||||||
session = ceph_get_mds_session(s);
|
|
||||||
seq = di->lease_seq;
|
|
||||||
di->lease_renew_after = 0;
|
|
||||||
di->lease_renew_from = jiffies;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1192,6 +1206,38 @@ static int dentry_lease_is_valid(struct dentry *dentry, unsigned int flags,
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called under dentry->d_lock.
|
||||||
|
*/
|
||||||
|
static int __dir_lease_try_check(const struct dentry *dentry)
|
||||||
|
{
|
||||||
|
struct ceph_dentry_info *di = ceph_dentry(dentry);
|
||||||
|
struct inode *dir;
|
||||||
|
struct ceph_inode_info *ci;
|
||||||
|
int valid = 0;
|
||||||
|
|
||||||
|
if (!di->lease_shared_gen)
|
||||||
|
return 0;
|
||||||
|
if (IS_ROOT(dentry))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
dir = d_inode(dentry->d_parent);
|
||||||
|
ci = ceph_inode(dir);
|
||||||
|
|
||||||
|
if (spin_trylock(&ci->i_ceph_lock)) {
|
||||||
|
if (atomic_read(&ci->i_shared_gen) == di->lease_shared_gen &&
|
||||||
|
__ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 0))
|
||||||
|
valid = 1;
|
||||||
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
|
} else {
|
||||||
|
valid = -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid)
|
||||||
|
di->lease_shared_gen = 0;
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if directory-wide content lease/cap is valid.
|
* Check if directory-wide content lease/cap is valid.
|
||||||
*/
|
*/
|
||||||
|
@ -1308,6 +1354,31 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete unused dentry that doesn't have valid lease
|
||||||
|
*
|
||||||
|
* Called under dentry->d_lock.
|
||||||
|
*/
|
||||||
|
static int ceph_d_delete(const struct dentry *dentry)
|
||||||
|
{
|
||||||
|
struct ceph_dentry_info *di;
|
||||||
|
|
||||||
|
/* won't release caps */
|
||||||
|
if (d_really_is_negative(dentry))
|
||||||
|
return 0;
|
||||||
|
if (ceph_snap(d_inode(dentry)) != CEPH_NOSNAP)
|
||||||
|
return 0;
|
||||||
|
/* vaild lease? */
|
||||||
|
di = ceph_dentry(dentry);
|
||||||
|
if (di) {
|
||||||
|
if (__dentry_lease_is_valid(di))
|
||||||
|
return 0;
|
||||||
|
if (__dir_lease_try_check(dentry))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release our ceph_dentry_info.
|
* Release our ceph_dentry_info.
|
||||||
*/
|
*/
|
||||||
|
@ -1531,6 +1602,7 @@ const struct inode_operations ceph_snapdir_iops = {
|
||||||
|
|
||||||
const struct dentry_operations ceph_dentry_ops = {
|
const struct dentry_operations ceph_dentry_ops = {
|
||||||
.d_revalidate = ceph_d_revalidate,
|
.d_revalidate = ceph_d_revalidate,
|
||||||
|
.d_delete = ceph_d_delete,
|
||||||
.d_release = ceph_d_release,
|
.d_release = ceph_d_release,
|
||||||
.d_prune = ceph_d_prune,
|
.d_prune = ceph_d_prune,
|
||||||
.d_init = ceph_d_init,
|
.d_init = ceph_d_init,
|
||||||
|
|
|
@ -497,7 +497,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
|
||||||
ci->i_wrbuffer_ref = 0;
|
ci->i_wrbuffer_ref = 0;
|
||||||
ci->i_wrbuffer_ref_head = 0;
|
ci->i_wrbuffer_ref_head = 0;
|
||||||
atomic_set(&ci->i_filelock_ref, 0);
|
atomic_set(&ci->i_filelock_ref, 0);
|
||||||
atomic_set(&ci->i_shared_gen, 0);
|
atomic_set(&ci->i_shared_gen, 1);
|
||||||
ci->i_rdcache_gen = 0;
|
ci->i_rdcache_gen = 0;
|
||||||
ci->i_rdcache_revoking = 0;
|
ci->i_rdcache_revoking = 0;
|
||||||
|
|
||||||
|
|
|
@ -621,7 +621,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
|
||||||
ceph_con_init(&s->s_con, s, &mds_con_ops, &mdsc->fsc->client->msgr);
|
ceph_con_init(&s->s_con, s, &mds_con_ops, &mdsc->fsc->client->msgr);
|
||||||
|
|
||||||
spin_lock_init(&s->s_gen_ttl_lock);
|
spin_lock_init(&s->s_gen_ttl_lock);
|
||||||
s->s_cap_gen = 0;
|
s->s_cap_gen = 1;
|
||||||
s->s_cap_ttl = jiffies - 1;
|
s->s_cap_ttl = jiffies - 1;
|
||||||
|
|
||||||
spin_lock_init(&s->s_cap_lock);
|
spin_lock_init(&s->s_cap_lock);
|
||||||
|
|
|
@ -594,7 +594,7 @@ extern u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v,
|
||||||
struct ceph_inode_frag *pfrag,
|
struct ceph_inode_frag *pfrag,
|
||||||
int *found);
|
int *found);
|
||||||
|
|
||||||
static inline struct ceph_dentry_info *ceph_dentry(struct dentry *dentry)
|
static inline struct ceph_dentry_info *ceph_dentry(const struct dentry *dentry)
|
||||||
{
|
{
|
||||||
return (struct ceph_dentry_info *)dentry->d_fsdata;
|
return (struct ceph_dentry_info *)dentry->d_fsdata;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue