patch-2.1.14 linux/drivers/char/mem.c
Next file: linux/drivers/char/pcxx.c
Previous file: linux/drivers/char/istallion.c
Back to the patch index
Back to the overall index
- Lines: 59
- Date:
Mon Nov 25 12:13:22 1996
- Orig file:
v2.1.13/linux/drivers/char/mem.c
- Orig date:
Tue Oct 29 19:58:06 1996
diff -u --recursive --new-file v2.1.13/linux/drivers/char/mem.c linux/drivers/char/mem.c
@@ -189,17 +189,52 @@
return count;
}
+/*
+ * For fun, somebody might look into using the MMU for this.
+ * NOTE! It's not trivial: you have to check that the mapping
+ * is a private mapping and if so you can just map in the
+ * zero page directly. But shared mappings _have_ to use the
+ * physical copy.
+ */
+static inline unsigned long read_zero_pagealigned(char * buf, unsigned long size)
+{
+ do {
+ if (clear_user(buf, PAGE_SIZE))
+ break;
+ if (need_resched)
+ schedule();
+ buf += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ } while (size);
+ return size;
+}
+
static long read_zero(struct inode * node, struct file * file,
char * buf, unsigned long count)
{
- int left;
+ unsigned long left;
- for (left = count; left > 0; left--) {
- put_user(0,buf);
- buf++;
- if (need_resched)
- schedule();
+ if (!access_ok(VERIFY_WRITE, buf, count))
+ return -EFAULT;
+
+ left = count;
+
+ /* do we want to be clever? Arbitrary cut-off */
+ if (count >= PAGE_SIZE*4) {
+ unsigned long partial, unwritten;
+
+ /* How much left of the page? */
+ partial = (PAGE_SIZE-1) & -(unsigned long) buf;
+ clear_user(buf, partial);
+ left -= partial;
+ buf += partial;
+ unwritten = read_zero_pagealigned(buf, left & PAGE_MASK);
+ buf += left & PAGE_MASK;
+ left &= ~PAGE_MASK;
+ if (unwritten)
+ return count - left - unwritten;
}
+ clear_user(buf, left);
return count;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov