unsigned long p = *ppos;
        void *src;
        int err = 0;
-       unsigned long total_size;
+       unsigned long total_size, c;
+       ssize_t ret;
 
        if (info->state != FBINFO_STATE_RUNNING)
                return -EPERM;
        if (info->fbops->fb_sync)
                info->fbops->fb_sync(info);
 
-       if (copy_to_user(buf, src, count))
+       c = copy_to_user(buf, src, count);
+       if (c)
                err = -EFAULT;
+       ret = count - c;
 
-       if  (!err)
-               *ppos += count;
+       *ppos += ret;
 
-       return (err) ? err : count;
+       return ret ? ret : err;
 }
 EXPORT_SYMBOL_GPL(fb_sys_read);
 
        unsigned long p = *ppos;
        void *dst;
        int err = 0;
-       unsigned long total_size;
+       unsigned long total_size, c;
+       size_t ret;
 
        if (info->state != FBINFO_STATE_RUNNING)
                return -EPERM;
        if (info->fbops->fb_sync)
                info->fbops->fb_sync(info);
 
-       if (copy_from_user(dst, buf, count))
+       c = copy_from_user(dst, buf, count);
+       if (c)
                err = -EFAULT;
+       ret = count - c;
 
-       if  (!err)
-               *ppos += count;
+       *ppos += ret;
 
-       return (err) ? err : count;
+       return ret ? ret : err;
 }
 EXPORT_SYMBOL_GPL(fb_sys_write);
 
 
        u8 *buffer, *dst;
        u8 __iomem *src;
        int c, cnt = 0, err = 0;
-       unsigned long total_size;
+       unsigned long total_size, trailing;
 
        if (!info || ! info->screen_base)
                return -ENODEV;
                dst += c;
                src += c;
 
-               if (copy_to_user(buf, buffer, c)) {
+               trailing = copy_to_user(buf, buffer, c);
+               if (trailing == c) {
                        err = -EFAULT;
                        break;
                }
+               c -= trailing;
+
                *ppos += c;
                buf += c;
                cnt += c;
 
        kfree(buffer);
 
-       return (err) ? err : cnt;
+       return cnt ? cnt : err;
 }
 
 static ssize_t
        u8 *buffer, *src;
        u8 __iomem *dst;
        int c, cnt = 0, err = 0;
-       unsigned long total_size;
+       unsigned long total_size, trailing;
 
        if (!info || !info->screen_base)
                return -ENODEV;
                c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
                src = buffer;
 
-               if (copy_from_user(src, buf, c)) {
+               trailing = copy_from_user(src, buf, c);
+               if (trailing == c) {
                        err = -EFAULT;
                        break;
                }
+               c -= trailing;
 
                fb_memcpy_tofb(dst, src, c);
                dst += c;