diff options
-rw-r--r-- | fs/ceph/dir.c | 28 | ||||
-rw-r--r-- | fs/ceph/super.h | 13 |
2 files changed, 41 insertions, 0 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 382abc9a6a54..97fb155b3242 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -1092,7 +1092,33 @@ static int ceph_snapdir_d_revalidate(struct dentry *dentry, | |||
1092 | return 1; | 1092 | return 1; |
1093 | } | 1093 | } |
1094 | 1094 | ||
1095 | /* | ||
1096 | * When the VFS prunes a dentry from the cache, we need to clear the | ||
1097 | * complete flag on the parent directory. | ||
1098 | * | ||
1099 | * Called under dentry->d_lock. | ||
1100 | */ | ||
1101 | static void ceph_d_prune(struct dentry *dentry) | ||
1102 | { | ||
1103 | struct ceph_dentry_info *di; | ||
1104 | |||
1105 | dout("d_release %p\n", dentry); | ||
1106 | |||
1107 | /* do we have a valid parent? */ | ||
1108 | if (!dentry->d_parent || IS_ROOT(dentry)) | ||
1109 | return; | ||
1110 | |||
1111 | /* if we are not hashed, we don't affect D_COMPLETE */ | ||
1112 | if (d_unhashed(dentry)) | ||
1113 | return; | ||
1095 | 1114 | ||
1115 | /* | ||
1116 | * we hold d_lock, so d_parent is stable, and d_fsdata is never | ||
1117 | * cleared until d_release | ||
1118 | */ | ||
1119 | di = ceph_dentry(dentry->d_parent); | ||
1120 | clear_bit(CEPH_D_COMPLETE, &di->flags); | ||
1121 | } | ||
1096 | 1122 | ||
1097 | /* | 1123 | /* |
1098 | * read() on a dir. This weird interface hack only works if mounted | 1124 | * read() on a dir. This weird interface hack only works if mounted |
@@ -1306,6 +1332,7 @@ const struct inode_operations ceph_dir_iops = { | |||
1306 | const struct dentry_operations ceph_dentry_ops = { | 1332 | const struct dentry_operations ceph_dentry_ops = { |
1307 | .d_revalidate = ceph_d_revalidate, | 1333 | .d_revalidate = ceph_d_revalidate, |
1308 | .d_release = ceph_d_release, | 1334 | .d_release = ceph_d_release, |
1335 | .d_prune = ceph_d_prune, | ||
1309 | }; | 1336 | }; |
1310 | 1337 | ||
1311 | const struct dentry_operations ceph_snapdir_dentry_ops = { | 1338 | const struct dentry_operations ceph_snapdir_dentry_ops = { |
@@ -1315,4 +1342,5 @@ const struct dentry_operations ceph_snapdir_dentry_ops = { | |||
1315 | 1342 | ||
1316 | const struct dentry_operations ceph_snap_dentry_ops = { | 1343 | const struct dentry_operations ceph_snap_dentry_ops = { |
1317 | .d_release = ceph_d_release, | 1344 | .d_release = ceph_d_release, |
1345 | .d_prune = ceph_d_prune, | ||
1318 | }; | 1346 | }; |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index b01442aaf278..98e60693c9a1 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -203,6 +203,7 @@ struct ceph_inode_xattr { | |||
203 | * Ceph dentry state | 203 | * Ceph dentry state |
204 | */ | 204 | */ |
205 | struct ceph_dentry_info { | 205 | struct ceph_dentry_info { |
206 | unsigned long flags; | ||
206 | struct ceph_mds_session *lease_session; | 207 | struct ceph_mds_session *lease_session; |
207 | u32 lease_gen, lease_shared_gen; | 208 | u32 lease_gen, lease_shared_gen; |
208 | u32 lease_seq; | 209 | u32 lease_seq; |
@@ -213,6 +214,18 @@ struct ceph_dentry_info { | |||
213 | u64 offset; | 214 | u64 offset; |
214 | }; | 215 | }; |
215 | 216 | ||
217 | /* | ||
218 | * dentry flags | ||
219 | * | ||
220 | * The locking for D_COMPLETE is a bit odd: | ||
221 | * - we can clear it at almost any time (see ceph_d_prune) | ||
222 | * - it is only meaningful if: | ||
223 | * - we hold dir inode i_lock | ||
224 | * - we hold dir FILE_SHARED caps | ||
225 | * - the dentry D_COMPLETE is set | ||
226 | */ | ||
227 | #define CEPH_D_COMPLETE 1 /* if set, d_u.d_subdirs is complete directory */ | ||
228 | |||
216 | struct ceph_inode_xattrs_info { | 229 | struct ceph_inode_xattrs_info { |
217 | /* | 230 | /* |
218 | * (still encoded) xattr blob. we avoid the overhead of parsing | 231 | * (still encoded) xattr blob. we avoid the overhead of parsing |