patch-2.1.128 linux/mm/filemap.c
Next file: linux/mm/vmscan.c
Previous file: linux/lib/vsprintf.c
Back to the patch index
Back to the overall index
- Lines: 102
- Date:
Wed Nov 11 22:48:13 1998
- Orig file:
v2.1.127/linux/mm/filemap.c
- Orig date:
Sun Nov 8 14:03:13 1998
diff -u --recursive --new-file v2.1.127/linux/mm/filemap.c linux/mm/filemap.c
@@ -1523,9 +1523,8 @@
unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
struct page *page, **hash;
unsigned long page_cache = 0;
- unsigned long pgpos, offset;
- unsigned long bytes, written;
- long status, sync, didread;
+ unsigned long written;
+ long status, sync;
if (!inode->i_op || !inode->i_op->updatepage)
return -EIO;
@@ -1556,18 +1555,20 @@
}
while (count) {
+ unsigned long bytes, pgpos, offset;
/*
* Try to find the page in the cache. If it isn't there,
* allocate a free page.
*/
offset = (pos & ~PAGE_MASK);
pgpos = pos & PAGE_MASK;
-
- if ((bytes = PAGE_SIZE - offset) > count)
+ bytes = PAGE_SIZE - offset;
+ if (bytes > count)
bytes = count;
hash = page_hash(inode, pgpos);
- if (!(page = __find_page(inode, pgpos, *hash))) {
+ page = __find_page(inode, pgpos, *hash);
+ if (!page) {
if (!page_cache) {
page_cache = __get_free_page(GFP_USER);
if (page_cache)
@@ -1580,51 +1581,25 @@
page_cache = 0;
}
- /*
- * Note: setting of the PG_locked bit is handled
- * below the i_op->xxx interface.
- */
- didread = 0;
-page_wait:
+ /* Get exclusive IO access to the page.. */
wait_on_page(page);
- if (PageUptodate(page))
- goto do_update_page;
+ set_bit(PG_locked, &page->flags);
/*
- * The page is not up-to-date ... if we're writing less
- * than a full page of data, we may have to read it first.
- * But if the page is past the current end of file, we must
- * clear it before updating.
+ * Do the real work.. If the writer ends up delaying the write,
+ * the writer needs to increment the page use counts until he
+ * is done with the page.
*/
- if (bytes < PAGE_SIZE) {
- if (pgpos < inode->i_size) {
- status = -EIO;
- if (didread >= 2)
- goto done_with_page;
- status = inode->i_op->readpage(file, page);
- if (status < 0)
- goto done_with_page;
- didread++;
- goto page_wait;
- } else {
- /* Must clear for partial writes */
- memset((void *) page_address(page), 0,
- PAGE_SIZE);
- }
- }
- /*
- * N.B. We should defer setting PG_uptodate at least until
- * the data is copied. A failure in i_op->updatepage() could
- * leave the page with garbage data.
- */
- set_bit(PG_uptodate, &page->flags);
-
-do_update_page:
- /* All right, the page is there. Now update it. */
- status = inode->i_op->updatepage(file, page, buf,
- offset, bytes, sync);
-done_with_page:
+ bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes);
+ status = -EFAULT;
+ if (bytes)
+ status = inode->i_op->updatepage(file, page, offset, bytes, sync);
+
+ /* Mark it unlocked again and drop the page.. */
+ clear_bit(PG_locked, &page->flags);
+ wake_up(&page->wait);
__free_page(page);
+
if (status < 0)
break;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov