summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/afs/flock.c126
-rw-r--r--fs/ext4/extents.c2
-rw-r--r--fs/gfs2/ops_file.c2
-rw-r--r--fs/isofs/inode.c9
-rw-r--r--fs/locks.c8
-rw-r--r--fs/ncpfs/ncplib_kernel.c3
-rw-r--r--fs/nfsd/export.c5
-rw-r--r--fs/nfsd/nfs4idmap.c6
-rw-r--r--fs/nfsd/nfs4proc.c10
-rw-r--r--fs/nfsd/vfs.c5
-rw-r--r--fs/open.c16
-rw-r--r--fs/proc/base.c2
-rw-r--r--fs/ramfs/file-nommu.c7
-rw-r--r--fs/udf/inode.c10
-rw-r--r--fs/udf/super.c2
-rw-r--r--fs/udf/udf_sb.h2
16 files changed, 139 insertions, 76 deletions
diff --git a/fs/afs/flock.c b/fs/afs/flock.c
index 4f77f3caee9..af6952e39a1 100644
--- a/fs/afs/flock.c
+++ b/fs/afs/flock.c
@@ -19,6 +19,7 @@ static void afs_fl_copy_lock(struct file_lock *new, struct file_lock *fl);
static void afs_fl_release_private(struct file_lock *fl);
static struct workqueue_struct *afs_lock_manager;
+static DEFINE_MUTEX(afs_lock_manager_mutex);
static struct file_lock_operations afs_lock_ops = {
.fl_copy_lock = afs_fl_copy_lock,
@@ -30,12 +31,20 @@ static struct file_lock_operations afs_lock_ops = {
*/
static int afs_init_lock_manager(void)
{
+ int ret;
+
+ ret = 0;
if (!afs_lock_manager) {
- afs_lock_manager = create_singlethread_workqueue("kafs_lockd");
- if (!afs_lock_manager)
- return -ENOMEM;
+ mutex_lock(&afs_lock_manager_mutex);
+ if (!afs_lock_manager) {
+ afs_lock_manager =
+ create_singlethread_workqueue("kafs_lockd");
+ if (!afs_lock_manager)
+ ret = -ENOMEM;
+ }
+ mutex_unlock(&afs_lock_manager_mutex);
}
- return 0;
+ return ret;
}
/*
@@ -68,6 +77,29 @@ static void afs_schedule_lock_extension(struct afs_vnode *vnode)
}
/*
+ * grant one or more locks (readlocks are allowed to jump the queue if the
+ * first lock in the queue is itself a readlock)
+ * - the caller must hold the vnode lock
+ */
+static void afs_grant_locks(struct afs_vnode *vnode, struct file_lock *fl)
+{
+ struct file_lock *p, *_p;
+
+ list_move_tail(&fl->fl_u.afs.link, &vnode->granted_locks);
+ if (fl->fl_type == F_RDLCK) {
+ list_for_each_entry_safe(p, _p, &vnode->pending_locks,
+ fl_u.afs.link) {
+ if (p->fl_type == F_RDLCK) {
+ p->fl_u.afs.state = AFS_LOCK_GRANTED;
+ list_move_tail(&p->fl_u.afs.link,
+ &vnode->granted_locks);
+ wake_up(&p->fl_wait);
+ }
+ }
+ }
+}
+
+/*
* do work for a lock, including:
* - probing for a lock we're waiting on but didn't get immediately
* - extending a lock that's close to timing out
@@ -172,8 +204,7 @@ void afs_lock_work(struct work_struct *work)
struct file_lock, fl_u.afs.link) == fl) {
fl->fl_u.afs.state = ret;
if (ret == AFS_LOCK_GRANTED)
- list_move_tail(&fl->fl_u.afs.link,
- &vnode->granted_locks);
+ afs_grant_locks(vnode, fl);
else
list_del_init(&fl->fl_u.afs.link);
wake_up(&fl->fl_wait);
@@ -258,49 +289,50 @@ static int afs_do_setlk(struct file *file, struct file_lock *fl)
spin_lock(&vnode->lock);
- if (list_empty(&vnode->pending_locks)) {
- /* if there's no-one else with a lock on this vnode, then we
- * need to ask the server for a lock */
- if (list_empty(&vnode->granted_locks)) {
- _debug("not locked");
- ASSERTCMP(vnode->flags &
- ((1 << AFS_VNODE_LOCKING) |
- (1 << AFS_VNODE_READLOCKED) |
- (1 << AFS_VNODE_WRITELOCKED)), ==, 0);
- list_add_tail(&fl->fl_u.afs.link, &vnode->pending_locks);
- set_bit(AFS_VNODE_LOCKING, &vnode->flags);
- spin_unlock(&vnode->lock);
+ /* if we've already got a readlock on the server then we can instantly
+ * grant another readlock, irrespective of whether there are any
+ * pending writelocks */
+ if (type == AFS_LOCK_READ &&
+ vnode->flags & (1 << AFS_VNODE_READLOCKED)) {
+ _debug("instant readlock");
+ ASSERTCMP(vnode->flags &
+ ((1 << AFS_VNODE_LOCKING) |
+ (1 << AFS_VNODE_WRITELOCKED)), ==, 0);
+ ASSERT(!list_empty(&vnode->granted_locks));
+ goto sharing_existing_lock;
+ }
- ret = afs_vnode_set_lock(vnode, key, type);
- clear_bit(AFS_VNODE_LOCKING, &vnode->flags);
- switch (ret) {
- case 0:
- goto acquired_server_lock;
- case -EWOULDBLOCK:
- spin_lock(&vnode->lock);
- ASSERT(list_empty(&vnode->granted_locks));
- ASSERTCMP(vnode->pending_locks.next, ==,
- &fl->fl_u.afs.link);
- goto wait;
- default:
- spin_lock(&vnode->lock);
- list_del_init(&fl->fl_u.afs.link);
- spin_unlock(&vnode->lock);
- goto error;
- }
- }
+ /* if there's no-one else with a lock on this vnode, then we need to
+ * ask the server for a lock */
+ if (list_empty(&vnode->pending_locks) &&
+ list_empty(&vnode->granted_locks)) {
+ _debug("not locked");
+ ASSERTCMP(vnode->flags &
+ ((1 << AFS_VNODE_LOCKING) |
+ (1 << AFS_VNODE_READLOCKED) |
+ (1 << AFS_VNODE_WRITELOCKED)), ==, 0);
+ list_add_tail(&fl->fl_u.afs.link, &vnode->pending_locks);
+ set_bit(AFS_VNODE_LOCKING, &vnode->flags);
+ spin_unlock(&vnode->lock);
- /* if we've already got a readlock on the server and no waiting
- * writelocks, then we might be able to instantly grant another
- * readlock */
- if (type == AFS_LOCK_READ &&
- vnode->flags & (1 << AFS_VNODE_READLOCKED)) {
- _debug("instant readlock");
- ASSERTCMP(vnode->flags &
- ((1 << AFS_VNODE_LOCKING) |
- (1 << AFS_VNODE_WRITELOCKED)), ==, 0);
- ASSERT(!list_empty(&vnode->granted_locks));
- goto sharing_existing_lock;
+ ret = afs_vnode_set_lock(vnode, key, type);
+ clear_bit(AFS_VNODE_LOCKING, &vnode->flags);
+ switch (ret) {
+ case 0:
+ _debug("acquired");
+ goto acquired_server_lock;
+ case -EWOULDBLOCK:
+ _debug("would block");
+ spin_lock(&vnode->lock);
+ ASSERT(list_empty(&vnode->granted_locks));
+ ASSERTCMP(vnode->pending_locks.next, ==,
+ &fl->fl_u.afs.link);
+ goto wait;
+ default:
+ spin_lock(&vnode->lock);
+ list_del_init(&fl->fl_u.afs.link);
+ spin_unlock(&vnode->lock);
+ goto error;
}
}
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 750c46f7d89..78beb096f57 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1544,7 +1544,7 @@ int ext4_ext_walk_space(struct inode *inode, unsigned long block,
static void
ext4_ext_put_in_cache(struct inode *inode, __u32 block,
- __u32 len, __u32 start, int type)
+ __u32 len, ext4_fsblk_t start, int type)
{
struct ext4_ext_cache *cex;
BUG_ON(len == 0);
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 1a5e8e893d7..77342113011 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -508,7 +508,7 @@ static int gfs2_setlease(struct file *file, long arg, struct file_lock **fl)
*/
if (!sdp->sd_args.ar_localflocks)
return -EINVAL;
- return setlease(file, arg, fl);
+ return generic_setlease(file, arg, fl);
}
/**
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 95c72aa8186..043b470fd3b 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -846,6 +846,15 @@ root_found:
goto out_no_root;
if (!inode->i_op)
goto out_bad_root;
+
+ /* Make sure the root inode is a directory */
+ if (!S_ISDIR(inode->i_mode)) {
+ printk(KERN_WARNING
+ "isofs_fill_super: root inode is not a directory. "
+ "Corrupted media?\n");
+ goto out_iput;
+ }
+
/* get the root dentry */
s->s_root = d_alloc_root(inode);
if (!(s->s_root))
diff --git a/fs/locks.c b/fs/locks.c
index 31051063724..50857d2d340 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1324,7 +1324,7 @@ int fcntl_getlease(struct file *filp)
}
/**
- * setlease - sets a lease on an open file
+ * generic_setlease - sets a lease on an open file
* @filp: file pointer
* @arg: type of lease to obtain
* @flp: input - file_lock to use, output - file_lock inserted
@@ -1334,7 +1334,7 @@ int fcntl_getlease(struct file *filp)
*
* Called with kernel lock held.
*/
-int setlease(struct file *filp, long arg, struct file_lock **flp)
+int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
{
struct file_lock *fl, **before, **my_before = NULL, *lease;
struct dentry *dentry = filp->f_path.dentry;
@@ -1419,7 +1419,7 @@ int setlease(struct file *filp, long arg, struct file_lock **flp)
out:
return error;
}
-EXPORT_SYMBOL(setlease);
+EXPORT_SYMBOL(generic_setlease);
/**
* vfs_setlease - sets a lease on an open file
@@ -1456,7 +1456,7 @@ int vfs_setlease(struct file *filp, long arg, struct file_lock **lease)
if (filp->f_op && filp->f_op->setlease)
error = filp->f_op->setlease(filp, arg, lease);
else
- error = setlease(filp, arg, lease);
+ error = generic_setlease(filp, arg, lease);
unlock_kernel();
return error;
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
index 551e0bac7aa..df6d60bdfcd 100644
--- a/fs/ncpfs/ncplib_kernel.c
+++ b/fs/ncpfs/ncplib_kernel.c
@@ -726,9 +726,6 @@ ncp_del_file_or_subdir2(struct ncp_server *server,
__le32 dirent;
if (!inode) {
-#ifdef CONFIG_NCPFS_DEBUGDENTRY
- PRINTK("ncpfs: ncpdel2: dentry->d_inode == NULL\n");
-#endif
return 0xFF; /* Any error */
}
volnum = NCP_FINFO(inode)->volNumber;
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 2d295dda4c1..cba899a3494 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -564,9 +564,10 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
/* flags */
err = get_int(&mesg, &an_int);
- if (err == -ENOENT)
+ if (err == -ENOENT) {
+ err = 0;
set_bit(CACHE_NEGATIVE, &exp.h.flags);
- else {
+ } else {
if (err || an_int < 0) goto out;
exp.ex_flags= an_int;
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 2cf9a9a2d89..2ccffde81b8 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -138,7 +138,7 @@ idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
char idstr[11];
qword_add(bpp, blen, ent->authname);
- snprintf(idstr, sizeof(idstr), "%d", ent->id);
+ snprintf(idstr, sizeof(idstr), "%u", ent->id);
qword_add(bpp, blen, ent->type == IDMAP_TYPE_GROUP ? "group" : "user");
qword_add(bpp, blen, idstr);
@@ -165,7 +165,7 @@ idtoname_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
return 0;
}
ent = container_of(h, struct ent, h);
- seq_printf(m, "%s %s %d", ent->authname,
+ seq_printf(m, "%s %s %u", ent->authname,
ent->type == IDMAP_TYPE_GROUP ? "group" : "user",
ent->id);
if (test_bit(CACHE_VALID, &h->flags))
@@ -349,7 +349,7 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
ent->type == IDMAP_TYPE_GROUP ? "group" : "user",
ent->name);
if (test_bit(CACHE_VALID, &h->flags))
- seq_printf(m, " %d", ent->id);
+ seq_printf(m, " %u", ent->id);
seq_printf(m, "\n");
return 0;
}
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 3c627128e20..29b7e63cb32 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -100,7 +100,15 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data,
open->op_fname.len, &open->op_iattr,
&resfh, open->op_createmode,
- (u32 *)open->op_verf.data, &open->op_truncate, &created);
+ (u32 *)open->op_verf.data,
+ &open->op_truncate, &created);
+
+ /* If we ever decide to use different attrs to store the
+ * verifier in nfsd_create_v3, then we'll need to change this
+ */
+ if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0)
+ open->op_bmval[1] |= (FATTR4_WORD1_TIME_ACCESS |
+ FATTR4_WORD1_TIME_MODIFY);
} else {
status = nfsd_lookup(rqstp, current_fh,
open->op_fname.data, open->op_fname.len, &resfh);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index ee96a897a29..a0c2b253818 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1309,7 +1309,10 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
if (createmode == NFS3_CREATE_EXCLUSIVE) {
/* solaris7 gets confused (bugid 4218508) if these have
- * the high bit set, so just clear the high bits.
+ * the high bit set, so just clear the high bits. If this is
+ * ever changed to use different attrs for storing the
+ * verifier, then do_open_lookup() will also need to be fixed
+ * accordingly.
*/
v_mtime = verifier[0]&0x7fffffff;
v_atime = verifier[1]&0x7fffffff;
diff --git a/fs/open.c b/fs/open.c
index e27c205364d..1d9e5e98bf4 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -256,24 +256,26 @@ static long do_sys_truncate(const char __user * path, loff_t length)
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
goto dput_and_out;
- /*
- * Make sure that there are no leases.
- */
- error = break_lease(inode, FMODE_WRITE);
+ error = get_write_access(inode);
if (error)
goto dput_and_out;
- error = get_write_access(inode);
+ /*
+ * Make sure that there are no leases. get_write_access() protects
+ * against the truncate racing with a lease-granting setlease().
+ */
+ error = break_lease(inode, FMODE_WRITE);
if (error)
- goto dput_and_out;
+ goto put_write_and_out;
error = locks_verify_truncate(inode, NULL, length);
if (!error) {
DQUOT_INIT(inode);
error = do_truncate(nd.dentry, length, 0, NULL);
}
- put_write_access(inode);
+put_write_and_out:
+ put_write_access(inode);
dput_and_out:
path_release(&nd);
out:
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 3c77d5a64e7..19489b0d555 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -927,7 +927,7 @@ static const struct file_operations proc_pid_sched_operations = {
.read = seq_read,
.write = sched_write,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = single_release,
};
#endif
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index cad2b7ace63..237fe8b8e81 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -295,5 +295,10 @@ unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
*/
int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma)
{
- return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS;
+ if (!(vma->vm_flags & VM_SHARED))
+ return -ENOSYS;
+
+ file_accessed(file);
+ vma->vm_ops = &generic_file_vm_ops;
+ return 0;
}
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 0d2c41666cd..1652b2c665b 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1127,13 +1127,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
}
inode->i_uid = le32_to_cpu(fe->uid);
- if (inode->i_uid == -1 || UDF_QUERY_FLAG(inode->i_sb,
- UDF_FLAG_UID_IGNORE))
+ if (inode->i_uid == -1 ||
+ UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_IGNORE) ||
+ UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_SET))
inode->i_uid = UDF_SB(inode->i_sb)->s_uid;
inode->i_gid = le32_to_cpu(fe->gid);
- if (inode->i_gid == -1 || UDF_QUERY_FLAG(inode->i_sb,
- UDF_FLAG_GID_IGNORE))
+ if (inode->i_gid == -1 ||
+ UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_IGNORE) ||
+ UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_SET))
inode->i_gid = UDF_SB(inode->i_sb)->s_gid;
inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 7b30964665d..382be7be5ae 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -366,11 +366,13 @@ static int udf_parse_options(char *options, struct udf_options *uopt)
if (match_int(args, &option))
return 0;
uopt->gid = option;
+ uopt->flags |= (1 << UDF_FLAG_GID_SET);
break;
case Opt_uid:
if (match_int(args, &option))
return 0;
uopt->uid = option;
+ uopt->flags |= (1 << UDF_FLAG_UID_SET);
break;
case Opt_umask:
if (match_octal(args, &option))
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h
index 3e937d3fb8f..3c2982017c6 100644
--- a/fs/udf/udf_sb.h
+++ b/fs/udf/udf_sb.h
@@ -24,6 +24,8 @@
#define UDF_FLAG_UID_IGNORE 12 /* use sb uid instead of on disk uid */
#define UDF_FLAG_GID_FORGET 13
#define UDF_FLAG_GID_IGNORE 14
+#define UDF_FLAG_UID_SET 15
+#define UDF_FLAG_GID_SET 16
#define UDF_PART_FLAG_UNALLOC_BITMAP 0x0001
#define UDF_PART_FLAG_UNALLOC_TABLE 0x0002