aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2011-03-15 18:53:40 -0400
committerSage Weil <sage@newdream.net>2011-11-03 12:23:49 -0400
commitb58dc4100b9190f2cb437f1f67ffcb9f9acc4923 (patch)
tree5956065af3d9b126b8ae4a37551837c389f12702 /fs/ceph
parent3f8ddb032afa729d4bad1bf2965d3ec068de6b72 (diff)
ceph: clear parent D_COMPLETE flag when on dentry prune
When the VFS prunes a dentry from the cache, clear the D_COMPLETE flag on the parent dentry. Do this for the live and snapshotted namespaces. Do not bother for the .snap dir contents, since we do not cache that. Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/dir.c28
-rw-r--r--fs/ceph/super.h13
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 */
1101static 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 = {
1306const struct dentry_operations ceph_dentry_ops = { 1332const 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
1311const struct dentry_operations ceph_snapdir_dentry_ops = { 1338const struct dentry_operations ceph_snapdir_dentry_ops = {
@@ -1315,4 +1342,5 @@ const struct dentry_operations ceph_snapdir_dentry_ops = {
1315 1342
1316const struct dentry_operations ceph_snap_dentry_ops = { 1343const 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 */
205struct ceph_dentry_info { 205struct 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
216struct ceph_inode_xattrs_info { 229struct 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