Skip to content

Commit 0e39037

Browse files
committed
drm/i915: Cache the error string
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 <jason@jlekstrand.net> Testcase: igt/gem_exec_capture/many* Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Cc: Jason Ekstrand <jason@jlekstrand.net> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20181123132325.26541-1-chris@chris-wilson.co.uk
1 parent 16c36c4 commit 0e39037

File tree

4 files changed

+243
-175
lines changed

4 files changed

+243
-175
lines changed

drivers/gpu/drm/i915/i915_debugfs.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -943,30 +943,30 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
943943
static ssize_t gpu_state_read(struct file *file, char __user *ubuf,
944944
size_t count, loff_t *pos)
945945
{
946-
struct i915_gpu_state *error = file->private_data;
947-
struct drm_i915_error_state_buf str;
946+
struct i915_gpu_state *error;
948947
ssize_t ret;
949-
loff_t tmp;
948+
void *buf;
950949

950+
error = file->private_data;
951951
if (!error)
952952
return 0;
953953

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

958-
ret = i915_error_state_to_str(&str, error);
959-
if (ret)
959+
ret = i915_gpu_state_copy_to_buffer(error, buf, *pos, count);
960+
if (ret <= 0)
960961
goto out;
961962

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

967-
*pos = str.start + ret;
968968
out:
969-
i915_error_state_buf_release(&str);
969+
kfree(buf);
970970
return ret;
971971
}
972972

0 commit comments

Comments
 (0)