patch-2.3.43 linux/mm/filemap.c
Next file: linux/mm/mlock.c
Previous file: linux/mm/bootmem.c
Back to the patch index
Back to the overall index
- Lines: 286
- Date:
Thu Feb 10 12:17:00 2000
- Orig file:
v2.3.42/linux/mm/filemap.c
- Orig date:
Fri Jan 28 15:09:09 2000
diff -u --recursive --new-file v2.3.42/linux/mm/filemap.c linux/mm/filemap.c
@@ -98,7 +98,7 @@
struct list_head *head, *curr;
struct page * page;
- head = &inode->i_data.pages;
+ head = &inode->i_mapping->pages;
spin_lock(&pagecache_lock);
curr = head->next;
@@ -134,7 +134,7 @@
start = (lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
repeat:
- head = &inode->i_data.pages;
+ head = &inode->i_mapping->pages;
spin_lock(&pagecache_lock);
curr = head->next;
while (curr != head) {
@@ -289,6 +289,12 @@
goto cache_unlock_continue;
/*
+ * We did the page aging part.
+ */
+ if (nr_lru_pages < freepages.min * priority)
+ goto cache_unlock_continue;
+
+ /*
* Is it a page swap page? If so, we want to
* drop it if it is no longer used, even if it
* were to be marked referenced..
@@ -417,7 +423,7 @@
struct page *page;
int retval = 0;
- head = &inode->i_data.pages;
+ head = &inode->i_mapping->pages;
spin_lock(&pagecache_lock);
curr = head->next;
@@ -519,11 +525,12 @@
static inline int page_cache_read(struct file * file, unsigned long offset)
{
struct inode *inode = file->f_dentry->d_inode;
- struct page **hash = page_hash(&inode->i_data, offset);
+ struct address_space *mapping = inode->i_mapping;
+ struct page **hash = page_hash(mapping, offset);
struct page *page;
spin_lock(&pagecache_lock);
- page = __find_page_nolock(&inode->i_data, offset, *hash);
+ page = __find_page_nolock(mapping, offset, *hash);
spin_unlock(&pagecache_lock);
if (page)
return 0;
@@ -532,8 +539,8 @@
if (!page)
return -ENOMEM;
- if (!add_to_page_cache_unique(page, &inode->i_data, offset, hash)) {
- int error = inode->i_op->readpage(file->f_dentry, page);
+ if (!add_to_page_cache_unique(page, mapping, offset, hash)) {
+ int error = mapping->a_ops->readpage(file->f_dentry, page);
page_cache_release(page);
return error;
}
@@ -949,6 +956,7 @@
{
struct dentry *dentry = filp->f_dentry;
struct inode *inode = dentry->d_inode;
+ struct address_space *mapping = inode->i_mapping;
unsigned long index, offset;
struct page *cached_page;
int reada_ok;
@@ -1017,10 +1025,10 @@
/*
* Try to find the data in the page cache..
*/
- hash = page_hash(&inode->i_data, index);
+ hash = page_hash(mapping, index);
spin_lock(&pagecache_lock);
- page = __find_page_nolock(&inode->i_data, index, *hash);
+ page = __find_page_nolock(mapping, index, *hash);
if (!page)
goto no_cached_page;
found_page:
@@ -1068,7 +1076,7 @@
readpage:
/* ... and start the actual read. The read will unlock the page. */
- error = inode->i_op->readpage(filp->f_dentry, page);
+ error = mapping->a_ops->readpage(filp->f_dentry, page);
if (!error) {
if (Page_Uptodate(page))
@@ -1107,7 +1115,7 @@
* dropped the page cache lock. Check for that.
*/
spin_lock(&pagecache_lock);
- page = __find_page_nolock(&inode->i_data, index, *hash);
+ page = __find_page_nolock(mapping, index, *hash);
if (page)
goto found_page;
}
@@ -1116,7 +1124,7 @@
* Ok, add the new page to the hash-queues...
*/
page = cached_page;
- __add_to_page_cache(page, &inode->i_data, index, hash);
+ __add_to_page_cache(page, mapping, index, hash);
spin_unlock(&pagecache_lock);
cached_page = NULL;
@@ -1227,7 +1235,7 @@
in_inode = in_file->f_dentry->d_inode;
if (!in_inode)
goto fput_in;
- if (!in_inode->i_op || !in_inode->i_op->readpage)
+ if (!in_inode->i_mapping->a_ops->readpage)
goto fput_in;
retval = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, in_file->f_pos, count);
if (retval)
@@ -1301,6 +1309,7 @@
struct file *file = area->vm_file;
struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
+ struct address_space *mapping = inode->i_mapping;
struct page *page, **hash, *old_page;
unsigned long size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
@@ -1319,9 +1328,9 @@
/*
* Do we have something in the page cache already?
*/
- hash = page_hash(&inode->i_data, pgoff);
+ hash = page_hash(mapping, pgoff);
retry_find:
- page = __find_get_page(&inode->i_data, pgoff, hash);
+ page = __find_get_page(mapping, pgoff, hash);
if (!page)
goto no_cached_page;
@@ -1390,7 +1399,7 @@
goto success;
}
- if (!inode->i_op->readpage(file->f_dentry, page)) {
+ if (!mapping->a_ops->readpage(file->f_dentry, page)) {
wait_on_page(page);
if (Page_Uptodate(page))
goto success;
@@ -1408,7 +1417,7 @@
goto success;
}
ClearPageError(page);
- if (!inode->i_op->readpage(file->f_dentry, page)) {
+ if (!mapping->a_ops->readpage(file->f_dentry, page)) {
wait_on_page(page);
if (Page_Uptodate(page))
goto success;
@@ -1440,7 +1449,7 @@
if (size_idx <= index)
return -EIO;
}
- writepage = inode->i_op->writepage;
+ writepage = inode->i_mapping->a_ops->writepage;
lock_page(page);
retval = writepage(file->f_dentry, page);
@@ -1652,13 +1661,13 @@
ops = &file_private_mmap;
if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) {
- if (!inode->i_op || !inode->i_op->writepage)
+ if (!inode->i_mapping->a_ops->writepage)
return -EINVAL;
ops = &file_shared_mmap;
}
if (!inode->i_sb || !S_ISREG(inode->i_mode))
return -EACCES;
- if (!inode->i_op || !inode->i_op->readpage)
+ if (!inode->i_mapping->a_ops->readpage)
return -ENOEXEC;
UPDATE_ATIME(inode);
vma->vm_ops = ops;
@@ -1810,6 +1819,21 @@
return page;
}
+static inline void remove_suid(struct inode *inode)
+{
+ unsigned int mode;
+
+ /* set S_IGID if S_IXGRP is set, and always set S_ISUID */
+ mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
+
+ /* was any of the uid bits set? */
+ mode &= inode->i_mode;
+ if (mode && !capable(CAP_FSETID)) {
+ inode->i_mode &= ~mode;
+ mark_inode_dirty(inode);
+ }
+}
+
/*
* Write to a file through the page cache. This is mainly for the
* benefit of NFS and possibly other network-based file systems.
@@ -1827,12 +1851,11 @@
* okir@monad.swb.de
*/
ssize_t
-generic_file_write(struct file *file, const char *buf,
- size_t count, loff_t *ppos,
- writepage_t write_one_page)
+generic_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
{
struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
+ struct address_space *mapping = inode->i_mapping;
unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
loff_t pos;
struct page *page, *cached_page;
@@ -1876,9 +1899,15 @@
}
status = 0;
+ if (count) {
+ remove_suid(inode);
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ mark_inode_dirty(inode);
+ }
while (count) {
unsigned long bytes, index, offset;
+ char *kaddr;
/*
* Try to find the page in the cache. If it isn't there,
@@ -1891,7 +1920,7 @@
bytes = count;
status = -ENOMEM; /* we'll assign it later anyway */
- page = __grab_cache_page(&inode->i_data, index, &cached_page);
+ page = __grab_cache_page(mapping, index, &cached_page);
if (!page)
break;
@@ -1900,7 +1929,16 @@
PAGE_BUG(page);
}
- status = write_one_page(file, page, offset, bytes, buf);
+ status = mapping->a_ops->prepare_write(page, offset, offset+bytes);
+ if (status)
+ goto unlock;
+ kaddr = (char*)page_address(page);
+ status = copy_from_user(kaddr+offset, buf, bytes);
+ if (status)
+ goto fail_write;
+ status = mapping->a_ops->commit_write(file, page, offset, offset+bytes);
+ if (!status)
+ status = bytes;
if (status >= 0) {
written += status;
@@ -1910,6 +1948,7 @@
if (pos > inode->i_size)
inode->i_size = pos;
}
+unlock:
/* Mark it unlocked again and drop the page.. */
UnlockPage(page);
page_cache_release(page);
@@ -1926,6 +1965,11 @@
out:
up(&inode->i_sem);
return err;
+fail_write:
+ status = -EFAULT;
+ ClearPageUptodate(page);
+ kunmap(page);
+ goto unlock;
}
void __init page_cache_init(unsigned long mempages)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)