Commit dca14191 authored by Jiri Slaby's avatar Jiri Slaby Committed by Greg Kroah-Hartman
Browse files

tty/vt: consolemap: extract dict unsharing to con_unshare_unimap()



The code in con_set_unimap() is too nested. Extract its obvious part
into a separate function and name it after what the code does:
con_unshare_unimap().

Reviewed-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20220607104946.18710-19-jslaby@suse.cz


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f052f62c
Loading
Loading
Loading
Loading
+68 −65
Original line number Diff line number Diff line
@@ -563,49 +563,28 @@ int con_clear_unimap(struct vc_data *vc)
	return ret;
}

int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
static struct uni_pagedict *con_unshare_unimap(struct vc_data *vc,
		struct uni_pagedict *p)
{
	int err = 0, err1, i;
	struct uni_pagedict *p, *q;
	struct unipair *unilist, *plist;

	if (!ct)
		return 0;

	unilist = vmemdup_user(list, array_size(sizeof(*unilist), ct));
	if (IS_ERR(unilist))
		return PTR_ERR(unilist);

	console_lock();

	/* Save original vc_unipagdir_loc in case we allocate a new one */
	p = *vc->vc_uni_pagedir_loc;
	if (!p) {
		err = -EINVAL;
		goto out_unlock;
	}

	if (p->refcount > 1) {
		int j, k;
	struct uni_pagedict *q;
	u16 **p1, *p2, l;
	int ret;
	int i, j, k;

		err1 = con_do_clear_unimap(vc);
		if (err1) {
			err = err1;
			goto out_unlock;
		}
	ret = con_do_clear_unimap(vc);
	if (ret)
		return ERR_PTR(ret);

	/*
		 * Since refcount was > 1, con_clear_unimap() allocated a
		 * a new uni_pagedict for this vc.  Re: p != q
	 * Since refcount was > 1, con_clear_unimap() allocated a new
	 * uni_pagedict for this vc.  Re: p != q
	 */
	q = *vc->vc_uni_pagedir_loc;

	/*
		 * uni_pgdir is a 32*32*64 table with rows allocated
		 * when its first entry is added.  The unicode value must
		 * still be incremented for empty rows.  We are copying
		 * entries from "p" (old) to "q" (new).
	 * uni_pgdir is a 32*32*64 table with rows allocated when its first
	 * entry is added. The unicode value must still be incremented for
	 * empty rows. We are copying entries from "p" (old) to "q" (new).
	 */
	l = 0;		/* unicode value */
	for (i = 0; i < UNI_DIRS; i++) {
@@ -619,9 +598,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
		for (j = 0; j < UNI_DIR_ROWS; j++) {
			p2 = p1[j];
			if (!p2) {
					/*
					 * Account for row of 64 empty entries
					 */
				/* Account for row of 64 empty entries */
				l += UNI_ROW_GLYPHS;
				continue;
			}
@@ -630,26 +607,52 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
				if (p2[k] == 0xffff)
					continue;
				/*
					 * Found one, copy entry for unicode
					 * l with fontpos value p2[k].
				 * Found one, copy entry for unicode l with
				 * fontpos value p2[k].
				 */
					err1 = con_insert_unipair(q, l, p2[k]);
					if (err1) {
				ret = con_insert_unipair(q, l, p2[k]);
				if (ret) {
					p->refcount++;
					*vc->vc_uni_pagedir_loc = p;
					con_release_unimap(q);
					kfree(q);
						err = err1;
						goto out_unlock;
					return ERR_PTR(ret);
				}
			}
		}
	}

		/*
		 * Finished copying font table, set vc_uni_pagedir to new table
		 */
		p = q;
	return q;
}

int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
{
	int err = 0, err1;
	struct uni_pagedict *p;
	struct unipair *unilist, *plist;

	if (!ct)
		return 0;

	unilist = vmemdup_user(list, array_size(sizeof(*unilist), ct));
	if (IS_ERR(unilist))
		return PTR_ERR(unilist);

	console_lock();

	/* Save original vc_unipagdir_loc in case we allocate a new one */
	p = *vc->vc_uni_pagedir_loc;
	if (!p) {
		err = -EINVAL;
		goto out_unlock;
	}

	if (p->refcount > 1) {
		p = con_unshare_unimap(vc, p);
		if (IS_ERR(p)) {
			err = PTR_ERR(p);
			goto out_unlock;
		}
	} else if (p == dflt) {
		dflt = NULL;
	}