diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 74 |
1 files changed, 60 insertions, 14 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 409e4f523e61..fa04a00d126d 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "cifs_unicode.h" | 40 | #include "cifs_unicode.h" |
41 | #include "cifs_debug.h" | 41 | #include "cifs_debug.h" |
42 | #include "cifs_fs_sb.h" | 42 | #include "cifs_fs_sb.h" |
43 | #include "fscache.h" | ||
43 | 44 | ||
44 | static inline int cifs_convert_flags(unsigned int flags) | 45 | static inline int cifs_convert_flags(unsigned int flags) |
45 | { | 46 | { |
@@ -282,6 +283,9 @@ int cifs_open(struct inode *inode, struct file *file) | |||
282 | CIFSSMBClose(xid, tcon, netfid); | 283 | CIFSSMBClose(xid, tcon, netfid); |
283 | rc = -ENOMEM; | 284 | rc = -ENOMEM; |
284 | } | 285 | } |
286 | |||
287 | cifs_fscache_set_inode_cookie(inode, file); | ||
288 | |||
285 | goto out; | 289 | goto out; |
286 | } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 290 | } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
287 | if (tcon->ses->serverNOS) | 291 | if (tcon->ses->serverNOS) |
@@ -373,6 +377,8 @@ int cifs_open(struct inode *inode, struct file *file) | |||
373 | goto out; | 377 | goto out; |
374 | } | 378 | } |
375 | 379 | ||
380 | cifs_fscache_set_inode_cookie(inode, file); | ||
381 | |||
376 | if (oplock & CIFS_CREATE_ACTION) { | 382 | if (oplock & CIFS_CREATE_ACTION) { |
377 | /* time to set mode which we can not set earlier due to | 383 | /* time to set mode which we can not set earlier due to |
378 | problems creating new read-only files */ | 384 | problems creating new read-only files */ |
@@ -427,7 +433,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush) | |||
427 | __u16 netfid; | 433 | __u16 netfid; |
428 | 434 | ||
429 | if (file->private_data) | 435 | if (file->private_data) |
430 | pCifsFile = (struct cifsFileInfo *)file->private_data; | 436 | pCifsFile = file->private_data; |
431 | else | 437 | else |
432 | return -EBADF; | 438 | return -EBADF; |
433 | 439 | ||
@@ -565,8 +571,7 @@ int cifs_close(struct inode *inode, struct file *file) | |||
565 | int xid, timeout; | 571 | int xid, timeout; |
566 | struct cifs_sb_info *cifs_sb; | 572 | struct cifs_sb_info *cifs_sb; |
567 | struct cifsTconInfo *pTcon; | 573 | struct cifsTconInfo *pTcon; |
568 | struct cifsFileInfo *pSMBFile = | 574 | struct cifsFileInfo *pSMBFile = file->private_data; |
569 | (struct cifsFileInfo *)file->private_data; | ||
570 | 575 | ||
571 | xid = GetXid(); | 576 | xid = GetXid(); |
572 | 577 | ||
@@ -641,8 +646,7 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
641 | { | 646 | { |
642 | int rc = 0; | 647 | int rc = 0; |
643 | int xid; | 648 | int xid; |
644 | struct cifsFileInfo *pCFileStruct = | 649 | struct cifsFileInfo *pCFileStruct = file->private_data; |
645 | (struct cifsFileInfo *)file->private_data; | ||
646 | char *ptmp; | 650 | char *ptmp; |
647 | 651 | ||
648 | cFYI(1, "Closedir inode = 0x%p", inode); | 652 | cFYI(1, "Closedir inode = 0x%p", inode); |
@@ -863,8 +867,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
863 | length, pfLock, | 867 | length, pfLock, |
864 | posix_lock_type, wait_flag); | 868 | posix_lock_type, wait_flag); |
865 | } else { | 869 | } else { |
866 | struct cifsFileInfo *fid = | 870 | struct cifsFileInfo *fid = file->private_data; |
867 | (struct cifsFileInfo *)file->private_data; | ||
868 | 871 | ||
869 | if (numLock) { | 872 | if (numLock) { |
870 | rc = CIFSSMBLock(xid, tcon, netfid, length, | 873 | rc = CIFSSMBLock(xid, tcon, netfid, length, |
@@ -965,7 +968,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
965 | 968 | ||
966 | if (file->private_data == NULL) | 969 | if (file->private_data == NULL) |
967 | return -EBADF; | 970 | return -EBADF; |
968 | open_file = (struct cifsFileInfo *) file->private_data; | 971 | open_file = file->private_data; |
969 | 972 | ||
970 | rc = generic_write_checks(file, poffset, &write_size, 0); | 973 | rc = generic_write_checks(file, poffset, &write_size, 0); |
971 | if (rc) | 974 | if (rc) |
@@ -1067,7 +1070,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
1067 | 1070 | ||
1068 | if (file->private_data == NULL) | 1071 | if (file->private_data == NULL) |
1069 | return -EBADF; | 1072 | return -EBADF; |
1070 | open_file = (struct cifsFileInfo *)file->private_data; | 1073 | open_file = file->private_data; |
1071 | 1074 | ||
1072 | xid = GetXid(); | 1075 | xid = GetXid(); |
1073 | 1076 | ||
@@ -1651,8 +1654,7 @@ int cifs_fsync(struct file *file, int datasync) | |||
1651 | int xid; | 1654 | int xid; |
1652 | int rc = 0; | 1655 | int rc = 0; |
1653 | struct cifsTconInfo *tcon; | 1656 | struct cifsTconInfo *tcon; |
1654 | struct cifsFileInfo *smbfile = | 1657 | struct cifsFileInfo *smbfile = file->private_data; |
1655 | (struct cifsFileInfo *)file->private_data; | ||
1656 | struct inode *inode = file->f_path.dentry->d_inode; | 1658 | struct inode *inode = file->f_path.dentry->d_inode; |
1657 | 1659 | ||
1658 | xid = GetXid(); | 1660 | xid = GetXid(); |
@@ -1756,7 +1758,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
1756 | FreeXid(xid); | 1758 | FreeXid(xid); |
1757 | return rc; | 1759 | return rc; |
1758 | } | 1760 | } |
1759 | open_file = (struct cifsFileInfo *)file->private_data; | 1761 | open_file = file->private_data; |
1760 | 1762 | ||
1761 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 1763 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) |
1762 | cFYI(1, "attempting read on write only file instance"); | 1764 | cFYI(1, "attempting read on write only file instance"); |
@@ -1837,7 +1839,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
1837 | FreeXid(xid); | 1839 | FreeXid(xid); |
1838 | return rc; | 1840 | return rc; |
1839 | } | 1841 | } |
1840 | open_file = (struct cifsFileInfo *)file->private_data; | 1842 | open_file = file->private_data; |
1841 | 1843 | ||
1842 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 1844 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) |
1843 | cFYI(1, "attempting read on write only file instance"); | 1845 | cFYI(1, "attempting read on write only file instance"); |
@@ -1942,6 +1944,9 @@ static void cifs_copy_cache_pages(struct address_space *mapping, | |||
1942 | SetPageUptodate(page); | 1944 | SetPageUptodate(page); |
1943 | unlock_page(page); | 1945 | unlock_page(page); |
1944 | data += PAGE_CACHE_SIZE; | 1946 | data += PAGE_CACHE_SIZE; |
1947 | |||
1948 | /* add page to FS-Cache */ | ||
1949 | cifs_readpage_to_fscache(mapping->host, page); | ||
1945 | } | 1950 | } |
1946 | return; | 1951 | return; |
1947 | } | 1952 | } |
@@ -1968,10 +1973,19 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1968 | FreeXid(xid); | 1973 | FreeXid(xid); |
1969 | return rc; | 1974 | return rc; |
1970 | } | 1975 | } |
1971 | open_file = (struct cifsFileInfo *)file->private_data; | 1976 | open_file = file->private_data; |
1972 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1977 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
1973 | pTcon = cifs_sb->tcon; | 1978 | pTcon = cifs_sb->tcon; |
1974 | 1979 | ||
1980 | /* | ||
1981 | * Reads as many pages as possible from fscache. Returns -ENOBUFS | ||
1982 | * immediately if the cookie is negative | ||
1983 | */ | ||
1984 | rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list, | ||
1985 | &num_pages); | ||
1986 | if (rc == 0) | ||
1987 | goto read_complete; | ||
1988 | |||
1975 | cFYI(DBG2, "rpages: num pages %d", num_pages); | 1989 | cFYI(DBG2, "rpages: num pages %d", num_pages); |
1976 | for (i = 0; i < num_pages; ) { | 1990 | for (i = 0; i < num_pages; ) { |
1977 | unsigned contig_pages; | 1991 | unsigned contig_pages; |
@@ -2082,6 +2096,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
2082 | smb_read_data = NULL; | 2096 | smb_read_data = NULL; |
2083 | } | 2097 | } |
2084 | 2098 | ||
2099 | read_complete: | ||
2085 | FreeXid(xid); | 2100 | FreeXid(xid); |
2086 | return rc; | 2101 | return rc; |
2087 | } | 2102 | } |
@@ -2092,6 +2107,11 @@ static int cifs_readpage_worker(struct file *file, struct page *page, | |||
2092 | char *read_data; | 2107 | char *read_data; |
2093 | int rc; | 2108 | int rc; |
2094 | 2109 | ||
2110 | /* Is the page cached? */ | ||
2111 | rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page); | ||
2112 | if (rc == 0) | ||
2113 | goto read_complete; | ||
2114 | |||
2095 | page_cache_get(page); | 2115 | page_cache_get(page); |
2096 | read_data = kmap(page); | 2116 | read_data = kmap(page); |
2097 | /* for reads over a certain size could initiate async read ahead */ | 2117 | /* for reads over a certain size could initiate async read ahead */ |
@@ -2111,11 +2131,17 @@ static int cifs_readpage_worker(struct file *file, struct page *page, | |||
2111 | 2131 | ||
2112 | flush_dcache_page(page); | 2132 | flush_dcache_page(page); |
2113 | SetPageUptodate(page); | 2133 | SetPageUptodate(page); |
2134 | |||
2135 | /* send this page to the cache */ | ||
2136 | cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page); | ||
2137 | |||
2114 | rc = 0; | 2138 | rc = 0; |
2115 | 2139 | ||
2116 | io_error: | 2140 | io_error: |
2117 | kunmap(page); | 2141 | kunmap(page); |
2118 | page_cache_release(page); | 2142 | page_cache_release(page); |
2143 | |||
2144 | read_complete: | ||
2119 | return rc; | 2145 | return rc; |
2120 | } | 2146 | } |
2121 | 2147 | ||
@@ -2265,6 +2291,22 @@ out: | |||
2265 | return rc; | 2291 | return rc; |
2266 | } | 2292 | } |
2267 | 2293 | ||
2294 | static int cifs_release_page(struct page *page, gfp_t gfp) | ||
2295 | { | ||
2296 | if (PagePrivate(page)) | ||
2297 | return 0; | ||
2298 | |||
2299 | return cifs_fscache_release_page(page, gfp); | ||
2300 | } | ||
2301 | |||
2302 | static void cifs_invalidate_page(struct page *page, unsigned long offset) | ||
2303 | { | ||
2304 | struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host); | ||
2305 | |||
2306 | if (offset == 0) | ||
2307 | cifs_fscache_invalidate_page(page, &cifsi->vfs_inode); | ||
2308 | } | ||
2309 | |||
2268 | static void | 2310 | static void |
2269 | cifs_oplock_break(struct slow_work *work) | 2311 | cifs_oplock_break(struct slow_work *work) |
2270 | { | 2312 | { |
@@ -2338,6 +2380,8 @@ const struct address_space_operations cifs_addr_ops = { | |||
2338 | .write_begin = cifs_write_begin, | 2380 | .write_begin = cifs_write_begin, |
2339 | .write_end = cifs_write_end, | 2381 | .write_end = cifs_write_end, |
2340 | .set_page_dirty = __set_page_dirty_nobuffers, | 2382 | .set_page_dirty = __set_page_dirty_nobuffers, |
2383 | .releasepage = cifs_release_page, | ||
2384 | .invalidatepage = cifs_invalidate_page, | ||
2341 | /* .sync_page = cifs_sync_page, */ | 2385 | /* .sync_page = cifs_sync_page, */ |
2342 | /* .direct_IO = */ | 2386 | /* .direct_IO = */ |
2343 | }; | 2387 | }; |
@@ -2354,6 +2398,8 @@ const struct address_space_operations cifs_addr_ops_smallbuf = { | |||
2354 | .write_begin = cifs_write_begin, | 2398 | .write_begin = cifs_write_begin, |
2355 | .write_end = cifs_write_end, | 2399 | .write_end = cifs_write_end, |
2356 | .set_page_dirty = __set_page_dirty_nobuffers, | 2400 | .set_page_dirty = __set_page_dirty_nobuffers, |
2401 | .releasepage = cifs_release_page, | ||
2402 | .invalidatepage = cifs_invalidate_page, | ||
2357 | /* .sync_page = cifs_sync_page, */ | 2403 | /* .sync_page = cifs_sync_page, */ |
2358 | /* .direct_IO = */ | 2404 | /* .direct_IO = */ |
2359 | }; | 2405 | }; |