diff options
Diffstat (limited to 'fs/gfs2/file.c')
-rw-r--r-- | fs/gfs2/file.c | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 4eb308aa323..a6abbae8a27 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -569,6 +569,40 @@ static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
569 | return ret; | 569 | return ret; |
570 | } | 570 | } |
571 | 571 | ||
572 | /** | ||
573 | * gfs2_file_aio_write - Perform a write to a file | ||
574 | * @iocb: The io context | ||
575 | * @iov: The data to write | ||
576 | * @nr_segs: Number of @iov segments | ||
577 | * @pos: The file position | ||
578 | * | ||
579 | * We have to do a lock/unlock here to refresh the inode size for | ||
580 | * O_APPEND writes, otherwise we can land up writing at the wrong | ||
581 | * offset. There is still a race, but provided the app is using its | ||
582 | * own file locking, this will make O_APPEND work as expected. | ||
583 | * | ||
584 | */ | ||
585 | |||
586 | static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | ||
587 | unsigned long nr_segs, loff_t pos) | ||
588 | { | ||
589 | struct file *file = iocb->ki_filp; | ||
590 | |||
591 | if (file->f_flags & O_APPEND) { | ||
592 | struct dentry *dentry = file->f_dentry; | ||
593 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | ||
594 | struct gfs2_holder gh; | ||
595 | int ret; | ||
596 | |||
597 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); | ||
598 | if (ret) | ||
599 | return ret; | ||
600 | gfs2_glock_dq_uninit(&gh); | ||
601 | } | ||
602 | |||
603 | return generic_file_aio_write(iocb, iov, nr_segs, pos); | ||
604 | } | ||
605 | |||
572 | #ifdef CONFIG_GFS2_FS_LOCKING_DLM | 606 | #ifdef CONFIG_GFS2_FS_LOCKING_DLM |
573 | 607 | ||
574 | /** | 608 | /** |
@@ -711,7 +745,7 @@ const struct file_operations gfs2_file_fops = { | |||
711 | .read = do_sync_read, | 745 | .read = do_sync_read, |
712 | .aio_read = generic_file_aio_read, | 746 | .aio_read = generic_file_aio_read, |
713 | .write = do_sync_write, | 747 | .write = do_sync_write, |
714 | .aio_write = generic_file_aio_write, | 748 | .aio_write = gfs2_file_aio_write, |
715 | .unlocked_ioctl = gfs2_ioctl, | 749 | .unlocked_ioctl = gfs2_ioctl, |
716 | .mmap = gfs2_mmap, | 750 | .mmap = gfs2_mmap, |
717 | .open = gfs2_open, | 751 | .open = gfs2_open, |
@@ -741,7 +775,7 @@ const struct file_operations gfs2_file_fops_nolock = { | |||
741 | .read = do_sync_read, | 775 | .read = do_sync_read, |
742 | .aio_read = generic_file_aio_read, | 776 | .aio_read = generic_file_aio_read, |
743 | .write = do_sync_write, | 777 | .write = do_sync_write, |
744 | .aio_write = generic_file_aio_write, | 778 | .aio_write = gfs2_file_aio_write, |
745 | .unlocked_ioctl = gfs2_ioctl, | 779 | .unlocked_ioctl = gfs2_ioctl, |
746 | .mmap = gfs2_mmap, | 780 | .mmap = gfs2_mmap, |
747 | .open = gfs2_open, | 781 | .open = gfs2_open, |