blob: 9f41a10523a1bad91ba0a9e8581ed89f552785e2 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <asm/div64.h>
36#include "cifsfs.h"
37#include "cifspdu.h"
38#include "cifsglob.h"
39#include "cifsproto.h"
40#include "cifs_unicode.h"
41#include "cifs_debug.h"
42#include "cifs_fs_sb.h"
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +053043#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
Linus Torvalds1da177e2005-04-16 15:20:36 -070045static inline int cifs_convert_flags(unsigned int flags)
46{
47 if ((flags & O_ACCMODE) == O_RDONLY)
48 return GENERIC_READ;
49 else if ((flags & O_ACCMODE) == O_WRONLY)
50 return GENERIC_WRITE;
51 else if ((flags & O_ACCMODE) == O_RDWR) {
52 /* GENERIC_ALL is too much permission to request
53 can cause unnecessary access denied on create */
54 /* return GENERIC_ALL; */
55 return (GENERIC_READ | GENERIC_WRITE);
56 }
57
Jeff Laytone10f7b52008-05-14 10:21:33 -070058 return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
59 FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA |
60 FILE_READ_DATA);
Steve French7fc8f4e2009-02-23 20:43:11 +000061}
Jeff Laytone10f7b52008-05-14 10:21:33 -070062
Jeff Layton608712f2010-10-15 15:33:56 -040063static u32 cifs_posix_convert_flags(unsigned int flags)
Steve French7fc8f4e2009-02-23 20:43:11 +000064{
Jeff Layton608712f2010-10-15 15:33:56 -040065 u32 posix_flags = 0;
Jeff Laytone10f7b52008-05-14 10:21:33 -070066
Steve French7fc8f4e2009-02-23 20:43:11 +000067 if ((flags & O_ACCMODE) == O_RDONLY)
Jeff Layton608712f2010-10-15 15:33:56 -040068 posix_flags = SMB_O_RDONLY;
Steve French7fc8f4e2009-02-23 20:43:11 +000069 else if ((flags & O_ACCMODE) == O_WRONLY)
Jeff Layton608712f2010-10-15 15:33:56 -040070 posix_flags = SMB_O_WRONLY;
71 else if ((flags & O_ACCMODE) == O_RDWR)
72 posix_flags = SMB_O_RDWR;
73
74 if (flags & O_CREAT)
75 posix_flags |= SMB_O_CREAT;
76 if (flags & O_EXCL)
77 posix_flags |= SMB_O_EXCL;
78 if (flags & O_TRUNC)
79 posix_flags |= SMB_O_TRUNC;
80 /* be safe and imply O_SYNC for O_DSYNC */
Christoph Hellwig6b2f3d12009-10-27 11:05:28 +010081 if (flags & O_DSYNC)
Jeff Layton608712f2010-10-15 15:33:56 -040082 posix_flags |= SMB_O_SYNC;
Steve French7fc8f4e2009-02-23 20:43:11 +000083 if (flags & O_DIRECTORY)
Jeff Layton608712f2010-10-15 15:33:56 -040084 posix_flags |= SMB_O_DIRECTORY;
Steve French7fc8f4e2009-02-23 20:43:11 +000085 if (flags & O_NOFOLLOW)
Jeff Layton608712f2010-10-15 15:33:56 -040086 posix_flags |= SMB_O_NOFOLLOW;
Steve French7fc8f4e2009-02-23 20:43:11 +000087 if (flags & O_DIRECT)
Jeff Layton608712f2010-10-15 15:33:56 -040088 posix_flags |= SMB_O_DIRECT;
Steve French7fc8f4e2009-02-23 20:43:11 +000089
90 return posix_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -070091}
92
93static inline int cifs_get_disposition(unsigned int flags)
94{
95 if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
96 return FILE_CREATE;
97 else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
98 return FILE_OVERWRITE_IF;
99 else if ((flags & O_CREAT) == O_CREAT)
100 return FILE_OPEN_IF;
Steve French55aa2e02006-05-30 18:09:31 +0000101 else if ((flags & O_TRUNC) == O_TRUNC)
102 return FILE_OVERWRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103 else
104 return FILE_OPEN;
105}
106
Jeff Layton608712f2010-10-15 15:33:56 -0400107int cifs_posix_open(char *full_path, struct inode **pinode,
108 struct super_block *sb, int mode, unsigned int f_flags,
109 __u32 *poplock, __u16 *pnetfid, int xid)
110{
111 int rc;
112 FILE_UNIX_BASIC_INFO *presp_data;
113 __u32 posix_flags = 0;
114 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
115 struct cifs_fattr fattr;
116 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000117 struct cifs_tcon *tcon;
Jeff Layton608712f2010-10-15 15:33:56 -0400118
119 cFYI(1, "posix open %s", full_path);
120
121 presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
122 if (presp_data == NULL)
123 return -ENOMEM;
124
125 tlink = cifs_sb_tlink(cifs_sb);
126 if (IS_ERR(tlink)) {
127 rc = PTR_ERR(tlink);
128 goto posix_open_ret;
129 }
130
131 tcon = tlink_tcon(tlink);
132 mode &= ~current_umask();
133
134 posix_flags = cifs_posix_convert_flags(f_flags);
135 rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data,
136 poplock, full_path, cifs_sb->local_nls,
137 cifs_sb->mnt_cifs_flags &
138 CIFS_MOUNT_MAP_SPECIAL_CHR);
139 cifs_put_tlink(tlink);
140
141 if (rc)
142 goto posix_open_ret;
143
144 if (presp_data->Type == cpu_to_le32(-1))
145 goto posix_open_ret; /* open ok, caller does qpathinfo */
146
147 if (!pinode)
148 goto posix_open_ret; /* caller does not need info */
149
150 cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
151
152 /* get new inode and set it up */
153 if (*pinode == NULL) {
154 cifs_fill_uniqueid(sb, &fattr);
155 *pinode = cifs_iget(sb, &fattr);
156 if (!*pinode) {
157 rc = -ENOMEM;
158 goto posix_open_ret;
159 }
160 } else {
161 cifs_fattr_to_inode(*pinode, &fattr);
162 }
163
164posix_open_ret:
165 kfree(presp_data);
166 return rc;
167}
168
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300169static int
170cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
Steve French96daf2b2011-05-27 04:34:02 +0000171 struct cifs_tcon *tcon, unsigned int f_flags, __u32 *poplock,
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300172 __u16 *pnetfid, int xid)
173{
174 int rc;
175 int desiredAccess;
176 int disposition;
177 FILE_ALL_INFO *buf;
178
179 desiredAccess = cifs_convert_flags(f_flags);
180
181/*********************************************************************
182 * open flag mapping table:
183 *
184 * POSIX Flag CIFS Disposition
185 * ---------- ----------------
186 * O_CREAT FILE_OPEN_IF
187 * O_CREAT | O_EXCL FILE_CREATE
188 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
189 * O_TRUNC FILE_OVERWRITE
190 * none of the above FILE_OPEN
191 *
192 * Note that there is not a direct match between disposition
193 * FILE_SUPERSEDE (ie create whether or not file exists although
194 * O_CREAT | O_TRUNC is similar but truncates the existing
195 * file rather than creating a new file as FILE_SUPERSEDE does
196 * (which uses the attributes / metadata passed in on open call)
197 *?
198 *? O_SYNC is a reasonable match to CIFS writethrough flag
199 *? and the read write flags match reasonably. O_LARGEFILE
200 *? is irrelevant because largefile support is always used
201 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
202 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
203 *********************************************************************/
204
205 disposition = cifs_get_disposition(f_flags);
206
207 /* BB pass O_SYNC flag through on file attributes .. BB */
208
209 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
210 if (!buf)
211 return -ENOMEM;
212
213 if (tcon->ses->capabilities & CAP_NT_SMBS)
214 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
215 desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf,
216 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
217 & CIFS_MOUNT_MAP_SPECIAL_CHR);
218 else
219 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
220 desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf,
221 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
222 & CIFS_MOUNT_MAP_SPECIAL_CHR);
223
224 if (rc)
225 goto out;
226
227 if (tcon->unix_ext)
228 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
229 xid);
230 else
231 rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
232 xid, pnetfid);
233
234out:
235 kfree(buf);
236 return rc;
237}
238
Jeff Layton15ecb432010-10-15 15:34:02 -0400239struct cifsFileInfo *
240cifs_new_fileinfo(__u16 fileHandle, struct file *file,
241 struct tcon_link *tlink, __u32 oplock)
242{
243 struct dentry *dentry = file->f_path.dentry;
244 struct inode *inode = dentry->d_inode;
245 struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
246 struct cifsFileInfo *pCifsFile;
247
248 pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
249 if (pCifsFile == NULL)
250 return pCifsFile;
251
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400252 pCifsFile->count = 1;
Jeff Layton15ecb432010-10-15 15:34:02 -0400253 pCifsFile->netfid = fileHandle;
254 pCifsFile->pid = current->tgid;
255 pCifsFile->uid = current_fsuid();
256 pCifsFile->dentry = dget(dentry);
257 pCifsFile->f_flags = file->f_flags;
258 pCifsFile->invalidHandle = false;
Jeff Layton15ecb432010-10-15 15:34:02 -0400259 pCifsFile->tlink = cifs_get_tlink(tlink);
260 mutex_init(&pCifsFile->fh_mutex);
261 mutex_init(&pCifsFile->lock_mutex);
262 INIT_LIST_HEAD(&pCifsFile->llist);
Jeff Layton15ecb432010-10-15 15:34:02 -0400263 INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
264
Jeff Layton44772882010-10-15 15:34:03 -0400265 spin_lock(&cifs_file_list_lock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400266 list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList));
267 /* if readable file instance put first in list*/
268 if (file->f_mode & FMODE_READ)
269 list_add(&pCifsFile->flist, &pCifsInode->openFileList);
270 else
271 list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList);
Jeff Layton44772882010-10-15 15:34:03 -0400272 spin_unlock(&cifs_file_list_lock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400273
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300274 cifs_set_oplock_level(pCifsInode, oplock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400275
276 file->private_data = pCifsFile;
277 return pCifsFile;
278}
279
Steve Frenchcdff08e2010-10-21 22:46:14 +0000280/*
281 * Release a reference on the file private data. This may involve closing
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400282 * the filehandle out on the server. Must be called without holding
283 * cifs_file_list_lock.
Steve Frenchcdff08e2010-10-21 22:46:14 +0000284 */
Jeff Laytonb33879a2010-10-15 15:34:04 -0400285void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
286{
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300287 struct inode *inode = cifs_file->dentry->d_inode;
Steve French96daf2b2011-05-27 04:34:02 +0000288 struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300289 struct cifsInodeInfo *cifsi = CIFS_I(inode);
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300290 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000291 struct cifsLockInfo *li, *tmp;
292
293 spin_lock(&cifs_file_list_lock);
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400294 if (--cifs_file->count > 0) {
Steve Frenchcdff08e2010-10-21 22:46:14 +0000295 spin_unlock(&cifs_file_list_lock);
296 return;
Jeff Laytonb33879a2010-10-15 15:34:04 -0400297 }
Steve Frenchcdff08e2010-10-21 22:46:14 +0000298
299 /* remove it from the lists */
300 list_del(&cifs_file->flist);
301 list_del(&cifs_file->tlist);
302
303 if (list_empty(&cifsi->openFileList)) {
304 cFYI(1, "closing last open instance for inode %p",
305 cifs_file->dentry->d_inode);
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300306
307 /* in strict cache mode we need invalidate mapping on the last
308 close because it may cause a error when we open this file
309 again and get at least level II oplock */
310 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
311 CIFS_I(inode)->invalid_mapping = true;
312
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300313 cifs_set_oplock_level(cifsi, 0);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000314 }
315 spin_unlock(&cifs_file_list_lock);
316
Jeff Laytonad635942011-07-26 12:20:17 -0400317 cancel_work_sync(&cifs_file->oplock_break);
318
Steve Frenchcdff08e2010-10-21 22:46:14 +0000319 if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
320 int xid, rc;
321
322 xid = GetXid();
323 rc = CIFSSMBClose(xid, tcon, cifs_file->netfid);
324 FreeXid(xid);
325 }
326
327 /* Delete any outstanding lock records. We'll lose them when the file
328 * is closed anyway.
329 */
330 mutex_lock(&cifs_file->lock_mutex);
331 list_for_each_entry_safe(li, tmp, &cifs_file->llist, llist) {
332 list_del(&li->llist);
333 kfree(li);
334 }
335 mutex_unlock(&cifs_file->lock_mutex);
336
337 cifs_put_tlink(cifs_file->tlink);
338 dput(cifs_file->dentry);
339 kfree(cifs_file);
Jeff Laytonb33879a2010-10-15 15:34:04 -0400340}
341
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342int cifs_open(struct inode *inode, struct file *file)
343{
344 int rc = -EACCES;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400345 int xid;
346 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000348 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400349 struct tcon_link *tlink;
Jeff Layton6ca9f3b2010-06-16 13:40:16 -0400350 struct cifsFileInfo *pCifsFile = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 char *full_path = NULL;
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300352 bool posix_open_ok = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 __u16 netfid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354
355 xid = GetXid();
356
357 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400358 tlink = cifs_sb_tlink(cifs_sb);
359 if (IS_ERR(tlink)) {
360 FreeXid(xid);
361 return PTR_ERR(tlink);
362 }
363 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -0800365 full_path = build_path_from_dentry(file->f_path.dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530367 rc = -ENOMEM;
Jeff Layton232341b2010-08-05 13:58:38 -0400368 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 }
370
Joe Perchesb6b38f72010-04-21 03:50:45 +0000371 cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
372 inode, file->f_flags, full_path);
Steve French276a74a2009-03-03 18:00:34 +0000373
374 if (oplockEnabled)
375 oplock = REQ_OPLOCK;
376 else
377 oplock = 0;
378
Steve French64cc2c62009-03-04 19:54:08 +0000379 if (!tcon->broken_posix_open && tcon->unix_ext &&
380 (tcon->ses->capabilities & CAP_UNIX) &&
Steve French276a74a2009-03-03 18:00:34 +0000381 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
382 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Steve French276a74a2009-03-03 18:00:34 +0000383 /* can not refresh inode info since size could be stale */
Jeff Layton2422f672010-06-16 13:40:16 -0400384 rc = cifs_posix_open(full_path, &inode, inode->i_sb,
Steve Frenchfa588e02010-04-22 19:21:55 +0000385 cifs_sb->mnt_file_mode /* ignored */,
Jeff Layton608712f2010-10-15 15:33:56 -0400386 file->f_flags, &oplock, &netfid, xid);
Steve French276a74a2009-03-03 18:00:34 +0000387 if (rc == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000388 cFYI(1, "posix open succeeded");
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300389 posix_open_ok = true;
Steve French64cc2c62009-03-04 19:54:08 +0000390 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
391 if (tcon->ses->serverNOS)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000392 cERROR(1, "server %s of type %s returned"
Steve French64cc2c62009-03-04 19:54:08 +0000393 " unexpected error on SMB posix open"
394 ", disabling posix open support."
395 " Check if server update available.",
396 tcon->ses->serverName,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000397 tcon->ses->serverNOS);
Steve French64cc2c62009-03-04 19:54:08 +0000398 tcon->broken_posix_open = true;
Steve French276a74a2009-03-03 18:00:34 +0000399 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
400 (rc != -EOPNOTSUPP)) /* path not found or net err */
401 goto out;
Steve French64cc2c62009-03-04 19:54:08 +0000402 /* else fallthrough to retry open the old way on network i/o
403 or DFS errors */
Steve French276a74a2009-03-03 18:00:34 +0000404 }
405
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300406 if (!posix_open_ok) {
407 rc = cifs_nt_open(full_path, inode, cifs_sb, tcon,
408 file->f_flags, &oplock, &netfid, xid);
409 if (rc)
410 goto out;
411 }
Jeff Layton47c78b72010-06-16 13:40:17 -0400412
Jeff Laytonabfe1ee2010-10-15 15:33:58 -0400413 pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock);
Jeff Layton6ca9f3b2010-06-16 13:40:16 -0400414 if (pCifsFile == NULL) {
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300415 CIFSSMBClose(xid, tcon, netfid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 rc = -ENOMEM;
417 goto out;
418 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530420 cifs_fscache_set_inode_cookie(inode, file);
421
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300422 if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 /* time to set mode which we can not set earlier due to
424 problems creating new read-only files */
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300425 struct cifs_unix_set_info_args args = {
426 .mode = inode->i_mode,
427 .uid = NO_CHANGE_64,
428 .gid = NO_CHANGE_64,
429 .ctime = NO_CHANGE_64,
430 .atime = NO_CHANGE_64,
431 .mtime = NO_CHANGE_64,
432 .device = 0,
433 };
Jeff Laytond44a9fe2011-01-07 11:30:29 -0500434 CIFSSMBUnixSetFileInfo(xid, tcon, &args, netfid,
435 pCifsFile->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 }
437
438out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 kfree(full_path);
440 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400441 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 return rc;
443}
444
Adrian Bunk04187262006-06-30 18:23:04 +0200445/* Try to reacquire byte range locks that were released when session */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446/* to server was lost */
447static int cifs_relock_file(struct cifsFileInfo *cifsFile)
448{
449 int rc = 0;
450
451/* BB list all locks open on this file and relock */
452
453 return rc;
454}
455
Jeff Layton15886172010-10-15 15:33:59 -0400456static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457{
458 int rc = -EACCES;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400459 int xid;
460 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000462 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 struct cifsInodeInfo *pCifsInode;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000464 struct inode *inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 char *full_path = NULL;
466 int desiredAccess;
467 int disposition = FILE_OPEN;
468 __u16 netfid;
469
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 xid = GetXid();
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400471 mutex_lock(&pCifsFile->fh_mutex);
Steve French4b18f2a2008-04-29 00:06:05 +0000472 if (!pCifsFile->invalidHandle) {
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400473 mutex_unlock(&pCifsFile->fh_mutex);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530474 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530476 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 }
478
Jeff Layton15886172010-10-15 15:33:59 -0400479 inode = pCifsFile->dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton13cfb732010-09-29 19:51:11 -0400481 tcon = tlink_tcon(pCifsFile->tlink);
Steve French3a9f4622007-04-04 17:10:24 +0000482
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483/* can not grab rename sem here because various ops, including
484 those that already have the rename sem can end up causing writepage
485 to get called and if the server was down that means we end up here,
486 and we can never tell if the caller already has the rename_sem */
Jeff Layton15886172010-10-15 15:33:59 -0400487 full_path = build_path_from_dentry(pCifsFile->dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 if (full_path == NULL) {
Steve French3a9f4622007-04-04 17:10:24 +0000489 rc = -ENOMEM;
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400490 mutex_unlock(&pCifsFile->fh_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 FreeXid(xid);
Steve French3a9f4622007-04-04 17:10:24 +0000492 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 }
494
Joe Perchesb6b38f72010-04-21 03:50:45 +0000495 cFYI(1, "inode = 0x%p file flags 0x%x for %s",
Jeff Layton15886172010-10-15 15:33:59 -0400496 inode, pCifsFile->f_flags, full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497
498 if (oplockEnabled)
499 oplock = REQ_OPLOCK;
500 else
Steve French4b18f2a2008-04-29 00:06:05 +0000501 oplock = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
Steve French7fc8f4e2009-02-23 20:43:11 +0000503 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
504 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
505 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton608712f2010-10-15 15:33:56 -0400506
507 /*
508 * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
509 * original open. Must mask them off for a reopen.
510 */
Jeff Layton15886172010-10-15 15:33:59 -0400511 unsigned int oflags = pCifsFile->f_flags &
512 ~(O_CREAT | O_EXCL | O_TRUNC);
Jeff Layton608712f2010-10-15 15:33:56 -0400513
Jeff Layton2422f672010-06-16 13:40:16 -0400514 rc = cifs_posix_open(full_path, NULL, inode->i_sb,
Steve Frenchfa588e02010-04-22 19:21:55 +0000515 cifs_sb->mnt_file_mode /* ignored */,
516 oflags, &oplock, &netfid, xid);
Steve French7fc8f4e2009-02-23 20:43:11 +0000517 if (rc == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000518 cFYI(1, "posix reopen succeeded");
Steve French7fc8f4e2009-02-23 20:43:11 +0000519 goto reopen_success;
520 }
521 /* fallthrough to retry open the old way on errors, especially
522 in the reconnect path it is important to retry hard */
523 }
524
Jeff Layton15886172010-10-15 15:33:59 -0400525 desiredAccess = cifs_convert_flags(pCifsFile->f_flags);
Steve French7fc8f4e2009-02-23 20:43:11 +0000526
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 /* Can not refresh inode by passing in file_info buf to be returned
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000528 by SMBOpen and then calling get_inode_info with returned buf
529 since file might have write behind data that needs to be flushed
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 and server version of file size can be stale. If we knew for sure
531 that inode was not dirty locally we could do this */
532
Steve French7fc8f4e2009-02-23 20:43:11 +0000533 rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 CREATE_NOT_DIR, &netfid, &oplock, NULL,
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000535 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
Steve French737b7582005-04-28 22:41:06 -0700536 CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 if (rc) {
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400538 mutex_unlock(&pCifsFile->fh_mutex);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000539 cFYI(1, "cifs_open returned 0x%x", rc);
540 cFYI(1, "oplock: %d", oplock);
Jeff Layton15886172010-10-15 15:33:59 -0400541 goto reopen_error_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 }
Jeff Layton15886172010-10-15 15:33:59 -0400543
544reopen_success:
545 pCifsFile->netfid = netfid;
546 pCifsFile->invalidHandle = false;
547 mutex_unlock(&pCifsFile->fh_mutex);
548 pCifsInode = CIFS_I(inode);
549
550 if (can_flush) {
551 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -0400552 mapping_set_error(inode->i_mapping, rc);
Jeff Layton15886172010-10-15 15:33:59 -0400553
Jeff Layton15886172010-10-15 15:33:59 -0400554 if (tcon->unix_ext)
555 rc = cifs_get_inode_info_unix(&inode,
556 full_path, inode->i_sb, xid);
557 else
558 rc = cifs_get_inode_info(&inode,
559 full_path, NULL, inode->i_sb,
560 xid, NULL);
561 } /* else we are writing out data to server already
562 and could deadlock if we tried to flush data, and
563 since we do not know if we have data that would
564 invalidate the current end of file on the server
565 we can not go to the server to get the new inod
566 info */
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300567
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300568 cifs_set_oplock_level(pCifsInode, oplock);
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300569
Jeff Layton15886172010-10-15 15:33:59 -0400570 cifs_relock_file(pCifsFile);
571
572reopen_error_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 kfree(full_path);
574 FreeXid(xid);
575 return rc;
576}
577
578int cifs_close(struct inode *inode, struct file *file)
579{
Jeff Layton77970692011-04-05 16:23:47 -0700580 if (file->private_data != NULL) {
581 cifsFileInfo_put(file->private_data);
582 file->private_data = NULL;
583 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
Steve Frenchcdff08e2010-10-21 22:46:14 +0000585 /* return code from the ->release op is always ignored */
586 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587}
588
589int cifs_closedir(struct inode *inode, struct file *file)
590{
591 int rc = 0;
592 int xid;
Joe Perchesc21dfb62010-07-12 13:50:14 -0700593 struct cifsFileInfo *pCFileStruct = file->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 char *ptmp;
595
Joe Perchesb6b38f72010-04-21 03:50:45 +0000596 cFYI(1, "Closedir inode = 0x%p", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597
598 xid = GetXid();
599
600 if (pCFileStruct) {
Steve French96daf2b2011-05-27 04:34:02 +0000601 struct cifs_tcon *pTcon = tlink_tcon(pCFileStruct->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
Joe Perchesb6b38f72010-04-21 03:50:45 +0000603 cFYI(1, "Freeing private data in close dir");
Jeff Layton44772882010-10-15 15:34:03 -0400604 spin_lock(&cifs_file_list_lock);
Steve French4b18f2a2008-04-29 00:06:05 +0000605 if (!pCFileStruct->srch_inf.endOfSearch &&
606 !pCFileStruct->invalidHandle) {
607 pCFileStruct->invalidHandle = true;
Jeff Layton44772882010-10-15 15:34:03 -0400608 spin_unlock(&cifs_file_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000610 cFYI(1, "Closing uncompleted readdir with rc %d",
611 rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 /* not much we can do if it fails anyway, ignore rc */
613 rc = 0;
Steve Frenchddb4cbf2008-11-20 20:00:44 +0000614 } else
Jeff Layton44772882010-10-15 15:34:03 -0400615 spin_unlock(&cifs_file_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
617 if (ptmp) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000618 cFYI(1, "closedir free smb buf in srch struct");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000620 if (pCFileStruct->srch_inf.smallBuf)
Steve Frenchd47d7c12006-02-28 03:45:48 +0000621 cifs_small_buf_release(ptmp);
622 else
623 cifs_buf_release(ptmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 }
Jeff Layton13cfb732010-09-29 19:51:11 -0400625 cifs_put_tlink(pCFileStruct->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 kfree(file->private_data);
627 file->private_data = NULL;
628 }
629 /* BB can we lock the filestruct while this is going on? */
630 FreeXid(xid);
631 return rc;
632}
633
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000634static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
635 __u64 offset, __u8 lockType)
636{
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000637 struct cifsLockInfo *li =
638 kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000639 if (li == NULL)
640 return -ENOMEM;
641 li->offset = offset;
642 li->length = len;
643 li->type = lockType;
Roland Dreier796e5662007-05-03 04:33:45 +0000644 mutex_lock(&fid->lock_mutex);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000645 list_add(&li->llist, &fid->llist);
Roland Dreier796e5662007-05-03 04:33:45 +0000646 mutex_unlock(&fid->lock_mutex);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000647 return 0;
648}
649
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
651{
652 int rc, xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 __u32 numLock = 0;
654 __u32 numUnlock = 0;
655 __u64 length;
Steve French4b18f2a2008-04-29 00:06:05 +0000656 bool wait_flag = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000658 struct cifs_tcon *tcon;
Steve French08547b02006-02-28 22:39:25 +0000659 __u16 netfid;
660 __u8 lockType = LOCKING_ANDX_LARGE_FILES;
Steve French13a6e422008-12-02 17:24:33 +0000661 bool posix_locking = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
663 length = 1 + pfLock->fl_end - pfLock->fl_start;
664 rc = -EACCES;
665 xid = GetXid();
666
Joe Perchesb6b38f72010-04-21 03:50:45 +0000667 cFYI(1, "Lock parm: 0x%x flockflags: "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 "0x%x flocktype: 0x%x start: %lld end: %lld",
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000669 cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000670 pfLock->fl_end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671
672 if (pfLock->fl_flags & FL_POSIX)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000673 cFYI(1, "Posix");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 if (pfLock->fl_flags & FL_FLOCK)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000675 cFYI(1, "Flock");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 if (pfLock->fl_flags & FL_SLEEP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000677 cFYI(1, "Blocking lock");
Steve French4b18f2a2008-04-29 00:06:05 +0000678 wait_flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 }
680 if (pfLock->fl_flags & FL_ACCESS)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000681 cFYI(1, "Process suspended by mandatory locking - "
682 "not implemented yet");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 if (pfLock->fl_flags & FL_LEASE)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000684 cFYI(1, "Lease on file - not implemented yet");
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000685 if (pfLock->fl_flags &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
Joe Perchesb6b38f72010-04-21 03:50:45 +0000687 cFYI(1, "Unknown lock flags 0x%x", pfLock->fl_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688
689 if (pfLock->fl_type == F_WRLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000690 cFYI(1, "F_WRLCK ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 numLock = 1;
692 } else if (pfLock->fl_type == F_UNLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000693 cFYI(1, "F_UNLCK");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 numUnlock = 1;
Steve Frenchd47d7c12006-02-28 03:45:48 +0000695 /* Check if unlock includes more than
696 one lock range */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 } else if (pfLock->fl_type == F_RDLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000698 cFYI(1, "F_RDLCK");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 lockType |= LOCKING_ANDX_SHARED_LOCK;
700 numLock = 1;
701 } else if (pfLock->fl_type == F_EXLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000702 cFYI(1, "F_EXLCK");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 numLock = 1;
704 } else if (pfLock->fl_type == F_SHLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000705 cFYI(1, "F_SHLCK");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 lockType |= LOCKING_ANDX_SHARED_LOCK;
707 numLock = 1;
708 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +0000709 cFYI(1, "Unknown type of lock");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -0800711 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Jeff Layton13cfb732010-09-29 19:51:11 -0400712 tcon = tlink_tcon(((struct cifsFileInfo *)file->private_data)->tlink);
Steve French08547b02006-02-28 22:39:25 +0000713 netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714
Steve French13a6e422008-12-02 17:24:33 +0000715 if ((tcon->ses->capabilities & CAP_UNIX) &&
716 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
Steve Frenchacc18aa2008-12-02 18:53:55 +0000717 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
Steve French13a6e422008-12-02 17:24:33 +0000718 posix_locking = 1;
Steve French08547b02006-02-28 22:39:25 +0000719 /* BB add code here to normalize offset and length to
720 account for negative length which we can not accept over the
721 wire */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 if (IS_GETLK(cmd)) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000723 if (posix_locking) {
Steve French08547b02006-02-28 22:39:25 +0000724 int posix_lock_type;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000725 if (lockType & LOCKING_ANDX_SHARED_LOCK)
Steve French08547b02006-02-28 22:39:25 +0000726 posix_lock_type = CIFS_RDLCK;
727 else
728 posix_lock_type = CIFS_WRLCK;
Steve French13a6e422008-12-02 17:24:33 +0000729 rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */,
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000730 length, pfLock, posix_lock_type,
731 wait_flag);
Steve French08547b02006-02-28 22:39:25 +0000732 FreeXid(xid);
733 return rc;
734 }
735
736 /* BB we could chain these into one lock request BB */
Steve French13a6e422008-12-02 17:24:33 +0000737 rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start,
Pavel Shilovsky12fed002011-01-17 20:15:44 +0300738 0, 1, lockType, 0 /* wait flag */, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 if (rc == 0) {
Steve French13a6e422008-12-02 17:24:33 +0000740 rc = CIFSSMBLock(xid, tcon, netfid, length,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 pfLock->fl_start, 1 /* numUnlock */ ,
742 0 /* numLock */ , lockType,
Pavel Shilovsky12fed002011-01-17 20:15:44 +0300743 0 /* wait flag */, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 pfLock->fl_type = F_UNLCK;
745 if (rc != 0)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000746 cERROR(1, "Error unlocking previously locked "
747 "range %d during test of lock", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 rc = 0;
749
750 } else {
751 /* if rc == ERR_SHARING_VIOLATION ? */
Pavel Shilovskyf05337c2010-04-05 09:59:14 +0400752 rc = 0;
753
754 if (lockType & LOCKING_ANDX_SHARED_LOCK) {
755 pfLock->fl_type = F_WRLCK;
756 } else {
757 rc = CIFSSMBLock(xid, tcon, netfid, length,
758 pfLock->fl_start, 0, 1,
759 lockType | LOCKING_ANDX_SHARED_LOCK,
Pavel Shilovsky12fed002011-01-17 20:15:44 +0300760 0 /* wait flag */, 0);
Pavel Shilovskyf05337c2010-04-05 09:59:14 +0400761 if (rc == 0) {
762 rc = CIFSSMBLock(xid, tcon, netfid,
763 length, pfLock->fl_start, 1, 0,
764 lockType |
765 LOCKING_ANDX_SHARED_LOCK,
Pavel Shilovsky12fed002011-01-17 20:15:44 +0300766 0 /* wait flag */, 0);
Pavel Shilovskyf05337c2010-04-05 09:59:14 +0400767 pfLock->fl_type = F_RDLCK;
768 if (rc != 0)
Steve Frenchf19159d2010-04-21 04:12:10 +0000769 cERROR(1, "Error unlocking "
Pavel Shilovskyf05337c2010-04-05 09:59:14 +0400770 "previously locked range %d "
Steve Frenchf19159d2010-04-21 04:12:10 +0000771 "during test of lock", rc);
Pavel Shilovskyf05337c2010-04-05 09:59:14 +0400772 rc = 0;
773 } else {
774 pfLock->fl_type = F_WRLCK;
775 rc = 0;
776 }
777 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 }
779
780 FreeXid(xid);
781 return rc;
782 }
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000783
784 if (!numLock && !numUnlock) {
785 /* if no lock or unlock then nothing
786 to do since we do not know what it is */
787 FreeXid(xid);
788 return -EOPNOTSUPP;
789 }
790
791 if (posix_locking) {
Steve French08547b02006-02-28 22:39:25 +0000792 int posix_lock_type;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000793 if (lockType & LOCKING_ANDX_SHARED_LOCK)
Steve French08547b02006-02-28 22:39:25 +0000794 posix_lock_type = CIFS_RDLCK;
795 else
796 posix_lock_type = CIFS_WRLCK;
Steve French50c2f752007-07-13 00:33:32 +0000797
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000798 if (numUnlock == 1)
Steve Frenchbeb84dc2006-03-03 23:36:34 +0000799 posix_lock_type = CIFS_UNLCK;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000800
Steve French13a6e422008-12-02 17:24:33 +0000801 rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */,
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000802 length, pfLock, posix_lock_type,
803 wait_flag);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000804 } else {
Joe Perchesc21dfb62010-07-12 13:50:14 -0700805 struct cifsFileInfo *fid = file->private_data;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000806
807 if (numLock) {
Steve French13a6e422008-12-02 17:24:33 +0000808 rc = CIFSSMBLock(xid, tcon, netfid, length,
Pavel Shilovsky12fed002011-01-17 20:15:44 +0300809 pfLock->fl_start, 0, numLock, lockType,
810 wait_flag, 0);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000811
812 if (rc == 0) {
813 /* For Windows locks we must store them. */
814 rc = store_file_lock(fid, length,
815 pfLock->fl_start, lockType);
816 }
817 } else if (numUnlock) {
818 /* For each stored lock that this unlock overlaps
819 completely, unlock it. */
820 int stored_rc = 0;
821 struct cifsLockInfo *li, *tmp;
822
Steve French6b70c952006-09-21 07:35:29 +0000823 rc = 0;
Roland Dreier796e5662007-05-03 04:33:45 +0000824 mutex_lock(&fid->lock_mutex);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000825 list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
826 if (pfLock->fl_start <= li->offset &&
Steve Frenchc19eb712007-08-24 03:22:48 +0000827 (pfLock->fl_start + length) >=
Jeff Layton39db8102007-08-24 03:16:51 +0000828 (li->offset + li->length)) {
Steve French13a6e422008-12-02 17:24:33 +0000829 stored_rc = CIFSSMBLock(xid, tcon,
Pavel Shilovsky12fed002011-01-17 20:15:44 +0300830 netfid, li->length,
831 li->offset, 1, 0,
832 li->type, false, 0);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000833 if (stored_rc)
834 rc = stored_rc;
Pavel Shilovsky2c964d12010-04-21 19:44:24 +0000835 else {
836 list_del(&li->llist);
837 kfree(li);
838 }
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000839 }
840 }
Roland Dreier796e5662007-05-03 04:33:45 +0000841 mutex_unlock(&fid->lock_mutex);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000842 }
843 }
844
Steve Frenchd634cc12005-08-26 14:42:59 -0500845 if (pfLock->fl_flags & FL_POSIX)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 posix_lock_file_wait(file, pfLock);
847 FreeXid(xid);
848 return rc;
849}
850
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400851/* update the file size (if needed) after a write */
Pavel Shilovsky72432ff2011-01-24 14:16:35 -0500852void
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400853cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
854 unsigned int bytes_written)
855{
856 loff_t end_of_write = offset + bytes_written;
857
858 if (end_of_write > cifsi->server_eof)
859 cifsi->server_eof = end_of_write;
860}
861
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +0400862static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
Jeff Layton7da4b492010-10-15 15:34:00 -0400863 const char *write_data, size_t write_size,
864 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865{
866 int rc = 0;
867 unsigned int bytes_written = 0;
868 unsigned int total_written;
869 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000870 struct cifs_tcon *pTcon;
Jeff Layton77499812011-01-11 07:24:23 -0500871 int xid;
Jeff Layton7da4b492010-10-15 15:34:00 -0400872 struct dentry *dentry = open_file->dentry;
873 struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +0400874 struct cifs_io_parms io_parms;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875
Jeff Layton7da4b492010-10-15 15:34:00 -0400876 cifs_sb = CIFS_SB(dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877
Joe Perchesb6b38f72010-04-21 03:50:45 +0000878 cFYI(1, "write %zd bytes to offset %lld of %s", write_size,
Jeff Layton7da4b492010-10-15 15:34:00 -0400879 *poffset, dentry->d_name.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880
Jeff Layton13cfb732010-09-29 19:51:11 -0400881 pTcon = tlink_tcon(open_file->tlink);
Steve French50c2f752007-07-13 00:33:32 +0000882
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 for (total_written = 0; write_size > total_written;
886 total_written += bytes_written) {
887 rc = -EAGAIN;
888 while (rc == -EAGAIN) {
Jeff Laytonca83ce32011-04-12 09:13:44 -0400889 struct kvec iov[2];
890 unsigned int len;
891
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 if (open_file->invalidHandle) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 /* we could deadlock if we called
894 filemap_fdatawait from here so tell
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000895 reopen_file not to flush data to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 server now */
Jeff Layton15886172010-10-15 15:33:59 -0400897 rc = cifs_reopen_file(open_file, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 if (rc != 0)
899 break;
900 }
Steve French3e844692005-10-03 13:37:24 -0700901
Jeff Laytonca83ce32011-04-12 09:13:44 -0400902 len = min((size_t)cifs_sb->wsize,
903 write_size - total_written);
904 /* iov[0] is reserved for smb header */
905 iov[1].iov_base = (char *)write_data + total_written;
906 iov[1].iov_len = len;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +0400907 io_parms.netfid = open_file->netfid;
908 io_parms.pid = pid;
909 io_parms.tcon = pTcon;
910 io_parms.offset = *poffset;
911 io_parms.length = len;
912 rc = CIFSSMBWrite2(xid, &io_parms, &bytes_written, iov,
913 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 }
915 if (rc || (bytes_written == 0)) {
916 if (total_written)
917 break;
918 else {
919 FreeXid(xid);
920 return rc;
921 }
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400922 } else {
923 cifs_update_eof(cifsi, *poffset, bytes_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 *poffset += bytes_written;
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400925 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 }
927
Steve Frencha4544342005-08-24 13:59:35 -0700928 cifs_stats_bytes_written(pTcon, total_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929
Jeff Layton7da4b492010-10-15 15:34:00 -0400930 if (total_written > 0) {
931 spin_lock(&dentry->d_inode->i_lock);
932 if (*poffset > dentry->d_inode->i_size)
933 i_size_write(dentry->d_inode, *poffset);
934 spin_unlock(&dentry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 }
Jeff Layton7da4b492010-10-15 15:34:00 -0400936 mark_inode_dirty_sync(dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 FreeXid(xid);
938 return total_written;
939}
940
Jeff Layton6508d902010-09-29 19:51:11 -0400941struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
942 bool fsuid_only)
Steve French630f3f02007-10-25 21:17:17 +0000943{
944 struct cifsFileInfo *open_file = NULL;
Jeff Layton6508d902010-09-29 19:51:11 -0400945 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
946
947 /* only filter by fsuid on multiuser mounts */
948 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
949 fsuid_only = false;
Steve French630f3f02007-10-25 21:17:17 +0000950
Jeff Layton44772882010-10-15 15:34:03 -0400951 spin_lock(&cifs_file_list_lock);
Steve French630f3f02007-10-25 21:17:17 +0000952 /* we could simply get the first_list_entry since write-only entries
953 are always at the end of the list but since the first entry might
954 have a close pending, we go through the whole list */
955 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -0400956 if (fsuid_only && open_file->uid != current_fsuid())
957 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -0400958 if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
Steve French630f3f02007-10-25 21:17:17 +0000959 if (!open_file->invalidHandle) {
960 /* found a good file */
961 /* lock it so it will not be closed on us */
Dave Kleikamp6ab409b2009-08-31 11:07:12 -0400962 cifsFileInfo_get(open_file);
Jeff Layton44772882010-10-15 15:34:03 -0400963 spin_unlock(&cifs_file_list_lock);
Steve French630f3f02007-10-25 21:17:17 +0000964 return open_file;
965 } /* else might as well continue, and look for
966 another, or simply have the caller reopen it
967 again rather than trying to fix this handle */
968 } else /* write only file */
969 break; /* write only files are last so must be done */
970 }
Jeff Layton44772882010-10-15 15:34:03 -0400971 spin_unlock(&cifs_file_list_lock);
Steve French630f3f02007-10-25 21:17:17 +0000972 return NULL;
973}
Steve French630f3f02007-10-25 21:17:17 +0000974
Jeff Layton6508d902010-09-29 19:51:11 -0400975struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
976 bool fsuid_only)
Steve French6148a742005-10-05 12:23:19 -0700977{
978 struct cifsFileInfo *open_file;
Jeff Laytond3892292010-11-02 16:22:50 -0400979 struct cifs_sb_info *cifs_sb;
Jeff Layton2846d382008-09-22 21:33:33 -0400980 bool any_available = false;
Steve Frenchdd99cd82005-10-05 19:32:49 -0700981 int rc;
Steve French6148a742005-10-05 12:23:19 -0700982
Steve French60808232006-04-22 15:53:05 +0000983 /* Having a null inode here (because mapping->host was set to zero by
984 the VFS or MM) should not happen but we had reports of on oops (due to
985 it being zero) during stress testcases so we need to check for it */
986
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000987 if (cifs_inode == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000988 cERROR(1, "Null inode passed to cifs_writeable_file");
Steve French60808232006-04-22 15:53:05 +0000989 dump_stack();
990 return NULL;
991 }
992
Jeff Laytond3892292010-11-02 16:22:50 -0400993 cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
994
Jeff Layton6508d902010-09-29 19:51:11 -0400995 /* only filter by fsuid on multiuser mounts */
996 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
997 fsuid_only = false;
998
Jeff Layton44772882010-10-15 15:34:03 -0400999 spin_lock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001000refind_writable:
Steve French6148a742005-10-05 12:23:19 -07001001 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001002 if (!any_available && open_file->pid != current->tgid)
1003 continue;
1004 if (fsuid_only && open_file->uid != current_fsuid())
1005 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001006 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001007 cifsFileInfo_get(open_file);
Steve French9b22b0b2007-10-02 01:11:08 +00001008
1009 if (!open_file->invalidHandle) {
1010 /* found a good writable file */
Jeff Layton44772882010-10-15 15:34:03 -04001011 spin_unlock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001012 return open_file;
1013 }
Steve French8840dee2007-11-16 23:05:52 +00001014
Jeff Layton44772882010-10-15 15:34:03 -04001015 spin_unlock(&cifs_file_list_lock);
Steve Frenchcdff08e2010-10-21 22:46:14 +00001016
Steve French9b22b0b2007-10-02 01:11:08 +00001017 /* Had to unlock since following call can block */
Jeff Layton15886172010-10-15 15:33:59 -04001018 rc = cifs_reopen_file(open_file, false);
Steve Frenchcdff08e2010-10-21 22:46:14 +00001019 if (!rc)
1020 return open_file;
Steve French9b22b0b2007-10-02 01:11:08 +00001021
Steve Frenchcdff08e2010-10-21 22:46:14 +00001022 /* if it fails, try another handle if possible */
Joe Perchesb6b38f72010-04-21 03:50:45 +00001023 cFYI(1, "wp failed on reopen file");
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001024 cifsFileInfo_put(open_file);
Steve French8840dee2007-11-16 23:05:52 +00001025
Steve Frenchcdff08e2010-10-21 22:46:14 +00001026 spin_lock(&cifs_file_list_lock);
1027
Steve French9b22b0b2007-10-02 01:11:08 +00001028 /* else we simply continue to the next entry. Thus
1029 we do not loop on reopen errors. If we
1030 can not reopen the file, for example if we
1031 reconnected to a server with another client
1032 racing to delete or lock the file we would not
1033 make progress if we restarted before the beginning
1034 of the loop here. */
Steve French6148a742005-10-05 12:23:19 -07001035 }
1036 }
Jeff Layton2846d382008-09-22 21:33:33 -04001037 /* couldn't find useable FH with same pid, try any available */
1038 if (!any_available) {
1039 any_available = true;
1040 goto refind_writable;
1041 }
Jeff Layton44772882010-10-15 15:34:03 -04001042 spin_unlock(&cifs_file_list_lock);
Steve French6148a742005-10-05 12:23:19 -07001043 return NULL;
1044}
1045
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1047{
1048 struct address_space *mapping = page->mapping;
1049 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1050 char *write_data;
1051 int rc = -EFAULT;
1052 int bytes_written = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 struct inode *inode;
Steve French6148a742005-10-05 12:23:19 -07001054 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
1056 if (!mapping || !mapping->host)
1057 return -EFAULT;
1058
1059 inode = page->mapping->host;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
1061 offset += (loff_t)from;
1062 write_data = kmap(page);
1063 write_data += from;
1064
1065 if ((to > PAGE_CACHE_SIZE) || (from > to)) {
1066 kunmap(page);
1067 return -EIO;
1068 }
1069
1070 /* racing with truncate? */
1071 if (offset > mapping->host->i_size) {
1072 kunmap(page);
1073 return 0; /* don't care */
1074 }
1075
1076 /* check to make sure that we are not extending the file */
1077 if (mapping->host->i_size - offset < (loff_t)to)
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001078 to = (unsigned)(mapping->host->i_size - offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079
Jeff Layton6508d902010-09-29 19:51:11 -04001080 open_file = find_writable_file(CIFS_I(mapping->host), false);
Steve French6148a742005-10-05 12:23:19 -07001081 if (open_file) {
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001082 bytes_written = cifs_write(open_file, open_file->pid,
1083 write_data, to - from, &offset);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001084 cifsFileInfo_put(open_file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 /* Does mm or vfs already set times? */
Steve French6148a742005-10-05 12:23:19 -07001086 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001087 if ((bytes_written > 0) && (offset))
Steve French6148a742005-10-05 12:23:19 -07001088 rc = 0;
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001089 else if (bytes_written < 0)
1090 rc = bytes_written;
Steve French6148a742005-10-05 12:23:19 -07001091 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001092 cFYI(1, "No writeable filehandles for inode");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 rc = -EIO;
1094 }
1095
1096 kunmap(page);
1097 return rc;
1098}
1099
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100static int cifs_writepages(struct address_space *mapping,
Steve French37c0eb42005-10-05 14:50:29 -07001101 struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102{
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001103 struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb);
1104 bool done = false, scanned = false, range_whole = false;
1105 pgoff_t end, index;
1106 struct cifs_writedata *wdata;
Steve French37c0eb42005-10-05 14:50:29 -07001107 struct page *page;
Steve French37c0eb42005-10-05 14:50:29 -07001108 int rc = 0;
Steve French50c2f752007-07-13 00:33:32 +00001109
Steve French37c0eb42005-10-05 14:50:29 -07001110 /*
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001111 * If wsize is smaller than the page cache size, default to writing
Steve French37c0eb42005-10-05 14:50:29 -07001112 * one page at a time via cifs_writepage
1113 */
1114 if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1115 return generic_writepages(mapping, wbc);
1116
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001117 if (wbc->range_cyclic) {
Steve French37c0eb42005-10-05 14:50:29 -07001118 index = mapping->writeback_index; /* Start from prev offset */
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001119 end = -1;
1120 } else {
1121 index = wbc->range_start >> PAGE_CACHE_SHIFT;
1122 end = wbc->range_end >> PAGE_CACHE_SHIFT;
1123 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001124 range_whole = true;
1125 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001126 }
1127retry:
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001128 while (!done && index <= end) {
1129 unsigned int i, nr_pages, found_pages;
1130 pgoff_t next = 0, tofind;
1131 struct page **pages;
Steve French37c0eb42005-10-05 14:50:29 -07001132
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001133 tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1,
1134 end - index) + 1;
Steve French37c0eb42005-10-05 14:50:29 -07001135
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001136 wdata = cifs_writedata_alloc((unsigned int)tofind);
1137 if (!wdata) {
1138 rc = -ENOMEM;
1139 break;
1140 }
1141
1142 /*
1143 * find_get_pages_tag seems to return a max of 256 on each
1144 * iteration, so we must call it several times in order to
1145 * fill the array or the wsize is effectively limited to
1146 * 256 * PAGE_CACHE_SIZE.
1147 */
1148 found_pages = 0;
1149 pages = wdata->pages;
1150 do {
1151 nr_pages = find_get_pages_tag(mapping, &index,
1152 PAGECACHE_TAG_DIRTY,
1153 tofind, pages);
1154 found_pages += nr_pages;
1155 tofind -= nr_pages;
1156 pages += nr_pages;
1157 } while (nr_pages && tofind && index <= end);
1158
1159 if (found_pages == 0) {
1160 kref_put(&wdata->refcount, cifs_writedata_release);
1161 break;
1162 }
1163
1164 nr_pages = 0;
1165 for (i = 0; i < found_pages; i++) {
1166 page = wdata->pages[i];
Steve French37c0eb42005-10-05 14:50:29 -07001167 /*
1168 * At this point we hold neither mapping->tree_lock nor
1169 * lock on the page itself: the page may be truncated or
1170 * invalidated (changing page->mapping to NULL), or even
1171 * swizzled back from swapper_space to tmpfs file
1172 * mapping
1173 */
1174
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001175 if (nr_pages == 0)
Steve French37c0eb42005-10-05 14:50:29 -07001176 lock_page(page);
Nick Piggin529ae9a2008-08-02 12:01:03 +02001177 else if (!trylock_page(page))
Steve French37c0eb42005-10-05 14:50:29 -07001178 break;
1179
1180 if (unlikely(page->mapping != mapping)) {
1181 unlock_page(page);
1182 break;
1183 }
1184
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001185 if (!wbc->range_cyclic && page->index > end) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001186 done = true;
Steve French37c0eb42005-10-05 14:50:29 -07001187 unlock_page(page);
1188 break;
1189 }
1190
1191 if (next && (page->index != next)) {
1192 /* Not next consecutive page */
1193 unlock_page(page);
1194 break;
1195 }
1196
1197 if (wbc->sync_mode != WB_SYNC_NONE)
1198 wait_on_page_writeback(page);
1199
1200 if (PageWriteback(page) ||
Linus Torvaldscb876f42006-12-23 16:19:07 -08001201 !clear_page_dirty_for_io(page)) {
Steve French37c0eb42005-10-05 14:50:29 -07001202 unlock_page(page);
1203 break;
1204 }
Steve French84d2f072005-10-12 15:32:05 -07001205
Linus Torvaldscb876f42006-12-23 16:19:07 -08001206 /*
1207 * This actually clears the dirty bit in the radix tree.
1208 * See cifs_writepage() for more commentary.
1209 */
1210 set_page_writeback(page);
1211
Steve French84d2f072005-10-12 15:32:05 -07001212 if (page_offset(page) >= mapping->host->i_size) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001213 done = true;
Steve French84d2f072005-10-12 15:32:05 -07001214 unlock_page(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001215 end_page_writeback(page);
Steve French84d2f072005-10-12 15:32:05 -07001216 break;
1217 }
1218
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001219 wdata->pages[i] = page;
Steve French37c0eb42005-10-05 14:50:29 -07001220 next = page->index + 1;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001221 ++nr_pages;
Steve French37c0eb42005-10-05 14:50:29 -07001222 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001223
1224 /* reset index to refind any pages skipped */
1225 if (nr_pages == 0)
1226 index = wdata->pages[0]->index + 1;
1227
1228 /* put any pages we aren't going to use */
1229 for (i = nr_pages; i < found_pages; i++) {
1230 page_cache_release(wdata->pages[i]);
1231 wdata->pages[i] = NULL;
1232 }
1233
1234 /* nothing to write? */
1235 if (nr_pages == 0) {
1236 kref_put(&wdata->refcount, cifs_writedata_release);
1237 continue;
1238 }
1239
1240 wdata->sync_mode = wbc->sync_mode;
1241 wdata->nr_pages = nr_pages;
1242 wdata->offset = page_offset(wdata->pages[0]);
1243
1244 do {
1245 if (wdata->cfile != NULL)
1246 cifsFileInfo_put(wdata->cfile);
1247 wdata->cfile = find_writable_file(CIFS_I(mapping->host),
1248 false);
1249 if (!wdata->cfile) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001250 cERROR(1, "No writable handles for inode");
Steve French23e7dd72005-10-20 13:44:56 -07001251 rc = -EBADF;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001252 break;
Steve French37c0eb42005-10-05 14:50:29 -07001253 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001254 rc = cifs_async_writev(wdata);
1255 } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN);
Jeff Laytonf3983c22010-09-22 16:17:40 -07001256
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001257 for (i = 0; i < nr_pages; ++i)
1258 unlock_page(wdata->pages[i]);
Jeff Layton941b8532011-01-11 07:24:01 -05001259
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001260 /* send failure -- clean up the mess */
1261 if (rc != 0) {
1262 for (i = 0; i < nr_pages; ++i) {
Jeff Layton941b8532011-01-11 07:24:01 -05001263 if (rc == -EAGAIN)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001264 redirty_page_for_writepage(wbc,
1265 wdata->pages[i]);
1266 else
1267 SetPageError(wdata->pages[i]);
1268 end_page_writeback(wdata->pages[i]);
1269 page_cache_release(wdata->pages[i]);
Steve French37c0eb42005-10-05 14:50:29 -07001270 }
Jeff Layton941b8532011-01-11 07:24:01 -05001271 if (rc != -EAGAIN)
1272 mapping_set_error(mapping, rc);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001273 }
1274 kref_put(&wdata->refcount, cifs_writedata_release);
Jeff Layton941b8532011-01-11 07:24:01 -05001275
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001276 wbc->nr_to_write -= nr_pages;
1277 if (wbc->nr_to_write <= 0)
1278 done = true;
Dave Kleikampb066a482008-11-18 03:49:05 +00001279
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001280 index = next;
Steve French37c0eb42005-10-05 14:50:29 -07001281 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001282
Steve French37c0eb42005-10-05 14:50:29 -07001283 if (!scanned && !done) {
1284 /*
1285 * We hit the last page and there is more work to be done: wrap
1286 * back to the start of the file
1287 */
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001288 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001289 index = 0;
1290 goto retry;
1291 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001292
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001293 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
Steve French37c0eb42005-10-05 14:50:29 -07001294 mapping->writeback_index = index;
1295
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 return rc;
1297}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001299static int
1300cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301{
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001302 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 int xid;
1304
1305 xid = GetXid();
1306/* BB add check for wbc flags */
1307 page_cache_get(page);
Steve Frenchad7a2922008-02-07 23:25:02 +00001308 if (!PageUptodate(page))
Joe Perchesb6b38f72010-04-21 03:50:45 +00001309 cFYI(1, "ppw - page not up to date");
Linus Torvaldscb876f42006-12-23 16:19:07 -08001310
1311 /*
1312 * Set the "writeback" flag, and clear "dirty" in the radix tree.
1313 *
1314 * A writepage() implementation always needs to do either this,
1315 * or re-dirty the page with "redirty_page_for_writepage()" in
1316 * the case of a failure.
1317 *
1318 * Just unlocking the page will cause the radix tree tag-bits
1319 * to fail to update with the state of the page correctly.
1320 */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001321 set_page_writeback(page);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001322retry_write:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001324 if (rc == -EAGAIN && wbc->sync_mode == WB_SYNC_ALL)
1325 goto retry_write;
1326 else if (rc == -EAGAIN)
1327 redirty_page_for_writepage(wbc, page);
1328 else if (rc != 0)
1329 SetPageError(page);
1330 else
1331 SetPageUptodate(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001332 end_page_writeback(page);
1333 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 FreeXid(xid);
1335 return rc;
1336}
1337
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001338static int cifs_writepage(struct page *page, struct writeback_control *wbc)
1339{
1340 int rc = cifs_writepage_locked(page, wbc);
1341 unlock_page(page);
1342 return rc;
1343}
1344
Nick Piggind9414772008-09-24 11:32:59 -04001345static int cifs_write_end(struct file *file, struct address_space *mapping,
1346 loff_t pos, unsigned len, unsigned copied,
1347 struct page *page, void *fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348{
Nick Piggind9414772008-09-24 11:32:59 -04001349 int rc;
1350 struct inode *inode = mapping->host;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001351 struct cifsFileInfo *cfile = file->private_data;
1352 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
1353 __u32 pid;
1354
1355 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1356 pid = cfile->pid;
1357 else
1358 pid = current->tgid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359
Joe Perchesb6b38f72010-04-21 03:50:45 +00001360 cFYI(1, "write_end for page %p from pos %lld with %d bytes",
1361 page, pos, copied);
Steve Frenchad7a2922008-02-07 23:25:02 +00001362
Jeff Laytona98ee8c2008-11-26 19:32:33 +00001363 if (PageChecked(page)) {
1364 if (copied == len)
1365 SetPageUptodate(page);
1366 ClearPageChecked(page);
1367 } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
Nick Piggind9414772008-09-24 11:32:59 -04001368 SetPageUptodate(page);
1369
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 if (!PageUptodate(page)) {
Nick Piggind9414772008-09-24 11:32:59 -04001371 char *page_data;
1372 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
1373 int xid;
1374
1375 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 /* this is probably better than directly calling
1377 partialpage_write since in this function the file handle is
1378 known which we might as well leverage */
1379 /* BB check if anything else missing out of ppw
1380 such as updating last write time */
1381 page_data = kmap(page);
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001382 rc = cifs_write(cfile, pid, page_data + offset, copied, &pos);
Nick Piggind9414772008-09-24 11:32:59 -04001383 /* if (rc < 0) should we set writebehind rc? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 kunmap(page);
Nick Piggind9414772008-09-24 11:32:59 -04001385
1386 FreeXid(xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001387 } else {
Nick Piggind9414772008-09-24 11:32:59 -04001388 rc = copied;
1389 pos += copied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 set_page_dirty(page);
1391 }
1392
Nick Piggind9414772008-09-24 11:32:59 -04001393 if (rc > 0) {
1394 spin_lock(&inode->i_lock);
1395 if (pos > inode->i_size)
1396 i_size_write(inode, pos);
1397 spin_unlock(&inode->i_lock);
1398 }
1399
1400 unlock_page(page);
1401 page_cache_release(page);
1402
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 return rc;
1404}
1405
Josef Bacik02c24a82011-07-16 20:44:56 -04001406int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
1407 int datasync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408{
1409 int xid;
1410 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00001411 struct cifs_tcon *tcon;
Joe Perchesc21dfb62010-07-12 13:50:14 -07001412 struct cifsFileInfo *smbfile = file->private_data;
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08001413 struct inode *inode = file->f_path.dentry->d_inode;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001414 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415
Josef Bacik02c24a82011-07-16 20:44:56 -04001416 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
1417 if (rc)
1418 return rc;
1419 mutex_lock(&inode->i_mutex);
1420
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 xid = GetXid();
1422
Joe Perchesb6b38f72010-04-21 03:50:45 +00001423 cFYI(1, "Sync file - name: %s datasync: 0x%x",
Christoph Hellwig7ea80852010-05-26 17:53:25 +02001424 file->f_path.dentry->d_name.name, datasync);
Steve French50c2f752007-07-13 00:33:32 +00001425
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001426 if (!CIFS_I(inode)->clientCanCacheRead) {
1427 rc = cifs_invalidate_mapping(inode);
1428 if (rc) {
1429 cFYI(1, "rc: %d during invalidate phase", rc);
1430 rc = 0; /* don't care about it in fsync */
1431 }
1432 }
Jeff Laytoneb4b7562010-10-22 14:52:29 -04001433
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001434 tcon = tlink_tcon(smbfile->tlink);
1435 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
1436 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
1437
1438 FreeXid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04001439 mutex_unlock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001440 return rc;
1441}
1442
Josef Bacik02c24a82011-07-16 20:44:56 -04001443int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001444{
1445 int xid;
1446 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00001447 struct cifs_tcon *tcon;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001448 struct cifsFileInfo *smbfile = file->private_data;
1449 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Josef Bacik02c24a82011-07-16 20:44:56 -04001450 struct inode *inode = file->f_mapping->host;
1451
1452 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
1453 if (rc)
1454 return rc;
1455 mutex_lock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001456
1457 xid = GetXid();
1458
1459 cFYI(1, "Sync file - name: %s datasync: 0x%x",
1460 file->f_path.dentry->d_name.name, datasync);
1461
1462 tcon = tlink_tcon(smbfile->tlink);
1463 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
1464 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
Steve Frenchb298f222009-02-21 21:17:43 +00001465
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 FreeXid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04001467 mutex_unlock(&inode->i_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 return rc;
1469}
1470
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471/*
1472 * As file closes, flush all cached write data for this inode checking
1473 * for write behind errors.
1474 */
Miklos Szeredi75e1fcc2006-06-23 02:05:12 -07001475int cifs_flush(struct file *file, fl_owner_t id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476{
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001477 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 int rc = 0;
1479
Jeff Laytoneb4b7562010-10-22 14:52:29 -04001480 if (file->f_mode & FMODE_WRITE)
Jeff Laytond3f13222010-10-15 15:34:07 -04001481 rc = filemap_write_and_wait(inode->i_mapping);
Steve French50c2f752007-07-13 00:33:32 +00001482
Joe Perchesb6b38f72010-04-21 03:50:45 +00001483 cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
1485 return rc;
1486}
1487
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001488static int
1489cifs_write_allocate_pages(struct page **pages, unsigned long num_pages)
1490{
1491 int rc = 0;
1492 unsigned long i;
1493
1494 for (i = 0; i < num_pages; i++) {
1495 pages[i] = alloc_page(__GFP_HIGHMEM);
1496 if (!pages[i]) {
1497 /*
1498 * save number of pages we have already allocated and
1499 * return with ENOMEM error
1500 */
1501 num_pages = i;
1502 rc = -ENOMEM;
1503 goto error;
1504 }
1505 }
1506
1507 return rc;
1508
1509error:
1510 for (i = 0; i < num_pages; i++)
1511 put_page(pages[i]);
1512 return rc;
1513}
1514
1515static inline
1516size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
1517{
1518 size_t num_pages;
1519 size_t clen;
1520
1521 clen = min_t(const size_t, len, wsize);
1522 num_pages = clen / PAGE_CACHE_SIZE;
1523 if (clen % PAGE_CACHE_SIZE)
1524 num_pages++;
1525
1526 if (cur_len)
1527 *cur_len = clen;
1528
1529 return num_pages;
1530}
1531
1532static ssize_t
1533cifs_iovec_write(struct file *file, const struct iovec *iov,
1534 unsigned long nr_segs, loff_t *poffset)
1535{
Pavel Shilovsky76429c12011-01-31 16:03:08 +03001536 unsigned int written;
1537 unsigned long num_pages, npages, i;
1538 size_t copied, len, cur_len;
1539 ssize_t total_written = 0;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001540 struct kvec *to_send;
1541 struct page **pages;
1542 struct iov_iter it;
1543 struct inode *inode;
1544 struct cifsFileInfo *open_file;
Steve French96daf2b2011-05-27 04:34:02 +00001545 struct cifs_tcon *pTcon;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001546 struct cifs_sb_info *cifs_sb;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001547 struct cifs_io_parms io_parms;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001548 int xid, rc;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001549 __u32 pid;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001550
1551 len = iov_length(iov, nr_segs);
1552 if (!len)
1553 return 0;
1554
1555 rc = generic_write_checks(file, poffset, &len, 0);
1556 if (rc)
1557 return rc;
1558
1559 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1560 num_pages = get_numpages(cifs_sb->wsize, len, &cur_len);
1561
1562 pages = kmalloc(sizeof(struct pages *)*num_pages, GFP_KERNEL);
1563 if (!pages)
1564 return -ENOMEM;
1565
1566 to_send = kmalloc(sizeof(struct kvec)*(num_pages + 1), GFP_KERNEL);
1567 if (!to_send) {
1568 kfree(pages);
1569 return -ENOMEM;
1570 }
1571
1572 rc = cifs_write_allocate_pages(pages, num_pages);
1573 if (rc) {
1574 kfree(pages);
1575 kfree(to_send);
1576 return rc;
1577 }
1578
1579 xid = GetXid();
1580 open_file = file->private_data;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001581
1582 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1583 pid = open_file->pid;
1584 else
1585 pid = current->tgid;
1586
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001587 pTcon = tlink_tcon(open_file->tlink);
1588 inode = file->f_path.dentry->d_inode;
1589
1590 iov_iter_init(&it, iov, nr_segs, len, 0);
1591 npages = num_pages;
1592
1593 do {
1594 size_t save_len = cur_len;
1595 for (i = 0; i < npages; i++) {
1596 copied = min_t(const size_t, cur_len, PAGE_CACHE_SIZE);
1597 copied = iov_iter_copy_from_user(pages[i], &it, 0,
1598 copied);
1599 cur_len -= copied;
1600 iov_iter_advance(&it, copied);
1601 to_send[i+1].iov_base = kmap(pages[i]);
1602 to_send[i+1].iov_len = copied;
1603 }
1604
1605 cur_len = save_len - cur_len;
1606
1607 do {
1608 if (open_file->invalidHandle) {
1609 rc = cifs_reopen_file(open_file, false);
1610 if (rc != 0)
1611 break;
1612 }
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001613 io_parms.netfid = open_file->netfid;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001614 io_parms.pid = pid;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001615 io_parms.tcon = pTcon;
1616 io_parms.offset = *poffset;
1617 io_parms.length = cur_len;
1618 rc = CIFSSMBWrite2(xid, &io_parms, &written, to_send,
1619 npages, 0);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001620 } while (rc == -EAGAIN);
1621
1622 for (i = 0; i < npages; i++)
1623 kunmap(pages[i]);
1624
1625 if (written) {
1626 len -= written;
1627 total_written += written;
1628 cifs_update_eof(CIFS_I(inode), *poffset, written);
1629 *poffset += written;
1630 } else if (rc < 0) {
1631 if (!total_written)
1632 total_written = rc;
1633 break;
1634 }
1635
1636 /* get length and number of kvecs of the next write */
1637 npages = get_numpages(cifs_sb->wsize, len, &cur_len);
1638 } while (len > 0);
1639
1640 if (total_written > 0) {
1641 spin_lock(&inode->i_lock);
1642 if (*poffset > inode->i_size)
1643 i_size_write(inode, *poffset);
1644 spin_unlock(&inode->i_lock);
1645 }
1646
1647 cifs_stats_bytes_written(pTcon, total_written);
1648 mark_inode_dirty_sync(inode);
1649
1650 for (i = 0; i < num_pages; i++)
1651 put_page(pages[i]);
1652 kfree(to_send);
1653 kfree(pages);
1654 FreeXid(xid);
1655 return total_written;
1656}
1657
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03001658ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001659 unsigned long nr_segs, loff_t pos)
1660{
1661 ssize_t written;
1662 struct inode *inode;
1663
1664 inode = iocb->ki_filp->f_path.dentry->d_inode;
1665
1666 /*
1667 * BB - optimize the way when signing is disabled. We can drop this
1668 * extra memory-to-memory copying and use iovec buffers for constructing
1669 * write request.
1670 */
1671
1672 written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos);
1673 if (written > 0) {
1674 CIFS_I(inode)->invalid_mapping = true;
1675 iocb->ki_pos = pos;
1676 }
1677
1678 return written;
1679}
1680
1681ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
1682 unsigned long nr_segs, loff_t pos)
1683{
1684 struct inode *inode;
1685
1686 inode = iocb->ki_filp->f_path.dentry->d_inode;
1687
1688 if (CIFS_I(inode)->clientCanCacheAll)
1689 return generic_file_aio_write(iocb, iov, nr_segs, pos);
1690
1691 /*
1692 * In strict cache mode we need to write the data to the server exactly
1693 * from the pos to pos+len-1 rather than flush all affected pages
1694 * because it may cause a error with mandatory locks on these pages but
1695 * not on the region from pos to ppos+len-1.
1696 */
1697
1698 return cifs_user_writev(iocb, iov, nr_segs, pos);
1699}
1700
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001701static ssize_t
1702cifs_iovec_read(struct file *file, const struct iovec *iov,
1703 unsigned long nr_segs, loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704{
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001705 int rc;
1706 int xid;
Pavel Shilovsky76429c12011-01-31 16:03:08 +03001707 ssize_t total_read;
1708 unsigned int bytes_read = 0;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001709 size_t len, cur_len;
1710 int iov_offset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00001712 struct cifs_tcon *pTcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 struct smb_com_read_rsp *pSMBr;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001715 struct cifs_io_parms io_parms;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001716 char *read_data;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001717 __u32 pid;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001718
1719 if (!nr_segs)
1720 return 0;
1721
1722 len = iov_length(iov, nr_segs);
1723 if (!len)
1724 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725
1726 xid = GetXid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08001727 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728
Joe Perchesc21dfb62010-07-12 13:50:14 -07001729 open_file = file->private_data;
Jeff Layton13cfb732010-09-29 19:51:11 -04001730 pTcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001732 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1733 pid = open_file->pid;
1734 else
1735 pid = current->tgid;
1736
Steve Frenchad7a2922008-02-07 23:25:02 +00001737 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001738 cFYI(1, "attempting read on write only file instance");
Steve Frenchad7a2922008-02-07 23:25:02 +00001739
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001740 for (total_read = 0; total_read < len; total_read += bytes_read) {
1741 cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 rc = -EAGAIN;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001743 read_data = NULL;
1744
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 while (rc == -EAGAIN) {
Steve Frenchec637e32005-12-12 20:53:18 -08001746 int buf_type = CIFS_NO_BUFFER;
Steve Frenchcdff08e2010-10-21 22:46:14 +00001747 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04001748 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 if (rc != 0)
1750 break;
1751 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001752 io_parms.netfid = open_file->netfid;
1753 io_parms.pid = pid;
1754 io_parms.tcon = pTcon;
1755 io_parms.offset = *poffset;
Pavel Shilovsky2cebaa52011-07-20 18:24:09 +04001756 io_parms.length = cur_len;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001757 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001758 &read_data, &buf_type);
1759 pSMBr = (struct smb_com_read_rsp *)read_data;
1760 if (read_data) {
1761 char *data_offset = read_data + 4 +
1762 le16_to_cpu(pSMBr->DataOffset);
1763 if (memcpy_toiovecend(iov, data_offset,
1764 iov_offset, bytes_read))
Steve French93544cc2006-02-14 22:30:52 -06001765 rc = -EFAULT;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001766 if (buf_type == CIFS_SMALL_BUFFER)
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001767 cifs_small_buf_release(read_data);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001768 else if (buf_type == CIFS_LARGE_BUFFER)
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001769 cifs_buf_release(read_data);
1770 read_data = NULL;
1771 iov_offset += bytes_read;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 }
1773 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001774
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 if (rc || (bytes_read == 0)) {
1776 if (total_read) {
1777 break;
1778 } else {
1779 FreeXid(xid);
1780 return rc;
1781 }
1782 } else {
Steve Frencha4544342005-08-24 13:59:35 -07001783 cifs_stats_bytes_read(pTcon, bytes_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 *poffset += bytes_read;
1785 }
1786 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001787
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 FreeXid(xid);
1789 return total_read;
1790}
1791
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03001792ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001793 unsigned long nr_segs, loff_t pos)
1794{
1795 ssize_t read;
1796
1797 read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos);
1798 if (read > 0)
1799 iocb->ki_pos = pos;
1800
1801 return read;
1802}
1803
1804ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov,
1805 unsigned long nr_segs, loff_t pos)
1806{
1807 struct inode *inode;
1808
1809 inode = iocb->ki_filp->f_path.dentry->d_inode;
1810
1811 if (CIFS_I(inode)->clientCanCacheRead)
1812 return generic_file_aio_read(iocb, iov, nr_segs, pos);
1813
1814 /*
1815 * In strict cache mode we need to read from the server all the time
1816 * if we don't have level II oplock because the server can delay mtime
1817 * change - so we can't make a decision about inode invalidating.
1818 * And we can also fail with pagereading if there are mandatory locks
1819 * on pages affected by this read but not on the region from pos to
1820 * pos+len-1.
1821 */
1822
1823 return cifs_user_readv(iocb, iov, nr_segs, pos);
1824}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825
1826static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001827 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828{
1829 int rc = -EACCES;
1830 unsigned int bytes_read = 0;
1831 unsigned int total_read;
1832 unsigned int current_read_size;
1833 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00001834 struct cifs_tcon *pTcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 int xid;
1836 char *current_offset;
1837 struct cifsFileInfo *open_file;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001838 struct cifs_io_parms io_parms;
Steve Frenchec637e32005-12-12 20:53:18 -08001839 int buf_type = CIFS_NO_BUFFER;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001840 __u32 pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841
1842 xid = GetXid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08001843 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844
1845 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301846 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301848 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 }
Joe Perchesc21dfb62010-07-12 13:50:14 -07001850 open_file = file->private_data;
Jeff Layton13cfb732010-09-29 19:51:11 -04001851 pTcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001853 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1854 pid = open_file->pid;
1855 else
1856 pid = current->tgid;
1857
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001859 cFYI(1, "attempting read on write only file instance");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001861 for (total_read = 0, current_offset = read_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 read_size > total_read;
1863 total_read += bytes_read, current_offset += bytes_read) {
1864 current_read_size = min_t(const int, read_size - total_read,
1865 cifs_sb->rsize);
Steve Frenchf9f5c812005-09-15 23:06:38 -07001866 /* For windows me and 9x we do not want to request more
1867 than it negotiated since it will refuse the read then */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001868 if ((pTcon->ses) &&
Steve Frenchf9f5c812005-09-15 23:06:38 -07001869 !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
1870 current_read_size = min_t(const int, current_read_size,
1871 pTcon->ses->server->maxBuf - 128);
1872 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 rc = -EAGAIN;
1874 while (rc == -EAGAIN) {
Steve Frenchcdff08e2010-10-21 22:46:14 +00001875 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04001876 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 if (rc != 0)
1878 break;
1879 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001880 io_parms.netfid = open_file->netfid;
1881 io_parms.pid = pid;
1882 io_parms.tcon = pTcon;
1883 io_parms.offset = *poffset;
1884 io_parms.length = current_read_size;
1885 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
1886 &current_offset, &buf_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 }
1888 if (rc || (bytes_read == 0)) {
1889 if (total_read) {
1890 break;
1891 } else {
1892 FreeXid(xid);
1893 return rc;
1894 }
1895 } else {
Steve Frencha4544342005-08-24 13:59:35 -07001896 cifs_stats_bytes_read(pTcon, total_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 *poffset += bytes_read;
1898 }
1899 }
1900 FreeXid(xid);
1901 return total_read;
1902}
1903
Jeff Laytonca83ce32011-04-12 09:13:44 -04001904/*
1905 * If the page is mmap'ed into a process' page tables, then we need to make
1906 * sure that it doesn't change while being written back.
1907 */
1908static int
1909cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1910{
1911 struct page *page = vmf->page;
1912
1913 lock_page(page);
1914 return VM_FAULT_LOCKED;
1915}
1916
1917static struct vm_operations_struct cifs_file_vm_ops = {
1918 .fault = filemap_fault,
1919 .page_mkwrite = cifs_page_mkwrite,
1920};
1921
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03001922int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
1923{
1924 int rc, xid;
1925 struct inode *inode = file->f_path.dentry->d_inode;
1926
1927 xid = GetXid();
1928
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001929 if (!CIFS_I(inode)->clientCanCacheRead) {
1930 rc = cifs_invalidate_mapping(inode);
1931 if (rc)
1932 return rc;
1933 }
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03001934
1935 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04001936 if (rc == 0)
1937 vma->vm_ops = &cifs_file_vm_ops;
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03001938 FreeXid(xid);
1939 return rc;
1940}
1941
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1943{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 int rc, xid;
1945
1946 xid = GetXid();
Jeff Laytonabab0952010-02-12 07:44:18 -05001947 rc = cifs_revalidate_file(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001949 cFYI(1, "Validation prior to mmap failed, error=%d", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 FreeXid(xid);
1951 return rc;
1952 }
1953 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04001954 if (rc == 0)
1955 vma->vm_ops = &cifs_file_vm_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 FreeXid(xid);
1957 return rc;
1958}
1959
1960
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001961static void cifs_copy_cache_pages(struct address_space *mapping,
Nick Piggin315e9952010-04-21 03:18:28 +00001962 struct list_head *pages, int bytes_read, char *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963{
1964 struct page *page;
1965 char *target;
1966
1967 while (bytes_read > 0) {
1968 if (list_empty(pages))
1969 break;
1970
1971 page = list_entry(pages->prev, struct page, lru);
1972 list_del(&page->lru);
1973
Nick Piggin315e9952010-04-21 03:18:28 +00001974 if (add_to_page_cache_lru(page, mapping, page->index,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 GFP_KERNEL)) {
1976 page_cache_release(page);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001977 cFYI(1, "Add page cache failed");
Steve French3079ca62005-06-09 14:44:07 -07001978 data += PAGE_CACHE_SIZE;
1979 bytes_read -= PAGE_CACHE_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 continue;
1981 }
Jeff Layton06b43672010-06-01 10:54:45 -04001982 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001984 target = kmap_atomic(page, KM_USER0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985
1986 if (PAGE_CACHE_SIZE > bytes_read) {
1987 memcpy(target, data, bytes_read);
1988 /* zero the tail end of this partial page */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001989 memset(target + bytes_read, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 PAGE_CACHE_SIZE - bytes_read);
1991 bytes_read = 0;
1992 } else {
1993 memcpy(target, data, PAGE_CACHE_SIZE);
1994 bytes_read -= PAGE_CACHE_SIZE;
1995 }
1996 kunmap_atomic(target, KM_USER0);
1997
1998 flush_dcache_page(page);
1999 SetPageUptodate(page);
2000 unlock_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 data += PAGE_CACHE_SIZE;
Suresh Jayaraman9dc06552010-07-05 18:13:11 +05302002
2003 /* add page to FS-Cache */
2004 cifs_readpage_to_fscache(mapping->host, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 }
2006 return;
2007}
2008
2009static int cifs_readpages(struct file *file, struct address_space *mapping,
2010 struct list_head *page_list, unsigned num_pages)
2011{
2012 int rc = -EACCES;
2013 int xid;
2014 loff_t offset;
2015 struct page *page;
2016 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00002017 struct cifs_tcon *pTcon;
Steve French2c2130e2007-10-12 19:10:28 +00002018 unsigned int bytes_read = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002019 unsigned int read_size, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 char *smb_read_data = NULL;
2021 struct smb_com_read_rsp *pSMBr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 struct cifsFileInfo *open_file;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002023 struct cifs_io_parms io_parms;
Steve Frenchec637e32005-12-12 20:53:18 -08002024 int buf_type = CIFS_NO_BUFFER;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002025 __u32 pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026
2027 xid = GetXid();
2028 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302029 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302031 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 }
Joe Perchesc21dfb62010-07-12 13:50:14 -07002033 open_file = file->private_data;
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002034 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Jeff Layton13cfb732010-09-29 19:51:11 -04002035 pTcon = tlink_tcon(open_file->tlink);
Steve Frenchbfa0d752005-08-31 21:50:37 -07002036
Suresh Jayaraman56698232010-07-05 18:13:25 +05302037 /*
2038 * Reads as many pages as possible from fscache. Returns -ENOBUFS
2039 * immediately if the cookie is negative
2040 */
2041 rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
2042 &num_pages);
2043 if (rc == 0)
2044 goto read_complete;
2045
Steve Frenchf19159d2010-04-21 04:12:10 +00002046 cFYI(DBG2, "rpages: num pages %d", num_pages);
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002047 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2048 pid = open_file->pid;
2049 else
2050 pid = current->tgid;
2051
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 for (i = 0; i < num_pages; ) {
2053 unsigned contig_pages;
2054 struct page *tmp_page;
2055 unsigned long expected_index;
2056
2057 if (list_empty(page_list))
2058 break;
2059
2060 page = list_entry(page_list->prev, struct page, lru);
2061 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
2062
2063 /* count adjacent pages that we will read into */
2064 contig_pages = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002065 expected_index =
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 list_entry(page_list->prev, struct page, lru)->index;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002067 list_for_each_entry_reverse(tmp_page, page_list, lru) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 if (tmp_page->index == expected_index) {
2069 contig_pages++;
2070 expected_index++;
2071 } else
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002072 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 }
2074 if (contig_pages + i > num_pages)
2075 contig_pages = num_pages - i;
2076
2077 /* for reads over a certain size could initiate async
2078 read ahead */
2079
2080 read_size = contig_pages * PAGE_CACHE_SIZE;
2081 /* Read size needs to be in multiples of one page */
2082 read_size = min_t(const unsigned int, read_size,
2083 cifs_sb->rsize & PAGE_CACHE_MASK);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002084 cFYI(DBG2, "rpages: read size 0x%x contiguous pages %d",
2085 read_size, contig_pages);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 rc = -EAGAIN;
2087 while (rc == -EAGAIN) {
Steve Frenchcdff08e2010-10-21 22:46:14 +00002088 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04002089 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 if (rc != 0)
2091 break;
2092 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002093 io_parms.netfid = open_file->netfid;
2094 io_parms.pid = pid;
2095 io_parms.tcon = pTcon;
2096 io_parms.offset = offset;
2097 io_parms.length = read_size;
2098 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
2099 &smb_read_data, &buf_type);
Steve Frencha9d02ad2005-08-24 23:06:05 -07002100 /* BB more RC checks ? */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002101 if (rc == -EAGAIN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 if (smb_read_data) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002103 if (buf_type == CIFS_SMALL_BUFFER)
Steve Frenchec637e32005-12-12 20:53:18 -08002104 cifs_small_buf_release(smb_read_data);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002105 else if (buf_type == CIFS_LARGE_BUFFER)
Steve Frenchec637e32005-12-12 20:53:18 -08002106 cifs_buf_release(smb_read_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 smb_read_data = NULL;
2108 }
2109 }
2110 }
2111 if ((rc < 0) || (smb_read_data == NULL)) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002112 cFYI(1, "Read error in readpages: %d", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 break;
2114 } else if (bytes_read > 0) {
Andrew Morton6f88cc22006-12-10 02:19:44 -08002115 task_io_account_read(bytes_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
2117 cifs_copy_cache_pages(mapping, page_list, bytes_read,
2118 smb_read_data + 4 /* RFC1001 hdr */ +
Nick Piggin315e9952010-04-21 03:18:28 +00002119 le16_to_cpu(pSMBr->DataOffset));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120
2121 i += bytes_read >> PAGE_CACHE_SHIFT;
Steve Frencha4544342005-08-24 13:59:35 -07002122 cifs_stats_bytes_read(pTcon, bytes_read);
Steve French2c2130e2007-10-12 19:10:28 +00002123 if ((bytes_read & PAGE_CACHE_MASK) != bytes_read) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 i++; /* account for partial page */
2125
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002126 /* server copy of file can have smaller size
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 than client */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002128 /* BB do we need to verify this common case ?
2129 this case is ok - if we are at server EOF
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130 we will hit it on next read */
2131
OGAWA Hirofumi05ac9d42006-11-02 22:07:08 -08002132 /* break; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 }
2134 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002135 cFYI(1, "No bytes read (%d) at offset %lld . "
Steve Frenchf19159d2010-04-21 04:12:10 +00002136 "Cleaning remaining pages from readahead list",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002137 bytes_read, offset);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002138 /* BB turn off caching and do new lookup on
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 file size at server? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 break;
2141 }
2142 if (smb_read_data) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002143 if (buf_type == CIFS_SMALL_BUFFER)
Steve Frenchec637e32005-12-12 20:53:18 -08002144 cifs_small_buf_release(smb_read_data);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002145 else if (buf_type == CIFS_LARGE_BUFFER)
Steve Frenchec637e32005-12-12 20:53:18 -08002146 cifs_buf_release(smb_read_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 smb_read_data = NULL;
2148 }
2149 bytes_read = 0;
2150 }
2151
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152/* need to free smb_read_data buf before exit */
2153 if (smb_read_data) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002154 if (buf_type == CIFS_SMALL_BUFFER)
Steve French47c886b2006-01-18 14:20:39 -08002155 cifs_small_buf_release(smb_read_data);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002156 else if (buf_type == CIFS_LARGE_BUFFER)
Steve French47c886b2006-01-18 14:20:39 -08002157 cifs_buf_release(smb_read_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 smb_read_data = NULL;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160
Suresh Jayaraman56698232010-07-05 18:13:25 +05302161read_complete:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 FreeXid(xid);
2163 return rc;
2164}
2165
2166static int cifs_readpage_worker(struct file *file, struct page *page,
2167 loff_t *poffset)
2168{
2169 char *read_data;
2170 int rc;
2171
Suresh Jayaraman56698232010-07-05 18:13:25 +05302172 /* Is the page cached? */
2173 rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page);
2174 if (rc == 0)
2175 goto read_complete;
2176
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 page_cache_get(page);
2178 read_data = kmap(page);
2179 /* for reads over a certain size could initiate async read ahead */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002180
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002182
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 if (rc < 0)
2184 goto io_error;
2185 else
Joe Perchesb6b38f72010-04-21 03:50:45 +00002186 cFYI(1, "Bytes read %d", rc);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002187
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002188 file->f_path.dentry->d_inode->i_atime =
2189 current_fs_time(file->f_path.dentry->d_inode->i_sb);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002190
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 if (PAGE_CACHE_SIZE > rc)
2192 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
2193
2194 flush_dcache_page(page);
2195 SetPageUptodate(page);
Suresh Jayaraman9dc06552010-07-05 18:13:11 +05302196
2197 /* send this page to the cache */
2198 cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page);
2199
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 rc = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002201
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202io_error:
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002203 kunmap(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 page_cache_release(page);
Suresh Jayaraman56698232010-07-05 18:13:25 +05302205
2206read_complete:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 return rc;
2208}
2209
2210static int cifs_readpage(struct file *file, struct page *page)
2211{
2212 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
2213 int rc = -EACCES;
2214 int xid;
2215
2216 xid = GetXid();
2217
2218 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302219 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302221 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 }
2223
Joe Perchesb6b38f72010-04-21 03:50:45 +00002224 cFYI(1, "readpage %p at offset %d 0x%x\n",
2225 page, (int)offset, (int)offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226
2227 rc = cifs_readpage_worker(file, page, &offset);
2228
2229 unlock_page(page);
2230
2231 FreeXid(xid);
2232 return rc;
2233}
2234
Steve Frencha403a0a2007-07-26 15:54:16 +00002235static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
2236{
2237 struct cifsFileInfo *open_file;
2238
Jeff Layton44772882010-10-15 15:34:03 -04002239 spin_lock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002240 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton2e396b82010-10-15 15:34:01 -04002241 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Jeff Layton44772882010-10-15 15:34:03 -04002242 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002243 return 1;
2244 }
2245 }
Jeff Layton44772882010-10-15 15:34:03 -04002246 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002247 return 0;
2248}
2249
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250/* We do not want to update the file size from server for inodes
2251 open for write - to avoid races with writepage extending
2252 the file - in the future we could consider allowing
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002253 refreshing the inode only on increases in the file size
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 but this is tricky to do without racing with writebehind
2255 page caching in the current Linux kernel design */
Steve French4b18f2a2008-04-29 00:06:05 +00002256bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257{
Steve Frencha403a0a2007-07-26 15:54:16 +00002258 if (!cifsInode)
Steve French4b18f2a2008-04-29 00:06:05 +00002259 return true;
Steve French23e7dd72005-10-20 13:44:56 -07002260
Steve Frencha403a0a2007-07-26 15:54:16 +00002261 if (is_inode_writable(cifsInode)) {
2262 /* This inode is open for write at least once */
Steve Frenchc32a0b62006-01-12 14:41:28 -08002263 struct cifs_sb_info *cifs_sb;
2264
Steve Frenchc32a0b62006-01-12 14:41:28 -08002265 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
Steve Frenchad7a2922008-02-07 23:25:02 +00002266 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002267 /* since no page cache to corrupt on directio
Steve Frenchc32a0b62006-01-12 14:41:28 -08002268 we can change size safely */
Steve French4b18f2a2008-04-29 00:06:05 +00002269 return true;
Steve Frenchc32a0b62006-01-12 14:41:28 -08002270 }
2271
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002272 if (i_size_read(&cifsInode->vfs_inode) < end_of_file)
Steve French4b18f2a2008-04-29 00:06:05 +00002273 return true;
Steve French7ba52632007-02-08 18:14:13 +00002274
Steve French4b18f2a2008-04-29 00:06:05 +00002275 return false;
Steve French23e7dd72005-10-20 13:44:56 -07002276 } else
Steve French4b18f2a2008-04-29 00:06:05 +00002277 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278}
2279
Nick Piggind9414772008-09-24 11:32:59 -04002280static int cifs_write_begin(struct file *file, struct address_space *mapping,
2281 loff_t pos, unsigned len, unsigned flags,
2282 struct page **pagep, void **fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283{
Nick Piggind9414772008-09-24 11:32:59 -04002284 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
2285 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002286 loff_t page_start = pos & PAGE_MASK;
2287 loff_t i_size;
2288 struct page *page;
2289 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290
Joe Perchesb6b38f72010-04-21 03:50:45 +00002291 cFYI(1, "write_begin from %lld len %d", (long long)pos, len);
Nick Piggind9414772008-09-24 11:32:59 -04002292
Nick Piggin54566b22009-01-04 12:00:53 -08002293 page = grab_cache_page_write_begin(mapping, index, flags);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002294 if (!page) {
2295 rc = -ENOMEM;
2296 goto out;
2297 }
Nick Piggind9414772008-09-24 11:32:59 -04002298
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002299 if (PageUptodate(page))
2300 goto out;
Steve French8a236262007-03-06 00:31:00 +00002301
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002302 /*
2303 * If we write a full page it will be up to date, no need to read from
2304 * the server. If the write is short, we'll end up doing a sync write
2305 * instead.
2306 */
2307 if (len == PAGE_CACHE_SIZE)
2308 goto out;
2309
2310 /*
2311 * optimize away the read when we have an oplock, and we're not
2312 * expecting to use any of the data we'd be reading in. That
2313 * is, when the page lies beyond the EOF, or straddles the EOF
2314 * and the write will cover all of the existing data.
2315 */
2316 if (CIFS_I(mapping->host)->clientCanCacheRead) {
2317 i_size = i_size_read(mapping->host);
2318 if (page_start >= i_size ||
2319 (offset == 0 && (pos + len) >= i_size)) {
2320 zero_user_segments(page, 0, offset,
2321 offset + len,
2322 PAGE_CACHE_SIZE);
2323 /*
2324 * PageChecked means that the parts of the page
2325 * to which we're not writing are considered up
2326 * to date. Once the data is copied to the
2327 * page, it can be set uptodate.
2328 */
2329 SetPageChecked(page);
2330 goto out;
2331 }
2332 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333
Nick Piggind9414772008-09-24 11:32:59 -04002334 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002335 /*
2336 * might as well read a page, it is fast enough. If we get
2337 * an error, we don't need to return it. cifs_write_end will
2338 * do a sync write instead since PG_uptodate isn't set.
2339 */
2340 cifs_readpage_worker(file, page, &page_start);
Steve French8a236262007-03-06 00:31:00 +00002341 } else {
2342 /* we could try using another file handle if there is one -
2343 but how would we lock it to prevent close of that handle
2344 racing with this read? In any case
Nick Piggind9414772008-09-24 11:32:59 -04002345 this will be written out by write_end so is fine */
Steve French8a236262007-03-06 00:31:00 +00002346 }
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002347out:
2348 *pagep = page;
2349 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350}
2351
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302352static int cifs_release_page(struct page *page, gfp_t gfp)
2353{
2354 if (PagePrivate(page))
2355 return 0;
2356
2357 return cifs_fscache_release_page(page, gfp);
2358}
2359
2360static void cifs_invalidate_page(struct page *page, unsigned long offset)
2361{
2362 struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
2363
2364 if (offset == 0)
2365 cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
2366}
2367
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002368static int cifs_launder_page(struct page *page)
2369{
2370 int rc = 0;
2371 loff_t range_start = page_offset(page);
2372 loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
2373 struct writeback_control wbc = {
2374 .sync_mode = WB_SYNC_ALL,
2375 .nr_to_write = 0,
2376 .range_start = range_start,
2377 .range_end = range_end,
2378 };
2379
2380 cFYI(1, "Launder page: %p", page);
2381
2382 if (clear_page_dirty_for_io(page))
2383 rc = cifs_writepage_locked(page, &wbc);
2384
2385 cifs_fscache_invalidate_page(page, page->mapping->host);
2386 return rc;
2387}
2388
Tejun Heo9b646972010-07-20 22:09:02 +02002389void cifs_oplock_break(struct work_struct *work)
Jeff Layton3bc303c2009-09-21 06:47:50 -04002390{
2391 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
2392 oplock_break);
Jeff Laytona5e18bc2010-10-11 15:07:18 -04002393 struct inode *inode = cfile->dentry->d_inode;
Jeff Layton3bc303c2009-09-21 06:47:50 -04002394 struct cifsInodeInfo *cinode = CIFS_I(inode);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002395 int rc = 0;
Jeff Layton3bc303c2009-09-21 06:47:50 -04002396
2397 if (inode && S_ISREG(inode->i_mode)) {
Steve Frenchd54ff732010-04-27 04:38:15 +00002398 if (cinode->clientCanCacheRead)
Al Viro8737c932009-12-24 06:47:55 -05002399 break_lease(inode, O_RDONLY);
Steve Frenchd54ff732010-04-27 04:38:15 +00002400 else
Al Viro8737c932009-12-24 06:47:55 -05002401 break_lease(inode, O_WRONLY);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002402 rc = filemap_fdatawrite(inode->i_mapping);
2403 if (cinode->clientCanCacheRead == 0) {
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002404 rc = filemap_fdatawait(inode->i_mapping);
2405 mapping_set_error(inode->i_mapping, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002406 invalidate_remote_inode(inode);
2407 }
Joe Perchesb6b38f72010-04-21 03:50:45 +00002408 cFYI(1, "Oplock flush inode %p rc %d", inode, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002409 }
2410
2411 /*
2412 * releasing stale oplock after recent reconnect of smb session using
2413 * a now incorrect file handle is not a data integrity issue but do
2414 * not bother sending an oplock release if session to server still is
2415 * disconnected since oplock already released by the server
2416 */
Steve Frenchcdff08e2010-10-21 22:46:14 +00002417 if (!cfile->oplock_break_cancelled) {
Jeff Layton13cfb732010-09-29 19:51:11 -04002418 rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0,
Pavel Shilovsky12fed002011-01-17 20:15:44 +03002419 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false,
2420 cinode->clientCanCacheRead ? 1 : 0);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002421 cFYI(1, "Oplock release rc = %d", rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002422 }
Jeff Layton3bc303c2009-09-21 06:47:50 -04002423}
2424
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07002425const struct address_space_operations cifs_addr_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 .readpage = cifs_readpage,
2427 .readpages = cifs_readpages,
2428 .writepage = cifs_writepage,
Steve French37c0eb42005-10-05 14:50:29 -07002429 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04002430 .write_begin = cifs_write_begin,
2431 .write_end = cifs_write_end,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302433 .releasepage = cifs_release_page,
2434 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002435 .launder_page = cifs_launder_page,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436};
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002437
2438/*
2439 * cifs_readpages requires the server to support a buffer large enough to
2440 * contain the header plus one complete page of data. Otherwise, we need
2441 * to leave cifs_readpages out of the address space operations.
2442 */
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07002443const struct address_space_operations cifs_addr_ops_smallbuf = {
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002444 .readpage = cifs_readpage,
2445 .writepage = cifs_writepage,
2446 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04002447 .write_begin = cifs_write_begin,
2448 .write_end = cifs_write_end,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002449 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302450 .releasepage = cifs_release_page,
2451 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002452 .launder_page = cifs_launder_page,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002453};