static int set_fs_root(struct libmnt_fs *result, struct libmnt_fs *fs, unsigned long mountflags)
{
	char *root = NULL, *mnt = NULL;
	const char *fstype;
	struct libmnt_table *tb = NULL;
	int rc = -ENOMEM;

	assert(fs);
	assert(result);

	DBG(UPDATE, mnt_debug("setting FS root"));

	fstype = mnt_fs_get_fstype(fs);

	/*
	 * bind-mount -- get fs-root and source device for the source filesystem
	 */
	if (mountflags & MS_BIND) {
		const char *src, *src_root;
		struct libmnt_fs *src_fs;

		DBG(UPDATE, mnt_debug("setting FS root: bind"));

		src = mnt_fs_get_srcpath(fs);
		if (src) {
			rc = mnt_fs_set_bindsrc(result, src);
			if (rc)
				goto err;
			mnt = mnt_get_mountpoint(src);
		}
		if (!mnt) {
			rc = -EINVAL;
			goto err;
		}
		root = mnt_get_fs_root(src, mnt);

		tb = __mnt_new_table_from_file(_PATH_PROC_MOUNTINFO, MNT_FMT_MOUNTINFO);
		if (!tb) {
			DBG(UPDATE, mnt_debug("failed to parse mountinfo -- using default"));
			goto dflt;
		}
		src_fs = mnt_table_find_target(tb, mnt, MNT_ITER_BACKWARD);
		if (!src_fs)  {
			DBG(UPDATE, mnt_debug("not found '%s' in mountinfo -- using default", mnt));
			goto dflt;
		}

		/* set device name and fs */
		src = mnt_fs_get_srcpath(src_fs);
		rc = mnt_fs_set_source(result, src);
		if (rc)
			goto err;

		mnt_fs_set_fstype(result, mnt_fs_get_fstype(src_fs));

		/* on btrfs the subvolume is used as fs-root in
		 * /proc/self/mountinfo, so we have get the original subvolume
		 * name from src_fs and prepend the subvolume name to the
		 * fs-root path
		 */
		src_root = mnt_fs_get_root(src_fs);
		if (src_root && !startswith(root, src_root)) {
			size_t sz = strlen(root) + strlen(src_root) + 1;
			char *tmp = malloc(sz);

			if (!tmp)
				goto err;
			snprintf(tmp, sz, "%s%s", src_root, root);
			free(root);
			root = tmp;
		}
	}

	/*
	 * btrfs-subvolume mount -- get subvolume name and use it as a root-fs path
	 */
	else if (fstype && !strcmp(fstype, "btrfs")) {
		char *vol = NULL, *p;
		size_t sz, volsz = 0;

		if (mnt_fs_get_option(fs, "subvol", &vol, &volsz))
			goto dflt;

		DBG(UPDATE, mnt_debug("setting FS root: btrfs subvol"));

		sz = volsz;
		if (*vol != '/')
			sz++;
		root = malloc(sz + 1);
		if (!root)
			goto err;
		p = root;
		if (*vol != '/')
			*p++ = '/';
		memcpy(p, vol, volsz);
		*(root + sz) = '\0';
	}
dflt:
	mnt_free_table(tb);
	if (!root) {
		root = strdup("/");
		if (!root)
			goto err;
	}
	result->root = root;

	DBG(UPDATE, mnt_debug("FS root result: %s", root));

	free(mnt);
	return 0;
err:
	free(root);
	free(mnt);
	return rc;
}
static int set_fs_root(struct libmnt_fs *result, struct libmnt_fs *fs, unsigned long mountflags)
{
	char *root = NULL, *mnt = NULL;
	const char *fstype;
	struct libmnt_table *tb = NULL;
	int rc = -ENOMEM;

	assert(fs);
	assert(result);

	DBG(UPDATE, mnt_debug("setting FS root"));

	fstype = mnt_fs_get_fstype(fs);

	 
	if (mountflags & MS_BIND) {
		const char *src, *src_root;
		struct libmnt_fs *src_fs;

		DBG(UPDATE, mnt_debug("setting FS root: bind"));

		src = mnt_fs_get_srcpath(fs);
		if (src) {
			rc = mnt_fs_set_bindsrc(result, src);
			if (rc)
				goto err;
			mnt = mnt_get_mountpoint(src);
		}
		if (!mnt) {
			rc = -EINVAL;
			goto err;
		}
		root = mnt_get_fs_root(src, mnt);

		tb = __mnt_new_table_from_file(_PATH_PROC_MOUNTINFO, MNT_FMT_MOUNTINFO);
		if (!tb) {
			DBG(UPDATE, mnt_debug("failed to parse mountinfo -- using default"));
			goto dflt;
		}
		src_fs = mnt_table_find_target(tb, mnt, MNT_ITER_BACKWARD);
		if (!src_fs)  {
			DBG(UPDATE, mnt_debug("not found '%s' in mountinfo -- using default", mnt));
			goto dflt;
		}

		 
		src = mnt_fs_get_srcpath(src_fs);
		rc = mnt_fs_set_source(result, src);
		if (rc)
			goto err;

		mnt_fs_set_fstype(result, mnt_fs_get_fstype(src_fs));

		 
		src_root = mnt_fs_get_root(src_fs);
		if (src_root && !startswith(root, src_root)) {
			size_t sz = strlen(root) + strlen(src_root) + 1;
			char *tmp = malloc(sz);

			if (!tmp)
				goto err;
			snprintf(tmp, sz, "%s%s", src_root, root);
			free(root);
			root = tmp;
		}
	}

	 
	else if (fstype && !strcmp(fstype, "btrfs")) {
		char *vol = NULL, *p;
		size_t sz, volsz = 0;

		if (mnt_fs_get_option(fs, "subvol", &vol, &volsz))
			goto dflt;

		DBG(UPDATE, mnt_debug("setting FS root: btrfs subvol"));

		sz = volsz;
		if (*vol != '/')
			sz++;
		root = malloc(sz + 1);
		if (!root)
			goto err;
		p = root;
		if (*vol != '/')
			*p++ = '/';
		memcpy(p, vol, volsz);
		*(root + sz) = '\0';
	}
dflt:
	mnt_free_table(tb);
	if (!root) {
		root = strdup("/");
		if (!root)
			goto err;
	}
	result->root = root;

	DBG(UPDATE, mnt_debug("FS root result: %s", root));

	free(mnt);
	return 0;
err:
	free(root);
	free(mnt);
	return rc;
}