aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/fs.h43
1 files changed, 26 insertions, 17 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 215cb1b09f47..a877ed3f389f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -893,6 +893,7 @@ static inline int file_check_writeable(struct file *filp)
#define FL_SLEEP 128 /* A blocking lock */
#define FL_DOWNGRADE_PENDING 256 /* Lease is being downgraded */
#define FL_UNLOCK_PENDING 512 /* Lease is being broken */
+#define FL_FILE_PVT 1024 /* lock is private to the file */
/*
* Special return value from posix_lock_file() and vfs_lock_file() for
@@ -997,12 +998,12 @@ struct file_lock {
extern void send_sigio(struct fown_struct *fown, int fd, int band);
#ifdef CONFIG_FILE_LOCKING
-extern int fcntl_getlk(struct file *, struct flock __user *);
+extern int fcntl_getlk(struct file *, unsigned int, struct flock __user *);
extern int fcntl_setlk(unsigned int, struct file *, unsigned int,
struct flock __user *);
#if BITS_PER_LONG == 32
-extern int fcntl_getlk64(struct file *, struct flock64 __user *);
+extern int fcntl_getlk64(struct file *, unsigned int, struct flock64 __user *);
extern int fcntl_setlk64(unsigned int, struct file *, unsigned int,
struct flock64 __user *);
#endif
@@ -1017,7 +1018,7 @@ extern struct file_lock * locks_alloc_lock(void);
extern void locks_copy_lock(struct file_lock *, struct file_lock *);
extern void __locks_copy_lock(struct file_lock *, const struct file_lock *);
extern void locks_remove_posix(struct file *, fl_owner_t);
-extern void locks_remove_flock(struct file *);
+extern void locks_remove_file(struct file *);
extern void locks_release_private(struct file_lock *);
extern void posix_test_lock(struct file *, struct file_lock *);
extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *);
@@ -1035,7 +1036,8 @@ extern int lease_modify(struct file_lock **, int);
extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
#else /* !CONFIG_FILE_LOCKING */
-static inline int fcntl_getlk(struct file *file, struct flock __user *user)
+static inline int fcntl_getlk(struct file *file, unsigned int cmd,
+ struct flock __user *user)
{
return -EINVAL;
}
@@ -1047,7 +1049,8 @@ static inline int fcntl_setlk(unsigned int fd, struct file *file,
}
#if BITS_PER_LONG == 32
-static inline int fcntl_getlk64(struct file *file, struct flock64 __user *user)
+static inline int fcntl_getlk64(struct file *file, unsigned int cmd,
+ struct flock64 __user *user)
{
return -EINVAL;
}
@@ -1088,7 +1091,7 @@ static inline void locks_remove_posix(struct file *filp, fl_owner_t owner)
return;
}
-static inline void locks_remove_flock(struct file *filp)
+static inline void locks_remove_file(struct file *filp)
{
return;
}
@@ -1916,6 +1919,11 @@ extern int current_umask(void);
extern void ihold(struct inode * inode);
extern void iput(struct inode *);
+static inline struct inode *file_inode(struct file *f)
+{
+ return f->f_inode;
+}
+
/* /sys/fs */
extern struct kobject *fs_kobj;
@@ -1925,7 +1933,7 @@ extern struct kobject *fs_kobj;
#define FLOCK_VERIFY_WRITE 2
#ifdef CONFIG_FILE_LOCKING
-extern int locks_mandatory_locked(struct inode *);
+extern int locks_mandatory_locked(struct file *);
extern int locks_mandatory_area(int, struct inode *, struct file *, loff_t, size_t);
/*
@@ -1948,10 +1956,10 @@ static inline int mandatory_lock(struct inode *ino)
return IS_MANDLOCK(ino) && __mandatory_lock(ino);
}
-static inline int locks_verify_locked(struct inode *inode)
+static inline int locks_verify_locked(struct file *file)
{
- if (mandatory_lock(inode))
- return locks_mandatory_locked(inode);
+ if (mandatory_lock(file_inode(file)))
+ return locks_mandatory_locked(file);
return 0;
}
@@ -1971,6 +1979,12 @@ static inline int locks_verify_truncate(struct inode *inode,
static inline int break_lease(struct inode *inode, unsigned int mode)
{
+ /*
+ * Since this check is lockless, we must ensure that any refcounts
+ * taken are done before checking inode->i_flock. Otherwise, we could
+ * end up racing with tasks trying to set a new lease on this file.
+ */
+ smp_mb();
if (inode->i_flock)
return __break_lease(inode, mode, FL_LEASE);
return 0;
@@ -2006,7 +2020,7 @@ static inline int break_deleg_wait(struct inode **delegated_inode)
}
#else /* !CONFIG_FILE_LOCKING */
-static inline int locks_mandatory_locked(struct inode *inode)
+static inline int locks_mandatory_locked(struct file *file)
{
return 0;
}
@@ -2028,7 +2042,7 @@ static inline int mandatory_lock(struct inode *inode)
return 0;
}
-static inline int locks_verify_locked(struct inode *inode)
+static inline int locks_verify_locked(struct file *file)
{
return 0;
}
@@ -2302,11 +2316,6 @@ static inline bool execute_ok(struct inode *inode)
return (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode);
}
-static inline struct inode *file_inode(struct file *f)
-{
- return f->f_inode;
-}
-
static inline void file_start_write(struct file *file)
{
if (!S_ISREG(file_inode(file)->i_mode))