Christopher,

It sounds like you disabled zero-copy entirely, which is not necessary.
As far as I recall, loading kernel modules is the only case in which
valloc() allocated buffers are used. In the worst case, we only need to
disable zero-copy on such buffers. I have been using a small patch to do
precisely that since yesterday. I have attached it to this email since
it sounds like the first version might be helpful to others while I take
the time to explore a few loose ends.

That being said, I would like to investigate a couple of things before I
send either this patch or some variant of it to the appropriate
subsystem maintainer. First, I need to review the valloc() routines to
ensure that range checking against [VMALLOC_START, VMALLOC_END) is the
correct way to identify valloc() generated buffers. Second, I want to
explore the feasibility of a suggestion by Alexander Graf to instead
rework the zero-copy to properly handle valloc() allocated buffers.

Yours truly,
Richard Yao

On 11/26/2013 10:16 AM, Christopher Covington wrote:
> Hi Richard,
> 
> On 11/25/2013 04:50 PM, Richard Yao wrote:
>> I figured out the problem. There is zerocopy IO is being done via DMA to
>> a buffer allocated with valloc(). Right now, I am running a hack-fix
>> locally so I can get some other stuff done first. I will propose a
>> proper fix to the list in a few days.
> 
> I've also encountered this issue on a non-QEMU simulator and have been
> carrying a disable-zero-copy hack for a few months. Let me know if there's
> anything I can help with.
> 
> Christopher
> 
diff --git a/net/9p/client.c b/net/9p/client.c
index ee8fd6b..0adfcf5 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -1557,7 +1557,9 @@ p9_client_read(struct p9_fid *fid, char *data, char 
__user *udata, u64 offset,
                rsize = count;
 
        /* Don't bother zerocopy for small IO (< 1024) */
-       if (clnt->trans_mod->zc_request && rsize > 1024) {
+       if (clnt->trans_mod->zc_request && rsize > 1024 &&
+               !(udata >= (char __user *)VMALLOC_START &&
+                       udata < (char __user *)VMALLOC_END)) {
                char *indata;
                if (data) {
                        kernel_buf = 1;

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to