Commit 0ba92e1c authored by Jeff Layton's avatar Jeff Layton Committed by Ilya Dryomov
Browse files

ceph: add ceph_change_snap_realm() helper



Consolidate some fiddly code for changing an inode's snap_realm
into a new helper function, and change the callers to use it.

While we're in here, nothing uses the i_snap_realm_counter field, so
remove that from the inode.

Signed-off-by: default avatarJeff Layton <jlayton@kernel.org>
Reviewed-by: default avatarLuis Henriques <lhenriques@suse.de>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent c80dc3ae
Loading
Loading
Loading
Loading
+3 −33
Original line number Diff line number Diff line
@@ -704,23 +704,7 @@ void ceph_add_cap(struct inode *inode,
		struct ceph_snap_realm *realm = ceph_lookup_snap_realm(mdsc,
							       realmino);
		if (realm) {
			struct ceph_snap_realm *oldrealm = ci->i_snap_realm;
			if (oldrealm) {
				spin_lock(&oldrealm->inodes_with_caps_lock);
				list_del_init(&ci->i_snap_realm_item);
				spin_unlock(&oldrealm->inodes_with_caps_lock);
			}

			spin_lock(&realm->inodes_with_caps_lock);
			list_add(&ci->i_snap_realm_item,
				 &realm->inodes_with_caps);
			ci->i_snap_realm = realm;
			if (realm->ino == ci->i_vino.ino)
				realm->inode = inode;
			spin_unlock(&realm->inodes_with_caps_lock);

			if (oldrealm)
				ceph_put_snap_realm(mdsc, oldrealm);
			ceph_change_snap_realm(inode, realm);
		} else {
			pr_err("ceph_add_cap: couldn't find snap realm %llx\n",
			       realmino);
@@ -1112,20 +1096,6 @@ int ceph_is_any_caps(struct inode *inode)
	return ret;
}

static void drop_inode_snap_realm(struct ceph_inode_info *ci)
{
	struct ceph_snap_realm *realm = ci->i_snap_realm;
	spin_lock(&realm->inodes_with_caps_lock);
	list_del_init(&ci->i_snap_realm_item);
	ci->i_snap_realm_counter++;
	ci->i_snap_realm = NULL;
	if (realm->ino == ci->i_vino.ino)
		realm->inode = NULL;
	spin_unlock(&realm->inodes_with_caps_lock);
	ceph_put_snap_realm(ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc,
			    realm);
}

/*
 * Remove a cap.  Take steps to deal with a racing iterate_session_caps.
 *
@@ -1201,7 +1171,7 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
		 * keep i_snap_realm.
		 */
		if (ci->i_wr_ref == 0 && ci->i_snap_realm)
			drop_inode_snap_realm(ci);
			ceph_change_snap_realm(&ci->vfs_inode, NULL);

		__cap_delay_cancel(mdsc, ci);
	}
@@ -3084,7 +3054,7 @@ static void __ceph_put_cap_refs(struct ceph_inode_info *ci, int had,
			}
			/* see comment in __ceph_remove_cap() */
			if (!__ceph_is_any_real_caps(ci) && ci->i_snap_realm)
				drop_inode_snap_realm(ci);
				ceph_change_snap_realm(inode, NULL);
		}
	}
	if (check_flushsnaps && __ceph_have_pending_cap_snap(ci)) {
+2 −9
Original line number Diff line number Diff line
@@ -581,16 +581,9 @@ void ceph_evict_inode(struct inode *inode)
	 */
	if (ci->i_snap_realm) {
		if (ceph_snap(inode) == CEPH_NOSNAP) {
			struct ceph_snap_realm *realm = ci->i_snap_realm;
			dout(" dropping residual ref to snap realm %p\n",
			     realm);
			spin_lock(&realm->inodes_with_caps_lock);
			list_del_init(&ci->i_snap_realm_item);
			ci->i_snap_realm = NULL;
			if (realm->ino == ci->i_vino.ino)
				realm->inode = NULL;
			spin_unlock(&realm->inodes_with_caps_lock);
			ceph_put_snap_realm(mdsc, realm);
			     ci->i_snap_realm);
			ceph_change_snap_realm(inode, NULL);
		} else {
			ceph_put_snapid_map(mdsc, ci->i_snapid_map);
			ci->i_snap_realm = NULL;
+39 −20
Original line number Diff line number Diff line
@@ -849,6 +849,43 @@ static void flush_snaps(struct ceph_mds_client *mdsc)
	dout("flush_snaps done\n");
}

/**
 * ceph_change_snap_realm - change the snap_realm for an inode
 * @inode: inode to move to new snap realm
 * @realm: new realm to move inode into (may be NULL)
 *
 * Detach an inode from its old snaprealm (if any) and attach it to
 * the new snaprealm (if any). The old snap realm reference held by
 * the inode is put. If realm is non-NULL, then the caller's reference
 * to it is taken over by the inode.
 */
void ceph_change_snap_realm(struct inode *inode, struct ceph_snap_realm *realm)
{
	struct ceph_inode_info *ci = ceph_inode(inode);
	struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
	struct ceph_snap_realm *oldrealm = ci->i_snap_realm;

	lockdep_assert_held(&ci->i_ceph_lock);

	if (oldrealm) {
		spin_lock(&oldrealm->inodes_with_caps_lock);
		list_del_init(&ci->i_snap_realm_item);
		if (oldrealm->ino == ci->i_vino.ino)
			oldrealm->inode = NULL;
		spin_unlock(&oldrealm->inodes_with_caps_lock);
		ceph_put_snap_realm(mdsc, oldrealm);
	}

	ci->i_snap_realm = realm;

	if (realm) {
		spin_lock(&realm->inodes_with_caps_lock);
		list_add(&ci->i_snap_realm_item, &realm->inodes_with_caps);
		if (realm->ino == ci->i_vino.ino)
			realm->inode = inode;
		spin_unlock(&realm->inodes_with_caps_lock);
	}
}

/*
 * Handle a snap notification from the MDS.
@@ -935,7 +972,6 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
			};
			struct inode *inode = ceph_find_inode(sb, vino);
			struct ceph_inode_info *ci;
			struct ceph_snap_realm *oldrealm;

			if (!inode)
				continue;
@@ -960,27 +996,10 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
			}
			dout(" will move %p to split realm %llx %p\n",
			     inode, realm->ino, realm);
			/*
			 * Move the inode to the new realm
			 */
			oldrealm = ci->i_snap_realm;
			spin_lock(&oldrealm->inodes_with_caps_lock);
			list_del_init(&ci->i_snap_realm_item);
			spin_unlock(&oldrealm->inodes_with_caps_lock);

			spin_lock(&realm->inodes_with_caps_lock);
			list_add(&ci->i_snap_realm_item,
				 &realm->inodes_with_caps);
			ci->i_snap_realm = realm;
			if (realm->ino == ci->i_vino.ino)
                                realm->inode = inode;
			spin_unlock(&realm->inodes_with_caps_lock);

			spin_unlock(&ci->i_ceph_lock);

			ceph_get_snap_realm(mdsc, realm);
			ceph_put_snap_realm(mdsc, oldrealm);

			ceph_change_snap_realm(inode, realm);
			spin_unlock(&ci->i_ceph_lock);
			iput(inode);
			continue;

+1 −1
Original line number Diff line number Diff line
@@ -418,7 +418,6 @@ struct ceph_inode_info {
		struct ceph_snap_realm *i_snap_realm; /* snap realm (if caps) */
		struct ceph_snapid_map *i_snapid_map; /* snapid -> dev_t */
	};
	int i_snap_realm_counter; /* snap realm (if caps) */
	struct list_head i_snap_realm_item;
	struct list_head i_snap_flush_item;
	struct timespec64 i_btime;
@@ -929,6 +928,7 @@ extern void ceph_put_snap_realm(struct ceph_mds_client *mdsc,
extern int ceph_update_snap_trace(struct ceph_mds_client *m,
				  void *p, void *e, bool deletion,
				  struct ceph_snap_realm **realm_ret);
void ceph_change_snap_realm(struct inode *inode, struct ceph_snap_realm *realm);
extern void ceph_handle_snap(struct ceph_mds_client *mdsc,
			     struct ceph_mds_session *session,
			     struct ceph_msg *msg);