* [PATCH v2 1/2] drm/i915: Store a permanent error in obj->mm.pages
@ 2017-03-07 12:03 Chris Wilson
2017-03-07 12:03 ` [PATCH v2 2/2] drm/i915: Use pagecache write to prepopulate shmemfs from pwrite-ioctl Chris Wilson
2017-03-07 13:20 ` [PATCH v3] drm/i915: Store a permanent error in obj->mm.pages Chris Wilson
0 siblings, 2 replies; 5+ messages in thread
From: Chris Wilson @ 2017-03-07 12:03 UTC (permalink / raw)
To: intel-gfx; +Cc: Chris Wilson, Joonas Lahtinen, # v4 . 10+
Once the object has been truncated, it is unrecoverable. To facilitate
detection of this state store the error in obj->mm.pages.
This is required for the next patch which should be applied to v4.10
(via stable), so we also need to mark this patch for backporting. In
that regard, let's consider this to be a fix/improvement too.
Fixes: 1233e2db199d ("drm/i915: Move object backing storage manipulation to its own locking")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: <stable@vger.kernel.org> # v4.10+
---
drivers/gpu/drm/i915/i915_gem.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 7c20601fe1de..1f92d25ca27d 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2130,6 +2130,7 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj)
*/
shmem_truncate_range(file_inode(obj->base.filp), 0, (loff_t)-1);
obj->mm.madv = __I915_MADV_PURGED;
+ obj->mm.pages = ERR_PTR(-EFAULT);
}
/* Try to discard unwanted pages */
@@ -2449,7 +2450,7 @@ int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
if (err)
return err;
- if (unlikely(!obj->mm.pages)) {
+ if (unlikely(IS_ERR_OR_NULL(obj->mm.pages))) {
err = ____i915_gem_object_get_pages(obj);
if (err)
goto unlock;
@@ -2527,7 +2528,7 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj,
pinned = true;
if (!atomic_inc_not_zero(&obj->mm.pages_pin_count)) {
- if (unlikely(!obj->mm.pages)) {
+ if (unlikely(IS_ERR_OR_NULL(obj->mm.pages))) {
ret = ____i915_gem_object_get_pages(obj);
if (ret)
goto err_unlock;
--
2.11.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/2] drm/i915: Use pagecache write to prepopulate shmemfs from pwrite-ioctl
2017-03-07 12:03 [PATCH v2 1/2] drm/i915: Store a permanent error in obj->mm.pages Chris Wilson
@ 2017-03-07 12:03 ` Chris Wilson
2017-03-07 13:20 ` [PATCH v3] drm/i915: Store a permanent error in obj->mm.pages Chris Wilson
1 sibling, 0 replies; 5+ messages in thread
From: Chris Wilson @ 2017-03-07 12:03 UTC (permalink / raw)
To: intel-gfx
Cc: Chris Wilson, Matthew Auld, Joonas Lahtinen, Mika Kuoppala,
# v4 . 10+
Before we instantiate/pin the backing store for our use, we
can prepopulate the shmemfs filp efficiently using a write into the
pagecache. We avoid the penalty of instantiating all the pages, important
if the user is just writing to a few and never uses the object on the GPU,
and using a direct write into shmemfs allows it to avoid the cost of
retrieving a page (mostly the clear-before-use, but in theory we could
curtail swapin) before it is overwritten.
This can be extended later to provide additional specialisation for
other backends (other than shmemfs). For now it provides a defense
against very large write-only allocations from exhausting all of system
memory.
v2: Smelling fixes.
Fixes: fe115628d567 ("drm/i915: Implement pwrite without struct-mutex")
References: https://bugs.freedesktop.org/show_bug.cgi?id=99107
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Matthew Auld <matthew.william.auld@gmail.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: <stable@vger.kernel.org> # v4.10+
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
drivers/gpu/drm/i915/i915_gem.c | 78 ++++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/i915_gem_object.h | 3 ++
2 files changed, 81 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 1f92d25ca27d..d00203d538d4 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1452,6 +1452,12 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
trace_i915_gem_object_pwrite(obj, args->offset, args->size);
+ ret = -ENODEV;
+ if (obj->ops->pwrite)
+ ret = obj->ops->pwrite(obj, args);
+ if (ret != -ENODEV)
+ goto err;
+
ret = i915_gem_object_wait(obj,
I915_WAIT_INTERRUPTIBLE |
I915_WAIT_ALL,
@@ -2576,6 +2582,75 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj,
goto out_unlock;
}
+static int
+i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj,
+ const struct drm_i915_gem_pwrite *arg)
+{
+ struct address_space *mapping = obj->base.filp->f_mapping;
+ char __user *user_data = u64_to_user_ptr(arg->data_ptr);
+ u64 remain, offset;
+ unsigned int pg;
+
+ /* Before we instantiate/pin the backing store for our use, we
+ * can prepopulate the shmemfs filp efficiently using a write into
+ * the pagecache. We avoid the penalty of instantiating all the
+ * pages, important if the user is just writing to a few and never
+ * uses the object on the GPU, and using a direct write into shmemfs
+ * allows it to avoid the cost of retrieving a page (either swapin
+ * or clearing-before-use) before it is overwritten.
+ */
+ if (READ_ONCE(obj->mm.pages))
+ return -ENODEV;
+
+ /* Before the pages are instantiated the object is treated as being
+ * in the CPU domain. The pages will be clflushed as required before
+ * use, and we can freely write into the pages directly. If userspace
+ * races pwrite with any other operation; corruption will ensue -
+ * that is userspace's prerogative!
+ */
+
+ remain = arg->size;
+ offset = arg->offset;
+ pg = offset_in_page(offset);
+
+ do {
+ unsigned int len, unwritten;
+ struct page *page;
+ void *data, *vaddr;
+ int err;
+
+ len = PAGE_SIZE - pg;
+ if (len > remain)
+ len = remain;
+
+ err = pagecache_write_begin(obj->base.filp, mapping,
+ offset, len, 0,
+ &page, &data);
+ if (err < 0)
+ return err;
+
+ vaddr = kmap(page);
+ unwritten = copy_from_user(vaddr + pg, user_data, len);
+ kunmap(page);
+
+ err = pagecache_write_end(obj->base.filp, mapping,
+ offset, len, len - unwritten,
+ page, data);
+ if (err < 0)
+ return err;
+
+ if (unwritten)
+ return -EFAULT;
+
+ remain -= len;
+ user_data += len;
+ offset += len;
+ pg = 0;
+ } while (remain);
+
+ return 0;
+}
+
static bool ban_context(const struct i915_gem_context *ctx)
{
return (i915_gem_context_is_bannable(ctx) &&
@@ -3992,8 +4067,11 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
static const struct drm_i915_gem_object_ops i915_gem_object_ops = {
.flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE |
I915_GEM_OBJECT_IS_SHRINKABLE,
+
.get_pages = i915_gem_object_get_pages_gtt,
.put_pages = i915_gem_object_put_pages_gtt,
+
+ .pwrite = i915_gem_object_pwrite_gtt,
};
struct drm_i915_gem_object *
diff --git a/drivers/gpu/drm/i915/i915_gem_object.h b/drivers/gpu/drm/i915/i915_gem_object.h
index 33b0dc4782a9..d26155e0a026 100644
--- a/drivers/gpu/drm/i915/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/i915_gem_object.h
@@ -56,6 +56,9 @@ struct drm_i915_gem_object_ops {
struct sg_table *(*get_pages)(struct drm_i915_gem_object *);
void (*put_pages)(struct drm_i915_gem_object *, struct sg_table *);
+ int (*pwrite)(struct drm_i915_gem_object *,
+ const struct drm_i915_gem_pwrite *);
+
int (*dmabuf_export)(struct drm_i915_gem_object *);
void (*release)(struct drm_i915_gem_object *);
};
--
2.11.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v3] drm/i915: Store a permanent error in obj->mm.pages
2017-03-07 12:03 [PATCH v2 1/2] drm/i915: Store a permanent error in obj->mm.pages Chris Wilson
2017-03-07 12:03 ` [PATCH v2 2/2] drm/i915: Use pagecache write to prepopulate shmemfs from pwrite-ioctl Chris Wilson
@ 2017-03-07 13:20 ` Chris Wilson
2017-03-07 17:47 ` Joonas Lahtinen
1 sibling, 1 reply; 5+ messages in thread
From: Chris Wilson @ 2017-03-07 13:20 UTC (permalink / raw)
To: intel-gfx; +Cc: Chris Wilson, Joonas Lahtinen, # v4 . 10+
Once the object has been truncated, it is unrecoverable. To facilitate
detection of this state store the error in obj->mm.pages.
This is required for the next patch which should be applied to v4.10
(via stable), so we also need to mark this patch for backporting. In
that regard, let's consider this to be a fix/improvement too.
v2: Avoid dereferencing the ERR_PTR when freeing the object.
Fixes: 1233e2db199d ("drm/i915: Move object backing storage manipulation to its own locking")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: <stable@vger.kernel.org> # v4.10+
---
drivers/gpu/drm/i915/i915_gem.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 7c20601fe1de..7ec2881de710 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2130,6 +2130,7 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj)
*/
shmem_truncate_range(file_inode(obj->base.filp), 0, (loff_t)-1);
obj->mm.madv = __I915_MADV_PURGED;
+ obj->mm.pages = ERR_PTR(-EFAULT);
}
/* Try to discard unwanted pages */
@@ -2229,7 +2230,9 @@ void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,
__i915_gem_object_reset_page_iter(obj);
- obj->ops->put_pages(obj, pages);
+ if (!IS_ERR(pages))
+ obj->ops->put_pages(obj, pages);
+
unlock:
mutex_unlock(&obj->mm.lock);
}
@@ -2449,7 +2452,7 @@ int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
if (err)
return err;
- if (unlikely(!obj->mm.pages)) {
+ if (unlikely(IS_ERR_OR_NULL(obj->mm.pages))) {
err = ____i915_gem_object_get_pages(obj);
if (err)
goto unlock;
@@ -2527,7 +2530,7 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj,
pinned = true;
if (!atomic_inc_not_zero(&obj->mm.pages_pin_count)) {
- if (unlikely(!obj->mm.pages)) {
+ if (unlikely(IS_ERR_OR_NULL(obj->mm.pages))) {
ret = ____i915_gem_object_get_pages(obj);
if (ret)
goto err_unlock;
--
2.11.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v3] drm/i915: Store a permanent error in obj->mm.pages
2017-03-07 13:20 ` [PATCH v3] drm/i915: Store a permanent error in obj->mm.pages Chris Wilson
@ 2017-03-07 17:47 ` Joonas Lahtinen
2017-03-07 21:41 ` Chris Wilson
0 siblings, 1 reply; 5+ messages in thread
From: Joonas Lahtinen @ 2017-03-07 17:47 UTC (permalink / raw)
To: Chris Wilson, intel-gfx; +Cc: # v4 . 10+
On ti, 2017-03-07 at 13:20 +0000, Chris Wilson wrote:
> Once the object has been truncated, it is unrecoverable. To facilitate
> detection of this state store the error in obj->mm.pages.
>
> This is required for the next patch which should be applied to v4.10
> (via stable), so we also need to mark this patch for backporting. In
> that regard, let's consider this to be a fix/improvement too.
>
> v2: Avoid dereferencing the ERR_PTR when freeing the object.
>
> Fixes: 1233e2db199d ("drm/i915: Move object backing storage manipulation to its own locking")
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Cc: <stable@vger.kernel.org> # v4.10+
I'd imagine we may want a couple more GEM_BUG_ON checks going forward.
Regardless;
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Regards, Joonas
--
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v3] drm/i915: Store a permanent error in obj->mm.pages
2017-03-07 17:47 ` Joonas Lahtinen
@ 2017-03-07 21:41 ` Chris Wilson
0 siblings, 0 replies; 5+ messages in thread
From: Chris Wilson @ 2017-03-07 21:41 UTC (permalink / raw)
To: Joonas Lahtinen; +Cc: intel-gfx, # v4 . 10+
On Tue, Mar 07, 2017 at 07:47:29PM +0200, Joonas Lahtinen wrote:
> On ti, 2017-03-07 at 13:20 +0000, Chris Wilson wrote:
> > Once the object has been truncated, it is unrecoverable. To facilitate
> > detection of this state store the error in obj->mm.pages.
> >
> > This is required for the next patch which should be applied to v4.10
> > (via stable), so we also need to mark this patch for backporting. In
> > that regard, let's consider this to be a fix/improvement too.
> >
> > v2: Avoid dereferencing the ERR_PTR when freeing the object.
> >
> > Fixes: 1233e2db199d ("drm/i915: Move object backing storage manipulation to its own locking")
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> > Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> > Cc: <stable@vger.kernel.org> # v4.10+
>
> I'd imagine we may want a couple more GEM_BUG_ON checks going forward.
Have a gander at https://patchwork.freedesktop.org/series/20312/
> Regardless;
>
> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Thanks for the review, pushed to stop vlc/libva misbehaving. One day the
shrinker will dtrt :)
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2017-03-07 21:41 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-03-07 12:03 [PATCH v2 1/2] drm/i915: Store a permanent error in obj->mm.pages Chris Wilson
2017-03-07 12:03 ` [PATCH v2 2/2] drm/i915: Use pagecache write to prepopulate shmemfs from pwrite-ioctl Chris Wilson
2017-03-07 13:20 ` [PATCH v3] drm/i915: Store a permanent error in obj->mm.pages Chris Wilson
2017-03-07 17:47 ` Joonas Lahtinen
2017-03-07 21:41 ` Chris Wilson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox