summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/fuse/file.c10
-rw-r--r--fs/ioprio.c31
-rw-r--r--fs/nfs/dir.c62
-rw-r--r--fs/nfs/direct.c2
-rw-r--r--fs/nfs/internal.h9
-rw-r--r--fs/nfs/nfs2xdr.c4
-rw-r--r--fs/nfs/nfs3xdr.c4
-rw-r--r--fs/nfs/nfs4xdr.c6
-rw-r--r--fs/nilfs2/dat.c2
-rw-r--r--fs/nilfs2/ioctl.c4
-rw-r--r--fs/proc/task_mmu.c3
-rw-r--r--fs/reiserfs/ioctl.c7
12 files changed, 79 insertions, 65 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index c8224587123..9242d294fe9 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -134,6 +134,7 @@ EXPORT_SYMBOL_GPL(fuse_do_open);
void fuse_finish_open(struct inode *inode, struct file *file)
{
struct fuse_file *ff = file->private_data;
+ struct fuse_conn *fc = get_fuse_conn(inode);
if (ff->open_flags & FOPEN_DIRECT_IO)
file->f_op = &fuse_direct_io_file_operations;
@@ -141,6 +142,15 @@ void fuse_finish_open(struct inode *inode, struct file *file)
invalidate_inode_pages2(inode->i_mapping);
if (ff->open_flags & FOPEN_NONSEEKABLE)
nonseekable_open(inode, file);
+ if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) {
+ struct fuse_inode *fi = get_fuse_inode(inode);
+
+ spin_lock(&fc->lock);
+ fi->attr_version = ++fc->attr_version;
+ i_size_write(inode, 0);
+ spin_unlock(&fc->lock);
+ fuse_invalidate_attr(inode);
+ }
}
int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
diff --git a/fs/ioprio.c b/fs/ioprio.c
index 2f7d05c8992..7da2a06508e 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -103,22 +103,15 @@ SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio)
}
ret = -ESRCH;
- /*
- * We want IOPRIO_WHO_PGRP/IOPRIO_WHO_USER to be "atomic",
- * so we can't use rcu_read_lock(). See re-copy of ->ioprio
- * in copy_process().
- */
- read_lock(&tasklist_lock);
+ rcu_read_lock();
switch (which) {
case IOPRIO_WHO_PROCESS:
- rcu_read_lock();
if (!who)
p = current;
else
p = find_task_by_vpid(who);
if (p)
ret = set_task_ioprio(p, ioprio);
- rcu_read_unlock();
break;
case IOPRIO_WHO_PGRP:
if (!who)
@@ -141,12 +134,7 @@ SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio)
break;
do_each_thread(g, p) {
- int match;
-
- rcu_read_lock();
- match = __task_cred(p)->uid == who;
- rcu_read_unlock();
- if (!match)
+ if (__task_cred(p)->uid != who)
continue;
ret = set_task_ioprio(p, ioprio);
if (ret)
@@ -160,7 +148,7 @@ free_uid:
ret = -EINVAL;
}
- read_unlock(&tasklist_lock);
+ rcu_read_unlock();
return ret;
}
@@ -204,17 +192,15 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who)
int ret = -ESRCH;
int tmpio;
- read_lock(&tasklist_lock);
+ rcu_read_lock();
switch (which) {
case IOPRIO_WHO_PROCESS:
- rcu_read_lock();
if (!who)
p = current;
else
p = find_task_by_vpid(who);
if (p)
ret = get_task_ioprio(p);
- rcu_read_unlock();
break;
case IOPRIO_WHO_PGRP:
if (!who)
@@ -241,12 +227,7 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who)
break;
do_each_thread(g, p) {
- int match;
-
- rcu_read_lock();
- match = __task_cred(p)->uid == user->uid;
- rcu_read_unlock();
- if (!match)
+ if (__task_cred(p)->uid != user->uid)
continue;
tmpio = get_task_ioprio(p);
if (tmpio < 0)
@@ -264,6 +245,6 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who)
ret = -EINVAL;
}
- read_unlock(&tasklist_lock);
+ rcu_read_unlock();
return ret;
}
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 662df2a5fad..8ea4a4180a8 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -162,6 +162,7 @@ struct nfs_cache_array_entry {
u64 cookie;
u64 ino;
struct qstr string;
+ unsigned char d_type;
};
struct nfs_cache_array {
@@ -171,8 +172,6 @@ struct nfs_cache_array {
struct nfs_cache_array_entry array[0];
};
-#define MAX_READDIR_ARRAY ((PAGE_SIZE - sizeof(struct nfs_cache_array)) / sizeof(struct nfs_cache_array_entry))
-
typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
typedef struct {
struct file *file;
@@ -257,13 +256,17 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
if (IS_ERR(array))
return PTR_ERR(array);
+
+ cache_entry = &array->array[array->size];
+
+ /* Check that this entry lies within the page bounds */
ret = -ENOSPC;
- if (array->size >= MAX_READDIR_ARRAY)
+ if ((char *)&cache_entry[1] - (char *)page_address(page) > PAGE_SIZE)
goto out;
- cache_entry = &array->array[array->size];
cache_entry->cookie = entry->prev_cookie;
cache_entry->ino = entry->ino;
+ cache_entry->d_type = entry->d_type;
ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len);
if (ret)
goto out;
@@ -466,8 +469,9 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
struct xdr_stream stream;
struct xdr_buf buf;
__be32 *ptr = xdr_page;
- int status;
struct nfs_cache_array *array;
+ unsigned int count = 0;
+ int status;
buf.head->iov_base = xdr_page;
buf.head->iov_len = buflen;
@@ -488,6 +492,8 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
break;
}
+ count++;
+
if (desc->plus == 1)
nfs_prime_dcache(desc->file->f_path.dentry, entry);
@@ -496,13 +502,14 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
break;
} while (!entry->eof);
- if (status == -EBADCOOKIE && entry->eof) {
+ if (count == 0 || (status == -EBADCOOKIE && entry->eof == 1)) {
array = nfs_readdir_get_array(page);
if (!IS_ERR(array)) {
array->eof_index = array->size;
status = 0;
nfs_readdir_release_array(page);
- }
+ } else
+ status = PTR_ERR(array);
}
return status;
}
@@ -696,21 +703,23 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
int i = 0;
int res = 0;
struct nfs_cache_array *array = NULL;
- unsigned int d_type = DT_UNKNOWN;
- struct dentry *dentry = NULL;
array = nfs_readdir_get_array(desc->page);
- if (IS_ERR(array))
- return PTR_ERR(array);
+ if (IS_ERR(array)) {
+ res = PTR_ERR(array);
+ goto out;
+ }
for (i = desc->cache_entry_index; i < array->size; i++) {
- d_type = DT_UNKNOWN;
+ struct nfs_cache_array_entry *ent;
- res = filldir(dirent, array->array[i].string.name,
- array->array[i].string.len, file->f_pos,
- nfs_compat_user_ino64(array->array[i].ino), d_type);
- if (res < 0)
+ ent = &array->array[i];
+ if (filldir(dirent, ent->string.name, ent->string.len,
+ file->f_pos, nfs_compat_user_ino64(ent->ino),
+ ent->d_type) < 0) {
+ desc->eof = 1;
break;
+ }
file->f_pos++;
desc->cache_entry_index = i;
if (i < (array->size-1))
@@ -722,9 +731,8 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
desc->eof = 1;
nfs_readdir_release_array(desc->page);
+out:
cache_page_release(desc);
- if (dentry != NULL)
- dput(dentry);
dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
(unsigned long long)*desc->dir_cookie, res);
return res;
@@ -759,13 +767,13 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
goto out;
}
- if (nfs_readdir_xdr_to_array(desc, page, inode) == -1) {
- status = -EIO;
- goto out_release;
- }
-
desc->page_index = 0;
desc->page = page;
+
+ status = nfs_readdir_xdr_to_array(desc, page, inode);
+ if (status < 0)
+ goto out_release;
+
status = nfs_do_filldir(desc, dirent, filldir);
out:
@@ -816,14 +824,14 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
res = readdir_search_pagecache(desc);
if (res == -EBADCOOKIE) {
+ res = 0;
/* This means either end of directory */
if (*desc->dir_cookie && desc->eof == 0) {
/* Or that the server has 'lost' a cookie */
res = uncached_readdir(desc, dirent, filldir);
- if (res >= 0)
+ if (res == 0)
continue;
}
- res = 0;
break;
}
if (res == -ETOOSMALL && desc->plus) {
@@ -838,10 +846,8 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
break;
res = nfs_do_filldir(desc, dirent, filldir);
- if (res < 0) {
- res = 0;
+ if (res < 0)
break;
- }
}
out:
nfs_unblock_sillyrename(dentry);
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 84d3c8b9020..e6ace0d93c7 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -867,7 +867,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov,
goto out;
nfs_alloc_commit_data(dreq);
- if (dreq->commit_data == NULL || count < wsize)
+ if (dreq->commit_data == NULL || count <= wsize)
sync = NFS_FILE_SYNC;
dreq->inode = inode;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index db08ff3ff45..e6356b750b7 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -362,6 +362,15 @@ unsigned int nfs_page_length(struct page *page)
}
/*
+ * Convert a umode to a dirent->d_type
+ */
+static inline
+unsigned char nfs_umode_to_dtype(umode_t mode)
+{
+ return (mode >> 12) & 15;
+}
+
+/*
* Determine the number of pages in an array of length 'len' and
* with a base offset of 'base'
*/
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 2563f765c9b..5914a1911c9 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -485,6 +485,8 @@ nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_se
entry->prev_cookie = entry->cookie;
entry->cookie = ntohl(*p++);
+ entry->d_type = DT_UNKNOWN;
+
p = xdr_inline_peek(xdr, 8);
if (p != NULL)
entry->eof = !p[0] && p[1];
@@ -495,7 +497,7 @@ nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_se
out_overflow:
print_overflow_msg(__func__, xdr);
- return ERR_PTR(-EIO);
+ return ERR_PTR(-EAGAIN);
}
/*
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 748dc91a4a1..f6cc60f06da 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -622,11 +622,13 @@ nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_s
entry->prev_cookie = entry->cookie;
p = xdr_decode_hyper(p, &entry->cookie);
+ entry->d_type = DT_UNKNOWN;
if (plus) {
entry->fattr->valid = 0;
p = xdr_decode_post_op_attr_stream(xdr, entry->fattr);
if (IS_ERR(p))
goto out_overflow_exit;
+ entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
/* In fact, a post_op_fh3: */
p = xdr_inline_decode(xdr, 4);
if (unlikely(!p))
@@ -656,7 +658,7 @@ nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_s
out_overflow:
print_overflow_msg(__func__, xdr);
out_overflow_exit:
- return ERR_PTR(-EIO);
+ return ERR_PTR(-EAGAIN);
}
/*
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index b7a204ff6fe..9f1826b012e 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -6208,6 +6208,10 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
entry->ino = entry->fattr->fileid;
+ entry->d_type = DT_UNKNOWN;
+ if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE)
+ entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
+
if (verify_attr_len(xdr, p, len) < 0)
goto out_overflow;
@@ -6221,7 +6225,7 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
out_overflow:
print_overflow_msg(__func__, xdr);
- return ERR_PTR(-EIO);
+ return ERR_PTR(-EAGAIN);
}
/*
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c
index 49c844dab33..59e5fe742f7 100644
--- a/fs/nilfs2/dat.c
+++ b/fs/nilfs2/dat.c
@@ -335,7 +335,7 @@ int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr)
* the device at this point.
*
* To prevent nilfs_dat_translate() from returning the
- * uncommited block number, this makes a copy of the entry
+ * uncommitted block number, this makes a copy of the entry
* buffer and redirects nilfs_dat_translate() to the copy.
*/
if (!buffer_nilfs_redirected(entry_bh)) {
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 3e90f86d5bf..e00d9457c25 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -349,8 +349,8 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,
ino = vdesc->vd_ino;
cno = vdesc->vd_cno;
inode = nilfs_iget_for_gc(sb, ino, cno);
- if (unlikely(inode == NULL)) {
- ret = -ENOMEM;
+ if (IS_ERR(inode)) {
+ ret = PTR_ERR(inode);
goto failed;
}
do {
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index da6b01d70f0..c126c83b9a4 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -706,6 +706,7 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask,
* skip over unmapped regions.
*/
#define PAGEMAP_WALK_SIZE (PMD_SIZE)
+#define PAGEMAP_WALK_MASK (PMD_MASK)
static ssize_t pagemap_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
@@ -776,7 +777,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
unsigned long end;
pm.pos = 0;
- end = start_vaddr + PAGEMAP_WALK_SIZE;
+ end = (start_vaddr + PAGEMAP_WALK_SIZE) & PAGEMAP_WALK_MASK;
/* overflow ? */
if (end < start_vaddr || end > end_vaddr)
end = end_vaddr;
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index bd9763e76ba..79265fdc317 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -183,12 +183,11 @@ int reiserfs_unpack(struct inode *inode, struct file *filp)
return 0;
}
- /* we need to make sure nobody is changing the file size beneath
- ** us
- */
- reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb);
depth = reiserfs_write_lock_once(inode->i_sb);
+ /* we need to make sure nobody is changing the file size beneath us */
+ reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb);
+
write_from = inode->i_size & (blocksize - 1);
/* if we are on a block boundary, we are already unpacked. */
if (write_from == 0) {