Skip to content

Commit 1e9c2eb

Browse files
ukernelidryomov
authored andcommitted
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" <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Ilya Dryomov <[email protected]>
1 parent 8d9c090 commit 1e9c2eb

File tree

4 files changed

+104
-32
lines changed

4 files changed

+104
-32
lines changed

fs/ceph/dir.c

Lines changed: 101 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,45 +1139,59 @@ void ceph_invalidate_dentry_lease(struct dentry *dentry)
11391139
* Check if dentry lease is valid. If not, delete the lease. Try to
11401140
* renew if the least is more than half up.
11411141
*/
1142+
static bool __dentry_lease_is_valid(struct ceph_dentry_info *di)
1143+
{
1144+
struct ceph_mds_session *session;
1145+
1146+
if (!di->lease_gen)
1147+
return false;
1148+
1149+
session = di->lease_session;
1150+
if (session) {
1151+
u32 gen;
1152+
unsigned long ttl;
1153+
1154+
spin_lock(&session->s_gen_ttl_lock);
1155+
gen = session->s_cap_gen;
1156+
ttl = session->s_cap_ttl;
1157+
spin_unlock(&session->s_gen_ttl_lock);
1158+
1159+
if (di->lease_gen == gen &&
1160+
time_before(jiffies, ttl) &&
1161+
time_before(jiffies, di->time))
1162+
return true;
1163+
}
1164+
di->lease_gen = 0;
1165+
return false;
1166+
}
1167+
11421168
static int dentry_lease_is_valid(struct dentry *dentry, unsigned int flags,
11431169
struct inode *dir)
11441170
{
11451171
struct ceph_dentry_info *di;
1146-
struct ceph_mds_session *s;
1147-
int valid = 0;
1148-
u32 gen;
1149-
unsigned long ttl;
11501172
struct ceph_mds_session *session = NULL;
11511173
u32 seq = 0;
1174+
int valid = 0;
11521175

11531176
spin_lock(&dentry->d_lock);
11541177
di = ceph_dentry(dentry);
1155-
if (di && di->lease_session) {
1156-
s = di->lease_session;
1157-
spin_lock(&s->s_gen_ttl_lock);
1158-
gen = s->s_cap_gen;
1159-
ttl = s->s_cap_ttl;
1160-
spin_unlock(&s->s_gen_ttl_lock);
1178+
if (di && __dentry_lease_is_valid(di)) {
1179+
valid = 1;
11611180

1162-
if (di->lease_gen == gen &&
1163-
time_before(jiffies, di->time) &&
1164-
time_before(jiffies, ttl)) {
1165-
valid = 1;
1166-
if (di->lease_renew_after &&
1167-
time_after(jiffies, di->lease_renew_after)) {
1168-
/*
1169-
* We should renew. If we're in RCU walk mode
1170-
* though, we can't do that so just return
1171-
* -ECHILD.
1172-
*/
1173-
if (flags & LOOKUP_RCU) {
1174-
valid = -ECHILD;
1175-
} else {
1176-
session = ceph_get_mds_session(s);
1177-
seq = di->lease_seq;
1178-
di->lease_renew_after = 0;
1179-
di->lease_renew_from = jiffies;
1180-
}
1181+
if (di->lease_renew_after &&
1182+
time_after(jiffies, di->lease_renew_after)) {
1183+
/*
1184+
* We should renew. If we're in RCU walk mode
1185+
* though, we can't do that so just return
1186+
* -ECHILD.
1187+
*/
1188+
if (flags & LOOKUP_RCU) {
1189+
valid = -ECHILD;
1190+
} else {
1191+
session = ceph_get_mds_session(di->lease_session);
1192+
seq = di->lease_seq;
1193+
di->lease_renew_after = 0;
1194+
di->lease_renew_from = jiffies;
11811195
}
11821196
}
11831197
}
@@ -1192,6 +1206,38 @@ static int dentry_lease_is_valid(struct dentry *dentry, unsigned int flags,
11921206
return valid;
11931207
}
11941208

1209+
/*
1210+
* Called under dentry->d_lock.
1211+
*/
1212+
static int __dir_lease_try_check(const struct dentry *dentry)
1213+
{
1214+
struct ceph_dentry_info *di = ceph_dentry(dentry);
1215+
struct inode *dir;
1216+
struct ceph_inode_info *ci;
1217+
int valid = 0;
1218+
1219+
if (!di->lease_shared_gen)
1220+
return 0;
1221+
if (IS_ROOT(dentry))
1222+
return 0;
1223+
1224+
dir = d_inode(dentry->d_parent);
1225+
ci = ceph_inode(dir);
1226+
1227+
if (spin_trylock(&ci->i_ceph_lock)) {
1228+
if (atomic_read(&ci->i_shared_gen) == di->lease_shared_gen &&
1229+
__ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 0))
1230+
valid = 1;
1231+
spin_unlock(&ci->i_ceph_lock);
1232+
} else {
1233+
valid = -EBUSY;
1234+
}
1235+
1236+
if (!valid)
1237+
di->lease_shared_gen = 0;
1238+
return valid;
1239+
}
1240+
11951241
/*
11961242
* Check if directory-wide content lease/cap is valid.
11971243
*/
@@ -1308,6 +1354,31 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
13081354
return valid;
13091355
}
13101356

1357+
/*
1358+
* Delete unused dentry that doesn't have valid lease
1359+
*
1360+
* Called under dentry->d_lock.
1361+
*/
1362+
static int ceph_d_delete(const struct dentry *dentry)
1363+
{
1364+
struct ceph_dentry_info *di;
1365+
1366+
/* won't release caps */
1367+
if (d_really_is_negative(dentry))
1368+
return 0;
1369+
if (ceph_snap(d_inode(dentry)) != CEPH_NOSNAP)
1370+
return 0;
1371+
/* vaild lease? */
1372+
di = ceph_dentry(dentry);
1373+
if (di) {
1374+
if (__dentry_lease_is_valid(di))
1375+
return 0;
1376+
if (__dir_lease_try_check(dentry))
1377+
return 0;
1378+
}
1379+
return 1;
1380+
}
1381+
13111382
/*
13121383
* Release our ceph_dentry_info.
13131384
*/
@@ -1531,6 +1602,7 @@ const struct inode_operations ceph_snapdir_iops = {
15311602

15321603
const struct dentry_operations ceph_dentry_ops = {
15331604
.d_revalidate = ceph_d_revalidate,
1605+
.d_delete = ceph_d_delete,
15341606
.d_release = ceph_d_release,
15351607
.d_prune = ceph_d_prune,
15361608
.d_init = ceph_d_init,

fs/ceph/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
497497
ci->i_wrbuffer_ref = 0;
498498
ci->i_wrbuffer_ref_head = 0;
499499
atomic_set(&ci->i_filelock_ref, 0);
500-
atomic_set(&ci->i_shared_gen, 0);
500+
atomic_set(&ci->i_shared_gen, 1);
501501
ci->i_rdcache_gen = 0;
502502
ci->i_rdcache_revoking = 0;
503503

fs/ceph/mds_client.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
621621
ceph_con_init(&s->s_con, s, &mds_con_ops, &mdsc->fsc->client->msgr);
622622

623623
spin_lock_init(&s->s_gen_ttl_lock);
624-
s->s_cap_gen = 0;
624+
s->s_cap_gen = 1;
625625
s->s_cap_ttl = jiffies - 1;
626626

627627
spin_lock_init(&s->s_cap_lock);

fs/ceph/super.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ extern u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v,
594594
struct ceph_inode_frag *pfrag,
595595
int *found);
596596

597-
static inline struct ceph_dentry_info *ceph_dentry(struct dentry *dentry)
597+
static inline struct ceph_dentry_info *ceph_dentry(const struct dentry *dentry)
598598
{
599599
return (struct ceph_dentry_info *)dentry->d_fsdata;
600600
}

0 commit comments

Comments
 (0)