blob: 34cbbee30b18af4a46841581a8c8b8b930ec40d1 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/file.c
3 *
4 * vfs operations that deal with files
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005 *
Steve Frenchf19159d2010-04-21 04:12:10 +00006 * Copyright (C) International Business Machines Corp., 2002,2010
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 * Author(s): Steve French (sfrench@us.ibm.com)
Jeremy Allison7ee1af72006-08-02 21:56:33 +00008 * Jeremy Allison (jra@samba.org)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 *
10 * This library is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published
12 * by the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
18 * the GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24#include <linux/fs.h>
Steve French37c0eb42005-10-05 14:50:29 -070025#include <linux/backing-dev.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/stat.h>
27#include <linux/fcntl.h>
28#include <linux/pagemap.h>
29#include <linux/pagevec.h>
Steve French37c0eb42005-10-05 14:50:29 -070030#include <linux/writeback.h>
Andrew Morton6f88cc22006-12-10 02:19:44 -080031#include <linux/task_io_accounting_ops.h>
Steve French23e7dd72005-10-20 13:44:56 -070032#include <linux/delay.h>
Jeff Layton3bc303c2009-09-21 06:47:50 -040033#include <linux/mount.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090034#include <linux/slab.h>
Jeff Layton690c5e32011-10-19 15:30:16 -040035#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <asm/div64.h>
37#include "cifsfs.h"
38#include "cifspdu.h"
39#include "cifsglob.h"
40#include "cifsproto.h"
41#include "cifs_unicode.h"
42#include "cifs_debug.h"
43#include "cifs_fs_sb.h"
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +053044#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
Linus Torvalds1da177e2005-04-16 15:20:36 -070046static inline int cifs_convert_flags(unsigned int flags)
47{
48 if ((flags & O_ACCMODE) == O_RDONLY)
49 return GENERIC_READ;
50 else if ((flags & O_ACCMODE) == O_WRONLY)
51 return GENERIC_WRITE;
52 else if ((flags & O_ACCMODE) == O_RDWR) {
53 /* GENERIC_ALL is too much permission to request
54 can cause unnecessary access denied on create */
55 /* return GENERIC_ALL; */
56 return (GENERIC_READ | GENERIC_WRITE);
57 }
58
Jeff Laytone10f7b52008-05-14 10:21:33 -070059 return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
60 FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA |
61 FILE_READ_DATA);
Steve French7fc8f4e2009-02-23 20:43:11 +000062}
Jeff Laytone10f7b52008-05-14 10:21:33 -070063
Jeff Layton608712f2010-10-15 15:33:56 -040064static u32 cifs_posix_convert_flags(unsigned int flags)
Steve French7fc8f4e2009-02-23 20:43:11 +000065{
Jeff Layton608712f2010-10-15 15:33:56 -040066 u32 posix_flags = 0;
Jeff Laytone10f7b52008-05-14 10:21:33 -070067
Steve French7fc8f4e2009-02-23 20:43:11 +000068 if ((flags & O_ACCMODE) == O_RDONLY)
Jeff Layton608712f2010-10-15 15:33:56 -040069 posix_flags = SMB_O_RDONLY;
Steve French7fc8f4e2009-02-23 20:43:11 +000070 else if ((flags & O_ACCMODE) == O_WRONLY)
Jeff Layton608712f2010-10-15 15:33:56 -040071 posix_flags = SMB_O_WRONLY;
72 else if ((flags & O_ACCMODE) == O_RDWR)
73 posix_flags = SMB_O_RDWR;
74
75 if (flags & O_CREAT)
76 posix_flags |= SMB_O_CREAT;
77 if (flags & O_EXCL)
78 posix_flags |= SMB_O_EXCL;
79 if (flags & O_TRUNC)
80 posix_flags |= SMB_O_TRUNC;
81 /* be safe and imply O_SYNC for O_DSYNC */
Christoph Hellwig6b2f3d12009-10-27 11:05:28 +010082 if (flags & O_DSYNC)
Jeff Layton608712f2010-10-15 15:33:56 -040083 posix_flags |= SMB_O_SYNC;
Steve French7fc8f4e2009-02-23 20:43:11 +000084 if (flags & O_DIRECTORY)
Jeff Layton608712f2010-10-15 15:33:56 -040085 posix_flags |= SMB_O_DIRECTORY;
Steve French7fc8f4e2009-02-23 20:43:11 +000086 if (flags & O_NOFOLLOW)
Jeff Layton608712f2010-10-15 15:33:56 -040087 posix_flags |= SMB_O_NOFOLLOW;
Steve French7fc8f4e2009-02-23 20:43:11 +000088 if (flags & O_DIRECT)
Jeff Layton608712f2010-10-15 15:33:56 -040089 posix_flags |= SMB_O_DIRECT;
Steve French7fc8f4e2009-02-23 20:43:11 +000090
91 return posix_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -070092}
93
94static inline int cifs_get_disposition(unsigned int flags)
95{
96 if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
97 return FILE_CREATE;
98 else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
99 return FILE_OVERWRITE_IF;
100 else if ((flags & O_CREAT) == O_CREAT)
101 return FILE_OPEN_IF;
Steve French55aa2e02006-05-30 18:09:31 +0000102 else if ((flags & O_TRUNC) == O_TRUNC)
103 return FILE_OVERWRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 else
105 return FILE_OPEN;
106}
107
Jeff Layton608712f2010-10-15 15:33:56 -0400108int cifs_posix_open(char *full_path, struct inode **pinode,
109 struct super_block *sb, int mode, unsigned int f_flags,
110 __u32 *poplock, __u16 *pnetfid, int xid)
111{
112 int rc;
113 FILE_UNIX_BASIC_INFO *presp_data;
114 __u32 posix_flags = 0;
115 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
116 struct cifs_fattr fattr;
117 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000118 struct cifs_tcon *tcon;
Jeff Layton608712f2010-10-15 15:33:56 -0400119
120 cFYI(1, "posix open %s", full_path);
121
122 presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
123 if (presp_data == NULL)
124 return -ENOMEM;
125
126 tlink = cifs_sb_tlink(cifs_sb);
127 if (IS_ERR(tlink)) {
128 rc = PTR_ERR(tlink);
129 goto posix_open_ret;
130 }
131
132 tcon = tlink_tcon(tlink);
133 mode &= ~current_umask();
134
135 posix_flags = cifs_posix_convert_flags(f_flags);
136 rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data,
137 poplock, full_path, cifs_sb->local_nls,
138 cifs_sb->mnt_cifs_flags &
139 CIFS_MOUNT_MAP_SPECIAL_CHR);
140 cifs_put_tlink(tlink);
141
142 if (rc)
143 goto posix_open_ret;
144
145 if (presp_data->Type == cpu_to_le32(-1))
146 goto posix_open_ret; /* open ok, caller does qpathinfo */
147
148 if (!pinode)
149 goto posix_open_ret; /* caller does not need info */
150
151 cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
152
153 /* get new inode and set it up */
154 if (*pinode == NULL) {
155 cifs_fill_uniqueid(sb, &fattr);
156 *pinode = cifs_iget(sb, &fattr);
157 if (!*pinode) {
158 rc = -ENOMEM;
159 goto posix_open_ret;
160 }
161 } else {
162 cifs_fattr_to_inode(*pinode, &fattr);
163 }
164
165posix_open_ret:
166 kfree(presp_data);
167 return rc;
168}
169
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300170static int
171cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
Steve French96daf2b2011-05-27 04:34:02 +0000172 struct cifs_tcon *tcon, unsigned int f_flags, __u32 *poplock,
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300173 __u16 *pnetfid, int xid)
174{
175 int rc;
176 int desiredAccess;
177 int disposition;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500178 int create_options = CREATE_NOT_DIR;
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300179 FILE_ALL_INFO *buf;
180
181 desiredAccess = cifs_convert_flags(f_flags);
182
183/*********************************************************************
184 * open flag mapping table:
185 *
186 * POSIX Flag CIFS Disposition
187 * ---------- ----------------
188 * O_CREAT FILE_OPEN_IF
189 * O_CREAT | O_EXCL FILE_CREATE
190 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
191 * O_TRUNC FILE_OVERWRITE
192 * none of the above FILE_OPEN
193 *
194 * Note that there is not a direct match between disposition
195 * FILE_SUPERSEDE (ie create whether or not file exists although
196 * O_CREAT | O_TRUNC is similar but truncates the existing
197 * file rather than creating a new file as FILE_SUPERSEDE does
198 * (which uses the attributes / metadata passed in on open call)
199 *?
200 *? O_SYNC is a reasonable match to CIFS writethrough flag
201 *? and the read write flags match reasonably. O_LARGEFILE
202 *? is irrelevant because largefile support is always used
203 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
204 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
205 *********************************************************************/
206
207 disposition = cifs_get_disposition(f_flags);
208
209 /* BB pass O_SYNC flag through on file attributes .. BB */
210
211 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
212 if (!buf)
213 return -ENOMEM;
214
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500215 if (backup_cred(cifs_sb))
216 create_options |= CREATE_OPEN_BACKUP_INTENT;
217
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300218 if (tcon->ses->capabilities & CAP_NT_SMBS)
219 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500220 desiredAccess, create_options, pnetfid, poplock, buf,
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300221 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
222 & CIFS_MOUNT_MAP_SPECIAL_CHR);
223 else
224 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
225 desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf,
226 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
227 & CIFS_MOUNT_MAP_SPECIAL_CHR);
228
229 if (rc)
230 goto out;
231
232 if (tcon->unix_ext)
233 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
234 xid);
235 else
236 rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
237 xid, pnetfid);
238
239out:
240 kfree(buf);
241 return rc;
242}
243
Jeff Layton15ecb432010-10-15 15:34:02 -0400244struct cifsFileInfo *
245cifs_new_fileinfo(__u16 fileHandle, struct file *file,
246 struct tcon_link *tlink, __u32 oplock)
247{
248 struct dentry *dentry = file->f_path.dentry;
249 struct inode *inode = dentry->d_inode;
250 struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
251 struct cifsFileInfo *pCifsFile;
252
253 pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
254 if (pCifsFile == NULL)
255 return pCifsFile;
256
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400257 pCifsFile->count = 1;
Jeff Layton15ecb432010-10-15 15:34:02 -0400258 pCifsFile->netfid = fileHandle;
259 pCifsFile->pid = current->tgid;
260 pCifsFile->uid = current_fsuid();
261 pCifsFile->dentry = dget(dentry);
262 pCifsFile->f_flags = file->f_flags;
263 pCifsFile->invalidHandle = false;
Jeff Layton15ecb432010-10-15 15:34:02 -0400264 pCifsFile->tlink = cifs_get_tlink(tlink);
265 mutex_init(&pCifsFile->fh_mutex);
Jeff Layton15ecb432010-10-15 15:34:02 -0400266 INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
267
Jeff Layton44772882010-10-15 15:34:03 -0400268 spin_lock(&cifs_file_list_lock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400269 list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList));
270 /* if readable file instance put first in list*/
271 if (file->f_mode & FMODE_READ)
272 list_add(&pCifsFile->flist, &pCifsInode->openFileList);
273 else
274 list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList);
Jeff Layton44772882010-10-15 15:34:03 -0400275 spin_unlock(&cifs_file_list_lock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400276
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300277 cifs_set_oplock_level(pCifsInode, oplock);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400278 pCifsInode->can_cache_brlcks = pCifsInode->clientCanCacheAll;
Jeff Layton15ecb432010-10-15 15:34:02 -0400279
280 file->private_data = pCifsFile;
281 return pCifsFile;
282}
283
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400284static void cifs_del_lock_waiters(struct cifsLockInfo *lock);
285
Steve Frenchcdff08e2010-10-21 22:46:14 +0000286/*
287 * Release a reference on the file private data. This may involve closing
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400288 * the filehandle out on the server. Must be called without holding
289 * cifs_file_list_lock.
Steve Frenchcdff08e2010-10-21 22:46:14 +0000290 */
Jeff Laytonb33879a2010-10-15 15:34:04 -0400291void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
292{
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300293 struct inode *inode = cifs_file->dentry->d_inode;
Steve French96daf2b2011-05-27 04:34:02 +0000294 struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300295 struct cifsInodeInfo *cifsi = CIFS_I(inode);
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300296 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000297 struct cifsLockInfo *li, *tmp;
298
299 spin_lock(&cifs_file_list_lock);
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400300 if (--cifs_file->count > 0) {
Steve Frenchcdff08e2010-10-21 22:46:14 +0000301 spin_unlock(&cifs_file_list_lock);
302 return;
Jeff Laytonb33879a2010-10-15 15:34:04 -0400303 }
Steve Frenchcdff08e2010-10-21 22:46:14 +0000304
305 /* remove it from the lists */
306 list_del(&cifs_file->flist);
307 list_del(&cifs_file->tlist);
308
309 if (list_empty(&cifsi->openFileList)) {
310 cFYI(1, "closing last open instance for inode %p",
311 cifs_file->dentry->d_inode);
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300312
313 /* in strict cache mode we need invalidate mapping on the last
314 close because it may cause a error when we open this file
315 again and get at least level II oplock */
316 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
317 CIFS_I(inode)->invalid_mapping = true;
318
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300319 cifs_set_oplock_level(cifsi, 0);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000320 }
321 spin_unlock(&cifs_file_list_lock);
322
Jeff Laytonad635942011-07-26 12:20:17 -0400323 cancel_work_sync(&cifs_file->oplock_break);
324
Steve Frenchcdff08e2010-10-21 22:46:14 +0000325 if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
326 int xid, rc;
327
328 xid = GetXid();
329 rc = CIFSSMBClose(xid, tcon, cifs_file->netfid);
330 FreeXid(xid);
331 }
332
333 /* Delete any outstanding lock records. We'll lose them when the file
334 * is closed anyway.
335 */
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400336 mutex_lock(&cifsi->lock_mutex);
337 list_for_each_entry_safe(li, tmp, &cifsi->llist, llist) {
338 if (li->netfid != cifs_file->netfid)
339 continue;
Steve Frenchcdff08e2010-10-21 22:46:14 +0000340 list_del(&li->llist);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400341 cifs_del_lock_waiters(li);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000342 kfree(li);
343 }
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400344 mutex_unlock(&cifsi->lock_mutex);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000345
346 cifs_put_tlink(cifs_file->tlink);
347 dput(cifs_file->dentry);
348 kfree(cifs_file);
Jeff Laytonb33879a2010-10-15 15:34:04 -0400349}
350
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351int cifs_open(struct inode *inode, struct file *file)
352{
353 int rc = -EACCES;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400354 int xid;
355 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000357 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400358 struct tcon_link *tlink;
Jeff Layton6ca9f3b2010-06-16 13:40:16 -0400359 struct cifsFileInfo *pCifsFile = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 char *full_path = NULL;
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300361 bool posix_open_ok = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 __u16 netfid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
364 xid = GetXid();
365
366 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400367 tlink = cifs_sb_tlink(cifs_sb);
368 if (IS_ERR(tlink)) {
369 FreeXid(xid);
370 return PTR_ERR(tlink);
371 }
372 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -0800374 full_path = build_path_from_dentry(file->f_path.dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530376 rc = -ENOMEM;
Jeff Layton232341b2010-08-05 13:58:38 -0400377 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 }
379
Joe Perchesb6b38f72010-04-21 03:50:45 +0000380 cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
381 inode, file->f_flags, full_path);
Steve French276a74a2009-03-03 18:00:34 +0000382
Steve Frenche7504732011-10-12 17:47:03 -0500383 if (enable_oplocks)
Steve French276a74a2009-03-03 18:00:34 +0000384 oplock = REQ_OPLOCK;
385 else
386 oplock = 0;
387
Steve French64cc2c62009-03-04 19:54:08 +0000388 if (!tcon->broken_posix_open && tcon->unix_ext &&
389 (tcon->ses->capabilities & CAP_UNIX) &&
Steve French276a74a2009-03-03 18:00:34 +0000390 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
391 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Steve French276a74a2009-03-03 18:00:34 +0000392 /* can not refresh inode info since size could be stale */
Jeff Layton2422f672010-06-16 13:40:16 -0400393 rc = cifs_posix_open(full_path, &inode, inode->i_sb,
Steve Frenchfa588e02010-04-22 19:21:55 +0000394 cifs_sb->mnt_file_mode /* ignored */,
Jeff Layton608712f2010-10-15 15:33:56 -0400395 file->f_flags, &oplock, &netfid, xid);
Steve French276a74a2009-03-03 18:00:34 +0000396 if (rc == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000397 cFYI(1, "posix open succeeded");
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300398 posix_open_ok = true;
Steve French64cc2c62009-03-04 19:54:08 +0000399 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
400 if (tcon->ses->serverNOS)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000401 cERROR(1, "server %s of type %s returned"
Steve French64cc2c62009-03-04 19:54:08 +0000402 " unexpected error on SMB posix open"
403 ", disabling posix open support."
404 " Check if server update available.",
405 tcon->ses->serverName,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000406 tcon->ses->serverNOS);
Steve French64cc2c62009-03-04 19:54:08 +0000407 tcon->broken_posix_open = true;
Steve French276a74a2009-03-03 18:00:34 +0000408 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
409 (rc != -EOPNOTSUPP)) /* path not found or net err */
410 goto out;
Steve French64cc2c62009-03-04 19:54:08 +0000411 /* else fallthrough to retry open the old way on network i/o
412 or DFS errors */
Steve French276a74a2009-03-03 18:00:34 +0000413 }
414
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300415 if (!posix_open_ok) {
416 rc = cifs_nt_open(full_path, inode, cifs_sb, tcon,
417 file->f_flags, &oplock, &netfid, xid);
418 if (rc)
419 goto out;
420 }
Jeff Layton47c78b72010-06-16 13:40:17 -0400421
Jeff Laytonabfe1ee2010-10-15 15:33:58 -0400422 pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock);
Jeff Layton6ca9f3b2010-06-16 13:40:16 -0400423 if (pCifsFile == NULL) {
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300424 CIFSSMBClose(xid, tcon, netfid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 rc = -ENOMEM;
426 goto out;
427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530429 cifs_fscache_set_inode_cookie(inode, file);
430
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300431 if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 /* time to set mode which we can not set earlier due to
433 problems creating new read-only files */
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300434 struct cifs_unix_set_info_args args = {
435 .mode = inode->i_mode,
436 .uid = NO_CHANGE_64,
437 .gid = NO_CHANGE_64,
438 .ctime = NO_CHANGE_64,
439 .atime = NO_CHANGE_64,
440 .mtime = NO_CHANGE_64,
441 .device = 0,
442 };
Jeff Laytond44a9fe2011-01-07 11:30:29 -0500443 CIFSSMBUnixSetFileInfo(xid, tcon, &args, netfid,
444 pCifsFile->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 }
446
447out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 kfree(full_path);
449 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400450 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 return rc;
452}
453
Adrian Bunk04187262006-06-30 18:23:04 +0200454/* Try to reacquire byte range locks that were released when session */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455/* to server was lost */
456static int cifs_relock_file(struct cifsFileInfo *cifsFile)
457{
458 int rc = 0;
459
460/* BB list all locks open on this file and relock */
461
462 return rc;
463}
464
Jeff Layton15886172010-10-15 15:33:59 -0400465static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466{
467 int rc = -EACCES;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400468 int xid;
469 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000471 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 struct cifsInodeInfo *pCifsInode;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000473 struct inode *inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 char *full_path = NULL;
475 int desiredAccess;
476 int disposition = FILE_OPEN;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500477 int create_options = CREATE_NOT_DIR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 __u16 netfid;
479
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 xid = GetXid();
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400481 mutex_lock(&pCifsFile->fh_mutex);
Steve French4b18f2a2008-04-29 00:06:05 +0000482 if (!pCifsFile->invalidHandle) {
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400483 mutex_unlock(&pCifsFile->fh_mutex);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530484 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530486 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 }
488
Jeff Layton15886172010-10-15 15:33:59 -0400489 inode = pCifsFile->dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton13cfb732010-09-29 19:51:11 -0400491 tcon = tlink_tcon(pCifsFile->tlink);
Steve French3a9f4622007-04-04 17:10:24 +0000492
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493/* can not grab rename sem here because various ops, including
494 those that already have the rename sem can end up causing writepage
495 to get called and if the server was down that means we end up here,
496 and we can never tell if the caller already has the rename_sem */
Jeff Layton15886172010-10-15 15:33:59 -0400497 full_path = build_path_from_dentry(pCifsFile->dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 if (full_path == NULL) {
Steve French3a9f4622007-04-04 17:10:24 +0000499 rc = -ENOMEM;
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400500 mutex_unlock(&pCifsFile->fh_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 FreeXid(xid);
Steve French3a9f4622007-04-04 17:10:24 +0000502 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 }
504
Joe Perchesb6b38f72010-04-21 03:50:45 +0000505 cFYI(1, "inode = 0x%p file flags 0x%x for %s",
Jeff Layton15886172010-10-15 15:33:59 -0400506 inode, pCifsFile->f_flags, full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
Steve Frenche7504732011-10-12 17:47:03 -0500508 if (enable_oplocks)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 oplock = REQ_OPLOCK;
510 else
Steve French4b18f2a2008-04-29 00:06:05 +0000511 oplock = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Steve French7fc8f4e2009-02-23 20:43:11 +0000513 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
514 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
515 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton608712f2010-10-15 15:33:56 -0400516
517 /*
518 * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
519 * original open. Must mask them off for a reopen.
520 */
Jeff Layton15886172010-10-15 15:33:59 -0400521 unsigned int oflags = pCifsFile->f_flags &
522 ~(O_CREAT | O_EXCL | O_TRUNC);
Jeff Layton608712f2010-10-15 15:33:56 -0400523
Jeff Layton2422f672010-06-16 13:40:16 -0400524 rc = cifs_posix_open(full_path, NULL, inode->i_sb,
Steve Frenchfa588e02010-04-22 19:21:55 +0000525 cifs_sb->mnt_file_mode /* ignored */,
526 oflags, &oplock, &netfid, xid);
Steve French7fc8f4e2009-02-23 20:43:11 +0000527 if (rc == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000528 cFYI(1, "posix reopen succeeded");
Steve French7fc8f4e2009-02-23 20:43:11 +0000529 goto reopen_success;
530 }
531 /* fallthrough to retry open the old way on errors, especially
532 in the reconnect path it is important to retry hard */
533 }
534
Jeff Layton15886172010-10-15 15:33:59 -0400535 desiredAccess = cifs_convert_flags(pCifsFile->f_flags);
Steve French7fc8f4e2009-02-23 20:43:11 +0000536
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500537 if (backup_cred(cifs_sb))
538 create_options |= CREATE_OPEN_BACKUP_INTENT;
539
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 /* Can not refresh inode by passing in file_info buf to be returned
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000541 by SMBOpen and then calling get_inode_info with returned buf
542 since file might have write behind data that needs to be flushed
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 and server version of file size can be stale. If we knew for sure
544 that inode was not dirty locally we could do this */
545
Steve French7fc8f4e2009-02-23 20:43:11 +0000546 rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess,
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500547 create_options, &netfid, &oplock, NULL,
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000548 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
Steve French737b7582005-04-28 22:41:06 -0700549 CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 if (rc) {
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400551 mutex_unlock(&pCifsFile->fh_mutex);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000552 cFYI(1, "cifs_open returned 0x%x", rc);
553 cFYI(1, "oplock: %d", oplock);
Jeff Layton15886172010-10-15 15:33:59 -0400554 goto reopen_error_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 }
Jeff Layton15886172010-10-15 15:33:59 -0400556
557reopen_success:
558 pCifsFile->netfid = netfid;
559 pCifsFile->invalidHandle = false;
560 mutex_unlock(&pCifsFile->fh_mutex);
561 pCifsInode = CIFS_I(inode);
562
563 if (can_flush) {
564 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -0400565 mapping_set_error(inode->i_mapping, rc);
Jeff Layton15886172010-10-15 15:33:59 -0400566
Jeff Layton15886172010-10-15 15:33:59 -0400567 if (tcon->unix_ext)
568 rc = cifs_get_inode_info_unix(&inode,
569 full_path, inode->i_sb, xid);
570 else
571 rc = cifs_get_inode_info(&inode,
572 full_path, NULL, inode->i_sb,
573 xid, NULL);
574 } /* else we are writing out data to server already
575 and could deadlock if we tried to flush data, and
576 since we do not know if we have data that would
577 invalidate the current end of file on the server
578 we can not go to the server to get the new inod
579 info */
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300580
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300581 cifs_set_oplock_level(pCifsInode, oplock);
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300582
Jeff Layton15886172010-10-15 15:33:59 -0400583 cifs_relock_file(pCifsFile);
584
585reopen_error_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 kfree(full_path);
587 FreeXid(xid);
588 return rc;
589}
590
591int cifs_close(struct inode *inode, struct file *file)
592{
Jeff Layton77970692011-04-05 16:23:47 -0700593 if (file->private_data != NULL) {
594 cifsFileInfo_put(file->private_data);
595 file->private_data = NULL;
596 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597
Steve Frenchcdff08e2010-10-21 22:46:14 +0000598 /* return code from the ->release op is always ignored */
599 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600}
601
602int cifs_closedir(struct inode *inode, struct file *file)
603{
604 int rc = 0;
605 int xid;
Joe Perchesc21dfb62010-07-12 13:50:14 -0700606 struct cifsFileInfo *pCFileStruct = file->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 char *ptmp;
608
Joe Perchesb6b38f72010-04-21 03:50:45 +0000609 cFYI(1, "Closedir inode = 0x%p", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
611 xid = GetXid();
612
613 if (pCFileStruct) {
Steve French96daf2b2011-05-27 04:34:02 +0000614 struct cifs_tcon *pTcon = tlink_tcon(pCFileStruct->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615
Joe Perchesb6b38f72010-04-21 03:50:45 +0000616 cFYI(1, "Freeing private data in close dir");
Jeff Layton44772882010-10-15 15:34:03 -0400617 spin_lock(&cifs_file_list_lock);
Steve French4b18f2a2008-04-29 00:06:05 +0000618 if (!pCFileStruct->srch_inf.endOfSearch &&
619 !pCFileStruct->invalidHandle) {
620 pCFileStruct->invalidHandle = true;
Jeff Layton44772882010-10-15 15:34:03 -0400621 spin_unlock(&cifs_file_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000623 cFYI(1, "Closing uncompleted readdir with rc %d",
624 rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 /* not much we can do if it fails anyway, ignore rc */
626 rc = 0;
Steve Frenchddb4cbf2008-11-20 20:00:44 +0000627 } else
Jeff Layton44772882010-10-15 15:34:03 -0400628 spin_unlock(&cifs_file_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
630 if (ptmp) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000631 cFYI(1, "closedir free smb buf in srch struct");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000633 if (pCFileStruct->srch_inf.smallBuf)
Steve Frenchd47d7c12006-02-28 03:45:48 +0000634 cifs_small_buf_release(ptmp);
635 else
636 cifs_buf_release(ptmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 }
Jeff Layton13cfb732010-09-29 19:51:11 -0400638 cifs_put_tlink(pCFileStruct->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 kfree(file->private_data);
640 file->private_data = NULL;
641 }
642 /* BB can we lock the filestruct while this is going on? */
643 FreeXid(xid);
644 return rc;
645}
646
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400647static struct cifsLockInfo *
648cifs_lock_init(__u64 len, __u64 offset, __u8 type, __u16 netfid)
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000649{
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000650 struct cifsLockInfo *li =
651 kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400652 if (!li)
653 return li;
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400654 li->netfid = netfid;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000655 li->offset = offset;
656 li->length = len;
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400657 li->type = type;
658 li->pid = current->tgid;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400659 INIT_LIST_HEAD(&li->blist);
660 init_waitqueue_head(&li->block_q);
661 return li;
662}
663
664static void
665cifs_del_lock_waiters(struct cifsLockInfo *lock)
666{
667 struct cifsLockInfo *li, *tmp;
668 list_for_each_entry_safe(li, tmp, &lock->blist, blist) {
669 list_del_init(&li->blist);
670 wake_up(&li->block_q);
671 }
672}
673
674static bool
675cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset,
676 __u64 length, __u8 type, __u16 netfid,
677 struct cifsLockInfo **conf_lock)
678{
679 struct cifsLockInfo *li, *tmp;
680
681 list_for_each_entry_safe(li, tmp, &cinode->llist, llist) {
682 if (offset + length <= li->offset ||
683 offset >= li->offset + li->length)
684 continue;
685 else if ((type & LOCKING_ANDX_SHARED_LOCK) &&
686 ((netfid == li->netfid && current->tgid == li->pid) ||
687 type == li->type))
688 continue;
689 else {
690 *conf_lock = li;
691 return true;
692 }
693 }
694 return false;
695}
696
697static int
698cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length,
699 __u8 type, __u16 netfid, struct file_lock *flock)
700{
701 int rc = 0;
702 struct cifsLockInfo *conf_lock;
703 bool exist;
704
705 mutex_lock(&cinode->lock_mutex);
706
707 exist = cifs_find_lock_conflict(cinode, offset, length, type, netfid,
708 &conf_lock);
709 if (exist) {
710 flock->fl_start = conf_lock->offset;
711 flock->fl_end = conf_lock->offset + conf_lock->length - 1;
712 flock->fl_pid = conf_lock->pid;
713 if (conf_lock->type & LOCKING_ANDX_SHARED_LOCK)
714 flock->fl_type = F_RDLCK;
715 else
716 flock->fl_type = F_WRLCK;
717 } else if (!cinode->can_cache_brlcks)
718 rc = 1;
719 else
720 flock->fl_type = F_UNLCK;
721
722 mutex_unlock(&cinode->lock_mutex);
723 return rc;
724}
725
726static int
727cifs_lock_add(struct cifsInodeInfo *cinode, __u64 len, __u64 offset,
728 __u8 type, __u16 netfid)
729{
730 struct cifsLockInfo *li;
731
732 li = cifs_lock_init(len, offset, type, netfid);
733 if (!li)
734 return -ENOMEM;
735
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400736 mutex_lock(&cinode->lock_mutex);
737 list_add_tail(&li->llist, &cinode->llist);
738 mutex_unlock(&cinode->lock_mutex);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000739 return 0;
740}
741
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400742static int
743cifs_lock_add_if(struct cifsInodeInfo *cinode, __u64 offset, __u64 length,
744 __u8 type, __u16 netfid, bool wait)
745{
746 struct cifsLockInfo *lock, *conf_lock;
747 bool exist;
748 int rc = 0;
749
750 lock = cifs_lock_init(length, offset, type, netfid);
751 if (!lock)
752 return -ENOMEM;
753
754try_again:
755 exist = false;
756 mutex_lock(&cinode->lock_mutex);
757
758 exist = cifs_find_lock_conflict(cinode, offset, length, type, netfid,
759 &conf_lock);
760 if (!exist && cinode->can_cache_brlcks) {
761 list_add_tail(&lock->llist, &cinode->llist);
762 mutex_unlock(&cinode->lock_mutex);
763 return rc;
764 }
765
766 if (!exist)
767 rc = 1;
768 else if (!wait)
769 rc = -EACCES;
770 else {
771 list_add_tail(&lock->blist, &conf_lock->blist);
772 mutex_unlock(&cinode->lock_mutex);
773 rc = wait_event_interruptible(lock->block_q,
774 (lock->blist.prev == &lock->blist) &&
775 (lock->blist.next == &lock->blist));
776 if (!rc)
777 goto try_again;
778 else {
779 mutex_lock(&cinode->lock_mutex);
780 list_del_init(&lock->blist);
781 mutex_unlock(&cinode->lock_mutex);
782 }
783 }
784
785 kfree(lock);
786 mutex_unlock(&cinode->lock_mutex);
787 return rc;
788}
789
790static int
791cifs_push_locks(struct cifsFileInfo *cfile)
792{
793 int xid, rc = 0, stored_rc;
794 struct cifsLockInfo *li, *tmp;
795 struct cifs_tcon *tcon;
796 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
797
798 xid = GetXid();
799 tcon = tlink_tcon(cfile->tlink);
800
801 mutex_lock(&cinode->lock_mutex);
802 if (!cinode->can_cache_brlcks) {
803 mutex_unlock(&cinode->lock_mutex);
804 FreeXid(xid);
805 return rc;
806 }
807
808 list_for_each_entry_safe(li, tmp, &cinode->llist, llist) {
809 stored_rc = CIFSSMBLock(xid, tcon, cfile->netfid,
810 li->pid, li->length, li->offset,
811 0, 1, li->type, 0, 0);
812 if (stored_rc)
813 rc = stored_rc;
814 }
815
816 cinode->can_cache_brlcks = false;
817 mutex_unlock(&cinode->lock_mutex);
818
819 FreeXid(xid);
820 return rc;
821}
822
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400823static void
824cifs_read_flock(struct file_lock *flock, __u8 *type, int *lock, int *unlock,
825 bool *wait_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826{
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400827 if (flock->fl_flags & FL_POSIX)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000828 cFYI(1, "Posix");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400829 if (flock->fl_flags & FL_FLOCK)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000830 cFYI(1, "Flock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400831 if (flock->fl_flags & FL_SLEEP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000832 cFYI(1, "Blocking lock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400833 *wait_flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 }
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400835 if (flock->fl_flags & FL_ACCESS)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000836 cFYI(1, "Process suspended by mandatory locking - "
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400837 "not implemented yet");
838 if (flock->fl_flags & FL_LEASE)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000839 cFYI(1, "Lease on file - not implemented yet");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400840 if (flock->fl_flags &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400842 cFYI(1, "Unknown lock flags 0x%x", flock->fl_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400844 *type = LOCKING_ANDX_LARGE_FILES;
845 if (flock->fl_type == F_WRLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000846 cFYI(1, "F_WRLCK ");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400847 *lock = 1;
848 } else if (flock->fl_type == F_UNLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000849 cFYI(1, "F_UNLCK");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400850 *unlock = 1;
851 /* Check if unlock includes more than one lock range */
852 } else if (flock->fl_type == F_RDLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000853 cFYI(1, "F_RDLCK");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400854 *type |= LOCKING_ANDX_SHARED_LOCK;
855 *lock = 1;
856 } else if (flock->fl_type == F_EXLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000857 cFYI(1, "F_EXLCK");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400858 *lock = 1;
859 } else if (flock->fl_type == F_SHLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000860 cFYI(1, "F_SHLCK");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400861 *type |= LOCKING_ANDX_SHARED_LOCK;
862 *lock = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +0000864 cFYI(1, "Unknown type of lock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400865}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400867static int
868cifs_getlk(struct cifsFileInfo *cfile, struct file_lock *flock, __u8 type,
869 bool wait_flag, bool posix_lck, int xid)
870{
871 int rc = 0;
872 __u64 length = 1 + flock->fl_end - flock->fl_start;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400873 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400874 __u16 netfid = cfile->netfid;
875 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400877 if (posix_lck) {
878 int posix_lock_type;
879 if (type & LOCKING_ANDX_SHARED_LOCK)
880 posix_lock_type = CIFS_RDLCK;
881 else
882 posix_lock_type = CIFS_WRLCK;
883 rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */,
884 length, flock, posix_lock_type,
885 wait_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 return rc;
887 }
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000888
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400889 rc = cifs_lock_test(cinode, flock->fl_start, length, type, netfid,
890 flock);
891 if (!rc)
892 return rc;
893
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400894 /* BB we could chain these into one lock request BB */
895 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length,
896 flock->fl_start, 0, 1, type, 0, 0);
897 if (rc == 0) {
898 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid,
899 length, flock->fl_start, 1, 0,
900 type, 0, 0);
901 flock->fl_type = F_UNLCK;
902 if (rc != 0)
903 cERROR(1, "Error unlocking previously locked "
904 "range %d during test of lock", rc);
905 rc = 0;
906 return rc;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000907 }
908
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400909 if (type & LOCKING_ANDX_SHARED_LOCK) {
910 flock->fl_type = F_WRLCK;
911 rc = 0;
912 return rc;
913 }
914
915 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length,
916 flock->fl_start, 0, 1,
917 type | LOCKING_ANDX_SHARED_LOCK, 0, 0);
918 if (rc == 0) {
919 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid,
920 length, flock->fl_start, 1, 0,
921 type | LOCKING_ANDX_SHARED_LOCK,
922 0, 0);
923 flock->fl_type = F_RDLCK;
924 if (rc != 0)
925 cERROR(1, "Error unlocking previously locked "
926 "range %d during test of lock", rc);
927 } else
928 flock->fl_type = F_WRLCK;
929
930 rc = 0;
931 return rc;
932}
933
934static int
935cifs_setlk(struct file *file, struct file_lock *flock, __u8 type,
936 bool wait_flag, bool posix_lck, int lock, int unlock, int xid)
937{
938 int rc = 0;
939 __u64 length = 1 + flock->fl_end - flock->fl_start;
940 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
941 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400942 struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode);
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400943 __u16 netfid = cfile->netfid;
944
945 if (posix_lck) {
Steve French08547b02006-02-28 22:39:25 +0000946 int posix_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400947 if (type & LOCKING_ANDX_SHARED_LOCK)
Steve French08547b02006-02-28 22:39:25 +0000948 posix_lock_type = CIFS_RDLCK;
949 else
950 posix_lock_type = CIFS_WRLCK;
Steve French50c2f752007-07-13 00:33:32 +0000951
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400952 if (unlock == 1)
Steve Frenchbeb84dc2006-03-03 23:36:34 +0000953 posix_lock_type = CIFS_UNLCK;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000954
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400955 rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */, length,
956 flock, posix_lock_type, wait_flag);
957 goto out;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000958 }
959
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400960 if (lock) {
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400961 rc = cifs_lock_add_if(cinode, flock->fl_start, length,
962 type, netfid, wait_flag);
963 if (rc < 0)
964 return rc;
965 else if (!rc)
966 goto out;
967
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400968 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length,
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400969 flock->fl_start, 0, 1, type, wait_flag, 0);
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400970 if (rc == 0) {
971 /* For Windows locks we must store them. */
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400972 rc = cifs_lock_add(cinode, length, flock->fl_start,
973 type, netfid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400974 }
975 } else if (unlock) {
976 /*
977 * For each stored lock that this unlock overlaps completely,
978 * unlock it.
979 */
980 int stored_rc = 0;
981 struct cifsLockInfo *li, *tmp;
982
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400983 mutex_lock(&cinode->lock_mutex);
984 list_for_each_entry_safe(li, tmp, &cinode->llist, llist) {
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400985 if (flock->fl_start > li->offset ||
986 (flock->fl_start + length) <
987 (li->offset + li->length))
988 continue;
989 if (current->tgid != li->pid)
990 continue;
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400991 if (cfile->netfid != li->netfid)
992 continue;
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400993
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400994 if (!cinode->can_cache_brlcks)
995 stored_rc = CIFSSMBLock(xid, tcon, netfid,
996 current->tgid,
997 li->length, li->offset,
998 1, 0, li->type, 0, 0);
999 else
1000 stored_rc = 0;
1001
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001002 if (stored_rc)
1003 rc = stored_rc;
1004 else {
1005 list_del(&li->llist);
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001006 cifs_del_lock_waiters(li);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001007 kfree(li);
1008 }
1009 }
Pavel Shilovskyd59dad22011-09-22 09:53:59 +04001010 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001011 }
1012out:
1013 if (flock->fl_flags & FL_POSIX)
1014 posix_lock_file_wait(file, flock);
1015 return rc;
1016}
1017
1018int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
1019{
1020 int rc, xid;
1021 int lock = 0, unlock = 0;
1022 bool wait_flag = false;
1023 bool posix_lck = false;
1024 struct cifs_sb_info *cifs_sb;
1025 struct cifs_tcon *tcon;
1026 struct cifsInodeInfo *cinode;
1027 struct cifsFileInfo *cfile;
1028 __u16 netfid;
1029 __u8 type;
1030
1031 rc = -EACCES;
1032 xid = GetXid();
1033
1034 cFYI(1, "Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld "
1035 "end: %lld", cmd, flock->fl_flags, flock->fl_type,
1036 flock->fl_start, flock->fl_end);
1037
1038 cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag);
1039
1040 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1041 cfile = (struct cifsFileInfo *)file->private_data;
1042 tcon = tlink_tcon(cfile->tlink);
1043 netfid = cfile->netfid;
1044 cinode = CIFS_I(file->f_path.dentry->d_inode);
1045
1046 if ((tcon->ses->capabilities & CAP_UNIX) &&
1047 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
1048 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
1049 posix_lck = true;
1050 /*
1051 * BB add code here to normalize offset and length to account for
1052 * negative length which we can not accept over the wire.
1053 */
1054 if (IS_GETLK(cmd)) {
1055 rc = cifs_getlk(cfile, flock, type, wait_flag, posix_lck, xid);
1056 FreeXid(xid);
1057 return rc;
1058 }
1059
1060 if (!lock && !unlock) {
1061 /*
1062 * if no lock or unlock then nothing to do since we do not
1063 * know what it is
1064 */
1065 FreeXid(xid);
1066 return -EOPNOTSUPP;
1067 }
1068
1069 rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock,
1070 xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 FreeXid(xid);
1072 return rc;
1073}
1074
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001075/* update the file size (if needed) after a write */
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001076void
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001077cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
1078 unsigned int bytes_written)
1079{
1080 loff_t end_of_write = offset + bytes_written;
1081
1082 if (end_of_write > cifsi->server_eof)
1083 cifsi->server_eof = end_of_write;
1084}
1085
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001086static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
Jeff Layton7da4b492010-10-15 15:34:00 -04001087 const char *write_data, size_t write_size,
1088 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089{
1090 int rc = 0;
1091 unsigned int bytes_written = 0;
1092 unsigned int total_written;
1093 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00001094 struct cifs_tcon *pTcon;
Jeff Layton77499812011-01-11 07:24:23 -05001095 int xid;
Jeff Layton7da4b492010-10-15 15:34:00 -04001096 struct dentry *dentry = open_file->dentry;
1097 struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001098 struct cifs_io_parms io_parms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
Jeff Layton7da4b492010-10-15 15:34:00 -04001100 cifs_sb = CIFS_SB(dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101
Joe Perchesb6b38f72010-04-21 03:50:45 +00001102 cFYI(1, "write %zd bytes to offset %lld of %s", write_size,
Jeff Layton7da4b492010-10-15 15:34:00 -04001103 *poffset, dentry->d_name.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104
Jeff Layton13cfb732010-09-29 19:51:11 -04001105 pTcon = tlink_tcon(open_file->tlink);
Steve French50c2f752007-07-13 00:33:32 +00001106
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 for (total_written = 0; write_size > total_written;
1110 total_written += bytes_written) {
1111 rc = -EAGAIN;
1112 while (rc == -EAGAIN) {
Jeff Laytonca83ce32011-04-12 09:13:44 -04001113 struct kvec iov[2];
1114 unsigned int len;
1115
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 if (open_file->invalidHandle) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 /* we could deadlock if we called
1118 filemap_fdatawait from here so tell
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001119 reopen_file not to flush data to
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 server now */
Jeff Layton15886172010-10-15 15:33:59 -04001121 rc = cifs_reopen_file(open_file, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 if (rc != 0)
1123 break;
1124 }
Steve French3e844692005-10-03 13:37:24 -07001125
Jeff Laytonca83ce32011-04-12 09:13:44 -04001126 len = min((size_t)cifs_sb->wsize,
1127 write_size - total_written);
1128 /* iov[0] is reserved for smb header */
1129 iov[1].iov_base = (char *)write_data + total_written;
1130 iov[1].iov_len = len;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001131 io_parms.netfid = open_file->netfid;
1132 io_parms.pid = pid;
1133 io_parms.tcon = pTcon;
1134 io_parms.offset = *poffset;
1135 io_parms.length = len;
1136 rc = CIFSSMBWrite2(xid, &io_parms, &bytes_written, iov,
1137 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 }
1139 if (rc || (bytes_written == 0)) {
1140 if (total_written)
1141 break;
1142 else {
1143 FreeXid(xid);
1144 return rc;
1145 }
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001146 } else {
1147 cifs_update_eof(cifsi, *poffset, bytes_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 *poffset += bytes_written;
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001149 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 }
1151
Steve Frencha4544342005-08-24 13:59:35 -07001152 cifs_stats_bytes_written(pTcon, total_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153
Jeff Layton7da4b492010-10-15 15:34:00 -04001154 if (total_written > 0) {
1155 spin_lock(&dentry->d_inode->i_lock);
1156 if (*poffset > dentry->d_inode->i_size)
1157 i_size_write(dentry->d_inode, *poffset);
1158 spin_unlock(&dentry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 }
Jeff Layton7da4b492010-10-15 15:34:00 -04001160 mark_inode_dirty_sync(dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 FreeXid(xid);
1162 return total_written;
1163}
1164
Jeff Layton6508d902010-09-29 19:51:11 -04001165struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1166 bool fsuid_only)
Steve French630f3f0c2007-10-25 21:17:17 +00001167{
1168 struct cifsFileInfo *open_file = NULL;
Jeff Layton6508d902010-09-29 19:51:11 -04001169 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1170
1171 /* only filter by fsuid on multiuser mounts */
1172 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1173 fsuid_only = false;
Steve French630f3f0c2007-10-25 21:17:17 +00001174
Jeff Layton44772882010-10-15 15:34:03 -04001175 spin_lock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001176 /* we could simply get the first_list_entry since write-only entries
1177 are always at the end of the list but since the first entry might
1178 have a close pending, we go through the whole list */
1179 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001180 if (fsuid_only && open_file->uid != current_fsuid())
1181 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001182 if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
Steve French630f3f0c2007-10-25 21:17:17 +00001183 if (!open_file->invalidHandle) {
1184 /* found a good file */
1185 /* lock it so it will not be closed on us */
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001186 cifsFileInfo_get(open_file);
Jeff Layton44772882010-10-15 15:34:03 -04001187 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001188 return open_file;
1189 } /* else might as well continue, and look for
1190 another, or simply have the caller reopen it
1191 again rather than trying to fix this handle */
1192 } else /* write only file */
1193 break; /* write only files are last so must be done */
1194 }
Jeff Layton44772882010-10-15 15:34:03 -04001195 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001196 return NULL;
1197}
Steve French630f3f0c2007-10-25 21:17:17 +00001198
Jeff Layton6508d902010-09-29 19:51:11 -04001199struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1200 bool fsuid_only)
Steve French6148a742005-10-05 12:23:19 -07001201{
1202 struct cifsFileInfo *open_file;
Jeff Laytond3892292010-11-02 16:22:50 -04001203 struct cifs_sb_info *cifs_sb;
Jeff Layton2846d382008-09-22 21:33:33 -04001204 bool any_available = false;
Steve Frenchdd99cd82005-10-05 19:32:49 -07001205 int rc;
Steve French6148a742005-10-05 12:23:19 -07001206
Steve French60808232006-04-22 15:53:05 +00001207 /* Having a null inode here (because mapping->host was set to zero by
1208 the VFS or MM) should not happen but we had reports of on oops (due to
1209 it being zero) during stress testcases so we need to check for it */
1210
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001211 if (cifs_inode == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001212 cERROR(1, "Null inode passed to cifs_writeable_file");
Steve French60808232006-04-22 15:53:05 +00001213 dump_stack();
1214 return NULL;
1215 }
1216
Jeff Laytond3892292010-11-02 16:22:50 -04001217 cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1218
Jeff Layton6508d902010-09-29 19:51:11 -04001219 /* only filter by fsuid on multiuser mounts */
1220 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1221 fsuid_only = false;
1222
Jeff Layton44772882010-10-15 15:34:03 -04001223 spin_lock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001224refind_writable:
Steve French6148a742005-10-05 12:23:19 -07001225 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001226 if (!any_available && open_file->pid != current->tgid)
1227 continue;
1228 if (fsuid_only && open_file->uid != current_fsuid())
1229 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001230 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001231 cifsFileInfo_get(open_file);
Steve French9b22b0b2007-10-02 01:11:08 +00001232
1233 if (!open_file->invalidHandle) {
1234 /* found a good writable file */
Jeff Layton44772882010-10-15 15:34:03 -04001235 spin_unlock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001236 return open_file;
1237 }
Steve French8840dee2007-11-16 23:05:52 +00001238
Jeff Layton44772882010-10-15 15:34:03 -04001239 spin_unlock(&cifs_file_list_lock);
Steve Frenchcdff08e2010-10-21 22:46:14 +00001240
Steve French9b22b0b2007-10-02 01:11:08 +00001241 /* Had to unlock since following call can block */
Jeff Layton15886172010-10-15 15:33:59 -04001242 rc = cifs_reopen_file(open_file, false);
Steve Frenchcdff08e2010-10-21 22:46:14 +00001243 if (!rc)
1244 return open_file;
Steve French9b22b0b2007-10-02 01:11:08 +00001245
Steve Frenchcdff08e2010-10-21 22:46:14 +00001246 /* if it fails, try another handle if possible */
Joe Perchesb6b38f72010-04-21 03:50:45 +00001247 cFYI(1, "wp failed on reopen file");
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001248 cifsFileInfo_put(open_file);
Steve French8840dee2007-11-16 23:05:52 +00001249
Steve Frenchcdff08e2010-10-21 22:46:14 +00001250 spin_lock(&cifs_file_list_lock);
1251
Steve French9b22b0b2007-10-02 01:11:08 +00001252 /* else we simply continue to the next entry. Thus
1253 we do not loop on reopen errors. If we
1254 can not reopen the file, for example if we
1255 reconnected to a server with another client
1256 racing to delete or lock the file we would not
1257 make progress if we restarted before the beginning
1258 of the loop here. */
Steve French6148a742005-10-05 12:23:19 -07001259 }
1260 }
Jeff Layton2846d382008-09-22 21:33:33 -04001261 /* couldn't find useable FH with same pid, try any available */
1262 if (!any_available) {
1263 any_available = true;
1264 goto refind_writable;
1265 }
Jeff Layton44772882010-10-15 15:34:03 -04001266 spin_unlock(&cifs_file_list_lock);
Steve French6148a742005-10-05 12:23:19 -07001267 return NULL;
1268}
1269
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1271{
1272 struct address_space *mapping = page->mapping;
1273 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1274 char *write_data;
1275 int rc = -EFAULT;
1276 int bytes_written = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 struct inode *inode;
Steve French6148a742005-10-05 12:23:19 -07001278 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279
1280 if (!mapping || !mapping->host)
1281 return -EFAULT;
1282
1283 inode = page->mapping->host;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
1285 offset += (loff_t)from;
1286 write_data = kmap(page);
1287 write_data += from;
1288
1289 if ((to > PAGE_CACHE_SIZE) || (from > to)) {
1290 kunmap(page);
1291 return -EIO;
1292 }
1293
1294 /* racing with truncate? */
1295 if (offset > mapping->host->i_size) {
1296 kunmap(page);
1297 return 0; /* don't care */
1298 }
1299
1300 /* check to make sure that we are not extending the file */
1301 if (mapping->host->i_size - offset < (loff_t)to)
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001302 to = (unsigned)(mapping->host->i_size - offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
Jeff Layton6508d902010-09-29 19:51:11 -04001304 open_file = find_writable_file(CIFS_I(mapping->host), false);
Steve French6148a742005-10-05 12:23:19 -07001305 if (open_file) {
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001306 bytes_written = cifs_write(open_file, open_file->pid,
1307 write_data, to - from, &offset);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001308 cifsFileInfo_put(open_file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 /* Does mm or vfs already set times? */
Steve French6148a742005-10-05 12:23:19 -07001310 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001311 if ((bytes_written > 0) && (offset))
Steve French6148a742005-10-05 12:23:19 -07001312 rc = 0;
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001313 else if (bytes_written < 0)
1314 rc = bytes_written;
Steve French6148a742005-10-05 12:23:19 -07001315 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001316 cFYI(1, "No writeable filehandles for inode");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 rc = -EIO;
1318 }
1319
1320 kunmap(page);
1321 return rc;
1322}
1323
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324static int cifs_writepages(struct address_space *mapping,
Steve French37c0eb42005-10-05 14:50:29 -07001325 struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326{
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001327 struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb);
1328 bool done = false, scanned = false, range_whole = false;
1329 pgoff_t end, index;
1330 struct cifs_writedata *wdata;
Steve French37c0eb42005-10-05 14:50:29 -07001331 struct page *page;
Steve French37c0eb42005-10-05 14:50:29 -07001332 int rc = 0;
Steve French50c2f752007-07-13 00:33:32 +00001333
Steve French37c0eb42005-10-05 14:50:29 -07001334 /*
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001335 * If wsize is smaller than the page cache size, default to writing
Steve French37c0eb42005-10-05 14:50:29 -07001336 * one page at a time via cifs_writepage
1337 */
1338 if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1339 return generic_writepages(mapping, wbc);
1340
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001341 if (wbc->range_cyclic) {
Steve French37c0eb42005-10-05 14:50:29 -07001342 index = mapping->writeback_index; /* Start from prev offset */
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001343 end = -1;
1344 } else {
1345 index = wbc->range_start >> PAGE_CACHE_SHIFT;
1346 end = wbc->range_end >> PAGE_CACHE_SHIFT;
1347 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001348 range_whole = true;
1349 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001350 }
1351retry:
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001352 while (!done && index <= end) {
1353 unsigned int i, nr_pages, found_pages;
1354 pgoff_t next = 0, tofind;
1355 struct page **pages;
Steve French37c0eb42005-10-05 14:50:29 -07001356
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001357 tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1,
1358 end - index) + 1;
Steve French37c0eb42005-10-05 14:50:29 -07001359
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001360 wdata = cifs_writedata_alloc((unsigned int)tofind);
1361 if (!wdata) {
1362 rc = -ENOMEM;
1363 break;
1364 }
1365
1366 /*
1367 * find_get_pages_tag seems to return a max of 256 on each
1368 * iteration, so we must call it several times in order to
1369 * fill the array or the wsize is effectively limited to
1370 * 256 * PAGE_CACHE_SIZE.
1371 */
1372 found_pages = 0;
1373 pages = wdata->pages;
1374 do {
1375 nr_pages = find_get_pages_tag(mapping, &index,
1376 PAGECACHE_TAG_DIRTY,
1377 tofind, pages);
1378 found_pages += nr_pages;
1379 tofind -= nr_pages;
1380 pages += nr_pages;
1381 } while (nr_pages && tofind && index <= end);
1382
1383 if (found_pages == 0) {
1384 kref_put(&wdata->refcount, cifs_writedata_release);
1385 break;
1386 }
1387
1388 nr_pages = 0;
1389 for (i = 0; i < found_pages; i++) {
1390 page = wdata->pages[i];
Steve French37c0eb42005-10-05 14:50:29 -07001391 /*
1392 * At this point we hold neither mapping->tree_lock nor
1393 * lock on the page itself: the page may be truncated or
1394 * invalidated (changing page->mapping to NULL), or even
1395 * swizzled back from swapper_space to tmpfs file
1396 * mapping
1397 */
1398
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001399 if (nr_pages == 0)
Steve French37c0eb42005-10-05 14:50:29 -07001400 lock_page(page);
Nick Piggin529ae9a2008-08-02 12:01:03 +02001401 else if (!trylock_page(page))
Steve French37c0eb42005-10-05 14:50:29 -07001402 break;
1403
1404 if (unlikely(page->mapping != mapping)) {
1405 unlock_page(page);
1406 break;
1407 }
1408
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001409 if (!wbc->range_cyclic && page->index > end) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001410 done = true;
Steve French37c0eb42005-10-05 14:50:29 -07001411 unlock_page(page);
1412 break;
1413 }
1414
1415 if (next && (page->index != next)) {
1416 /* Not next consecutive page */
1417 unlock_page(page);
1418 break;
1419 }
1420
1421 if (wbc->sync_mode != WB_SYNC_NONE)
1422 wait_on_page_writeback(page);
1423
1424 if (PageWriteback(page) ||
Linus Torvaldscb876f42006-12-23 16:19:07 -08001425 !clear_page_dirty_for_io(page)) {
Steve French37c0eb42005-10-05 14:50:29 -07001426 unlock_page(page);
1427 break;
1428 }
Steve French84d2f072005-10-12 15:32:05 -07001429
Linus Torvaldscb876f42006-12-23 16:19:07 -08001430 /*
1431 * This actually clears the dirty bit in the radix tree.
1432 * See cifs_writepage() for more commentary.
1433 */
1434 set_page_writeback(page);
1435
Steve French84d2f072005-10-12 15:32:05 -07001436 if (page_offset(page) >= mapping->host->i_size) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001437 done = true;
Steve French84d2f072005-10-12 15:32:05 -07001438 unlock_page(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001439 end_page_writeback(page);
Steve French84d2f072005-10-12 15:32:05 -07001440 break;
1441 }
1442
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001443 wdata->pages[i] = page;
Steve French37c0eb42005-10-05 14:50:29 -07001444 next = page->index + 1;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001445 ++nr_pages;
Steve French37c0eb42005-10-05 14:50:29 -07001446 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001447
1448 /* reset index to refind any pages skipped */
1449 if (nr_pages == 0)
1450 index = wdata->pages[0]->index + 1;
1451
1452 /* put any pages we aren't going to use */
1453 for (i = nr_pages; i < found_pages; i++) {
1454 page_cache_release(wdata->pages[i]);
1455 wdata->pages[i] = NULL;
1456 }
1457
1458 /* nothing to write? */
1459 if (nr_pages == 0) {
1460 kref_put(&wdata->refcount, cifs_writedata_release);
1461 continue;
1462 }
1463
1464 wdata->sync_mode = wbc->sync_mode;
1465 wdata->nr_pages = nr_pages;
1466 wdata->offset = page_offset(wdata->pages[0]);
1467
1468 do {
1469 if (wdata->cfile != NULL)
1470 cifsFileInfo_put(wdata->cfile);
1471 wdata->cfile = find_writable_file(CIFS_I(mapping->host),
1472 false);
1473 if (!wdata->cfile) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001474 cERROR(1, "No writable handles for inode");
Steve French23e7dd72005-10-20 13:44:56 -07001475 rc = -EBADF;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001476 break;
Steve French37c0eb42005-10-05 14:50:29 -07001477 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001478 rc = cifs_async_writev(wdata);
1479 } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN);
Jeff Laytonf3983c22010-09-22 16:17:40 -07001480
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001481 for (i = 0; i < nr_pages; ++i)
1482 unlock_page(wdata->pages[i]);
Jeff Layton941b8532011-01-11 07:24:01 -05001483
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001484 /* send failure -- clean up the mess */
1485 if (rc != 0) {
1486 for (i = 0; i < nr_pages; ++i) {
Jeff Layton941b8532011-01-11 07:24:01 -05001487 if (rc == -EAGAIN)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001488 redirty_page_for_writepage(wbc,
1489 wdata->pages[i]);
1490 else
1491 SetPageError(wdata->pages[i]);
1492 end_page_writeback(wdata->pages[i]);
1493 page_cache_release(wdata->pages[i]);
Steve French37c0eb42005-10-05 14:50:29 -07001494 }
Jeff Layton941b8532011-01-11 07:24:01 -05001495 if (rc != -EAGAIN)
1496 mapping_set_error(mapping, rc);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001497 }
1498 kref_put(&wdata->refcount, cifs_writedata_release);
Jeff Layton941b8532011-01-11 07:24:01 -05001499
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001500 wbc->nr_to_write -= nr_pages;
1501 if (wbc->nr_to_write <= 0)
1502 done = true;
Dave Kleikampb066a482008-11-18 03:49:05 +00001503
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001504 index = next;
Steve French37c0eb42005-10-05 14:50:29 -07001505 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001506
Steve French37c0eb42005-10-05 14:50:29 -07001507 if (!scanned && !done) {
1508 /*
1509 * We hit the last page and there is more work to be done: wrap
1510 * back to the start of the file
1511 */
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001512 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001513 index = 0;
1514 goto retry;
1515 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001516
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001517 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
Steve French37c0eb42005-10-05 14:50:29 -07001518 mapping->writeback_index = index;
1519
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 return rc;
1521}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001523static int
1524cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525{
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001526 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 int xid;
1528
1529 xid = GetXid();
1530/* BB add check for wbc flags */
1531 page_cache_get(page);
Steve Frenchad7a2922008-02-07 23:25:02 +00001532 if (!PageUptodate(page))
Joe Perchesb6b38f72010-04-21 03:50:45 +00001533 cFYI(1, "ppw - page not up to date");
Linus Torvaldscb876f42006-12-23 16:19:07 -08001534
1535 /*
1536 * Set the "writeback" flag, and clear "dirty" in the radix tree.
1537 *
1538 * A writepage() implementation always needs to do either this,
1539 * or re-dirty the page with "redirty_page_for_writepage()" in
1540 * the case of a failure.
1541 *
1542 * Just unlocking the page will cause the radix tree tag-bits
1543 * to fail to update with the state of the page correctly.
1544 */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001545 set_page_writeback(page);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001546retry_write:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001548 if (rc == -EAGAIN && wbc->sync_mode == WB_SYNC_ALL)
1549 goto retry_write;
1550 else if (rc == -EAGAIN)
1551 redirty_page_for_writepage(wbc, page);
1552 else if (rc != 0)
1553 SetPageError(page);
1554 else
1555 SetPageUptodate(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001556 end_page_writeback(page);
1557 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 FreeXid(xid);
1559 return rc;
1560}
1561
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001562static int cifs_writepage(struct page *page, struct writeback_control *wbc)
1563{
1564 int rc = cifs_writepage_locked(page, wbc);
1565 unlock_page(page);
1566 return rc;
1567}
1568
Nick Piggind9414772008-09-24 11:32:59 -04001569static int cifs_write_end(struct file *file, struct address_space *mapping,
1570 loff_t pos, unsigned len, unsigned copied,
1571 struct page *page, void *fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572{
Nick Piggind9414772008-09-24 11:32:59 -04001573 int rc;
1574 struct inode *inode = mapping->host;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001575 struct cifsFileInfo *cfile = file->private_data;
1576 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
1577 __u32 pid;
1578
1579 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1580 pid = cfile->pid;
1581 else
1582 pid = current->tgid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
Joe Perchesb6b38f72010-04-21 03:50:45 +00001584 cFYI(1, "write_end for page %p from pos %lld with %d bytes",
1585 page, pos, copied);
Steve Frenchad7a2922008-02-07 23:25:02 +00001586
Jeff Laytona98ee8c2008-11-26 19:32:33 +00001587 if (PageChecked(page)) {
1588 if (copied == len)
1589 SetPageUptodate(page);
1590 ClearPageChecked(page);
1591 } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
Nick Piggind9414772008-09-24 11:32:59 -04001592 SetPageUptodate(page);
1593
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 if (!PageUptodate(page)) {
Nick Piggind9414772008-09-24 11:32:59 -04001595 char *page_data;
1596 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
1597 int xid;
1598
1599 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 /* this is probably better than directly calling
1601 partialpage_write since in this function the file handle is
1602 known which we might as well leverage */
1603 /* BB check if anything else missing out of ppw
1604 such as updating last write time */
1605 page_data = kmap(page);
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001606 rc = cifs_write(cfile, pid, page_data + offset, copied, &pos);
Nick Piggind9414772008-09-24 11:32:59 -04001607 /* if (rc < 0) should we set writebehind rc? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 kunmap(page);
Nick Piggind9414772008-09-24 11:32:59 -04001609
1610 FreeXid(xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001611 } else {
Nick Piggind9414772008-09-24 11:32:59 -04001612 rc = copied;
1613 pos += copied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 set_page_dirty(page);
1615 }
1616
Nick Piggind9414772008-09-24 11:32:59 -04001617 if (rc > 0) {
1618 spin_lock(&inode->i_lock);
1619 if (pos > inode->i_size)
1620 i_size_write(inode, pos);
1621 spin_unlock(&inode->i_lock);
1622 }
1623
1624 unlock_page(page);
1625 page_cache_release(page);
1626
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 return rc;
1628}
1629
Josef Bacik02c24a82011-07-16 20:44:56 -04001630int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
1631 int datasync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632{
1633 int xid;
1634 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00001635 struct cifs_tcon *tcon;
Joe Perchesc21dfb62010-07-12 13:50:14 -07001636 struct cifsFileInfo *smbfile = file->private_data;
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08001637 struct inode *inode = file->f_path.dentry->d_inode;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001638 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639
Josef Bacik02c24a82011-07-16 20:44:56 -04001640 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
1641 if (rc)
1642 return rc;
1643 mutex_lock(&inode->i_mutex);
1644
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 xid = GetXid();
1646
Joe Perchesb6b38f72010-04-21 03:50:45 +00001647 cFYI(1, "Sync file - name: %s datasync: 0x%x",
Christoph Hellwig7ea80852010-05-26 17:53:25 +02001648 file->f_path.dentry->d_name.name, datasync);
Steve French50c2f752007-07-13 00:33:32 +00001649
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001650 if (!CIFS_I(inode)->clientCanCacheRead) {
1651 rc = cifs_invalidate_mapping(inode);
1652 if (rc) {
1653 cFYI(1, "rc: %d during invalidate phase", rc);
1654 rc = 0; /* don't care about it in fsync */
1655 }
1656 }
Jeff Laytoneb4b7562010-10-22 14:52:29 -04001657
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001658 tcon = tlink_tcon(smbfile->tlink);
1659 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
1660 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
1661
1662 FreeXid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04001663 mutex_unlock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001664 return rc;
1665}
1666
Josef Bacik02c24a82011-07-16 20:44:56 -04001667int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001668{
1669 int xid;
1670 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00001671 struct cifs_tcon *tcon;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001672 struct cifsFileInfo *smbfile = file->private_data;
1673 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Josef Bacik02c24a82011-07-16 20:44:56 -04001674 struct inode *inode = file->f_mapping->host;
1675
1676 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
1677 if (rc)
1678 return rc;
1679 mutex_lock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001680
1681 xid = GetXid();
1682
1683 cFYI(1, "Sync file - name: %s datasync: 0x%x",
1684 file->f_path.dentry->d_name.name, datasync);
1685
1686 tcon = tlink_tcon(smbfile->tlink);
1687 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
1688 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
Steve Frenchb298f222009-02-21 21:17:43 +00001689
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 FreeXid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04001691 mutex_unlock(&inode->i_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 return rc;
1693}
1694
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695/*
1696 * As file closes, flush all cached write data for this inode checking
1697 * for write behind errors.
1698 */
Miklos Szeredi75e1fcc2006-06-23 02:05:12 -07001699int cifs_flush(struct file *file, fl_owner_t id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700{
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001701 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 int rc = 0;
1703
Jeff Laytoneb4b7562010-10-22 14:52:29 -04001704 if (file->f_mode & FMODE_WRITE)
Jeff Laytond3f13222010-10-15 15:34:07 -04001705 rc = filemap_write_and_wait(inode->i_mapping);
Steve French50c2f752007-07-13 00:33:32 +00001706
Joe Perchesb6b38f72010-04-21 03:50:45 +00001707 cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708
1709 return rc;
1710}
1711
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001712static int
1713cifs_write_allocate_pages(struct page **pages, unsigned long num_pages)
1714{
1715 int rc = 0;
1716 unsigned long i;
1717
1718 for (i = 0; i < num_pages; i++) {
1719 pages[i] = alloc_page(__GFP_HIGHMEM);
1720 if (!pages[i]) {
1721 /*
1722 * save number of pages we have already allocated and
1723 * return with ENOMEM error
1724 */
1725 num_pages = i;
1726 rc = -ENOMEM;
1727 goto error;
1728 }
1729 }
1730
1731 return rc;
1732
1733error:
1734 for (i = 0; i < num_pages; i++)
1735 put_page(pages[i]);
1736 return rc;
1737}
1738
1739static inline
1740size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
1741{
1742 size_t num_pages;
1743 size_t clen;
1744
1745 clen = min_t(const size_t, len, wsize);
1746 num_pages = clen / PAGE_CACHE_SIZE;
1747 if (clen % PAGE_CACHE_SIZE)
1748 num_pages++;
1749
1750 if (cur_len)
1751 *cur_len = clen;
1752
1753 return num_pages;
1754}
1755
1756static ssize_t
1757cifs_iovec_write(struct file *file, const struct iovec *iov,
1758 unsigned long nr_segs, loff_t *poffset)
1759{
Pavel Shilovsky76429c12011-01-31 16:03:08 +03001760 unsigned int written;
1761 unsigned long num_pages, npages, i;
1762 size_t copied, len, cur_len;
1763 ssize_t total_written = 0;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001764 struct kvec *to_send;
1765 struct page **pages;
1766 struct iov_iter it;
1767 struct inode *inode;
1768 struct cifsFileInfo *open_file;
Steve French96daf2b2011-05-27 04:34:02 +00001769 struct cifs_tcon *pTcon;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001770 struct cifs_sb_info *cifs_sb;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001771 struct cifs_io_parms io_parms;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001772 int xid, rc;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001773 __u32 pid;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001774
1775 len = iov_length(iov, nr_segs);
1776 if (!len)
1777 return 0;
1778
1779 rc = generic_write_checks(file, poffset, &len, 0);
1780 if (rc)
1781 return rc;
1782
1783 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1784 num_pages = get_numpages(cifs_sb->wsize, len, &cur_len);
1785
1786 pages = kmalloc(sizeof(struct pages *)*num_pages, GFP_KERNEL);
1787 if (!pages)
1788 return -ENOMEM;
1789
1790 to_send = kmalloc(sizeof(struct kvec)*(num_pages + 1), GFP_KERNEL);
1791 if (!to_send) {
1792 kfree(pages);
1793 return -ENOMEM;
1794 }
1795
1796 rc = cifs_write_allocate_pages(pages, num_pages);
1797 if (rc) {
1798 kfree(pages);
1799 kfree(to_send);
1800 return rc;
1801 }
1802
1803 xid = GetXid();
1804 open_file = file->private_data;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001805
1806 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1807 pid = open_file->pid;
1808 else
1809 pid = current->tgid;
1810
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001811 pTcon = tlink_tcon(open_file->tlink);
1812 inode = file->f_path.dentry->d_inode;
1813
1814 iov_iter_init(&it, iov, nr_segs, len, 0);
1815 npages = num_pages;
1816
1817 do {
1818 size_t save_len = cur_len;
1819 for (i = 0; i < npages; i++) {
1820 copied = min_t(const size_t, cur_len, PAGE_CACHE_SIZE);
1821 copied = iov_iter_copy_from_user(pages[i], &it, 0,
1822 copied);
1823 cur_len -= copied;
1824 iov_iter_advance(&it, copied);
1825 to_send[i+1].iov_base = kmap(pages[i]);
1826 to_send[i+1].iov_len = copied;
1827 }
1828
1829 cur_len = save_len - cur_len;
1830
1831 do {
1832 if (open_file->invalidHandle) {
1833 rc = cifs_reopen_file(open_file, false);
1834 if (rc != 0)
1835 break;
1836 }
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001837 io_parms.netfid = open_file->netfid;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001838 io_parms.pid = pid;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001839 io_parms.tcon = pTcon;
1840 io_parms.offset = *poffset;
1841 io_parms.length = cur_len;
1842 rc = CIFSSMBWrite2(xid, &io_parms, &written, to_send,
1843 npages, 0);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001844 } while (rc == -EAGAIN);
1845
1846 for (i = 0; i < npages; i++)
1847 kunmap(pages[i]);
1848
1849 if (written) {
1850 len -= written;
1851 total_written += written;
1852 cifs_update_eof(CIFS_I(inode), *poffset, written);
1853 *poffset += written;
1854 } else if (rc < 0) {
1855 if (!total_written)
1856 total_written = rc;
1857 break;
1858 }
1859
1860 /* get length and number of kvecs of the next write */
1861 npages = get_numpages(cifs_sb->wsize, len, &cur_len);
1862 } while (len > 0);
1863
1864 if (total_written > 0) {
1865 spin_lock(&inode->i_lock);
1866 if (*poffset > inode->i_size)
1867 i_size_write(inode, *poffset);
1868 spin_unlock(&inode->i_lock);
1869 }
1870
1871 cifs_stats_bytes_written(pTcon, total_written);
1872 mark_inode_dirty_sync(inode);
1873
1874 for (i = 0; i < num_pages; i++)
1875 put_page(pages[i]);
1876 kfree(to_send);
1877 kfree(pages);
1878 FreeXid(xid);
1879 return total_written;
1880}
1881
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03001882ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001883 unsigned long nr_segs, loff_t pos)
1884{
1885 ssize_t written;
1886 struct inode *inode;
1887
1888 inode = iocb->ki_filp->f_path.dentry->d_inode;
1889
1890 /*
1891 * BB - optimize the way when signing is disabled. We can drop this
1892 * extra memory-to-memory copying and use iovec buffers for constructing
1893 * write request.
1894 */
1895
1896 written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos);
1897 if (written > 0) {
1898 CIFS_I(inode)->invalid_mapping = true;
1899 iocb->ki_pos = pos;
1900 }
1901
1902 return written;
1903}
1904
1905ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
1906 unsigned long nr_segs, loff_t pos)
1907{
1908 struct inode *inode;
1909
1910 inode = iocb->ki_filp->f_path.dentry->d_inode;
1911
1912 if (CIFS_I(inode)->clientCanCacheAll)
1913 return generic_file_aio_write(iocb, iov, nr_segs, pos);
1914
1915 /*
1916 * In strict cache mode we need to write the data to the server exactly
1917 * from the pos to pos+len-1 rather than flush all affected pages
1918 * because it may cause a error with mandatory locks on these pages but
1919 * not on the region from pos to ppos+len-1.
1920 */
1921
1922 return cifs_user_writev(iocb, iov, nr_segs, pos);
1923}
1924
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001925static ssize_t
1926cifs_iovec_read(struct file *file, const struct iovec *iov,
1927 unsigned long nr_segs, loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928{
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001929 int rc;
1930 int xid;
Pavel Shilovsky76429c12011-01-31 16:03:08 +03001931 ssize_t total_read;
1932 unsigned int bytes_read = 0;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001933 size_t len, cur_len;
1934 int iov_offset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00001936 struct cifs_tcon *pTcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 struct smb_com_read_rsp *pSMBr;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001939 struct cifs_io_parms io_parms;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001940 char *read_data;
Jeff Layton5eba8ab2011-10-19 15:30:26 -04001941 unsigned int rsize;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001942 __u32 pid;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001943
1944 if (!nr_segs)
1945 return 0;
1946
1947 len = iov_length(iov, nr_segs);
1948 if (!len)
1949 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950
1951 xid = GetXid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08001952 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953
Jeff Layton5eba8ab2011-10-19 15:30:26 -04001954 /* FIXME: set up handlers for larger reads and/or convert to async */
1955 rsize = min_t(unsigned int, cifs_sb->rsize, CIFSMaxBufSize);
1956
Joe Perchesc21dfb62010-07-12 13:50:14 -07001957 open_file = file->private_data;
Jeff Layton13cfb732010-09-29 19:51:11 -04001958 pTcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001960 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1961 pid = open_file->pid;
1962 else
1963 pid = current->tgid;
1964
Steve Frenchad7a2922008-02-07 23:25:02 +00001965 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001966 cFYI(1, "attempting read on write only file instance");
Steve Frenchad7a2922008-02-07 23:25:02 +00001967
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001968 for (total_read = 0; total_read < len; total_read += bytes_read) {
Jeff Layton5eba8ab2011-10-19 15:30:26 -04001969 cur_len = min_t(const size_t, len - total_read, rsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 rc = -EAGAIN;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001971 read_data = NULL;
1972
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 while (rc == -EAGAIN) {
Steve Frenchec637e32005-12-12 20:53:18 -08001974 int buf_type = CIFS_NO_BUFFER;
Steve Frenchcdff08e2010-10-21 22:46:14 +00001975 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04001976 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 if (rc != 0)
1978 break;
1979 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001980 io_parms.netfid = open_file->netfid;
1981 io_parms.pid = pid;
1982 io_parms.tcon = pTcon;
1983 io_parms.offset = *poffset;
Pavel Shilovsky2cebaa52011-07-20 18:24:09 +04001984 io_parms.length = cur_len;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001985 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001986 &read_data, &buf_type);
1987 pSMBr = (struct smb_com_read_rsp *)read_data;
1988 if (read_data) {
1989 char *data_offset = read_data + 4 +
1990 le16_to_cpu(pSMBr->DataOffset);
1991 if (memcpy_toiovecend(iov, data_offset,
1992 iov_offset, bytes_read))
Steve French93544cc2006-02-14 22:30:52 -06001993 rc = -EFAULT;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001994 if (buf_type == CIFS_SMALL_BUFFER)
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001995 cifs_small_buf_release(read_data);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001996 else if (buf_type == CIFS_LARGE_BUFFER)
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001997 cifs_buf_release(read_data);
1998 read_data = NULL;
1999 iov_offset += bytes_read;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 }
2001 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002002
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 if (rc || (bytes_read == 0)) {
2004 if (total_read) {
2005 break;
2006 } else {
2007 FreeXid(xid);
2008 return rc;
2009 }
2010 } else {
Steve Frencha4544342005-08-24 13:59:35 -07002011 cifs_stats_bytes_read(pTcon, bytes_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 *poffset += bytes_read;
2013 }
2014 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002015
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 FreeXid(xid);
2017 return total_read;
2018}
2019
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03002020ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002021 unsigned long nr_segs, loff_t pos)
2022{
2023 ssize_t read;
2024
2025 read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos);
2026 if (read > 0)
2027 iocb->ki_pos = pos;
2028
2029 return read;
2030}
2031
2032ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov,
2033 unsigned long nr_segs, loff_t pos)
2034{
2035 struct inode *inode;
2036
2037 inode = iocb->ki_filp->f_path.dentry->d_inode;
2038
2039 if (CIFS_I(inode)->clientCanCacheRead)
2040 return generic_file_aio_read(iocb, iov, nr_segs, pos);
2041
2042 /*
2043 * In strict cache mode we need to read from the server all the time
2044 * if we don't have level II oplock because the server can delay mtime
2045 * change - so we can't make a decision about inode invalidating.
2046 * And we can also fail with pagereading if there are mandatory locks
2047 * on pages affected by this read but not on the region from pos to
2048 * pos+len-1.
2049 */
2050
2051 return cifs_user_readv(iocb, iov, nr_segs, pos);
2052}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053
2054static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002055 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056{
2057 int rc = -EACCES;
2058 unsigned int bytes_read = 0;
2059 unsigned int total_read;
2060 unsigned int current_read_size;
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002061 unsigned int rsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00002063 struct cifs_tcon *pTcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 int xid;
2065 char *current_offset;
2066 struct cifsFileInfo *open_file;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002067 struct cifs_io_parms io_parms;
Steve Frenchec637e32005-12-12 20:53:18 -08002068 int buf_type = CIFS_NO_BUFFER;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002069 __u32 pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070
2071 xid = GetXid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002072 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002074 /* FIXME: set up handlers for larger reads and/or convert to async */
2075 rsize = min_t(unsigned int, cifs_sb->rsize, CIFSMaxBufSize);
2076
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302078 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302080 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 }
Joe Perchesc21dfb62010-07-12 13:50:14 -07002082 open_file = file->private_data;
Jeff Layton13cfb732010-09-29 19:51:11 -04002083 pTcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002085 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2086 pid = open_file->pid;
2087 else
2088 pid = current->tgid;
2089
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002091 cFYI(1, "attempting read on write only file instance");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002093 for (total_read = 0, current_offset = read_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 read_size > total_read;
2095 total_read += bytes_read, current_offset += bytes_read) {
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002096 current_read_size = min_t(uint, read_size - total_read, rsize);
2097
Steve Frenchf9f5c8172005-09-15 23:06:38 -07002098 /* For windows me and 9x we do not want to request more
2099 than it negotiated since it will refuse the read then */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002100 if ((pTcon->ses) &&
Steve Frenchf9f5c8172005-09-15 23:06:38 -07002101 !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
Dan Carpenter7748dd62011-10-18 12:41:35 +03002102 current_read_size = min_t(uint, current_read_size,
Jeff Laytonc974bef2011-10-11 06:41:32 -04002103 CIFSMaxBufSize);
Steve Frenchf9f5c8172005-09-15 23:06:38 -07002104 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 rc = -EAGAIN;
2106 while (rc == -EAGAIN) {
Steve Frenchcdff08e2010-10-21 22:46:14 +00002107 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04002108 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 if (rc != 0)
2110 break;
2111 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002112 io_parms.netfid = open_file->netfid;
2113 io_parms.pid = pid;
2114 io_parms.tcon = pTcon;
2115 io_parms.offset = *poffset;
2116 io_parms.length = current_read_size;
2117 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
2118 &current_offset, &buf_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 }
2120 if (rc || (bytes_read == 0)) {
2121 if (total_read) {
2122 break;
2123 } else {
2124 FreeXid(xid);
2125 return rc;
2126 }
2127 } else {
Steve Frencha4544342005-08-24 13:59:35 -07002128 cifs_stats_bytes_read(pTcon, total_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 *poffset += bytes_read;
2130 }
2131 }
2132 FreeXid(xid);
2133 return total_read;
2134}
2135
Jeff Laytonca83ce32011-04-12 09:13:44 -04002136/*
2137 * If the page is mmap'ed into a process' page tables, then we need to make
2138 * sure that it doesn't change while being written back.
2139 */
2140static int
2141cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
2142{
2143 struct page *page = vmf->page;
2144
2145 lock_page(page);
2146 return VM_FAULT_LOCKED;
2147}
2148
2149static struct vm_operations_struct cifs_file_vm_ops = {
2150 .fault = filemap_fault,
2151 .page_mkwrite = cifs_page_mkwrite,
2152};
2153
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002154int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
2155{
2156 int rc, xid;
2157 struct inode *inode = file->f_path.dentry->d_inode;
2158
2159 xid = GetXid();
2160
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002161 if (!CIFS_I(inode)->clientCanCacheRead) {
2162 rc = cifs_invalidate_mapping(inode);
2163 if (rc)
2164 return rc;
2165 }
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002166
2167 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04002168 if (rc == 0)
2169 vma->vm_ops = &cifs_file_vm_ops;
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002170 FreeXid(xid);
2171 return rc;
2172}
2173
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
2175{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 int rc, xid;
2177
2178 xid = GetXid();
Jeff Laytonabab0952010-02-12 07:44:18 -05002179 rc = cifs_revalidate_file(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002181 cFYI(1, "Validation prior to mmap failed, error=%d", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 FreeXid(xid);
2183 return rc;
2184 }
2185 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04002186 if (rc == 0)
2187 vma->vm_ops = &cifs_file_vm_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 FreeXid(xid);
2189 return rc;
2190}
2191
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192static int cifs_readpages(struct file *file, struct address_space *mapping,
2193 struct list_head *page_list, unsigned num_pages)
2194{
Jeff Layton690c5e32011-10-19 15:30:16 -04002195 int rc;
2196 struct list_head tmplist;
2197 struct cifsFileInfo *open_file = file->private_data;
2198 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
2199 unsigned int rsize = cifs_sb->rsize;
2200 pid_t pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201
Jeff Layton690c5e32011-10-19 15:30:16 -04002202 /*
2203 * Give up immediately if rsize is too small to read an entire page.
2204 * The VFS will fall back to readpage. We should never reach this
2205 * point however since we set ra_pages to 0 when the rsize is smaller
2206 * than a cache page.
2207 */
2208 if (unlikely(rsize < PAGE_CACHE_SIZE))
2209 return 0;
Steve Frenchbfa0d752005-08-31 21:50:37 -07002210
Suresh Jayaraman56698232010-07-05 18:13:25 +05302211 /*
2212 * Reads as many pages as possible from fscache. Returns -ENOBUFS
2213 * immediately if the cookie is negative
2214 */
2215 rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
2216 &num_pages);
2217 if (rc == 0)
Jeff Layton690c5e32011-10-19 15:30:16 -04002218 return rc;
Suresh Jayaraman56698232010-07-05 18:13:25 +05302219
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002220 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2221 pid = open_file->pid;
2222 else
2223 pid = current->tgid;
2224
Jeff Layton690c5e32011-10-19 15:30:16 -04002225 rc = 0;
2226 INIT_LIST_HEAD(&tmplist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227
Jeff Layton690c5e32011-10-19 15:30:16 -04002228 cFYI(1, "%s: file=%p mapping=%p num_pages=%u", __func__, file,
2229 mapping, num_pages);
2230
2231 /*
2232 * Start with the page at end of list and move it to private
2233 * list. Do the same with any following pages until we hit
2234 * the rsize limit, hit an index discontinuity, or run out of
2235 * pages. Issue the async read and then start the loop again
2236 * until the list is empty.
2237 *
2238 * Note that list order is important. The page_list is in
2239 * the order of declining indexes. When we put the pages in
2240 * the rdata->pages, then we want them in increasing order.
2241 */
2242 while (!list_empty(page_list)) {
2243 unsigned int bytes = PAGE_CACHE_SIZE;
2244 unsigned int expected_index;
2245 unsigned int nr_pages = 1;
2246 loff_t offset;
2247 struct page *page, *tpage;
2248 struct cifs_readdata *rdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249
2250 page = list_entry(page_list->prev, struct page, lru);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
Jeff Layton690c5e32011-10-19 15:30:16 -04002252 /*
2253 * Lock the page and put it in the cache. Since no one else
2254 * should have access to this page, we're safe to simply set
2255 * PG_locked without checking it first.
2256 */
2257 __set_page_locked(page);
2258 rc = add_to_page_cache_locked(page, mapping,
2259 page->index, GFP_KERNEL);
2260
2261 /* give up if we can't stick it in the cache */
2262 if (rc) {
2263 __clear_page_locked(page);
2264 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266
Jeff Layton690c5e32011-10-19 15:30:16 -04002267 /* move first page to the tmplist */
2268 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
2269 list_move_tail(&page->lru, &tmplist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270
Jeff Layton690c5e32011-10-19 15:30:16 -04002271 /* now try and add more pages onto the request */
2272 expected_index = page->index + 1;
2273 list_for_each_entry_safe_reverse(page, tpage, page_list, lru) {
2274 /* discontinuity ? */
2275 if (page->index != expected_index)
2276 break;
2277
2278 /* would this page push the read over the rsize? */
2279 if (bytes + PAGE_CACHE_SIZE > rsize)
2280 break;
2281
2282 __set_page_locked(page);
2283 if (add_to_page_cache_locked(page, mapping,
2284 page->index, GFP_KERNEL)) {
2285 __clear_page_locked(page);
2286 break;
2287 }
2288 list_move_tail(&page->lru, &tmplist);
2289 bytes += PAGE_CACHE_SIZE;
2290 expected_index++;
2291 nr_pages++;
2292 }
2293
2294 rdata = cifs_readdata_alloc(nr_pages);
2295 if (!rdata) {
2296 /* best to give up if we're out of mem */
2297 list_for_each_entry_safe(page, tpage, &tmplist, lru) {
2298 list_del(&page->lru);
2299 lru_cache_add_file(page);
2300 unlock_page(page);
2301 page_cache_release(page);
2302 }
2303 rc = -ENOMEM;
2304 break;
2305 }
2306
2307 spin_lock(&cifs_file_list_lock);
2308 cifsFileInfo_get(open_file);
2309 spin_unlock(&cifs_file_list_lock);
2310 rdata->cfile = open_file;
2311 rdata->mapping = mapping;
2312 rdata->offset = offset;
2313 rdata->bytes = bytes;
2314 rdata->pid = pid;
2315 list_splice_init(&tmplist, &rdata->pages);
2316
2317 do {
Steve Frenchcdff08e2010-10-21 22:46:14 +00002318 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04002319 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 if (rc != 0)
Jeff Layton690c5e32011-10-19 15:30:16 -04002321 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 }
Jeff Layton690c5e32011-10-19 15:30:16 -04002323 rc = cifs_async_readv(rdata);
2324 } while (rc == -EAGAIN);
2325
2326 if (rc != 0) {
2327 list_for_each_entry_safe(page, tpage, &rdata->pages,
2328 lru) {
2329 list_del(&page->lru);
2330 lru_cache_add_file(page);
2331 unlock_page(page);
2332 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 }
Jeff Layton690c5e32011-10-19 15:30:16 -04002334 cifs_readdata_free(rdata);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 break;
2336 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 }
2338
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 return rc;
2340}
2341
2342static int cifs_readpage_worker(struct file *file, struct page *page,
2343 loff_t *poffset)
2344{
2345 char *read_data;
2346 int rc;
2347
Suresh Jayaraman56698232010-07-05 18:13:25 +05302348 /* Is the page cached? */
2349 rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page);
2350 if (rc == 0)
2351 goto read_complete;
2352
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 page_cache_get(page);
2354 read_data = kmap(page);
2355 /* for reads over a certain size could initiate async read ahead */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002356
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002358
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 if (rc < 0)
2360 goto io_error;
2361 else
Joe Perchesb6b38f72010-04-21 03:50:45 +00002362 cFYI(1, "Bytes read %d", rc);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002363
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002364 file->f_path.dentry->d_inode->i_atime =
2365 current_fs_time(file->f_path.dentry->d_inode->i_sb);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002366
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 if (PAGE_CACHE_SIZE > rc)
2368 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
2369
2370 flush_dcache_page(page);
2371 SetPageUptodate(page);
Suresh Jayaraman9dc06552010-07-05 18:13:11 +05302372
2373 /* send this page to the cache */
2374 cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page);
2375
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 rc = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002377
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378io_error:
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002379 kunmap(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 page_cache_release(page);
Suresh Jayaraman56698232010-07-05 18:13:25 +05302381
2382read_complete:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 return rc;
2384}
2385
2386static int cifs_readpage(struct file *file, struct page *page)
2387{
2388 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
2389 int rc = -EACCES;
2390 int xid;
2391
2392 xid = GetXid();
2393
2394 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302395 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302397 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 }
2399
Joe Perchesb6b38f72010-04-21 03:50:45 +00002400 cFYI(1, "readpage %p at offset %d 0x%x\n",
2401 page, (int)offset, (int)offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402
2403 rc = cifs_readpage_worker(file, page, &offset);
2404
2405 unlock_page(page);
2406
2407 FreeXid(xid);
2408 return rc;
2409}
2410
Steve Frencha403a0a2007-07-26 15:54:16 +00002411static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
2412{
2413 struct cifsFileInfo *open_file;
2414
Jeff Layton44772882010-10-15 15:34:03 -04002415 spin_lock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002416 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton2e396b82010-10-15 15:34:01 -04002417 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Jeff Layton44772882010-10-15 15:34:03 -04002418 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002419 return 1;
2420 }
2421 }
Jeff Layton44772882010-10-15 15:34:03 -04002422 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002423 return 0;
2424}
2425
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426/* We do not want to update the file size from server for inodes
2427 open for write - to avoid races with writepage extending
2428 the file - in the future we could consider allowing
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002429 refreshing the inode only on increases in the file size
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 but this is tricky to do without racing with writebehind
2431 page caching in the current Linux kernel design */
Steve French4b18f2a2008-04-29 00:06:05 +00002432bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433{
Steve Frencha403a0a2007-07-26 15:54:16 +00002434 if (!cifsInode)
Steve French4b18f2a2008-04-29 00:06:05 +00002435 return true;
Steve French23e7dd72005-10-20 13:44:56 -07002436
Steve Frencha403a0a2007-07-26 15:54:16 +00002437 if (is_inode_writable(cifsInode)) {
2438 /* This inode is open for write at least once */
Steve Frenchc32a0b62006-01-12 14:41:28 -08002439 struct cifs_sb_info *cifs_sb;
2440
Steve Frenchc32a0b62006-01-12 14:41:28 -08002441 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
Steve Frenchad7a2922008-02-07 23:25:02 +00002442 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002443 /* since no page cache to corrupt on directio
Steve Frenchc32a0b62006-01-12 14:41:28 -08002444 we can change size safely */
Steve French4b18f2a2008-04-29 00:06:05 +00002445 return true;
Steve Frenchc32a0b62006-01-12 14:41:28 -08002446 }
2447
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002448 if (i_size_read(&cifsInode->vfs_inode) < end_of_file)
Steve French4b18f2a2008-04-29 00:06:05 +00002449 return true;
Steve French7ba52632007-02-08 18:14:13 +00002450
Steve French4b18f2a2008-04-29 00:06:05 +00002451 return false;
Steve French23e7dd72005-10-20 13:44:56 -07002452 } else
Steve French4b18f2a2008-04-29 00:06:05 +00002453 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454}
2455
Nick Piggind9414772008-09-24 11:32:59 -04002456static int cifs_write_begin(struct file *file, struct address_space *mapping,
2457 loff_t pos, unsigned len, unsigned flags,
2458 struct page **pagep, void **fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459{
Nick Piggind9414772008-09-24 11:32:59 -04002460 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
2461 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002462 loff_t page_start = pos & PAGE_MASK;
2463 loff_t i_size;
2464 struct page *page;
2465 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466
Joe Perchesb6b38f72010-04-21 03:50:45 +00002467 cFYI(1, "write_begin from %lld len %d", (long long)pos, len);
Nick Piggind9414772008-09-24 11:32:59 -04002468
Nick Piggin54566b22009-01-04 12:00:53 -08002469 page = grab_cache_page_write_begin(mapping, index, flags);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002470 if (!page) {
2471 rc = -ENOMEM;
2472 goto out;
2473 }
Nick Piggind9414772008-09-24 11:32:59 -04002474
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002475 if (PageUptodate(page))
2476 goto out;
Steve French8a236262007-03-06 00:31:00 +00002477
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002478 /*
2479 * If we write a full page it will be up to date, no need to read from
2480 * the server. If the write is short, we'll end up doing a sync write
2481 * instead.
2482 */
2483 if (len == PAGE_CACHE_SIZE)
2484 goto out;
2485
2486 /*
2487 * optimize away the read when we have an oplock, and we're not
2488 * expecting to use any of the data we'd be reading in. That
2489 * is, when the page lies beyond the EOF, or straddles the EOF
2490 * and the write will cover all of the existing data.
2491 */
2492 if (CIFS_I(mapping->host)->clientCanCacheRead) {
2493 i_size = i_size_read(mapping->host);
2494 if (page_start >= i_size ||
2495 (offset == 0 && (pos + len) >= i_size)) {
2496 zero_user_segments(page, 0, offset,
2497 offset + len,
2498 PAGE_CACHE_SIZE);
2499 /*
2500 * PageChecked means that the parts of the page
2501 * to which we're not writing are considered up
2502 * to date. Once the data is copied to the
2503 * page, it can be set uptodate.
2504 */
2505 SetPageChecked(page);
2506 goto out;
2507 }
2508 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509
Nick Piggind9414772008-09-24 11:32:59 -04002510 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002511 /*
2512 * might as well read a page, it is fast enough. If we get
2513 * an error, we don't need to return it. cifs_write_end will
2514 * do a sync write instead since PG_uptodate isn't set.
2515 */
2516 cifs_readpage_worker(file, page, &page_start);
Steve French8a236262007-03-06 00:31:00 +00002517 } else {
2518 /* we could try using another file handle if there is one -
2519 but how would we lock it to prevent close of that handle
2520 racing with this read? In any case
Nick Piggind9414772008-09-24 11:32:59 -04002521 this will be written out by write_end so is fine */
Steve French8a236262007-03-06 00:31:00 +00002522 }
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002523out:
2524 *pagep = page;
2525 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526}
2527
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302528static int cifs_release_page(struct page *page, gfp_t gfp)
2529{
2530 if (PagePrivate(page))
2531 return 0;
2532
2533 return cifs_fscache_release_page(page, gfp);
2534}
2535
2536static void cifs_invalidate_page(struct page *page, unsigned long offset)
2537{
2538 struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
2539
2540 if (offset == 0)
2541 cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
2542}
2543
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002544static int cifs_launder_page(struct page *page)
2545{
2546 int rc = 0;
2547 loff_t range_start = page_offset(page);
2548 loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
2549 struct writeback_control wbc = {
2550 .sync_mode = WB_SYNC_ALL,
2551 .nr_to_write = 0,
2552 .range_start = range_start,
2553 .range_end = range_end,
2554 };
2555
2556 cFYI(1, "Launder page: %p", page);
2557
2558 if (clear_page_dirty_for_io(page))
2559 rc = cifs_writepage_locked(page, &wbc);
2560
2561 cifs_fscache_invalidate_page(page, page->mapping->host);
2562 return rc;
2563}
2564
Tejun Heo9b646972010-07-20 22:09:02 +02002565void cifs_oplock_break(struct work_struct *work)
Jeff Layton3bc303c2009-09-21 06:47:50 -04002566{
2567 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
2568 oplock_break);
Jeff Laytona5e18bc2010-10-11 15:07:18 -04002569 struct inode *inode = cfile->dentry->d_inode;
Jeff Layton3bc303c2009-09-21 06:47:50 -04002570 struct cifsInodeInfo *cinode = CIFS_I(inode);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002571 int rc = 0;
Jeff Layton3bc303c2009-09-21 06:47:50 -04002572
2573 if (inode && S_ISREG(inode->i_mode)) {
Steve Frenchd54ff732010-04-27 04:38:15 +00002574 if (cinode->clientCanCacheRead)
Al Viro8737c932009-12-24 06:47:55 -05002575 break_lease(inode, O_RDONLY);
Steve Frenchd54ff732010-04-27 04:38:15 +00002576 else
Al Viro8737c932009-12-24 06:47:55 -05002577 break_lease(inode, O_WRONLY);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002578 rc = filemap_fdatawrite(inode->i_mapping);
2579 if (cinode->clientCanCacheRead == 0) {
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002580 rc = filemap_fdatawait(inode->i_mapping);
2581 mapping_set_error(inode->i_mapping, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002582 invalidate_remote_inode(inode);
2583 }
Joe Perchesb6b38f72010-04-21 03:50:45 +00002584 cFYI(1, "Oplock flush inode %p rc %d", inode, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002585 }
2586
Pavel Shilovsky85160e02011-10-22 15:33:29 +04002587 rc = cifs_push_locks(cfile);
2588 if (rc)
2589 cERROR(1, "Push locks rc = %d", rc);
2590
Jeff Layton3bc303c2009-09-21 06:47:50 -04002591 /*
2592 * releasing stale oplock after recent reconnect of smb session using
2593 * a now incorrect file handle is not a data integrity issue but do
2594 * not bother sending an oplock release if session to server still is
2595 * disconnected since oplock already released by the server
2596 */
Steve Frenchcdff08e2010-10-21 22:46:14 +00002597 if (!cfile->oplock_break_cancelled) {
Pavel Shilovsky03776f42010-08-17 11:26:00 +04002598 rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid,
2599 current->tgid, 0, 0, 0, 0,
2600 LOCKING_ANDX_OPLOCK_RELEASE, false,
Pavel Shilovsky12fed002011-01-17 20:15:44 +03002601 cinode->clientCanCacheRead ? 1 : 0);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002602 cFYI(1, "Oplock release rc = %d", rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002603 }
Jeff Layton3bc303c2009-09-21 06:47:50 -04002604}
2605
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07002606const struct address_space_operations cifs_addr_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607 .readpage = cifs_readpage,
2608 .readpages = cifs_readpages,
2609 .writepage = cifs_writepage,
Steve French37c0eb42005-10-05 14:50:29 -07002610 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04002611 .write_begin = cifs_write_begin,
2612 .write_end = cifs_write_end,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302614 .releasepage = cifs_release_page,
2615 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002616 .launder_page = cifs_launder_page,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617};
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002618
2619/*
2620 * cifs_readpages requires the server to support a buffer large enough to
2621 * contain the header plus one complete page of data. Otherwise, we need
2622 * to leave cifs_readpages out of the address space operations.
2623 */
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07002624const struct address_space_operations cifs_addr_ops_smallbuf = {
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002625 .readpage = cifs_readpage,
2626 .writepage = cifs_writepage,
2627 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04002628 .write_begin = cifs_write_begin,
2629 .write_end = cifs_write_end,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002630 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302631 .releasepage = cifs_release_page,
2632 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002633 .launder_page = cifs_launder_page,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002634};