summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/inotify.c13
-rw-r--r--fs/lockd/clntlock.c4
-rw-r--r--fs/nfs/direct.c24
-rw-r--r--fs/nfs/file.c23
-rw-r--r--fs/nfs/inode.c28
-rw-r--r--fs/nfsd/nfs2acl.c2
-rw-r--r--fs/nfsd/nfs3acl.c2
-rw-r--r--fs/reiserfs/inode.c26
-rw-r--r--fs/reiserfs/journal.c18
-rw-r--r--fs/relayfs/relay.c8
-rw-r--r--fs/xattr.c2
-rw-r--r--fs/xfs/quota/xfs_qm.c4
12 files changed, 90 insertions, 64 deletions
diff --git a/fs/inotify.c b/fs/inotify.c
index bf7ce1d2412b..2fecb7af4a77 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -364,11 +364,12 @@ static int inotify_dev_get_wd(struct inotify_device *dev,
/*
* find_inode - resolve a user-given path to a specific inode and return a nd
*/
-static int find_inode(const char __user *dirname, struct nameidata *nd)
+static int find_inode(const char __user *dirname, struct nameidata *nd,
+ unsigned flags)
{
int error;
- error = __user_walk(dirname, LOOKUP_FOLLOW, nd);
+ error = __user_walk(dirname, flags, nd);
if (error)
return error;
/* you can only watch an inode if you have read permissions on it */
@@ -933,6 +934,7 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
struct file *filp;
int ret, fput_needed;
int mask_add = 0;
+ unsigned flags = 0;
filp = fget_light(fd, &fput_needed);
if (unlikely(!filp))
@@ -944,7 +946,12 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
goto fput_and_out;
}
- ret = find_inode(path, &nd);
+ if (!(mask & IN_DONT_FOLLOW))
+ flags |= LOOKUP_FOLLOW;
+ if (mask & IN_ONLYDIR)
+ flags |= LOOKUP_DIRECTORY;
+
+ ret = find_inode(path, &nd, flags);
if (unlikely(ret))
goto fput_and_out;
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 006bb9e14579..3eaf6e701087 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -157,6 +157,8 @@ void nlmclnt_mark_reclaim(struct nlm_host *host)
inode = fl->fl_file->f_dentry->d_inode;
if (inode->i_sb->s_magic != NFS_SUPER_MAGIC)
continue;
+ if (fl->fl_u.nfs_fl.owner == NULL)
+ continue;
if (fl->fl_u.nfs_fl.owner->host != host)
continue;
if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_GRANTED))
@@ -226,6 +228,8 @@ restart:
inode = fl->fl_file->f_dentry->d_inode;
if (inode->i_sb->s_magic != NFS_SUPER_MAGIC)
continue;
+ if (fl->fl_u.nfs_fl.owner == NULL)
+ continue;
if (fl->fl_u.nfs_fl.owner->host != host)
continue;
if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_RECLAIM))
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index b497c71384e8..079228817603 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -678,15 +678,9 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t
if (!count)
goto out;
- if (mapping->nrpages) {
- retval = filemap_fdatawrite(mapping);
- if (retval == 0)
- retval = nfs_wb_all(inode);
- if (retval == 0)
- retval = filemap_fdatawait(mapping);
- if (retval)
- goto out;
- }
+ retval = nfs_sync_mapping(mapping);
+ if (retval)
+ goto out;
retval = nfs_direct_read(inode, ctx, &iov, pos, 1);
if (retval > 0)
@@ -764,15 +758,9 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
if (!count)
goto out;
- if (mapping->nrpages) {
- retval = filemap_fdatawrite(mapping);
- if (retval == 0)
- retval = nfs_wb_all(inode);
- if (retval == 0)
- retval = filemap_fdatawait(mapping);
- if (retval)
- goto out;
- }
+ retval = nfs_sync_mapping(mapping);
+ if (retval)
+ goto out;
retval = nfs_direct_write(inode, ctx, &iov, pos, 1);
if (mapping->nrpages)
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 57d3e77d97ee..eb5cd4c3bbfd 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -433,11 +433,7 @@ static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
* Flush all pending writes before doing anything
* with locks..
*/
- filemap_fdatawrite(filp->f_mapping);
- down(&inode->i_sem);
- nfs_wb_all(inode);
- up(&inode->i_sem);
- filemap_fdatawait(filp->f_mapping);
+ nfs_sync_mapping(filp->f_mapping);
/* NOTE: special case
* If we're signalled while cleaning up locks on process exit, we
@@ -465,15 +461,8 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
* Flush all pending writes before doing anything
* with locks..
*/
- status = filemap_fdatawrite(filp->f_mapping);
- if (status == 0) {
- down(&inode->i_sem);
- status = nfs_wb_all(inode);
- up(&inode->i_sem);
- if (status == 0)
- status = filemap_fdatawait(filp->f_mapping);
- }
- if (status < 0)
+ status = nfs_sync_mapping(filp->f_mapping);
+ if (status != 0)
goto out;
lock_kernel();
@@ -497,11 +486,7 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
* Make sure we clear the cache whenever we try to get the lock.
* This makes locking act as a cache coherency point.
*/
- filemap_fdatawrite(filp->f_mapping);
- down(&inode->i_sem);
- nfs_wb_all(inode); /* we may have slept */
- up(&inode->i_sem);
- filemap_fdatawait(filp->f_mapping);
+ nfs_sync_mapping(filp->f_mapping);
nfs_zap_caches(inode);
out:
rpc_clnt_sigunmask(NFS_CLIENT(inode), &oldset);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index afd75d0463fd..432f41cd75e6 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -640,6 +640,27 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
return 0;
}
+/**
+ * nfs_sync_mapping - helper to flush all mmapped dirty data to disk
+ */
+int nfs_sync_mapping(struct address_space *mapping)
+{
+ int ret;
+
+ if (mapping->nrpages == 0)
+ return 0;
+ unmap_mapping_range(mapping, 0, 0, 0);
+ ret = filemap_fdatawrite(mapping);
+ if (ret != 0)
+ goto out;
+ ret = filemap_fdatawait(mapping);
+ if (ret != 0)
+ goto out;
+ ret = nfs_wb_all(mapping->host);
+out:
+ return ret;
+}
+
/*
* Invalidate the local caches
*/
@@ -1179,11 +1200,8 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
struct nfs_inode *nfsi = NFS_I(inode);
if (nfsi->cache_validity & NFS_INO_INVALID_DATA) {
- if (S_ISREG(inode->i_mode)) {
- if (filemap_fdatawrite(mapping) == 0)
- filemap_fdatawait(mapping);
- nfs_wb_all(inode);
- }
+ if (S_ISREG(inode->i_mode))
+ nfs_sync_mapping(mapping);
invalidate_inode_pages2(mapping);
spin_lock(&inode->i_lock);
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 7cbf0682b2f0..fc95c4df6693 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -107,7 +107,7 @@ static int nfsacld_proc_setacl(struct svc_rqst * rqstp,
dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
fh = fh_copy(&resp->fh, &argp->fh);
- nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+ nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_SATTR);
if (!nfserr) {
nfserr = nfserrno( nfsd_set_posix_acl(
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index 64ba40572fea..16e10c170aed 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -101,7 +101,7 @@ static int nfsd3_proc_setacl(struct svc_rqst * rqstp,
int nfserr = 0;
fh = fh_copy(&resp->fh, &argp->fh);
- nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+ nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_SATTR);
if (!nfserr) {
nfserr = nfserrno( nfsd_set_posix_acl(
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 0a044ad98885..a5e3a0ddbe53 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -32,6 +32,7 @@ void reiserfs_delete_inode(struct inode *inode)
JOURNAL_PER_BALANCE_CNT * 2 +
2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
struct reiserfs_transaction_handle th;
+ int err;
truncate_inode_pages(&inode->i_data, 0);
@@ -49,15 +50,13 @@ void reiserfs_delete_inode(struct inode *inode)
}
reiserfs_update_inode_transaction(inode);
- if (reiserfs_delete_object(&th, inode)) {
- up(&inode->i_sem);
- goto out;
- }
+ err = reiserfs_delete_object(&th, inode);
/* Do quota update inside a transaction for journaled quotas. We must do that
* after delete_object so that quota updates go into the same transaction as
* stat data deletion */
- DQUOT_FREE_INODE(inode);
+ if (!err)
+ DQUOT_FREE_INODE(inode);
if (journal_end(&th, inode->i_sb, jbegin_count)) {
up(&inode->i_sem);
@@ -66,6 +65,12 @@ void reiserfs_delete_inode(struct inode *inode)
up(&inode->i_sem);
+ /* check return value from reiserfs_delete_object after
+ * ending the transaction
+ */
+ if (err)
+ goto out;
+
/* all items of file are deleted, so we can remove "save" link */
remove_save_link(inode, 0 /* not truncate */ ); /* we can't do anything
* about an error here */
@@ -2099,6 +2104,7 @@ int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps)
struct page *page = NULL;
int error;
struct buffer_head *bh = NULL;
+ int err2;
reiserfs_write_lock(p_s_inode->i_sb);
@@ -2136,14 +2142,18 @@ int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps)
transaction of truncating gets committed - on reboot the file
either appears truncated properly or not truncated at all */
add_save_link(&th, p_s_inode, 1);
- error = reiserfs_do_truncate(&th, p_s_inode, page, update_timestamps);
- if (error)
- goto out;
+ err2 = reiserfs_do_truncate(&th, p_s_inode, page, update_timestamps);
error =
journal_end(&th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1);
if (error)
goto out;
+ /* check reiserfs_do_truncate after ending the transaction */
+ if (err2) {
+ error = err2;
+ goto out;
+ }
+
if (update_timestamps) {
error = remove_save_link(p_s_inode, 1 /* truncate */ );
if (error)
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 68b7b78638ff..3f17ef844fb6 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -1039,6 +1039,10 @@ static int flush_commit_list(struct super_block *s,
}
atomic_dec(&journal->j_async_throttle);
+ /* We're skipping the commit if there's an error */
+ if (retval || reiserfs_is_journal_aborted(journal))
+ barrier = 0;
+
/* wait on everything written so far before writing the commit
* if we are in barrier mode, send the commit down now
*/
@@ -1077,10 +1081,16 @@ static int flush_commit_list(struct super_block *s,
BUG_ON(atomic_read(&(jl->j_commit_left)) != 1);
if (!barrier) {
- if (buffer_dirty(jl->j_commit_bh))
- BUG();
- mark_buffer_dirty(jl->j_commit_bh);
- sync_dirty_buffer(jl->j_commit_bh);
+ /* If there was a write error in the journal - we can't commit
+ * this transaction - it will be invalid and, if successful,
+ * will just end up propogating the write error out to
+ * the file system. */
+ if (likely(!retval && !reiserfs_is_journal_aborted (journal))) {
+ if (buffer_dirty(jl->j_commit_bh))
+ BUG();
+ mark_buffer_dirty(jl->j_commit_bh) ;
+ sync_dirty_buffer(jl->j_commit_bh) ;
+ }
} else
wait_on_buffer(jl->j_commit_bh);
diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c
index 16446a15c96d..2a6f7f12b7f9 100644
--- a/fs/relayfs/relay.c
+++ b/fs/relayfs/relay.c
@@ -333,8 +333,7 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
return length;
toobig:
- printk(KERN_WARNING "relayfs: event too large (%Zd)\n", length);
- WARN_ON(1);
+ buf->chan->last_toobig = length;
return 0;
}
@@ -399,6 +398,11 @@ void relay_close(struct rchan *chan)
relay_close_buf(chan->buf[i]);
}
+ if (chan->last_toobig)
+ printk(KERN_WARNING "relayfs: one or more items not logged "
+ "[item size (%Zd) > sub-buffer size (%Zd)]\n",
+ chan->last_toobig, chan->subbuf_size);
+
kref_put(&chan->kref, relay_destroy_channel);
}
diff --git a/fs/xattr.c b/fs/xattr.c
index a9db22557998..bcc2156d4d28 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -245,7 +245,7 @@ listxattr(struct dentry *d, char __user *list, size_t size)
error = d->d_inode->i_op->listxattr(d, klist, size);
} else {
error = security_inode_listsecurity(d->d_inode, klist, size);
- if (size && error >= size)
+ if (size && error > size)
error = -ERANGE;
}
if (error > 0) {
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 1aea42d71a64..5328a2937127 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -78,7 +78,7 @@ STATIC int xfs_qm_dqhashlock_nowait(xfs_dquot_t *);
STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
-STATIC int xfs_qm_shake(int, unsigned int);
+STATIC int xfs_qm_shake(int, gfp_t);
#ifdef DEBUG
extern mutex_t qcheck_lock;
@@ -2197,7 +2197,7 @@ xfs_qm_shake_freelist(
*/
/* ARGSUSED */
STATIC int
-xfs_qm_shake(int nr_to_scan, unsigned int gfp_mask)
+xfs_qm_shake(int nr_to_scan, gfp_t gfp_mask)
{
int ndqused, nfree, n;