diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 167 |
1 files changed, 56 insertions, 111 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index faf59529e847..c672afef0c09 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -857,95 +857,6 @@ cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | |||
857 | cifsi->server_eof = end_of_write; | 857 | cifsi->server_eof = end_of_write; |
858 | } | 858 | } |
859 | 859 | ||
860 | ssize_t cifs_user_write(struct file *file, const char __user *write_data, | ||
861 | size_t write_size, loff_t *poffset) | ||
862 | { | ||
863 | struct inode *inode = file->f_path.dentry->d_inode; | ||
864 | int rc = 0; | ||
865 | unsigned int bytes_written = 0; | ||
866 | unsigned int total_written; | ||
867 | struct cifs_sb_info *cifs_sb; | ||
868 | struct cifsTconInfo *pTcon; | ||
869 | int xid; | ||
870 | struct cifsFileInfo *open_file; | ||
871 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | ||
872 | |||
873 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
874 | |||
875 | /* cFYI(1, " write %d bytes to offset %lld of %s", write_size, | ||
876 | *poffset, file->f_path.dentry->d_name.name); */ | ||
877 | |||
878 | if (file->private_data == NULL) | ||
879 | return -EBADF; | ||
880 | |||
881 | open_file = file->private_data; | ||
882 | pTcon = tlink_tcon(open_file->tlink); | ||
883 | |||
884 | rc = generic_write_checks(file, poffset, &write_size, 0); | ||
885 | if (rc) | ||
886 | return rc; | ||
887 | |||
888 | xid = GetXid(); | ||
889 | |||
890 | for (total_written = 0; write_size > total_written; | ||
891 | total_written += bytes_written) { | ||
892 | rc = -EAGAIN; | ||
893 | while (rc == -EAGAIN) { | ||
894 | if (file->private_data == NULL) { | ||
895 | /* file has been closed on us */ | ||
896 | FreeXid(xid); | ||
897 | /* if we have gotten here we have written some data | ||
898 | and blocked, and the file has been freed on us while | ||
899 | we blocked so return what we managed to write */ | ||
900 | return total_written; | ||
901 | } | ||
902 | if (open_file->invalidHandle) { | ||
903 | /* we could deadlock if we called | ||
904 | filemap_fdatawait from here so tell | ||
905 | reopen_file not to flush data to server | ||
906 | now */ | ||
907 | rc = cifs_reopen_file(open_file, false); | ||
908 | if (rc != 0) | ||
909 | break; | ||
910 | } | ||
911 | |||
912 | rc = CIFSSMBWrite(xid, pTcon, | ||
913 | open_file->netfid, | ||
914 | min_t(const int, cifs_sb->wsize, | ||
915 | write_size - total_written), | ||
916 | *poffset, &bytes_written, | ||
917 | NULL, write_data + total_written, 0); | ||
918 | } | ||
919 | if (rc || (bytes_written == 0)) { | ||
920 | if (total_written) | ||
921 | break; | ||
922 | else { | ||
923 | FreeXid(xid); | ||
924 | return rc; | ||
925 | } | ||
926 | } else { | ||
927 | cifs_update_eof(cifsi, *poffset, bytes_written); | ||
928 | *poffset += bytes_written; | ||
929 | } | ||
930 | } | ||
931 | |||
932 | cifs_stats_bytes_written(pTcon, total_written); | ||
933 | |||
934 | /* Do not update local mtime - server will set its actual value on write | ||
935 | * inode->i_ctime = inode->i_mtime = | ||
936 | * current_fs_time(inode->i_sb);*/ | ||
937 | if (total_written > 0) { | ||
938 | spin_lock(&inode->i_lock); | ||
939 | if (*poffset > inode->i_size) | ||
940 | i_size_write(inode, *poffset); | ||
941 | spin_unlock(&inode->i_lock); | ||
942 | } | ||
943 | mark_inode_dirty_sync(inode); | ||
944 | |||
945 | FreeXid(xid); | ||
946 | return total_written; | ||
947 | } | ||
948 | |||
949 | static ssize_t cifs_write(struct cifsFileInfo *open_file, | 860 | static ssize_t cifs_write(struct cifsFileInfo *open_file, |
950 | const char *write_data, size_t write_size, | 861 | const char *write_data, size_t write_size, |
951 | loff_t *poffset) | 862 | loff_t *poffset) |
@@ -1420,9 +1331,10 @@ retry_write: | |||
1420 | return rc; | 1331 | return rc; |
1421 | } | 1332 | } |
1422 | 1333 | ||
1423 | static int cifs_writepage(struct page *page, struct writeback_control *wbc) | 1334 | static int |
1335 | cifs_writepage_locked(struct page *page, struct writeback_control *wbc) | ||
1424 | { | 1336 | { |
1425 | int rc = -EFAULT; | 1337 | int rc; |
1426 | int xid; | 1338 | int xid; |
1427 | 1339 | ||
1428 | xid = GetXid(); | 1340 | xid = GetXid(); |
@@ -1442,15 +1354,29 @@ static int cifs_writepage(struct page *page, struct writeback_control *wbc) | |||
1442 | * to fail to update with the state of the page correctly. | 1354 | * to fail to update with the state of the page correctly. |
1443 | */ | 1355 | */ |
1444 | set_page_writeback(page); | 1356 | set_page_writeback(page); |
1357 | retry_write: | ||
1445 | rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE); | 1358 | rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE); |
1446 | SetPageUptodate(page); /* BB add check for error and Clearuptodate? */ | 1359 | if (rc == -EAGAIN && wbc->sync_mode == WB_SYNC_ALL) |
1447 | unlock_page(page); | 1360 | goto retry_write; |
1361 | else if (rc == -EAGAIN) | ||
1362 | redirty_page_for_writepage(wbc, page); | ||
1363 | else if (rc != 0) | ||
1364 | SetPageError(page); | ||
1365 | else | ||
1366 | SetPageUptodate(page); | ||
1448 | end_page_writeback(page); | 1367 | end_page_writeback(page); |
1449 | page_cache_release(page); | 1368 | page_cache_release(page); |
1450 | FreeXid(xid); | 1369 | FreeXid(xid); |
1451 | return rc; | 1370 | return rc; |
1452 | } | 1371 | } |
1453 | 1372 | ||
1373 | static int cifs_writepage(struct page *page, struct writeback_control *wbc) | ||
1374 | { | ||
1375 | int rc = cifs_writepage_locked(page, wbc); | ||
1376 | unlock_page(page); | ||
1377 | return rc; | ||
1378 | } | ||
1379 | |||
1454 | static int cifs_write_end(struct file *file, struct address_space *mapping, | 1380 | static int cifs_write_end(struct file *file, struct address_space *mapping, |
1455 | loff_t pos, unsigned len, unsigned copied, | 1381 | loff_t pos, unsigned len, unsigned copied, |
1456 | struct page *page, void *fsdata) | 1382 | struct page *page, void *fsdata) |
@@ -1519,8 +1445,13 @@ int cifs_strict_fsync(struct file *file, int datasync) | |||
1519 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | 1445 | cFYI(1, "Sync file - name: %s datasync: 0x%x", |
1520 | file->f_path.dentry->d_name.name, datasync); | 1446 | file->f_path.dentry->d_name.name, datasync); |
1521 | 1447 | ||
1522 | if (!CIFS_I(inode)->clientCanCacheRead) | 1448 | if (!CIFS_I(inode)->clientCanCacheRead) { |
1523 | cifs_invalidate_mapping(inode); | 1449 | rc = cifs_invalidate_mapping(inode); |
1450 | if (rc) { | ||
1451 | cFYI(1, "rc: %d during invalidate phase", rc); | ||
1452 | rc = 0; /* don't care about it in fsync */ | ||
1453 | } | ||
1454 | } | ||
1524 | 1455 | ||
1525 | tcon = tlink_tcon(smbfile->tlink); | 1456 | tcon = tlink_tcon(smbfile->tlink); |
1526 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | 1457 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) |
@@ -1726,7 +1657,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | |||
1726 | return total_written; | 1657 | return total_written; |
1727 | } | 1658 | } |
1728 | 1659 | ||
1729 | static ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, | 1660 | ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, |
1730 | unsigned long nr_segs, loff_t pos) | 1661 | unsigned long nr_segs, loff_t pos) |
1731 | { | 1662 | { |
1732 | ssize_t written; | 1663 | ssize_t written; |
@@ -1849,17 +1780,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, | |||
1849 | return total_read; | 1780 | return total_read; |
1850 | } | 1781 | } |
1851 | 1782 | ||
1852 | ssize_t cifs_user_read(struct file *file, char __user *read_data, | 1783 | ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, |
1853 | size_t read_size, loff_t *poffset) | ||
1854 | { | ||
1855 | struct iovec iov; | ||
1856 | iov.iov_base = read_data; | ||
1857 | iov.iov_len = read_size; | ||
1858 | |||
1859 | return cifs_iovec_read(file, &iov, 1, poffset); | ||
1860 | } | ||
1861 | |||
1862 | static ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, | ||
1863 | unsigned long nr_segs, loff_t pos) | 1784 | unsigned long nr_segs, loff_t pos) |
1864 | { | 1785 | { |
1865 | ssize_t read; | 1786 | ssize_t read; |
@@ -1987,8 +1908,11 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) | |||
1987 | 1908 | ||
1988 | xid = GetXid(); | 1909 | xid = GetXid(); |
1989 | 1910 | ||
1990 | if (!CIFS_I(inode)->clientCanCacheRead) | 1911 | if (!CIFS_I(inode)->clientCanCacheRead) { |
1991 | cifs_invalidate_mapping(inode); | 1912 | rc = cifs_invalidate_mapping(inode); |
1913 | if (rc) | ||
1914 | return rc; | ||
1915 | } | ||
1992 | 1916 | ||
1993 | rc = generic_file_mmap(file, vma); | 1917 | rc = generic_file_mmap(file, vma); |
1994 | if (rc == 0) | 1918 | if (rc == 0) |
@@ -2415,6 +2339,27 @@ static void cifs_invalidate_page(struct page *page, unsigned long offset) | |||
2415 | cifs_fscache_invalidate_page(page, &cifsi->vfs_inode); | 2339 | cifs_fscache_invalidate_page(page, &cifsi->vfs_inode); |
2416 | } | 2340 | } |
2417 | 2341 | ||
2342 | static int cifs_launder_page(struct page *page) | ||
2343 | { | ||
2344 | int rc = 0; | ||
2345 | loff_t range_start = page_offset(page); | ||
2346 | loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); | ||
2347 | struct writeback_control wbc = { | ||
2348 | .sync_mode = WB_SYNC_ALL, | ||
2349 | .nr_to_write = 0, | ||
2350 | .range_start = range_start, | ||
2351 | .range_end = range_end, | ||
2352 | }; | ||
2353 | |||
2354 | cFYI(1, "Launder page: %p", page); | ||
2355 | |||
2356 | if (clear_page_dirty_for_io(page)) | ||
2357 | rc = cifs_writepage_locked(page, &wbc); | ||
2358 | |||
2359 | cifs_fscache_invalidate_page(page, page->mapping->host); | ||
2360 | return rc; | ||
2361 | } | ||
2362 | |||
2418 | void cifs_oplock_break(struct work_struct *work) | 2363 | void cifs_oplock_break(struct work_struct *work) |
2419 | { | 2364 | { |
2420 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, | 2365 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, |
@@ -2486,7 +2431,7 @@ const struct address_space_operations cifs_addr_ops = { | |||
2486 | .set_page_dirty = __set_page_dirty_nobuffers, | 2431 | .set_page_dirty = __set_page_dirty_nobuffers, |
2487 | .releasepage = cifs_release_page, | 2432 | .releasepage = cifs_release_page, |
2488 | .invalidatepage = cifs_invalidate_page, | 2433 | .invalidatepage = cifs_invalidate_page, |
2489 | /* .direct_IO = */ | 2434 | .launder_page = cifs_launder_page, |
2490 | }; | 2435 | }; |
2491 | 2436 | ||
2492 | /* | 2437 | /* |
@@ -2503,5 +2448,5 @@ const struct address_space_operations cifs_addr_ops_smallbuf = { | |||
2503 | .set_page_dirty = __set_page_dirty_nobuffers, | 2448 | .set_page_dirty = __set_page_dirty_nobuffers, |
2504 | .releasepage = cifs_release_page, | 2449 | .releasepage = cifs_release_page, |
2505 | .invalidatepage = cifs_invalidate_page, | 2450 | .invalidatepage = cifs_invalidate_page, |
2506 | /* .direct_IO = */ | 2451 | .launder_page = cifs_launder_page, |
2507 | }; | 2452 | }; |