Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd3d66b8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'ceph-for-4.15-rc4' of git://github.com/ceph/ceph-client

Pull ceph fix from Ilya Dryomov:
 "CephFS inode trimming fix from Zheng, marked for stable"

* tag 'ceph-for-4.15-rc4' of git://github.com/ceph/ceph-client:
  ceph: drop negative child dentries before try pruning inode's alias
parents 227701e0 040d7860
Loading
Loading
Loading
Loading
+38 −4
Original line number Diff line number Diff line
@@ -1440,6 +1440,29 @@ static int __close_session(struct ceph_mds_client *mdsc,
	return request_close_session(mdsc, session);
}

static bool drop_negative_children(struct dentry *dentry)
{
	struct dentry *child;
	bool all_negative = true;

	if (!d_is_dir(dentry))
		goto out;

	spin_lock(&dentry->d_lock);
	list_for_each_entry(child, &dentry->d_subdirs, d_child) {
		if (d_really_is_positive(child)) {
			all_negative = false;
			break;
		}
	}
	spin_unlock(&dentry->d_lock);

	if (all_negative)
		shrink_dcache_parent(dentry);
out:
	return all_negative;
}

/*
 * Trim old(er) caps.
 *
@@ -1490,16 +1513,27 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg)
	if ((used | wanted) & ~oissued & mine)
		goto out;   /* we need these caps */

	session->s_trim_caps--;
	if (oissued) {
		/* we aren't the only cap.. just remove us */
		__ceph_remove_cap(cap, true);
		session->s_trim_caps--;
	} else {
		struct dentry *dentry;
		/* try dropping referring dentries */
		spin_unlock(&ci->i_ceph_lock);
		dentry = d_find_any_alias(inode);
		if (dentry && drop_negative_children(dentry)) {
			int count;
			dput(dentry);
			d_prune_aliases(inode);
			count = atomic_read(&inode->i_count);
			if (count == 1)
				session->s_trim_caps--;
			dout("trim_caps_cb %p cap %p pruned, count now %d\n",
		     inode, cap, atomic_read(&inode->i_count));
			     inode, cap, count);
		} else {
			dput(dentry);
		}
		return 0;
	}