diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/afs/flock.c | 126 | ||||
| -rw-r--r-- | fs/ext4/extents.c | 2 | ||||
| -rw-r--r-- | fs/gfs2/ops_file.c | 2 | ||||
| -rw-r--r-- | fs/isofs/inode.c | 9 | ||||
| -rw-r--r-- | fs/locks.c | 8 | ||||
| -rw-r--r-- | fs/ncpfs/ncplib_kernel.c | 3 | ||||
| -rw-r--r-- | fs/nfsd/export.c | 5 | ||||
| -rw-r--r-- | fs/nfsd/nfs4idmap.c | 6 | ||||
| -rw-r--r-- | fs/nfsd/nfs4proc.c | 10 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 5 | ||||
| -rw-r--r-- | fs/open.c | 16 | ||||
| -rw-r--r-- | fs/proc/base.c | 2 | ||||
| -rw-r--r-- | fs/ramfs/file-nommu.c | 7 | ||||
| -rw-r--r-- | fs/udf/inode.c | 10 | ||||
| -rw-r--r-- | fs/udf/super.c | 2 | ||||
| -rw-r--r-- | fs/udf/udf_sb.h | 2 |
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 |
