|
@@ -1753,6 +1753,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
|
|
|
struct file_lock *file_lock = locks_alloc_lock();
|
|
|
struct flock flock;
|
|
|
struct inode *inode;
|
|
|
+ struct file *f;
|
|
|
int error;
|
|
|
|
|
|
if (file_lock == NULL)
|
|
@@ -1825,7 +1826,15 @@ again:
|
|
|
* Attempt to detect a close/fcntl race and recover by
|
|
|
* releasing the lock that was just acquired.
|
|
|
*/
|
|
|
- if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) {
|
|
|
+ /*
|
|
|
+ * we need that spin_lock here - it prevents reordering between
|
|
|
+ * update of inode->i_flock and check for it done in close().
|
|
|
+ * rcu_read_lock() wouldn't do.
|
|
|
+ */
|
|
|
+ spin_lock(¤t->files->file_lock);
|
|
|
+ f = fcheck(fd);
|
|
|
+ spin_unlock(¤t->files->file_lock);
|
|
|
+ if (!error && f != filp && flock.l_type != F_UNLCK) {
|
|
|
flock.l_type = F_UNLCK;
|
|
|
goto again;
|
|
|
}
|
|
@@ -1881,6 +1890,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
|
|
|
struct file_lock *file_lock = locks_alloc_lock();
|
|
|
struct flock64 flock;
|
|
|
struct inode *inode;
|
|
|
+ struct file *f;
|
|
|
int error;
|
|
|
|
|
|
if (file_lock == NULL)
|
|
@@ -1953,7 +1963,10 @@ again:
|
|
|
* Attempt to detect a close/fcntl race and recover by
|
|
|
* releasing the lock that was just acquired.
|
|
|
*/
|
|
|
- if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) {
|
|
|
+ spin_lock(¤t->files->file_lock);
|
|
|
+ f = fcheck(fd);
|
|
|
+ spin_unlock(¤t->files->file_lock);
|
|
|
+ if (!error && f != filp && flock.l_type != F_UNLCK) {
|
|
|
flock.l_type = F_UNLCK;
|
|
|
goto again;
|
|
|
}
|