aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Brandenburg <martin@omnibond.com>2018-01-25 19:39:44 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-01-25 20:26:24 -0500
commit6793f1c450b1533a5e9c2493490de771d38b24f9 (patch)
tree5d821cb1fa344cb6c99f9a58e2da5e68ed039653
parent6e20630e300486045bf480139c9e17e7071629ce (diff)
orangefs: fix deadlock; do not write i_size in read_iter
After do_readv_writev, the inode cache is invalidated anyway, so i_size will never be read. It will be fetched from the server which will also know about updates from other machines. Fixes deadlock on 32-bit SMP. See https://marc.info/?l=linux-fsdevel&m=151268557427760&w=2 Signed-off-by: Martin Brandenburg <martin@omnibond.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Mike Marshall <hubcap@omnibond.com> Cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/orangefs/file.c7
-rw-r--r--fs/orangefs/orangefs-kernel.h11
2 files changed, 2 insertions, 16 deletions
diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index 1668fd645c45..0d228cd087e6 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -452,7 +452,7 @@ ssize_t orangefs_inode_read(struct inode *inode,
452static ssize_t orangefs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) 452static ssize_t orangefs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
453{ 453{
454 struct file *file = iocb->ki_filp; 454 struct file *file = iocb->ki_filp;
455 loff_t pos = *(&iocb->ki_pos); 455 loff_t pos = iocb->ki_pos;
456 ssize_t rc = 0; 456 ssize_t rc = 0;
457 457
458 BUG_ON(iocb->private); 458 BUG_ON(iocb->private);
@@ -492,9 +492,6 @@ static ssize_t orangefs_file_write_iter(struct kiocb *iocb, struct iov_iter *ite
492 } 492 }
493 } 493 }
494 494
495 if (file->f_pos > i_size_read(file->f_mapping->host))
496 orangefs_i_size_write(file->f_mapping->host, file->f_pos);
497
498 rc = generic_write_checks(iocb, iter); 495 rc = generic_write_checks(iocb, iter);
499 496
500 if (rc <= 0) { 497 if (rc <= 0) {
@@ -508,7 +505,7 @@ static ssize_t orangefs_file_write_iter(struct kiocb *iocb, struct iov_iter *ite
508 * pos to the end of the file, so we will wait till now to set 505 * pos to the end of the file, so we will wait till now to set
509 * pos... 506 * pos...
510 */ 507 */
511 pos = *(&iocb->ki_pos); 508 pos = iocb->ki_pos;
512 509
513 rc = do_readv_writev(ORANGEFS_IO_WRITE, 510 rc = do_readv_writev(ORANGEFS_IO_WRITE,
514 file, 511 file,
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index 97adf7d100b5..2595453fe737 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -533,17 +533,6 @@ do { \
533 sys_attr.mask = ORANGEFS_ATTR_SYS_ALL_SETABLE; \ 533 sys_attr.mask = ORANGEFS_ATTR_SYS_ALL_SETABLE; \
534} while (0) 534} while (0)
535 535
536static inline void orangefs_i_size_write(struct inode *inode, loff_t i_size)
537{
538#if BITS_PER_LONG == 32 && defined(CONFIG_SMP)
539 inode_lock(inode);
540#endif
541 i_size_write(inode, i_size);
542#if BITS_PER_LONG == 32 && defined(CONFIG_SMP)
543 inode_unlock(inode);
544#endif
545}
546
547static inline void orangefs_set_timeout(struct dentry *dentry) 536static inline void orangefs_set_timeout(struct dentry *dentry)
548{ 537{
549 unsigned long time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000; 538 unsigned long time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000;