diff options
author | Steve French <sfrench@us.ibm.com> | 2006-01-12 17:41:28 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2006-01-12 17:41:28 -0500 |
commit | c32a0b689cb9cc160cfcd19735bbf50bb70c6ef4 (patch) | |
tree | 97addaf85d16d817d4a51d5d04d4e8ceb1edfe17 /fs/cifs | |
parent | f3f6ec4b77f627a6427460d6f8884e1042eef134 (diff) |
[CIFS] Allow local filesize for file that is open for write to be updated
from server when mount forcedirectio.
Allowing update of file size with non forcedirectio mounts should be
allowed in the fiture but requires carefully writing out the
last page in the local file if it is a partial page in order to
avoid corruption and careful serialization
Thanks to Maximiliano Curia who suggested similar changes and provided
a testcase.
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsfs.c | 17 | ||||
-rw-r--r-- | fs/cifs/file.c | 10 |
2 files changed, 25 insertions, 2 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 582d66ca6da5..136af8a08f45 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -513,6 +513,17 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf, | |||
513 | return written; | 513 | return written; |
514 | } | 514 | } |
515 | 515 | ||
516 | static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) | ||
517 | { | ||
518 | /* origin == SEEK_END => we must revalidate the cached file length */ | ||
519 | if (origin == 2) { | ||
520 | int retval = cifs_revalidate(file->f_dentry); | ||
521 | if (retval < 0) | ||
522 | return (loff_t)retval; | ||
523 | } | ||
524 | return remote_llseek(file, offset, origin); | ||
525 | } | ||
526 | |||
516 | static struct file_system_type cifs_fs_type = { | 527 | static struct file_system_type cifs_fs_type = { |
517 | .owner = THIS_MODULE, | 528 | .owner = THIS_MODULE, |
518 | .name = "cifs", | 529 | .name = "cifs", |
@@ -586,6 +597,7 @@ struct file_operations cifs_file_ops = { | |||
586 | .flush = cifs_flush, | 597 | .flush = cifs_flush, |
587 | .mmap = cifs_file_mmap, | 598 | .mmap = cifs_file_mmap, |
588 | .sendfile = generic_file_sendfile, | 599 | .sendfile = generic_file_sendfile, |
600 | .llseek = cifs_llseek, | ||
589 | #ifdef CONFIG_CIFS_POSIX | 601 | #ifdef CONFIG_CIFS_POSIX |
590 | .ioctl = cifs_ioctl, | 602 | .ioctl = cifs_ioctl, |
591 | #endif /* CONFIG_CIFS_POSIX */ | 603 | #endif /* CONFIG_CIFS_POSIX */ |
@@ -609,7 +621,7 @@ struct file_operations cifs_file_direct_ops = { | |||
609 | #ifdef CONFIG_CIFS_POSIX | 621 | #ifdef CONFIG_CIFS_POSIX |
610 | .ioctl = cifs_ioctl, | 622 | .ioctl = cifs_ioctl, |
611 | #endif /* CONFIG_CIFS_POSIX */ | 623 | #endif /* CONFIG_CIFS_POSIX */ |
612 | 624 | .llseek = cifs_llseek, | |
613 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 625 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
614 | .dir_notify = cifs_dir_notify, | 626 | .dir_notify = cifs_dir_notify, |
615 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 627 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
@@ -627,6 +639,7 @@ struct file_operations cifs_file_nobrl_ops = { | |||
627 | .flush = cifs_flush, | 639 | .flush = cifs_flush, |
628 | .mmap = cifs_file_mmap, | 640 | .mmap = cifs_file_mmap, |
629 | .sendfile = generic_file_sendfile, | 641 | .sendfile = generic_file_sendfile, |
642 | .llseek = cifs_llseek, | ||
630 | #ifdef CONFIG_CIFS_POSIX | 643 | #ifdef CONFIG_CIFS_POSIX |
631 | .ioctl = cifs_ioctl, | 644 | .ioctl = cifs_ioctl, |
632 | #endif /* CONFIG_CIFS_POSIX */ | 645 | #endif /* CONFIG_CIFS_POSIX */ |
@@ -649,7 +662,7 @@ struct file_operations cifs_file_direct_nobrl_ops = { | |||
649 | #ifdef CONFIG_CIFS_POSIX | 662 | #ifdef CONFIG_CIFS_POSIX |
650 | .ioctl = cifs_ioctl, | 663 | .ioctl = cifs_ioctl, |
651 | #endif /* CONFIG_CIFS_POSIX */ | 664 | #endif /* CONFIG_CIFS_POSIX */ |
652 | 665 | .llseek = cifs_llseek, | |
653 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 666 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
654 | .dir_notify = cifs_dir_notify, | 667 | .dir_notify = cifs_dir_notify, |
655 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 668 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index c249b628fd1c..670ec1e84da0 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1835,10 +1835,20 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode) | |||
1835 | open_file = find_writable_file(cifsInode); | 1835 | open_file = find_writable_file(cifsInode); |
1836 | 1836 | ||
1837 | if(open_file) { | 1837 | if(open_file) { |
1838 | struct cifs_sb_info *cifs_sb; | ||
1839 | |||
1838 | /* there is not actually a write pending so let | 1840 | /* there is not actually a write pending so let |
1839 | this handle go free and allow it to | 1841 | this handle go free and allow it to |
1840 | be closable if needed */ | 1842 | be closable if needed */ |
1841 | atomic_dec(&open_file->wrtPending); | 1843 | atomic_dec(&open_file->wrtPending); |
1844 | |||
1845 | cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb); | ||
1846 | if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) { | ||
1847 | /* since no page cache to corrupt on directio | ||
1848 | we can change size safely */ | ||
1849 | return 1; | ||
1850 | } | ||
1851 | |||
1842 | return 0; | 1852 | return 0; |
1843 | } else | 1853 | } else |
1844 | return 1; | 1854 | return 1; |