diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 203 |
1 files changed, 108 insertions, 95 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index f1ff785b2292..db11fdef0e92 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 | { |
@@ -162,44 +163,12 @@ psx_client_can_cache: | |||
162 | return 0; | 163 | return 0; |
163 | } | 164 | } |
164 | 165 | ||
165 | static struct cifsFileInfo * | ||
166 | cifs_fill_filedata(struct file *file) | ||
167 | { | ||
168 | struct list_head *tmp; | ||
169 | struct cifsFileInfo *pCifsFile = NULL; | ||
170 | struct cifsInodeInfo *pCifsInode = NULL; | ||
171 | |||
172 | /* search inode for this file and fill in file->private_data */ | ||
173 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); | ||
174 | read_lock(&GlobalSMBSeslock); | ||
175 | list_for_each(tmp, &pCifsInode->openFileList) { | ||
176 | pCifsFile = list_entry(tmp, struct cifsFileInfo, flist); | ||
177 | if ((pCifsFile->pfile == NULL) && | ||
178 | (pCifsFile->pid == current->tgid)) { | ||
179 | /* mode set in cifs_create */ | ||
180 | |||
181 | /* needed for writepage */ | ||
182 | pCifsFile->pfile = file; | ||
183 | file->private_data = pCifsFile; | ||
184 | break; | ||
185 | } | ||
186 | } | ||
187 | read_unlock(&GlobalSMBSeslock); | ||
188 | |||
189 | if (file->private_data != NULL) { | ||
190 | return pCifsFile; | ||
191 | } else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL)) | ||
192 | cERROR(1, "could not find file instance for " | ||
193 | "new file %p", file); | ||
194 | return NULL; | ||
195 | } | ||
196 | |||
197 | /* all arguments to this function must be checked for validity in caller */ | 166 | /* all arguments to this function must be checked for validity in caller */ |
198 | static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, | 167 | static inline int cifs_open_inode_helper(struct inode *inode, |
199 | struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile, | ||
200 | struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf, | 168 | struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf, |
201 | char *full_path, int xid) | 169 | char *full_path, int xid) |
202 | { | 170 | { |
171 | struct cifsInodeInfo *pCifsInode = CIFS_I(inode); | ||
203 | struct timespec temp; | 172 | struct timespec temp; |
204 | int rc; | 173 | int rc; |
205 | 174 | ||
@@ -213,36 +182,35 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, | |||
213 | /* if not oplocked, invalidate inode pages if mtime or file | 182 | /* if not oplocked, invalidate inode pages if mtime or file |
214 | size changed */ | 183 | size changed */ |
215 | temp = cifs_NTtimeToUnix(buf->LastWriteTime); | 184 | temp = cifs_NTtimeToUnix(buf->LastWriteTime); |
216 | if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) && | 185 | if (timespec_equal(&inode->i_mtime, &temp) && |
217 | (file->f_path.dentry->d_inode->i_size == | 186 | (inode->i_size == |
218 | (loff_t)le64_to_cpu(buf->EndOfFile))) { | 187 | (loff_t)le64_to_cpu(buf->EndOfFile))) { |
219 | cFYI(1, "inode unchanged on server"); | 188 | cFYI(1, "inode unchanged on server"); |
220 | } else { | 189 | } else { |
221 | if (file->f_path.dentry->d_inode->i_mapping) { | 190 | if (inode->i_mapping) { |
222 | /* BB no need to lock inode until after invalidate | 191 | /* BB no need to lock inode until after invalidate |
223 | since namei code should already have it locked? */ | 192 | since namei code should already have it locked? */ |
224 | rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); | 193 | rc = filemap_write_and_wait(inode->i_mapping); |
225 | if (rc != 0) | 194 | if (rc != 0) |
226 | CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc; | 195 | pCifsInode->write_behind_rc = rc; |
227 | } | 196 | } |
228 | cFYI(1, "invalidating remote inode since open detected it " | 197 | cFYI(1, "invalidating remote inode since open detected it " |
229 | "changed"); | 198 | "changed"); |
230 | invalidate_remote_inode(file->f_path.dentry->d_inode); | 199 | invalidate_remote_inode(inode); |
231 | } | 200 | } |
232 | 201 | ||
233 | client_can_cache: | 202 | client_can_cache: |
234 | if (pTcon->unix_ext) | 203 | if (pTcon->unix_ext) |
235 | rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode, | 204 | rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, |
236 | full_path, inode->i_sb, xid); | 205 | xid); |
237 | else | 206 | else |
238 | rc = cifs_get_inode_info(&file->f_path.dentry->d_inode, | 207 | rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, |
239 | full_path, buf, inode->i_sb, xid, NULL); | 208 | xid, NULL); |
240 | 209 | ||
241 | if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) { | 210 | if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) { |
242 | pCifsInode->clientCanCacheAll = true; | 211 | pCifsInode->clientCanCacheAll = true; |
243 | pCifsInode->clientCanCacheRead = true; | 212 | pCifsInode->clientCanCacheRead = true; |
244 | cFYI(1, "Exclusive Oplock granted on inode %p", | 213 | cFYI(1, "Exclusive Oplock granted on inode %p", inode); |
245 | file->f_path.dentry->d_inode); | ||
246 | } else if ((*oplock & 0xF) == OPLOCK_READ) | 214 | } else if ((*oplock & 0xF) == OPLOCK_READ) |
247 | pCifsInode->clientCanCacheRead = true; | 215 | pCifsInode->clientCanCacheRead = true; |
248 | 216 | ||
@@ -256,7 +224,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
256 | __u32 oplock; | 224 | __u32 oplock; |
257 | struct cifs_sb_info *cifs_sb; | 225 | struct cifs_sb_info *cifs_sb; |
258 | struct cifsTconInfo *tcon; | 226 | struct cifsTconInfo *tcon; |
259 | struct cifsFileInfo *pCifsFile; | 227 | struct cifsFileInfo *pCifsFile = NULL; |
260 | struct cifsInodeInfo *pCifsInode; | 228 | struct cifsInodeInfo *pCifsInode; |
261 | char *full_path = NULL; | 229 | char *full_path = NULL; |
262 | int desiredAccess; | 230 | int desiredAccess; |
@@ -270,12 +238,6 @@ int cifs_open(struct inode *inode, struct file *file) | |||
270 | tcon = cifs_sb->tcon; | 238 | tcon = cifs_sb->tcon; |
271 | 239 | ||
272 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); | 240 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); |
273 | pCifsFile = cifs_fill_filedata(file); | ||
274 | if (pCifsFile) { | ||
275 | rc = 0; | ||
276 | FreeXid(xid); | ||
277 | return rc; | ||
278 | } | ||
279 | 241 | ||
280 | full_path = build_path_from_dentry(file->f_path.dentry); | 242 | full_path = build_path_from_dentry(file->f_path.dentry); |
281 | if (full_path == NULL) { | 243 | if (full_path == NULL) { |
@@ -299,8 +261,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
299 | int oflags = (int) cifs_posix_convert_flags(file->f_flags); | 261 | int oflags = (int) cifs_posix_convert_flags(file->f_flags); |
300 | oflags |= SMB_O_CREAT; | 262 | oflags |= SMB_O_CREAT; |
301 | /* can not refresh inode info since size could be stale */ | 263 | /* can not refresh inode info since size could be stale */ |
302 | rc = cifs_posix_open(full_path, &inode, file->f_path.mnt, | 264 | rc = cifs_posix_open(full_path, &inode, inode->i_sb, |
303 | inode->i_sb, | ||
304 | cifs_sb->mnt_file_mode /* ignored */, | 265 | cifs_sb->mnt_file_mode /* ignored */, |
305 | oflags, &oplock, &netfid, xid); | 266 | oflags, &oplock, &netfid, xid); |
306 | if (rc == 0) { | 267 | if (rc == 0) { |
@@ -308,9 +269,23 @@ int cifs_open(struct inode *inode, struct file *file) | |||
308 | /* no need for special case handling of setting mode | 269 | /* no need for special case handling of setting mode |
309 | on read only files needed here */ | 270 | on read only files needed here */ |
310 | 271 | ||
311 | pCifsFile = cifs_fill_filedata(file); | 272 | rc = cifs_posix_open_inode_helper(inode, file, |
312 | cifs_posix_open_inode_helper(inode, file, pCifsInode, | 273 | pCifsInode, oplock, netfid); |
313 | oplock, netfid); | 274 | if (rc != 0) { |
275 | CIFSSMBClose(xid, tcon, netfid); | ||
276 | goto out; | ||
277 | } | ||
278 | |||
279 | pCifsFile = cifs_new_fileinfo(inode, netfid, file, | ||
280 | file->f_path.mnt, | ||
281 | oflags); | ||
282 | if (pCifsFile == NULL) { | ||
283 | CIFSSMBClose(xid, tcon, netfid); | ||
284 | rc = -ENOMEM; | ||
285 | } | ||
286 | |||
287 | cifs_fscache_set_inode_cookie(inode, file); | ||
288 | |||
314 | goto out; | 289 | goto out; |
315 | } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 290 | } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
316 | if (tcon->ses->serverNOS) | 291 | if (tcon->ses->serverNOS) |
@@ -391,16 +366,18 @@ int cifs_open(struct inode *inode, struct file *file) | |||
391 | goto out; | 366 | goto out; |
392 | } | 367 | } |
393 | 368 | ||
369 | rc = cifs_open_inode_helper(inode, tcon, &oplock, buf, full_path, xid); | ||
370 | if (rc != 0) | ||
371 | goto out; | ||
372 | |||
394 | pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, | 373 | pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, |
395 | file->f_flags); | 374 | file->f_flags); |
396 | file->private_data = pCifsFile; | 375 | if (pCifsFile == NULL) { |
397 | if (file->private_data == NULL) { | ||
398 | rc = -ENOMEM; | 376 | rc = -ENOMEM; |
399 | goto out; | 377 | goto out; |
400 | } | 378 | } |
401 | 379 | ||
402 | rc = cifs_open_inode_helper(inode, file, pCifsInode, pCifsFile, tcon, | 380 | cifs_fscache_set_inode_cookie(inode, file); |
403 | &oplock, buf, full_path, xid); | ||
404 | 381 | ||
405 | if (oplock & CIFS_CREATE_ACTION) { | 382 | if (oplock & CIFS_CREATE_ACTION) { |
406 | /* 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 |
@@ -456,7 +433,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush) | |||
456 | __u16 netfid; | 433 | __u16 netfid; |
457 | 434 | ||
458 | if (file->private_data) | 435 | if (file->private_data) |
459 | pCifsFile = (struct cifsFileInfo *)file->private_data; | 436 | pCifsFile = file->private_data; |
460 | else | 437 | else |
461 | return -EBADF; | 438 | return -EBADF; |
462 | 439 | ||
@@ -513,8 +490,7 @@ reopen_error_exit: | |||
513 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 490 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
514 | int oflags = (int) cifs_posix_convert_flags(file->f_flags); | 491 | int oflags = (int) cifs_posix_convert_flags(file->f_flags); |
515 | /* can not refresh inode info since size could be stale */ | 492 | /* can not refresh inode info since size could be stale */ |
516 | rc = cifs_posix_open(full_path, NULL, file->f_path.mnt, | 493 | rc = cifs_posix_open(full_path, NULL, inode->i_sb, |
517 | inode->i_sb, | ||
518 | cifs_sb->mnt_file_mode /* ignored */, | 494 | cifs_sb->mnt_file_mode /* ignored */, |
519 | oflags, &oplock, &netfid, xid); | 495 | oflags, &oplock, &netfid, xid); |
520 | if (rc == 0) { | 496 | if (rc == 0) { |
@@ -595,8 +571,7 @@ int cifs_close(struct inode *inode, struct file *file) | |||
595 | int xid, timeout; | 571 | int xid, timeout; |
596 | struct cifs_sb_info *cifs_sb; | 572 | struct cifs_sb_info *cifs_sb; |
597 | struct cifsTconInfo *pTcon; | 573 | struct cifsTconInfo *pTcon; |
598 | struct cifsFileInfo *pSMBFile = | 574 | struct cifsFileInfo *pSMBFile = file->private_data; |
599 | (struct cifsFileInfo *)file->private_data; | ||
600 | 575 | ||
601 | xid = GetXid(); | 576 | xid = GetXid(); |
602 | 577 | ||
@@ -671,8 +646,7 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
671 | { | 646 | { |
672 | int rc = 0; | 647 | int rc = 0; |
673 | int xid; | 648 | int xid; |
674 | struct cifsFileInfo *pCFileStruct = | 649 | struct cifsFileInfo *pCFileStruct = file->private_data; |
675 | (struct cifsFileInfo *)file->private_data; | ||
676 | char *ptmp; | 650 | char *ptmp; |
677 | 651 | ||
678 | cFYI(1, "Closedir inode = 0x%p", inode); | 652 | cFYI(1, "Closedir inode = 0x%p", inode); |
@@ -893,8 +867,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
893 | length, pfLock, | 867 | length, pfLock, |
894 | posix_lock_type, wait_flag); | 868 | posix_lock_type, wait_flag); |
895 | } else { | 869 | } else { |
896 | struct cifsFileInfo *fid = | 870 | struct cifsFileInfo *fid = file->private_data; |
897 | (struct cifsFileInfo *)file->private_data; | ||
898 | 871 | ||
899 | if (numLock) { | 872 | if (numLock) { |
900 | rc = CIFSSMBLock(xid, tcon, netfid, length, | 873 | rc = CIFSSMBLock(xid, tcon, netfid, length, |
@@ -995,7 +968,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
995 | 968 | ||
996 | if (file->private_data == NULL) | 969 | if (file->private_data == NULL) |
997 | return -EBADF; | 970 | return -EBADF; |
998 | open_file = (struct cifsFileInfo *) file->private_data; | 971 | open_file = file->private_data; |
999 | 972 | ||
1000 | rc = generic_write_checks(file, poffset, &write_size, 0); | 973 | rc = generic_write_checks(file, poffset, &write_size, 0); |
1001 | if (rc) | 974 | if (rc) |
@@ -1097,7 +1070,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
1097 | 1070 | ||
1098 | if (file->private_data == NULL) | 1071 | if (file->private_data == NULL) |
1099 | return -EBADF; | 1072 | return -EBADF; |
1100 | open_file = (struct cifsFileInfo *)file->private_data; | 1073 | open_file = file->private_data; |
1101 | 1074 | ||
1102 | xid = GetXid(); | 1075 | xid = GetXid(); |
1103 | 1076 | ||
@@ -1681,8 +1654,7 @@ int cifs_fsync(struct file *file, int datasync) | |||
1681 | int xid; | 1654 | int xid; |
1682 | int rc = 0; | 1655 | int rc = 0; |
1683 | struct cifsTconInfo *tcon; | 1656 | struct cifsTconInfo *tcon; |
1684 | struct cifsFileInfo *smbfile = | 1657 | struct cifsFileInfo *smbfile = file->private_data; |
1685 | (struct cifsFileInfo *)file->private_data; | ||
1686 | struct inode *inode = file->f_path.dentry->d_inode; | 1658 | struct inode *inode = file->f_path.dentry->d_inode; |
1687 | 1659 | ||
1688 | xid = GetXid(); | 1660 | xid = GetXid(); |
@@ -1786,7 +1758,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
1786 | FreeXid(xid); | 1758 | FreeXid(xid); |
1787 | return rc; | 1759 | return rc; |
1788 | } | 1760 | } |
1789 | open_file = (struct cifsFileInfo *)file->private_data; | 1761 | open_file = file->private_data; |
1790 | 1762 | ||
1791 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 1763 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) |
1792 | cFYI(1, "attempting read on write only file instance"); | 1764 | cFYI(1, "attempting read on write only file instance"); |
@@ -1867,7 +1839,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
1867 | FreeXid(xid); | 1839 | FreeXid(xid); |
1868 | return rc; | 1840 | return rc; |
1869 | } | 1841 | } |
1870 | open_file = (struct cifsFileInfo *)file->private_data; | 1842 | open_file = file->private_data; |
1871 | 1843 | ||
1872 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 1844 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) |
1873 | cFYI(1, "attempting read on write only file instance"); | 1845 | cFYI(1, "attempting read on write only file instance"); |
@@ -1952,6 +1924,7 @@ static void cifs_copy_cache_pages(struct address_space *mapping, | |||
1952 | bytes_read -= PAGE_CACHE_SIZE; | 1924 | bytes_read -= PAGE_CACHE_SIZE; |
1953 | continue; | 1925 | continue; |
1954 | } | 1926 | } |
1927 | page_cache_release(page); | ||
1955 | 1928 | ||
1956 | target = kmap_atomic(page, KM_USER0); | 1929 | target = kmap_atomic(page, KM_USER0); |
1957 | 1930 | ||
@@ -1971,6 +1944,9 @@ static void cifs_copy_cache_pages(struct address_space *mapping, | |||
1971 | SetPageUptodate(page); | 1944 | SetPageUptodate(page); |
1972 | unlock_page(page); | 1945 | unlock_page(page); |
1973 | data += PAGE_CACHE_SIZE; | 1946 | data += PAGE_CACHE_SIZE; |
1947 | |||
1948 | /* add page to FS-Cache */ | ||
1949 | cifs_readpage_to_fscache(mapping->host, page); | ||
1974 | } | 1950 | } |
1975 | return; | 1951 | return; |
1976 | } | 1952 | } |
@@ -1997,10 +1973,19 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1997 | FreeXid(xid); | 1973 | FreeXid(xid); |
1998 | return rc; | 1974 | return rc; |
1999 | } | 1975 | } |
2000 | open_file = (struct cifsFileInfo *)file->private_data; | 1976 | open_file = file->private_data; |
2001 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1977 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
2002 | pTcon = cifs_sb->tcon; | 1978 | pTcon = cifs_sb->tcon; |
2003 | 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 | |||
2004 | cFYI(DBG2, "rpages: num pages %d", num_pages); | 1989 | cFYI(DBG2, "rpages: num pages %d", num_pages); |
2005 | for (i = 0; i < num_pages; ) { | 1990 | for (i = 0; i < num_pages; ) { |
2006 | unsigned contig_pages; | 1991 | unsigned contig_pages; |
@@ -2111,6 +2096,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
2111 | smb_read_data = NULL; | 2096 | smb_read_data = NULL; |
2112 | } | 2097 | } |
2113 | 2098 | ||
2099 | read_complete: | ||
2114 | FreeXid(xid); | 2100 | FreeXid(xid); |
2115 | return rc; | 2101 | return rc; |
2116 | } | 2102 | } |
@@ -2121,6 +2107,11 @@ static int cifs_readpage_worker(struct file *file, struct page *page, | |||
2121 | char *read_data; | 2107 | char *read_data; |
2122 | int rc; | 2108 | int rc; |
2123 | 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 | |||
2124 | page_cache_get(page); | 2115 | page_cache_get(page); |
2125 | read_data = kmap(page); | 2116 | read_data = kmap(page); |
2126 | /* for reads over a certain size could initiate async read ahead */ | 2117 | /* for reads over a certain size could initiate async read ahead */ |
@@ -2140,11 +2131,17 @@ static int cifs_readpage_worker(struct file *file, struct page *page, | |||
2140 | 2131 | ||
2141 | flush_dcache_page(page); | 2132 | flush_dcache_page(page); |
2142 | 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 | |||
2143 | rc = 0; | 2138 | rc = 0; |
2144 | 2139 | ||
2145 | io_error: | 2140 | io_error: |
2146 | kunmap(page); | 2141 | kunmap(page); |
2147 | page_cache_release(page); | 2142 | page_cache_release(page); |
2143 | |||
2144 | read_complete: | ||
2148 | return rc; | 2145 | return rc; |
2149 | } | 2146 | } |
2150 | 2147 | ||
@@ -2294,8 +2291,23 @@ out: | |||
2294 | return rc; | 2291 | return rc; |
2295 | } | 2292 | } |
2296 | 2293 | ||
2297 | static void | 2294 | static int cifs_release_page(struct page *page, gfp_t gfp) |
2298 | cifs_oplock_break(struct slow_work *work) | 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 | |||
2310 | void cifs_oplock_break(struct work_struct *work) | ||
2299 | { | 2311 | { |
2300 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, | 2312 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, |
2301 | oplock_break); | 2313 | oplock_break); |
@@ -2332,33 +2344,30 @@ cifs_oplock_break(struct slow_work *work) | |||
2332 | LOCKING_ANDX_OPLOCK_RELEASE, false); | 2344 | LOCKING_ANDX_OPLOCK_RELEASE, false); |
2333 | cFYI(1, "Oplock release rc = %d", rc); | 2345 | cFYI(1, "Oplock release rc = %d", rc); |
2334 | } | 2346 | } |
2347 | |||
2348 | /* | ||
2349 | * We might have kicked in before is_valid_oplock_break() | ||
2350 | * finished grabbing reference for us. Make sure it's done by | ||
2351 | * waiting for GlobalSMSSeslock. | ||
2352 | */ | ||
2353 | write_lock(&GlobalSMBSeslock); | ||
2354 | write_unlock(&GlobalSMBSeslock); | ||
2355 | |||
2356 | cifs_oplock_break_put(cfile); | ||
2335 | } | 2357 | } |
2336 | 2358 | ||
2337 | static int | 2359 | void cifs_oplock_break_get(struct cifsFileInfo *cfile) |
2338 | cifs_oplock_break_get(struct slow_work *work) | ||
2339 | { | 2360 | { |
2340 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, | ||
2341 | oplock_break); | ||
2342 | mntget(cfile->mnt); | 2361 | mntget(cfile->mnt); |
2343 | cifsFileInfo_get(cfile); | 2362 | cifsFileInfo_get(cfile); |
2344 | return 0; | ||
2345 | } | 2363 | } |
2346 | 2364 | ||
2347 | static void | 2365 | void cifs_oplock_break_put(struct cifsFileInfo *cfile) |
2348 | cifs_oplock_break_put(struct slow_work *work) | ||
2349 | { | 2366 | { |
2350 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, | ||
2351 | oplock_break); | ||
2352 | mntput(cfile->mnt); | 2367 | mntput(cfile->mnt); |
2353 | cifsFileInfo_put(cfile); | 2368 | cifsFileInfo_put(cfile); |
2354 | } | 2369 | } |
2355 | 2370 | ||
2356 | const struct slow_work_ops cifs_oplock_break_ops = { | ||
2357 | .get_ref = cifs_oplock_break_get, | ||
2358 | .put_ref = cifs_oplock_break_put, | ||
2359 | .execute = cifs_oplock_break, | ||
2360 | }; | ||
2361 | |||
2362 | const struct address_space_operations cifs_addr_ops = { | 2371 | const struct address_space_operations cifs_addr_ops = { |
2363 | .readpage = cifs_readpage, | 2372 | .readpage = cifs_readpage, |
2364 | .readpages = cifs_readpages, | 2373 | .readpages = cifs_readpages, |
@@ -2367,6 +2376,8 @@ const struct address_space_operations cifs_addr_ops = { | |||
2367 | .write_begin = cifs_write_begin, | 2376 | .write_begin = cifs_write_begin, |
2368 | .write_end = cifs_write_end, | 2377 | .write_end = cifs_write_end, |
2369 | .set_page_dirty = __set_page_dirty_nobuffers, | 2378 | .set_page_dirty = __set_page_dirty_nobuffers, |
2379 | .releasepage = cifs_release_page, | ||
2380 | .invalidatepage = cifs_invalidate_page, | ||
2370 | /* .sync_page = cifs_sync_page, */ | 2381 | /* .sync_page = cifs_sync_page, */ |
2371 | /* .direct_IO = */ | 2382 | /* .direct_IO = */ |
2372 | }; | 2383 | }; |
@@ -2383,6 +2394,8 @@ const struct address_space_operations cifs_addr_ops_smallbuf = { | |||
2383 | .write_begin = cifs_write_begin, | 2394 | .write_begin = cifs_write_begin, |
2384 | .write_end = cifs_write_end, | 2395 | .write_end = cifs_write_end, |
2385 | .set_page_dirty = __set_page_dirty_nobuffers, | 2396 | .set_page_dirty = __set_page_dirty_nobuffers, |
2397 | .releasepage = cifs_release_page, | ||
2398 | .invalidatepage = cifs_invalidate_page, | ||
2386 | /* .sync_page = cifs_sync_page, */ | 2399 | /* .sync_page = cifs_sync_page, */ |
2387 | /* .direct_IO = */ | 2400 | /* .direct_IO = */ |
2388 | }; | 2401 | }; |