aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 09:10:19 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 09:10:19 -0700
commit790eac5640abf7a57fa3a644386df330e18c11b0 (patch)
tree08de20bde44f59e51b91ff473a71047c2957e8c9
parent0b0585c3e192967cb2ef0ac0816eb8a8c8d99840 (diff)
parent48bde8d3620f5f3c6ae9ff599eb404055ae51664 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull second set of VFS changes from Al Viro: "Assorted f_pos race fixes, making do_splice_direct() safe to call with i_mutex on parent, O_TMPFILE support, Jeff's locks.c series, ->d_hash/->d_compare calling conventions changes from Linus, misc stuff all over the place." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (63 commits) Document ->tmpfile() ext4: ->tmpfile() support vfs: export lseek_execute() to modules lseek_execute() doesn't need an inode passed to it block_dev: switch to fixed_size_llseek() cpqphp_sysfs: switch to fixed_size_llseek() tile-srom: switch to fixed_size_llseek() proc_powerpc: switch to fixed_size_llseek() ubi/cdev: switch to fixed_size_llseek() pci/proc: switch to fixed_size_llseek() isapnp: switch to fixed_size_llseek() lpfc: switch to fixed_size_llseek() locks: give the blocked_hash its own spinlock locks: add a new "lm_owner_key" lock operation locks: turn the blocked_list into a hashtable locks: convert fl_link to a hlist_node locks: avoid taking global lock if possible when waking up blocked waiters locks: protect most of the file_lock handling with i_lock locks: encapsulate the fl_link list handling locks: make "added" in __posix_lock_file a bool ...
-rw-r--r--Documentation/filesystems/Locking35
-rw-r--r--Documentation/filesystems/vfs.txt24
-rw-r--r--arch/alpha/include/uapi/asm/fcntl.h1
-rw-r--r--arch/arc/kernel/troubleshoot.c2
-rw-r--r--arch/parisc/include/uapi/asm/fcntl.h1
-rw-r--r--arch/powerpc/kernel/proc_powerpc.c20
-rw-r--r--arch/sparc/include/uapi/asm/fcntl.h1
-rw-r--r--drivers/char/ps3flash.c28
-rw-r--r--drivers/char/tile-srom.c28
-rw-r--r--drivers/mtd/mtdchar.c20
-rw-r--r--drivers/mtd/ubi/cdev.c26
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad_debugfs.c22
-rw-r--r--drivers/net/wireless/ti/wlcore/debugfs.c4
-rw-r--r--drivers/parisc/eisa_eeprom.c15
-rw-r--r--drivers/pci/hotplug/cpqphp_sysfs.c22
-rw-r--r--drivers/pci/proc.c23
-rw-r--r--drivers/pnp/isapnp/proc.c22
-rw-r--r--drivers/scsi/bfa/bfad_debugfs.c28
-rw-r--r--drivers/scsi/fnic/fnic_debugfs.c16
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c18
-rw-r--r--drivers/staging/android/logger.c2
-rw-r--r--drivers/staging/comedi/comedi_fops.c3
-rw-r--r--drivers/tty/vt/vc_screen.c17
-rw-r--r--drivers/zorro/proc.c22
-rw-r--r--fs/adfs/dir.c6
-rw-r--r--fs/affs/namei.c26
-rw-r--r--fs/afs/flock.c7
-rw-r--r--fs/aio.c2
-rw-r--r--fs/block_dev.c23
-rw-r--r--fs/btrfs/file.c15
-rw-r--r--fs/btrfs/ioctl.c8
-rw-r--r--fs/ceph/file.c11
-rw-r--r--fs/ceph/locks.c2
-rw-r--r--fs/ceph/mds_client.c8
-rw-r--r--fs/cifs/cifsfs.c2
-rw-r--r--fs/cifs/dir.c9
-rw-r--r--fs/cifs/file.c15
-rw-r--r--fs/coda/dir.c8
-rw-r--r--fs/dcache.c66
-rw-r--r--fs/ecryptfs/crypto.c5
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h2
-rw-r--r--fs/ecryptfs/file.c9
-rw-r--r--fs/ecryptfs/inode.c2
-rw-r--r--fs/efivarfs/super.c9
-rw-r--r--fs/exec.c10
-rw-r--r--fs/ext2/namei.c24
-rw-r--r--fs/ext3/namei.c47
-rw-r--r--fs/ext4/file.c24
-rw-r--r--fs/ext4/namei.c47
-rw-r--r--fs/fat/namei_msdos.c6
-rw-r--r--fs/fat/namei_vfat.c12
-rw-r--r--fs/file_table.c2
-rw-r--r--fs/fuse/file.c3
-rw-r--r--fs/gfs2/dentry.c3
-rw-r--r--fs/gfs2/file.c2
-rw-r--r--fs/hfs/hfs_fs.h7
-rw-r--r--fs/hfs/string.c6
-rw-r--r--fs/hfsplus/hfsplus_fs.h7
-rw-r--r--fs/hfsplus/unicode.c7
-rw-r--r--fs/hpfs/dentry.c7
-rw-r--r--fs/inode.c4
-rw-r--r--fs/internal.h6
-rw-r--r--fs/isofs/inode.c48
-rw-r--r--fs/isofs/namei.c3
-rw-r--r--fs/jfs/namei.c7
-rw-r--r--fs/lockd/svclock.c14
-rw-r--r--fs/lockd/svcsubs.c12
-rw-r--r--fs/locks.c281
-rw-r--r--fs/minix/dir.c2
-rw-r--r--fs/minix/namei.c13
-rw-r--r--fs/namei.c113
-rw-r--r--fs/ncpfs/dir.c45
-rw-r--r--fs/ncpfs/inode.c4
-rw-r--r--fs/nfs/delegation.c10
-rw-r--r--fs/nfs/nfs4state.c8
-rw-r--r--fs/nfsd/nfs4state.c8
-rw-r--r--fs/notify/fanotify/fanotify_user.c3
-rw-r--r--fs/ocfs2/file.c12
-rw-r--r--fs/open.c63
-rw-r--r--fs/proc/base.c105
-rw-r--r--fs/proc/fd.c18
-rw-r--r--fs/proc/internal.h2
-rw-r--r--fs/proc/namespaces.c13
-rw-r--r--fs/proc/proc_sysctl.c7
-rw-r--r--fs/read_write.c65
-rw-r--r--fs/splice.c38
-rw-r--r--fs/sysv/namei.c3
-rw-r--r--fs/udf/namei.c24
-rw-r--r--fs/xfs/xfs_file.c6
-rw-r--r--include/linux/dcache.h11
-rw-r--r--include/linux/fs.h49
-rw-r--r--include/linux/fsnotify.h8
-rw-r--r--include/uapi/asm-generic/fcntl.h4
-rw-r--r--mm/shmem.c37
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c4
-rw-r--r--security/integrity/ima/ima_main.c2
-rw-r--r--security/selinux/hooks.c24
-rw-r--r--sound/core/pcm_native.c40
98 files changed, 979 insertions, 986 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 9858f337529..fe7afe22538 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -11,10 +11,8 @@ be able to use diff(1).
prototypes:
int (*d_revalidate)(struct dentry *, unsigned int);
int (*d_weak_revalidate)(struct dentry *, unsigned int);
- int (*d_hash)(const struct dentry *, const struct inode *,
- struct qstr *);
- int (*d_compare)(const struct dentry *, const struct inode *,
- const struct dentry *, const struct inode *,
+ int (*d_hash)(const struct dentry *, struct qstr *);
+ int (*d_compare)(const struct dentry *, const struct dentry *,
unsigned int, const char *, const struct qstr *);
int (*d_delete)(struct dentry *);
void (*d_release)(struct dentry *);
@@ -66,6 +64,7 @@ prototypes:
int (*atomic_open)(struct inode *, struct dentry *,
struct file *, unsigned open_flag,
umode_t create_mode, int *opened);
+ int (*tmpfile) (struct inode *, struct dentry *, umode_t);
locking rules:
all may block
@@ -93,6 +92,7 @@ removexattr: yes
fiemap: no
update_time: no
atomic_open: yes
+tmpfile: no
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
victim.
@@ -344,25 +344,38 @@ prototypes:
locking rules:
- file_lock_lock may block
+ inode->i_lock may block
fl_copy_lock: yes no
fl_release_private: maybe no
----------------------- lock_manager_operations ---------------------------
prototypes:
int (*lm_compare_owner)(struct file_lock *, struct file_lock *);
+ unsigned long (*lm_owner_key)(struct file_lock *);
void (*lm_notify)(struct file_lock *); /* unblock callback */
int (*lm_grant)(struct file_lock *, struct file_lock *, int);
void (*lm_break)(struct file_lock *); /* break_lease callback */
int (*lm_change)(struct file_lock **, int);
locking rules:
- file_lock_lock may block
-lm_compare_owner: yes no
-lm_notify: yes no
-lm_grant: no no
-lm_break: yes no
-lm_change yes no
+
+ inode->i_lock blocked_lock_lock may block
+lm_compare_owner: yes[1] maybe no
+lm_owner_key yes[1] yes no
+lm_notify: yes yes no
+lm_grant: no no no
+lm_break: yes no no
+lm_change yes no no
+
+[1]: ->lm_compare_owner and ->lm_owner_key are generally called with
+*an* inode->i_lock held. It may not be the i_lock of the inode
+associated with either file_lock argument! This is the case with deadlock
+detection, since the code has to chase down the owners of locks that may
+be entirely unrelated to the one on which the lock is being acquired.
+For deadlock detection however, the blocked_lock_lock is also held. The
+fact that these locks are held ensures that the file_locks do not
+disappear out from under you while doing the comparison or generating an
+owner key.
--------------------------- buffer_head -----------------------------------
prototypes:
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index e6bd1ffd821..1f0ba30ae47 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -360,6 +360,8 @@ struct inode_operations {
int (*removexattr) (struct dentry *, const char *);
void (*update_time)(struct inode *, struct timespec *, int);
int (*atomic_open)(struct inode *, struct dentry *,
+ int (*tmpfile) (struct inode *, struct dentry *, umode_t);
+} ____cacheline_aligned;
struct file *, unsigned open_flag,
umode_t create_mode, int *opened);
};
@@ -472,6 +474,9 @@ otherwise noted.
component is negative or needs lookup. Cached positive dentries are
still handled by f_op->open().
+ tmpfile: called in the end of O_TMPFILE open(). Optional, equivalent to
+ atomically creating, opening and unlinking a file in given directory.
+
The Address Space Object
========================
@@ -901,10 +906,8 @@ defined:
struct dentry_operations {
int (*d_revalidate)(struct dentry *, unsigned int);
int (*d_weak_revalidate)(struct dentry *, unsigned int);
- int (*d_hash)(const struct dentry *, const struct inode *,
- struct qstr *);
- int (*d_compare)(const struct dentry *, const struct inode *,
- const struct dentry *, const struct inode *,
+ int (*d_hash)(const struct dentry *, struct qstr *);
+ int (*d_compare)(const struct dentry *, const struct dentry *,
unsigned int, const char *, const struct qstr *);
int (*d_delete)(const struct dentry *);
void (*d_release)(struct dentry *);
@@ -949,25 +952,24 @@ struct dentry_operations {
d_hash: called when the VFS adds a dentry to the hash table. The first
dentry passed to d_hash is the parent directory that the name is
- to be hashed into. The inode is the dentry's inode.
+ to be hashed into.
Same locking and synchronisation rules as d_compare regarding
what is safe to dereference etc.
d_compare: called to compare a dentry name with a given name. The first
dentry is the parent of the dentry to be compared, the second is
- the parent's inode, then the dentry and inode (may be NULL) of the
- child dentry. len and name string are properties of the dentry to be
- compared. qstr is the name to compare it with.
+ the child dentry. len and name string are properties of the dentry
+ to be compared. qstr is the name to compare it with.
Must be constant and idempotent, and should not take locks if
- possible, and should not or store into the dentry or inodes.
- Should not dereference pointers outside the dentry or inodes without
+ possible, and should not or store into the dentry.
+ Should not dereference pointers outside the dentry without
lots of care (eg. d_parent, d_inode, d_name should not be used).
However, our vfsmount is pinned, and RCU held, so the dentries and
inodes won't disappear, neither will our sb or filesystem module.
- ->i_sb and ->d_sb may be used.
+ ->d_sb may be used.
It is a tricky calling convention because it needs to be called under
"rcu-walk", ie. without any locks or references on things.
diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
index 6d9e805f18a..dfdadb0b4be 100644
--- a/arch/alpha/include/uapi/asm/fcntl.h
+++ b/arch/alpha/include/uapi/asm/fcntl.h
@@ -32,6 +32,7 @@
#define O_SYNC (__O_SYNC|O_DSYNC)
#define O_PATH 040000000
+#define O_TMPFILE 0100000000
#define F_GETLK 7
#define F_SETLK 8
diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c
index 11c301b81c9..a03528ecd27 100644
--- a/arch/arc/kernel/troubleshoot.c
+++ b/arch/arc/kernel/troubleshoot.c
@@ -101,7 +101,7 @@ static void show_faulting_vma(unsigned long address, char *buf)
if (file) {
struct path *path = &file->f_path;
nm = d_path(path, buf, PAGE_SIZE - 1);
- inode = vma->vm_file->f_path.dentry->d_inode;
+ inode = file_inode(vma->vm_file);
dev = inode->i_sb->s_dev;
ino = inode->i_ino;
}
diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h
index 0304b92ccfe..cc61c475f27 100644
--- a/arch/parisc/include/uapi/asm/fcntl.h
+++ b/arch/parisc/include/uapi/asm/fcntl.h
@@ -20,6 +20,7 @@
#define O_INVISIBLE 004000000 /* invisible I/O, for DMAPI/XDSM */
#define O_PATH 020000000
+#define O_TMPFILE 040000000
#define F_GETLK64 8
#define F_SETLK64 9
diff --git a/arch/powerpc/kernel/proc_powerpc.c b/arch/powerpc/kernel/proc_powerpc.c
index feb8580fdc8..c30612aad68 100644
--- a/arch/powerpc/kernel/proc_powerpc.c
+++ b/arch/powerpc/kernel/proc_powerpc.c
@@ -29,25 +29,9 @@
#ifdef CONFIG_PPC64
-static loff_t page_map_seek( struct file *file, loff_t off, int whence)
+static loff_t page_map_seek(struct file *file, loff_t off, int whence)
{
- loff_t new;
- switch(whence) {
- case 0:
- new = off;
- break;
- case 1:
- new = file->f_pos + off;
- break;
- case 2:
- new = PAGE_SIZE + off;
- break;
- default:
- return -EINVAL;
- }
- if ( new < 0 || new > PAGE_SIZE )
- return -EINVAL;
- return (file->f_pos = new);
+ return fixed_size_llseek(file, off, whence, PAGE_SIZE);
}
static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes,
diff --git a/arch/sparc/include/uapi/asm/fcntl.h b/arch/sparc/include/uapi/asm/fcntl.h
index d0b83f66f35..d73e5e008b0 100644
--- a/arch/sparc/include/uapi/asm/fcntl.h
+++ b/arch/sparc/include/uapi/asm/fcntl.h
@@ -35,6 +35,7 @@
#define O_SYNC (__O_SYNC|O_DSYNC)
#define O_PATH 0x1000000
+#define O_TMPFILE 0x2000000
#define F_GETOWN 5 /* for sockets. */
#define F_SETOWN 6 /* for sockets. */
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c
index 8cafa9ccd43..0b311fa277e 100644
--- a/drivers/char/ps3flash.c
+++ b/drivers/char/ps3flash.c
@@ -98,32 +98,8 @@ static int ps3flash_fetch(struct ps3_storage_device *dev, u64 start_sector)
static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
{
struct ps3_storage_device *dev = ps3flash_dev;
- loff_t res;
-
- mutex_lock(&file->f_mapping->host->i_mutex);
- switch (origin) {
- case 0:
- break;
- case 1:
- offset += file->f_pos;
- break;
- case 2:
- offset += dev->regions[dev->region_idx].size*dev->blk_size;
- break;
- default:
- offset = -1;
- }
- if (offset < 0) {
- res = -EINVAL;
- goto out;
- }
-
- file->f_pos = offset;
- res = file->f_pos;
-
-out:
- mutex_unlock(&file->f_mapping->host->i_mutex);
- return res;
+ return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
+ dev->regions[dev->region_idx].size*dev->blk_size);
}
static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf,
diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c
index 2e2036e940f..7faeb1cde97 100644
--- a/drivers/char/tile-srom.c
+++ b/drivers/char/tile-srom.c
@@ -273,32 +273,10 @@ static ssize_t srom_write(struct file *filp, const char __user *buf,
}
/* Provide our own implementation so we can use srom->total_size. */
-loff_t srom_llseek(struct file *filp, loff_t offset, int origin)
+loff_t srom_lls