summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/hostfs/hostfs_kern.c9
-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.c26
-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/partitions/Kconfig2
-rw-r--r--fs/proc/generic.c47
-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
15 files changed, 122 insertions, 93 deletions
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 4684eb7d48c..b3ad0bd0312 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -501,11 +501,16 @@ int hostfs_commit_write(struct file *file, struct page *page, unsigned from,
long long start;
int err = 0;
- start = (long long) (page->index << PAGE_CACHE_SHIFT) + from;
+ start = (((long long) page->index) << PAGE_CACHE_SHIFT) + from;
buffer = kmap(page);
err = write_file(FILE_HOSTFS_I(file)->fd, &start, buffer + from,
to - from);
if(err > 0) err = 0;
+
+ /* Actually, if !err, write_file has added to-from to start, so, despite
+ * the appearance, we are comparing i_size against the _last_ written
+ * location, as we should. */
+
if(!err && (start > inode->i_size))
inode->i_size = start;
@@ -910,10 +915,8 @@ static struct inode_operations hostfs_dir_iops = {
int hostfs_link_readpage(struct file *file, struct page *page)
{
char *buffer, *name;
- long long start;
int err;
- start = page->index << PAGE_CACHE_SHIFT;
buffer = kmap(page);
name = inode_name(page->mapping->host, 0);
if(name == NULL) return(-ENOMEM);
diff --git a/fs/inotify.c b/fs/inotify.c
index bf7ce1d2412..2fecb7af4a7 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 006bb9e1457..3eaf6e70108 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 b497c71384e..07922881760 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 57d3e77d97e..7a79fbe9f53 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);
@@ -524,7 +509,8 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
return -EINVAL;
/* No mandatory locks over NFS */
- if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+ if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
+ fl->fl_type != F_UNLCK)
return -ENOLCK;
if (IS_GETLK(cmd))
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index afd75d0463f..432f41cd75e 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 7cbf0682b2f..fc95c4df669 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 64ba40572fe..16e10c170ae 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/partitions/Kconfig b/fs/partitions/Kconfig
index deb25b661f0..656bc43431b 100644
--- a/fs/partitions/Kconfig
+++ b/fs/partitions/Kconfig
@@ -203,7 +203,7 @@ config ULTRIX_PARTITION
config SUN_PARTITION
bool "Sun partition tables support" if PARTITION_ADVANCED
- default y if (SPARC32 || SPARC64 || SUN3 || SUN3X)
+ default y if (SPARC || SUN3 || SUN3X)
---help---
Like most systems, SunOS uses its own hard disk partition table
format, incompatible with all others. Saying Y here allows you to
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index b638fb50074..72b431d0a0a 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -54,6 +54,18 @@ proc_file_read(struct file *file, char __user *buf, size_t nbytes,
ssize_t n, count;
char *start;
struct proc_dir_entry * dp;
+ unsigned long long pos;
+
+ /*
+ * Gaah, please just use "seq_file" instead. The legacy /proc
+ * interfaces cut loff_t down to off_t for reads, and ignore
+ * the offset entirely for writes..
+ */
+ pos = *ppos;
+ if (pos > MAX_NON_LFS)
+ return 0;
+ if (nbytes > MAX_NON_LFS - pos)
+ nbytes = MAX_NON_LFS - pos;
dp = PDE(inode);
if (!(page = (char*) __get_free_page(GFP_KERNEL)))
@@ -202,30 +214,17 @@ proc_file_write(struct file *file, const char __user *buffer,
static loff_t
proc_file_lseek(struct file *file, loff_t offset, int orig)
{
- lock_kernel();
-
- switch (orig) {
- case 0:
- if (offset < 0)
- goto out;
- file->f_pos = offset;
- unlock_kernel();
- return(file->f_pos);
- case 1:
- if (offset + file->f_pos < 0)
- goto out;
- file->f_pos += offset;
- unlock_kernel();
- return(file->f_pos);
- case 2:
- goto out;
- default:
- goto out;
- }
-
-out:
- unlock_kernel();
- return -EINVAL;
+ loff_t retval = -EINVAL;
+ switch (orig) {
+ case 1:
+ offset += file->f_pos;
+ /* fallthrough */
+ case 0:
+ if (offset < 0 || offset > MAX_NON_LFS)
+ break;
+ file->f_pos = retval = offset;
+ }
+ return retval;
}
static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 0a044ad9888..a5e3a0ddbe5 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 68b7b78638f..3f17ef844fb 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 16446a15c96..2a6f7f12b7f 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 a9db2255799..bcc2156d4d2 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 1aea42d71a6..5328a293712 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;