|
@@ -2333,6 +2333,38 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
|
|
|
iput(inode);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Invalidate unlinked inode's aliases, so we can drop the inode ASAP.
|
|
|
+ */
|
|
|
+static void invalidate_aliases(struct inode *inode)
|
|
|
+{
|
|
|
+ struct dentry *dn, *prev = NULL;
|
|
|
+
|
|
|
+ dout("invalidate_aliases inode %p\n", inode);
|
|
|
+ d_prune_aliases(inode);
|
|
|
+ /*
|
|
|
+ * For non-directory inode, d_find_alias() only returns
|
|
|
+ * connected dentry. After calling d_delete(), the dentry
|
|
|
+ * become disconnected.
|
|
|
+ *
|
|
|
+ * For directory inode, d_find_alias() only can return
|
|
|
+ * disconnected dentry. But directory inode should have
|
|
|
+ * one alias at most.
|
|
|
+ */
|
|
|
+ while ((dn = d_find_alias(inode))) {
|
|
|
+ if (dn == prev) {
|
|
|
+ dput(dn);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ d_delete(dn);
|
|
|
+ if (prev)
|
|
|
+ dput(prev);
|
|
|
+ prev = dn;
|
|
|
+ }
|
|
|
+ if (prev)
|
|
|
+ dput(prev);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Handle a cap GRANT message from the MDS. (Note that a GRANT may
|
|
|
* actually be a revocation if it specifies a smaller cap set.)
|
|
@@ -2363,6 +2395,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
|
|
|
int writeback = 0;
|
|
|
int revoked_rdcache = 0;
|
|
|
int queue_invalidate = 0;
|
|
|
+ int deleted_inode = 0;
|
|
|
|
|
|
dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
|
|
|
inode, cap, mds, seq, ceph_cap_string(newcaps));
|
|
@@ -2407,8 +2440,12 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
|
|
|
from_kgid(&init_user_ns, inode->i_gid));
|
|
|
}
|
|
|
|
|
|
- if ((issued & CEPH_CAP_LINK_EXCL) == 0)
|
|
|
+ if ((issued & CEPH_CAP_LINK_EXCL) == 0) {
|
|
|
set_nlink(inode, le32_to_cpu(grant->nlink));
|
|
|
+ if (inode->i_nlink == 0 &&
|
|
|
+ (newcaps & (CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL)))
|
|
|
+ deleted_inode = 1;
|
|
|
+ }
|
|
|
|
|
|
if ((issued & CEPH_CAP_XATTR_EXCL) == 0 && grant->xattr_len) {
|
|
|
int len = le32_to_cpu(grant->xattr_len);
|
|
@@ -2517,6 +2554,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
|
|
|
ceph_queue_writeback(inode);
|
|
|
if (queue_invalidate)
|
|
|
ceph_queue_invalidate(inode);
|
|
|
+ if (deleted_inode)
|
|
|
+ invalidate_aliases(inode);
|
|
|
if (wake)
|
|
|
wake_up_all(&ci->i_cap_wq);
|
|
|
|