Skip to content

Commit

Permalink
drm/i915: Cache the error string
Browse files Browse the repository at this point in the history
Currently, we convert the error state into a string every time we read
from sysfs (and sysfs reads in page size (4KiB) chunks). We do try to
window the string and only capture the portion that is being read, but
that means that we must always convert up to the window to find the
start. For a very large error state bordering on EXEC_OBJECT_CAPTURE
abuse, this is noticeable as it degrades to O(N^2)!

As we do not have a convenient hook for sysfs open(), and we would like
to keep the lazy conversion into a string, do the conversion of the
whole string on the first read and keep the string until the error state
is freed.

v2: Don't double advance simple_read_from_buffer
v3: Due to extreme pain of lack of vrealloc, use a scatterlist
v4: Keep the forward iterator loosely cached
v5: Stylistic improvements to reduce patch size

Reported-by: Jason Ekstrand <[email protected]>
Testcase: igt/gem_exec_capture/many*
Signed-off-by: Chris Wilson <[email protected]>
Cc: Mika Kuoppala <[email protected]>
Cc: Jason Ekstrand <[email protected]>
Reviewed-by: Joonas Lahtinen <[email protected]>
Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
  • Loading branch information
ickle committed Nov 23, 2018
1 parent 16c36c4 commit 0e39037
Show file tree
Hide file tree
Showing 4 changed files with 243 additions and 175 deletions.
28 changes: 14 additions & 14 deletions drivers/gpu/drm/i915/i915_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -943,30 +943,30 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
static ssize_t gpu_state_read(struct file *file, char __user *ubuf,
size_t count, loff_t *pos)
{
struct i915_gpu_state *error = file->private_data;
struct drm_i915_error_state_buf str;
struct i915_gpu_state *error;
ssize_t ret;
loff_t tmp;
void *buf;

error = file->private_data;
if (!error)
return 0;

ret = i915_error_state_buf_init(&str, error->i915, count, *pos);
if (ret)
return ret;
/* Bounce buffer required because of kernfs __user API convenience. */
buf = kmalloc(count, GFP_KERNEL);
if (!buf)
return -ENOMEM;

ret = i915_error_state_to_str(&str, error);
if (ret)
ret = i915_gpu_state_copy_to_buffer(error, buf, *pos, count);
if (ret <= 0)
goto out;

tmp = 0;
ret = simple_read_from_buffer(ubuf, count, &tmp, str.buf, str.bytes);
if (ret < 0)
goto out;
if (!copy_to_user(ubuf, buf, ret))
*pos += ret;
else
ret = -EFAULT;

*pos = str.start + ret;
out:
i915_error_state_buf_release(&str);
kfree(buf);
return ret;
}

Expand Down
Loading

0 comments on commit 0e39037

Please sign in to comment.