Commit 790eac56 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
  ...
parents 0b0585c3 48bde8d3
Loading
Loading
Loading
Loading
+24 −11
Original line number Original line Diff line number Diff line
@@ -11,10 +11,8 @@ be able to use diff(1).
prototypes:
prototypes:
	int (*d_revalidate)(struct dentry *, unsigned int);
	int (*d_revalidate)(struct dentry *, unsigned int);
	int (*d_weak_revalidate)(struct dentry *, unsigned int);
	int (*d_weak_revalidate)(struct dentry *, unsigned int);
	int (*d_hash)(const struct dentry *, const struct inode *,
	int (*d_hash)(const struct dentry *, struct qstr *);
			struct qstr *);
	int (*d_compare)(const struct dentry *, const struct dentry *,
	int (*d_compare)(const struct dentry *, const struct inode *,
			const struct dentry *, const struct inode *,
			unsigned int, const char *, const struct qstr *);
			unsigned int, const char *, const struct qstr *);
	int (*d_delete)(struct dentry *);
	int (*d_delete)(struct dentry *);
	void (*d_release)(struct dentry *);
	void (*d_release)(struct dentry *);
@@ -66,6 +64,7 @@ prototypes:
	int (*atomic_open)(struct inode *, struct dentry *,
	int (*atomic_open)(struct inode *, struct dentry *,
				struct file *, unsigned open_flag,
				struct file *, unsigned open_flag,
				umode_t create_mode, int *opened);
				umode_t create_mode, int *opened);
	int (*tmpfile) (struct inode *, struct dentry *, umode_t);


locking rules:
locking rules:
	all may block
	all may block
@@ -93,6 +92,7 @@ removexattr: yes
fiemap:		no
fiemap:		no
update_time:	no
update_time:	no
atomic_open:	yes
atomic_open:	yes
tmpfile:	no


	Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
	Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
victim.
victim.
@@ -344,25 +344,38 @@ prototypes:




locking rules:
locking rules:
			file_lock_lock	may block
			inode->i_lock	may block
fl_copy_lock:		yes		no
fl_copy_lock:		yes		no
fl_release_private:	maybe		no
fl_release_private:	maybe		no


----------------------- lock_manager_operations ---------------------------
----------------------- lock_manager_operations ---------------------------
prototypes:
prototypes:
	int (*lm_compare_owner)(struct file_lock *, struct file_lock *);
	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 */
	void (*lm_notify)(struct file_lock *);  /* unblock callback */
	int (*lm_grant)(struct file_lock *, struct file_lock *, int);
	int (*lm_grant)(struct file_lock *, struct file_lock *, int);
	void (*lm_break)(struct file_lock *); /* break_lease callback */
	void (*lm_break)(struct file_lock *); /* break_lease callback */
	int (*lm_change)(struct file_lock **, int);
	int (*lm_change)(struct file_lock **, int);


locking rules:
locking rules:
			file_lock_lock	may block

lm_compare_owner:	yes		no
			inode->i_lock	blocked_lock_lock	may block
lm_notify:		yes		no
lm_compare_owner:	yes[1]		maybe			no
lm_grant:		no		no
lm_owner_key		yes[1]		yes			no
lm_break:		yes		no
lm_notify:		yes		yes			no
lm_change		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 -----------------------------------
--------------------------- buffer_head -----------------------------------
prototypes:
prototypes:
+13 −11
Original line number Original line Diff line number Diff line
@@ -360,6 +360,8 @@ struct inode_operations {
	int (*removexattr) (struct dentry *, const char *);
	int (*removexattr) (struct dentry *, const char *);
	void (*update_time)(struct inode *, struct timespec *, int);
	void (*update_time)(struct inode *, struct timespec *, int);
	int (*atomic_open)(struct inode *, struct dentry *,
	int (*atomic_open)(struct inode *, struct dentry *,
	int (*tmpfile) (struct inode *, struct dentry *, umode_t);
} ____cacheline_aligned;
				struct file *, unsigned open_flag,
				struct file *, unsigned open_flag,
				umode_t create_mode, int *opened);
				umode_t create_mode, int *opened);
};
};
@@ -472,6 +474,9 @@ otherwise noted.
  	component is negative or needs lookup.  Cached positive dentries are
  	component is negative or needs lookup.  Cached positive dentries are
  	still handled by f_op->open().
  	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
The Address Space Object
========================
========================


@@ -901,10 +906,8 @@ defined:
struct dentry_operations {
struct dentry_operations {
	int (*d_revalidate)(struct dentry *, unsigned int);
	int (*d_revalidate)(struct dentry *, unsigned int);
	int (*d_weak_revalidate)(struct dentry *, unsigned int);
	int (*d_weak_revalidate)(struct dentry *, unsigned int);
	int (*d_hash)(const struct dentry *, const struct inode *,
	int (*d_hash)(const struct dentry *, struct qstr *);
			struct qstr *);
	int (*d_compare)(const struct dentry *, const struct dentry *,
	int (*d_compare)(const struct dentry *, const struct inode *,
			const struct dentry *, const struct inode *,
			unsigned int, const char *, const struct qstr *);
			unsigned int, const char *, const struct qstr *);
	int (*d_delete)(const struct dentry *);
	int (*d_delete)(const struct dentry *);
	void (*d_release)(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
  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
	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
	Same locking and synchronisation rules as d_compare regarding
	what is safe to dereference etc.
	what is safe to dereference etc.


  d_compare: called to compare a dentry name with a given name. The first
  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
	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
	the child dentry. len and name string are properties of the dentry
	child dentry. len and name string are properties of the dentry to be
	to be compared. qstr is the name to compare it with.
	compared. qstr is the name to compare it with.


	Must be constant and idempotent, and should not take locks if
	Must be constant and idempotent, and should not take locks if
	possible, and should not or store into the dentry or inodes.
	possible, and should not or store into the dentry.
	Should not dereference pointers outside the dentry or inodes without
	Should not dereference pointers outside the dentry without
	lots of care (eg.  d_parent, d_inode, d_name should not be used).
	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
	However, our vfsmount is pinned, and RCU held, so the dentries and
	inodes won't disappear, neither will our sb or filesystem module.
	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
	It is a tricky calling convention because it needs to be called under
	"rcu-walk", ie. without any locks or references on things.
	"rcu-walk", ie. without any locks or references on things.
+1 −0
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@
#define O_SYNC		(__O_SYNC|O_DSYNC)
#define O_SYNC		(__O_SYNC|O_DSYNC)


#define O_PATH		040000000
#define O_PATH		040000000
#define O_TMPFILE	0100000000


#define F_GETLK		7
#define F_GETLK		7
#define F_SETLK		8
#define F_SETLK		8
+1 −1
Original line number Original line Diff line number Diff line
@@ -101,7 +101,7 @@ static void show_faulting_vma(unsigned long address, char *buf)
		if (file) {
		if (file) {
			struct path *path = &file->f_path;
			struct path *path = &file->f_path;
			nm = d_path(path, buf, PAGE_SIZE - 1);
			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;
			dev = inode->i_sb->s_dev;
			ino = inode->i_ino;
			ino = inode->i_ino;
		}
		}
+1 −0
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@
#define O_INVISIBLE	004000000 /* invisible I/O, for DMAPI/XDSM */
#define O_INVISIBLE	004000000 /* invisible I/O, for DMAPI/XDSM */


#define O_PATH		020000000
#define O_PATH		020000000
#define O_TMPFILE	040000000


#define F_GETLK64	8
#define F_GETLK64	8
#define F_SETLK64	9
#define F_SETLK64	9
Loading