fuse_buf_copy: check if buffers are the same
authorMiklos Szeredi <miklos@szeredi.hu>
Wed, 10 Nov 2010 10:41:21 +0000 (11:41 +0100)
committerMiklos Szeredi <mszeredi@suse.cz>
Wed, 10 Nov 2010 10:41:21 +0000 (11:41 +0100)
When copying fuse buffers, check if the source and destination are the
same and omit the copy as appropriate.  Also check if the source and
destination memory regions overlap and use memmove in that case.

lib/buffer.c

index 0006cbf7d04c6c46c5474547f4a9b7f629977eda..cb734a3c72763d4bd9612b42c5767d0e6c11adfd 100644 (file)
@@ -217,7 +217,16 @@ static ssize_t fuse_buf_copy_one(const struct fuse_buf *dst, size_t dst_off,
        int dst_is_fd = dst->flags & FUSE_BUF_IS_FD;
 
        if (!src_is_fd && !dst_is_fd) {
-               memcpy(dst->mem + dst_off, src->mem + src_off, len);
+               void *dstmem = dst->mem + dst_off;
+               void *srcmem = src->mem + src_off;
+
+               if (dstmem != srcmem) {
+                       if (dstmem + len <= srcmem || srcmem + len <= dstmem)
+                               memcpy(dstmem, srcmem, len);
+                       else
+                               memmove(dstmem, srcmem, len);
+               }
+
                return len;
        } else if (!src_is_fd) {
                return fuse_buf_write(dst, dst_off, src, src_off, len);
@@ -259,6 +268,9 @@ ssize_t fuse_buf_copy(struct fuse_bufvec *dstv, struct fuse_bufvec *srcv,
 {
        size_t copied = 0;
 
+       if (dstv == srcv)
+               return fuse_buf_size(dstv);
+
        for (;;) {
                const struct fuse_buf *src = fuse_bufvec_current(srcv);
                const struct fuse_buf *dst = fuse_bufvec_current(dstv);