aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/buffer.c2
-rw-r--r--fs/fs-writeback.c4
-rw-r--r--fs/inode.c9
-rw-r--r--fs/ioprio.c29
-rw-r--r--fs/ncpfs/mmap.c2
-rw-r--r--fs/nfs/pagelist.c1
-rw-r--r--fs/nfs/write.c9
-rw-r--r--fs/nfsd/export.c2
-rw-r--r--fs/nfsd/nfs4state.c32
-rw-r--r--fs/nfsd/nfsfh.c27
-rw-r--r--fs/nfsd/vfs.c14
-rw-r--r--fs/proc/proc_misc.c23
12 files changed, 91 insertions, 63 deletions
diff --git a/fs/buffer.c b/fs/buffer.c
index bf22bb56a08..3660dcb9759 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -851,7 +851,7 @@ int __set_page_dirty_buffers(struct page *page)
write_lock_irq(&mapping->tree_lock);
if (page->mapping) { /* Race with truncate? */
if (mapping_cap_account_dirty(mapping))
- inc_page_state(nr_dirty);
+ __inc_zone_page_state(page, NR_FILE_DIRTY);
radix_tree_tag_set(&mapping->page_tree,
page_index(page),
PAGECACHE_TAG_DIRTY);
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 031b27a4bc9..892643dc9af 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -464,8 +464,8 @@ void sync_inodes_sb(struct super_block *sb, int wait)
.range_start = 0,
.range_end = LLONG_MAX,
};
- unsigned long nr_dirty = read_page_state(nr_dirty);
- unsigned long nr_unstable = read_page_state(nr_unstable);
+ unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY);
+ unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS);
wbc.nr_to_write = nr_dirty + nr_unstable +
(inodes_stat.nr_inodes - inodes_stat.nr_unused) +
diff --git a/fs/inode.c b/fs/inode.c
index e53796a6d88..0bf9f0444a9 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -451,15 +451,14 @@ static void prune_icache(int nr_to_scan)
nr_pruned++;
}
inodes_stat.nr_unused -= nr_pruned;
+ if (current_is_kswapd())
+ __count_vm_events(KSWAPD_INODESTEAL, reap);
+ else
+ __count_vm_events(PGINODESTEAL, reap);
spin_unlock(&inode_lock);
dispose_list(&freeable);
mutex_unlock(&iprune_mutex);
-
- if (current_is_kswapd())
- mod_page_state(kswapd_inodesteal, reap);
- else
- mod_page_state(pginodesteal, reap);
}
/*
diff --git a/fs/ioprio.c b/fs/ioprio.c
index 7fa76ed53c1..93aa5715f22 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -125,11 +125,24 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
return ret;
}
+static int get_task_ioprio(struct task_struct *p)
+{
+ int ret;
+
+ ret = security_task_getioprio(p);
+ if (ret)
+ goto out;
+ ret = p->ioprio;
+out:
+ return ret;
+}
+
asmlinkage long sys_ioprio_get(int which, int who)
{
struct task_struct *g, *p;
struct user_struct *user;
int ret = -ESRCH;
+ int tmpio;
read_lock_irq(&tasklist_lock);
switch (which) {
@@ -139,16 +152,19 @@ asmlinkage long sys_ioprio_get(int which, int who)
else
p = find_task_by_pid(who);
if (p)
- ret = p->ioprio;
+ ret = get_task_ioprio(p);
break;
case IOPRIO_WHO_PGRP:
if (!who)
who = process_group(current);
do_each_task_pid(who, PIDTYPE_PGID, p) {
+ tmpio = get_task_ioprio(p);
+ if (tmpio < 0)
+ continue;
if (ret == -ESRCH)
- ret = p->ioprio;
+ ret = tmpio;
else
- ret = ioprio_best(ret, p->ioprio);
+ ret = ioprio_best(ret, tmpio);
} while_each_task_pid(who, PIDTYPE_PGID, p);
break;
case IOPRIO_WHO_USER:
@@ -163,10 +179,13 @@ asmlinkage long sys_ioprio_get(int which, int who)
do_each_thread(g, p) {
if (p->uid != user->uid)
continue;
+ tmpio = get_task_ioprio(p);
+ if (tmpio < 0)
+ continue;
if (ret == -ESRCH)
- ret = p->ioprio;
+ ret = tmpio;
else
- ret = ioprio_best(ret, p->ioprio);
+ ret = ioprio_best(ret, tmpio);
} while_each_thread(g, p);
if (who)
diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c
index 52d60c3d899..e7d5a3097fe 100644
--- a/fs/ncpfs/mmap.c
+++ b/fs/ncpfs/mmap.c
@@ -93,7 +93,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area,
*/
if (type)
*type = VM_FAULT_MAJOR;
- inc_page_state(pgmajfault);
+ count_vm_event(PGMAJFAULT);
return page;
}
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index d3ff7abcf54..36e902a88ca 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -314,6 +314,7 @@ nfs_scan_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst,
req->wb_index, NFS_PAGE_TAG_DIRTY);
nfs_list_remove_request(req);
nfs_list_add_request(req, dst);
+ dec_zone_page_state(req->wb_page, NR_FILE_DIRTY);
res++;
}
}
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 1aadc138ec4..bca5734ca9f 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -496,7 +496,7 @@ nfs_mark_request_dirty(struct nfs_page *req)
nfs_list_add_request(req, &nfsi->dirty);
nfsi->ndirty++;
spin_unlock(&nfsi->req_lock);
- inc_page_state(nr_dirty);
+ inc_zone_page_state(req->wb_page, NR_FILE_DIRTY);
mark_inode_dirty(inode);
}
@@ -524,7 +524,7 @@ nfs_mark_request_commit(struct nfs_page *req)
nfs_list_add_request(req, &nfsi->commit);
nfsi->ncommit++;
spin_unlock(&nfsi->req_lock);
- inc_page_state(nr_unstable);
+ inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
mark_inode_dirty(inode);
}
#endif
@@ -608,7 +608,6 @@ nfs_scan_dirty(struct inode *inode, struct list_head *dst, unsigned long idx_sta
if (nfsi->ndirty != 0) {
res = nfs_scan_lock_dirty(nfsi, dst, idx_start, npages);
nfsi->ndirty -= res;
- sub_page_state(nr_dirty,res);
if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty))
printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n");
}
@@ -1393,7 +1392,6 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
{
struct nfs_write_data *data = calldata;
struct nfs_page *req;
- int res = 0;
dprintk("NFS: %4d nfs_commit_done (status %d)\n",
task->tk_pid, task->tk_status);
@@ -1405,6 +1403,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
while (!list_empty(&data->pages)) {
req = nfs_list_entry(data->pages.next);
nfs_list_remove_request(req);
+ dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
dprintk("NFS: commit (%s/%Ld %d@%Ld)",
req->wb_context->dentry->d_inode->i_sb->s_id,
@@ -1431,9 +1430,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
nfs_mark_request_dirty(req);
next:
nfs_clear_page_writeback(req);
- res++;
}
- sub_page_state(nr_unstable,res);
}
static const struct rpc_call_ops nfs_commit_ops = {
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 3eec30000f3..01bc68c628a 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -126,7 +126,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
if (*ep)
goto out;
dprintk("found fsidtype %d\n", fsidtype);
- if (fsidtype > 2)
+ if (key_len(fsidtype)==0) /* invalid type */
goto out;
if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
goto out;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 7c7d01672d3..9daa0b9feb8 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1237,8 +1237,15 @@ find_file(struct inode *ino)
return NULL;
}
-#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0)
-#define TEST_DENY(x) ((x >= 0 || x < 5)?1:0)
+static int access_valid(u32 x)
+{
+ return (x > 0 && x < 4);
+}
+
+static int deny_valid(u32 x)
+{
+ return (x >= 0 && x < 5);
+}
static void
set_access(unsigned int *access, unsigned long bmap) {
@@ -1745,7 +1752,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
int status;
status = nfserr_inval;
- if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
+ if (!access_valid(open->op_share_access)
+ || !deny_valid(open->op_share_deny))
goto out;
/*
* Lookup file; if found, lookup stateid and check open request,
@@ -1782,10 +1790,10 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
} else {
/* Stateid was not found, this is a new OPEN */
int flags = 0;
+ if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
+ flags |= MAY_READ;
if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
- flags = MAY_WRITE;
- else
- flags = MAY_READ;
+ flags |= MAY_WRITE;
status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags);
if (status)
goto out;
@@ -2070,16 +2078,12 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
if (!stateid->si_fileid) { /* delegation stateid */
if(!(dp = find_delegation_stateid(ino, stateid))) {
dprintk("NFSD: delegation stateid not found\n");
- if (nfs4_in_grace())
- status = nfserr_grace;
goto out;
}
stidp = &dp->dl_stateid;
} else { /* open or lock stateid */
if (!(stp = find_stateid(stateid, flags))) {
dprintk("NFSD: open or lock stateid not found\n");
- if (nfs4_in_grace())
- status = nfserr_grace;
goto out;
}
if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp))
@@ -2252,8 +2256,9 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
(int)current_fh->fh_dentry->d_name.len,
current_fh->fh_dentry->d_name.name);
- if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0)))
- goto out;
+ status = fh_verify(rqstp, current_fh, S_IFREG, 0);
+ if (status)
+ return status;
nfs4_lock_state();
@@ -2320,7 +2325,8 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n
(int)current_fh->fh_dentry->d_name.len,
current_fh->fh_dentry->d_name.name);
- if (!TEST_ACCESS(od->od_share_access) || !TEST_DENY(od->od_share_deny))
+ if (!access_valid(od->od_share_access)
+ || !deny_valid(od->od_share_deny))
return nfserr_inval;
nfs4_lock_state();
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 3f2ec2e6d06..ecc439d2565 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -187,13 +187,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
goto out;
}
- /* Set user creds for this exportpoint */
- error = nfsd_setuser(rqstp, exp);
- if (error) {
- error = nfserrno(error);
- goto out;
- }
-
/*
* Look up the dentry using the NFS file handle.
*/
@@ -251,6 +244,14 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
}
cache_get(&exp->h);
+ /* Set user creds for this exportpoint; necessary even in the "just
+ * checking" case because this may be a filehandle that was created by
+ * fh_compose, and that is about to be used in another nfsv4 compound
+ * operation */
+ error = nfserrno(nfsd_setuser(rqstp, exp));
+ if (error)
+ goto out;
+
error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
if (error)
goto out;
@@ -312,8 +313,8 @@ int
fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh)
{
/* ref_fh is a reference file handle.
- * if it is non-null, then we should compose a filehandle which is
- * of the same version, where possible.
+ * if it is non-null and for the same filesystem, then we should compose
+ * a filehandle which is of the same version, where possible.
* Currently, that means that if ref_fh->fh_handle.fh_version == 0xca
* Then create a 32byte filehandle using nfs_fhbase_old
*
@@ -332,7 +333,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
parent->d_name.name, dentry->d_name.name,
(inode ? inode->i_ino : 0));
- if (ref_fh) {
+ if (ref_fh && ref_fh->fh_export == exp) {
ref_fh_version = ref_fh->fh_handle.fh_version;
if (ref_fh_version == 0xca)
ref_fh_fsid_type = 0;
@@ -461,7 +462,7 @@ fh_update(struct svc_fh *fhp)
} else {
int size;
if (fhp->fh_handle.fh_fileid_type != 0)
- goto out_uptodate;
+ goto out;
datap = fhp->fh_handle.fh_auth+
fhp->fh_handle.fh_size/4 -1;
size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
@@ -481,10 +482,6 @@ out_negative:
printk(KERN_ERR "fh_update: %s/%s still negative!\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
goto out;
-out_uptodate:
- printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
- goto out;
}
/*
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index da3ec74d8a4..c9e3b5a8fe0 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -672,7 +672,10 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
goto out_nfserr;
if (access & MAY_WRITE) {
- flags = O_WRONLY|O_LARGEFILE;
+ if (access & MAY_READ)
+ flags = O_RDWR|O_LARGEFILE;
+ else
+ flags = O_WRONLY|O_LARGEFILE;
DQUOT_INIT(inode);
}
@@ -833,7 +836,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
if (ra && ra->p_set)
file->f_ra = ra->p_ra;
- if (file->f_op->sendfile) {
+ if (file->f_op->sendfile && rqstp->rq_sendfile_ok) {
svc_pushback_unused_pages(rqstp);
err = file->f_op->sendfile(file, &offset, *count,
nfsd_read_actor, rqstp);
@@ -1516,14 +1519,15 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
err = nfserrno(err);
}
- fh_unlock(ffhp);
dput(dnew);
+out_unlock:
+ fh_unlock(ffhp);
out:
return err;
out_nfserr:
err = nfserrno(err);
- goto out;
+ goto out_unlock;
}
/*
@@ -1552,7 +1556,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
tdir = tdentry->d_inode;
err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;
- if (fdir->i_sb != tdir->i_sb)
+ if (ffhp->fh_export != tfhp->fh_export)
goto out;
err = nfserr_perm;
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index b8d48852649..9f2cfc30f9c 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -119,7 +119,6 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
{
struct sysinfo i;
int len;
- struct page_state ps;
unsigned long inactive;
unsigned long active;
unsigned long free;
@@ -128,7 +127,6 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
struct vmalloc_info vmi;
long cached;
- get_page_state(&ps);
get_zone_counts(&active, &inactive, &free);
/*
@@ -141,7 +139,8 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
allowed = ((totalram_pages - hugetlb_total_pages())
* sysctl_overcommit_ratio / 100) + total_swap_pages;
- cached = get_page_cache_size() - total_swapcache_pages - i.bufferram;
+ cached = global_page_state(NR_FILE_PAGES) -
+ total_swapcache_pages - i.bufferram;
if (cached < 0)
cached = 0;
@@ -166,11 +165,14 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
"SwapFree: %8lu kB\n"
"Dirty: %8lu kB\n"
"Writeback: %8lu kB\n"
+ "AnonPages: %8lu kB\n"
"Mapped: %8lu kB\n"
"Slab: %8lu kB\n"
+ "PageTables: %8lu kB\n"
+ "NFS Unstable: %8lu kB\n"
+ "Bounce: %8lu kB\n"
"CommitLimit: %8lu kB\n"
"Committed_AS: %8lu kB\n"
- "PageTables: %8lu kB\n"
"VmallocTotal: %8lu kB\n"
"VmallocUsed: %8lu kB\n"
"VmallocChunk: %8lu kB\n",
@@ -187,13 +189,16 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
K(i.freeram-i.freehigh),
K(i.totalswap),
K(i.freeswap),
- K(ps.nr_dirty),
- K(ps.nr_writeback),
- K(ps.nr_mapped),
- K(ps.nr_slab),
+ K(global_page_state(NR_FILE_DIRTY)),
+ K(global_page_state(NR_WRITEBACK)),
+ K(global_page_state(NR_ANON_PAGES)),
+ K(global_page_state(NR_FILE_MAPPED)),
+ K(global_page_state(NR_SLAB)),
+ K(global_page_state(NR_PAGETABLE)),
+ K(global_page_state(NR_UNSTABLE_NFS)),
+ K(global_page_state(NR_BOUNCE)),
K(allowed),
K(committed),
- K(ps.nr_page_table_pages),
(unsigned long)VMALLOC_TOTAL >> 10,
vmi.used >> 10,
vmi.largest_chunk >> 10