@@ -1139,45 +1139,59 @@ void ceph_invalidate_dentry_lease(struct dentry *dentry)
1139
1139
* Check if dentry lease is valid. If not, delete the lease. Try to
1140
1140
* renew if the least is more than half up.
1141
1141
*/
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
+
1142
1168
static int dentry_lease_is_valid (struct dentry * dentry , unsigned int flags ,
1143
1169
struct inode * dir )
1144
1170
{
1145
1171
struct ceph_dentry_info * di ;
1146
- struct ceph_mds_session * s ;
1147
- int valid = 0 ;
1148
- u32 gen ;
1149
- unsigned long ttl ;
1150
1172
struct ceph_mds_session * session = NULL ;
1151
1173
u32 seq = 0 ;
1174
+ int valid = 0 ;
1152
1175
1153
1176
spin_lock (& dentry -> d_lock );
1154
1177
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 ;
1161
1180
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 ;
1181
1195
}
1182
1196
}
1183
1197
}
@@ -1192,6 +1206,38 @@ static int dentry_lease_is_valid(struct dentry *dentry, unsigned int flags,
1192
1206
return valid ;
1193
1207
}
1194
1208
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
+
1195
1241
/*
1196
1242
* Check if directory-wide content lease/cap is valid.
1197
1243
*/
@@ -1308,6 +1354,31 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
1308
1354
return valid ;
1309
1355
}
1310
1356
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
+
1311
1382
/*
1312
1383
* Release our ceph_dentry_info.
1313
1384
*/
@@ -1531,6 +1602,7 @@ const struct inode_operations ceph_snapdir_iops = {
1531
1602
1532
1603
const struct dentry_operations ceph_dentry_ops = {
1533
1604
.d_revalidate = ceph_d_revalidate ,
1605
+ .d_delete = ceph_d_delete ,
1534
1606
.d_release = ceph_d_release ,
1535
1607
.d_prune = ceph_d_prune ,
1536
1608
.d_init = ceph_d_init ,
0 commit comments