blob: 237192ae7587b444dfcc1c659bc981baa062f74f [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;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500177 int create_options = CREATE_NOT_DIR;
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300178 FILE_ALL_INFO *buf;
179
180 desiredAccess = cifs_convert_flags(f_flags);
181
182/*********************************************************************
183 * open flag mapping table:
184 *
185 * POSIX Flag CIFS Disposition
186 * ---------- ----------------
187 * O_CREAT FILE_OPEN_IF
188 * O_CREAT | O_EXCL FILE_CREATE
189 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
190 * O_TRUNC FILE_OVERWRITE
191 * none of the above FILE_OPEN
192 *
193 * Note that there is not a direct match between disposition
194 * FILE_SUPERSEDE (ie create whether or not file exists although
195 * O_CREAT | O_TRUNC is similar but truncates the existing
196 * file rather than creating a new file as FILE_SUPERSEDE does
197 * (which uses the attributes / metadata passed in on open call)
198 *?
199 *? O_SYNC is a reasonable match to CIFS writethrough flag
200 *? and the read write flags match reasonably. O_LARGEFILE
201 *? is irrelevant because largefile support is always used
202 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
203 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
204 *********************************************************************/
205
206 disposition = cifs_get_disposition(f_flags);
207
208 /* BB pass O_SYNC flag through on file attributes .. BB */
209
210 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
211 if (!buf)
212 return -ENOMEM;
213
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500214 if (backup_cred(cifs_sb))
215 create_options |= CREATE_OPEN_BACKUP_INTENT;
216
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300217 if (tcon->ses->capabilities & CAP_NT_SMBS)
218 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500219 desiredAccess, create_options, pnetfid, poplock, buf,
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300220 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
221 & CIFS_MOUNT_MAP_SPECIAL_CHR);
222 else
223 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
224 desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf,
225 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
226 & CIFS_MOUNT_MAP_SPECIAL_CHR);
227
228 if (rc)
229 goto out;
230
231 if (tcon->unix_ext)
232 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
233 xid);
234 else
235 rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
236 xid, pnetfid);
237
238out:
239 kfree(buf);
240 return rc;
241}
242
Jeff Layton15ecb432010-10-15 15:34:02 -0400243struct cifsFileInfo *
244cifs_new_fileinfo(__u16 fileHandle, struct file *file,
245 struct tcon_link *tlink, __u32 oplock)
246{
247 struct dentry *dentry = file->f_path.dentry;
248 struct inode *inode = dentry->d_inode;
249 struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
250 struct cifsFileInfo *pCifsFile;
251
252 pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
253 if (pCifsFile == NULL)
254 return pCifsFile;
255
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400256 pCifsFile->count = 1;
Jeff Layton15ecb432010-10-15 15:34:02 -0400257 pCifsFile->netfid = fileHandle;
258 pCifsFile->pid = current->tgid;
259 pCifsFile->uid = current_fsuid();
260 pCifsFile->dentry = dget(dentry);
261 pCifsFile->f_flags = file->f_flags;
262 pCifsFile->invalidHandle = false;
Jeff Layton15ecb432010-10-15 15:34:02 -0400263 pCifsFile->tlink = cifs_get_tlink(tlink);
264 mutex_init(&pCifsFile->fh_mutex);
265 mutex_init(&pCifsFile->lock_mutex);
266 INIT_LIST_HEAD(&pCifsFile->llist);
Jeff Layton15ecb432010-10-15 15:34:02 -0400267 INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
268
Jeff Layton44772882010-10-15 15:34:03 -0400269 spin_lock(&cifs_file_list_lock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400270 list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList));
271 /* if readable file instance put first in list*/
272 if (file->f_mode & FMODE_READ)
273 list_add(&pCifsFile->flist, &pCifsInode->openFileList);
274 else
275 list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList);
Jeff Layton44772882010-10-15 15:34:03 -0400276 spin_unlock(&cifs_file_list_lock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400277
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300278 cifs_set_oplock_level(pCifsInode, oplock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400279
280 file->private_data = pCifsFile;
281 return pCifsFile;
282}
283
Steve Frenchcdff08e2010-10-21 22:46:14 +0000284/*
285 * Release a reference on the file private data. This may involve closing
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400286 * the filehandle out on the server. Must be called without holding
287 * cifs_file_list_lock.
Steve Frenchcdff08e2010-10-21 22:46:14 +0000288 */
Jeff Laytonb33879a2010-10-15 15:34:04 -0400289void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
290{
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300291 struct inode *inode = cifs_file->dentry->d_inode;
Steve French96daf2b2011-05-27 04:34:02 +0000292 struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300293 struct cifsInodeInfo *cifsi = CIFS_I(inode);
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300294 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000295 struct cifsLockInfo *li, *tmp;
296
297 spin_lock(&cifs_file_list_lock);
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400298 if (--cifs_file->count > 0) {
Steve Frenchcdff08e2010-10-21 22:46:14 +0000299 spin_unlock(&cifs_file_list_lock);
300 return;
Jeff Laytonb33879a2010-10-15 15:34:04 -0400301 }
Steve Frenchcdff08e2010-10-21 22:46:14 +0000302
303 /* remove it from the lists */
304 list_del(&cifs_file->flist);
305 list_del(&cifs_file->tlist);
306
307 if (list_empty(&cifsi->openFileList)) {
308 cFYI(1, "closing last open instance for inode %p",
309 cifs_file->dentry->d_inode);
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300310
311 /* in strict cache mode we need invalidate mapping on the last
312 close because it may cause a error when we open this file
313 again and get at least level II oplock */
314 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
315 CIFS_I(inode)->invalid_mapping = true;
316
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300317 cifs_set_oplock_level(cifsi, 0);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000318 }
319 spin_unlock(&cifs_file_list_lock);
320
Jeff Laytonad635942011-07-26 12:20:17 -0400321 cancel_work_sync(&cifs_file->oplock_break);
322
Steve Frenchcdff08e2010-10-21 22:46:14 +0000323 if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
324 int xid, rc;
325
326 xid = GetXid();
327 rc = CIFSSMBClose(xid, tcon, cifs_file->netfid);
328 FreeXid(xid);
329 }
330
331 /* Delete any outstanding lock records. We'll lose them when the file
332 * is closed anyway.
333 */
334 mutex_lock(&cifs_file->lock_mutex);
335 list_for_each_entry_safe(li, tmp, &cifs_file->llist, llist) {
336 list_del(&li->llist);
337 kfree(li);
338 }
339 mutex_unlock(&cifs_file->lock_mutex);
340
341 cifs_put_tlink(cifs_file->tlink);
342 dput(cifs_file->dentry);
343 kfree(cifs_file);
Jeff Laytonb33879a2010-10-15 15:34:04 -0400344}
345
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346int cifs_open(struct inode *inode, struct file *file)
347{
348 int rc = -EACCES;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400349 int xid;
350 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000352 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400353 struct tcon_link *tlink;
Jeff Layton6ca9f3b2010-06-16 13:40:16 -0400354 struct cifsFileInfo *pCifsFile = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 char *full_path = NULL;
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300356 bool posix_open_ok = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 __u16 netfid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358
359 xid = GetXid();
360
361 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400362 tlink = cifs_sb_tlink(cifs_sb);
363 if (IS_ERR(tlink)) {
364 FreeXid(xid);
365 return PTR_ERR(tlink);
366 }
367 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -0800369 full_path = build_path_from_dentry(file->f_path.dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530371 rc = -ENOMEM;
Jeff Layton232341b2010-08-05 13:58:38 -0400372 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 }
374
Joe Perchesb6b38f72010-04-21 03:50:45 +0000375 cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
376 inode, file->f_flags, full_path);
Steve French276a74a2009-03-03 18:00:34 +0000377
Steve Frenche7504732011-10-12 17:47:03 -0500378 if (enable_oplocks)
Steve French276a74a2009-03-03 18:00:34 +0000379 oplock = REQ_OPLOCK;
380 else
381 oplock = 0;
382
Steve French64cc2c62009-03-04 19:54:08 +0000383 if (!tcon->broken_posix_open && tcon->unix_ext &&
384 (tcon->ses->capabilities & CAP_UNIX) &&
Steve French276a74a2009-03-03 18:00:34 +0000385 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
386 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Steve French276a74a2009-03-03 18:00:34 +0000387 /* can not refresh inode info since size could be stale */
Jeff Layton2422f672010-06-16 13:40:16 -0400388 rc = cifs_posix_open(full_path, &inode, inode->i_sb,
Steve Frenchfa588e02010-04-22 19:21:55 +0000389 cifs_sb->mnt_file_mode /* ignored */,
Jeff Layton608712f2010-10-15 15:33:56 -0400390 file->f_flags, &oplock, &netfid, xid);
Steve French276a74a2009-03-03 18:00:34 +0000391 if (rc == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000392 cFYI(1, "posix open succeeded");
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300393 posix_open_ok = true;
Steve French64cc2c62009-03-04 19:54:08 +0000394 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
395 if (tcon->ses->serverNOS)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000396 cERROR(1, "server %s of type %s returned"
Steve French64cc2c62009-03-04 19:54:08 +0000397 " unexpected error on SMB posix open"
398 ", disabling posix open support."
399 " Check if server update available.",
400 tcon->ses->serverName,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000401 tcon->ses->serverNOS);
Steve French64cc2c62009-03-04 19:54:08 +0000402 tcon->broken_posix_open = true;
Steve French276a74a2009-03-03 18:00:34 +0000403 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
404 (rc != -EOPNOTSUPP)) /* path not found or net err */
405 goto out;
Steve French64cc2c62009-03-04 19:54:08 +0000406 /* else fallthrough to retry open the old way on network i/o
407 or DFS errors */
Steve French276a74a2009-03-03 18:00:34 +0000408 }
409
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300410 if (!posix_open_ok) {
411 rc = cifs_nt_open(full_path, inode, cifs_sb, tcon,
412 file->f_flags, &oplock, &netfid, xid);
413 if (rc)
414 goto out;
415 }
Jeff Layton47c78b72010-06-16 13:40:17 -0400416
Jeff Laytonabfe1ee2010-10-15 15:33:58 -0400417 pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock);
Jeff Layton6ca9f3b2010-06-16 13:40:16 -0400418 if (pCifsFile == NULL) {
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300419 CIFSSMBClose(xid, tcon, netfid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 rc = -ENOMEM;
421 goto out;
422 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530424 cifs_fscache_set_inode_cookie(inode, file);
425
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300426 if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 /* time to set mode which we can not set earlier due to
428 problems creating new read-only files */
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300429 struct cifs_unix_set_info_args args = {
430 .mode = inode->i_mode,
431 .uid = NO_CHANGE_64,
432 .gid = NO_CHANGE_64,
433 .ctime = NO_CHANGE_64,
434 .atime = NO_CHANGE_64,
435 .mtime = NO_CHANGE_64,
436 .device = 0,
437 };
Jeff Laytond44a9fe2011-01-07 11:30:29 -0500438 CIFSSMBUnixSetFileInfo(xid, tcon, &args, netfid,
439 pCifsFile->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 }
441
442out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 kfree(full_path);
444 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400445 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 return rc;
447}
448
Adrian Bunk04187262006-06-30 18:23:04 +0200449/* Try to reacquire byte range locks that were released when session */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450/* to server was lost */
451static int cifs_relock_file(struct cifsFileInfo *cifsFile)
452{
453 int rc = 0;
454
455/* BB list all locks open on this file and relock */
456
457 return rc;
458}
459
Jeff Layton15886172010-10-15 15:33:59 -0400460static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461{
462 int rc = -EACCES;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400463 int xid;
464 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000466 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 struct cifsInodeInfo *pCifsInode;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000468 struct inode *inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 char *full_path = NULL;
470 int desiredAccess;
471 int disposition = FILE_OPEN;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500472 int create_options = CREATE_NOT_DIR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 __u16 netfid;
474
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 xid = GetXid();
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400476 mutex_lock(&pCifsFile->fh_mutex);
Steve French4b18f2a2008-04-29 00:06:05 +0000477 if (!pCifsFile->invalidHandle) {
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400478 mutex_unlock(&pCifsFile->fh_mutex);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530479 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530481 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 }
483
Jeff Layton15886172010-10-15 15:33:59 -0400484 inode = pCifsFile->dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton13cfb732010-09-29 19:51:11 -0400486 tcon = tlink_tcon(pCifsFile->tlink);
Steve French3a9f4622007-04-04 17:10:24 +0000487
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488/* can not grab rename sem here because various ops, including
489 those that already have the rename sem can end up causing writepage
490 to get called and if the server was down that means we end up here,
491 and we can never tell if the caller already has the rename_sem */
Jeff Layton15886172010-10-15 15:33:59 -0400492 full_path = build_path_from_dentry(pCifsFile->dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 if (full_path == NULL) {
Steve French3a9f4622007-04-04 17:10:24 +0000494 rc = -ENOMEM;
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400495 mutex_unlock(&pCifsFile->fh_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 FreeXid(xid);
Steve French3a9f4622007-04-04 17:10:24 +0000497 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 }
499
Joe Perchesb6b38f72010-04-21 03:50:45 +0000500 cFYI(1, "inode = 0x%p file flags 0x%x for %s",
Jeff Layton15886172010-10-15 15:33:59 -0400501 inode, pCifsFile->f_flags, full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
Steve Frenche7504732011-10-12 17:47:03 -0500503 if (enable_oplocks)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 oplock = REQ_OPLOCK;
505 else
Steve French4b18f2a2008-04-29 00:06:05 +0000506 oplock = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
Steve French7fc8f4e2009-02-23 20:43:11 +0000508 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
509 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
510 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton608712f2010-10-15 15:33:56 -0400511
512 /*
513 * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
514 * original open. Must mask them off for a reopen.
515 */
Jeff Layton15886172010-10-15 15:33:59 -0400516 unsigned int oflags = pCifsFile->f_flags &
517 ~(O_CREAT | O_EXCL | O_TRUNC);
Jeff Layton608712f2010-10-15 15:33:56 -0400518
Jeff Layton2422f672010-06-16 13:40:16 -0400519 rc = cifs_posix_open(full_path, NULL, inode->i_sb,
Steve Frenchfa588e02010-04-22 19:21:55 +0000520 cifs_sb->mnt_file_mode /* ignored */,
521 oflags, &oplock, &netfid, xid);
Steve French7fc8f4e2009-02-23 20:43:11 +0000522 if (rc == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000523 cFYI(1, "posix reopen succeeded");
Steve French7fc8f4e2009-02-23 20:43:11 +0000524 goto reopen_success;
525 }
526 /* fallthrough to retry open the old way on errors, especially
527 in the reconnect path it is important to retry hard */
528 }
529
Jeff Layton15886172010-10-15 15:33:59 -0400530 desiredAccess = cifs_convert_flags(pCifsFile->f_flags);
Steve French7fc8f4e2009-02-23 20:43:11 +0000531
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500532 if (backup_cred(cifs_sb))
533 create_options |= CREATE_OPEN_BACKUP_INTENT;
534
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 /* Can not refresh inode by passing in file_info buf to be returned
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000536 by SMBOpen and then calling get_inode_info with returned buf
537 since file might have write behind data that needs to be flushed
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 and server version of file size can be stale. If we knew for sure
539 that inode was not dirty locally we could do this */
540
Steve French7fc8f4e2009-02-23 20:43:11 +0000541 rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess,
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500542 create_options, &netfid, &oplock, NULL,
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000543 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
Steve French737b7582005-04-28 22:41:06 -0700544 CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 if (rc) {
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400546 mutex_unlock(&pCifsFile->fh_mutex);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000547 cFYI(1, "cifs_open returned 0x%x", rc);
548 cFYI(1, "oplock: %d", oplock);
Jeff Layton15886172010-10-15 15:33:59 -0400549 goto reopen_error_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 }
Jeff Layton15886172010-10-15 15:33:59 -0400551
552reopen_success:
553 pCifsFile->netfid = netfid;
554 pCifsFile->invalidHandle = false;
555 mutex_unlock(&pCifsFile->fh_mutex);
556 pCifsInode = CIFS_I(inode);
557
558 if (can_flush) {
559 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -0400560 mapping_set_error(inode->i_mapping, rc);
Jeff Layton15886172010-10-15 15:33:59 -0400561
Jeff Layton15886172010-10-15 15:33:59 -0400562 if (tcon->unix_ext)
563 rc = cifs_get_inode_info_unix(&inode,
564 full_path, inode->i_sb, xid);
565 else
566 rc = cifs_get_inode_info(&inode,
567 full_path, NULL, inode->i_sb,
568 xid, NULL);
569 } /* else we are writing out data to server already
570 and could deadlock if we tried to flush data, and
571 since we do not know if we have data that would
572 invalidate the current end of file on the server
573 we can not go to the server to get the new inod
574 info */
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300575
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300576 cifs_set_oplock_level(pCifsInode, oplock);
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300577
Jeff Layton15886172010-10-15 15:33:59 -0400578 cifs_relock_file(pCifsFile);
579
580reopen_error_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 kfree(full_path);
582 FreeXid(xid);
583 return rc;
584}
585
586int cifs_close(struct inode *inode, struct file *file)
587{
Jeff Layton77970692011-04-05 16:23:47 -0700588 if (file->private_data != NULL) {
589 cifsFileInfo_put(file->private_data);
590 file->private_data = NULL;
591 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
Steve Frenchcdff08e2010-10-21 22:46:14 +0000593 /* return code from the ->release op is always ignored */
594 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595}
596
597int cifs_closedir(struct inode *inode, struct file *file)
598{
599 int rc = 0;
600 int xid;
Joe Perchesc21dfb62010-07-12 13:50:14 -0700601 struct cifsFileInfo *pCFileStruct = file->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 char *ptmp;
603
Joe Perchesb6b38f72010-04-21 03:50:45 +0000604 cFYI(1, "Closedir inode = 0x%p", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605
606 xid = GetXid();
607
608 if (pCFileStruct) {
Steve French96daf2b2011-05-27 04:34:02 +0000609 struct cifs_tcon *pTcon = tlink_tcon(pCFileStruct->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
Joe Perchesb6b38f72010-04-21 03:50:45 +0000611 cFYI(1, "Freeing private data in close dir");
Jeff Layton44772882010-10-15 15:34:03 -0400612 spin_lock(&cifs_file_list_lock);
Steve French4b18f2a2008-04-29 00:06:05 +0000613 if (!pCFileStruct->srch_inf.endOfSearch &&
614 !pCFileStruct->invalidHandle) {
615 pCFileStruct->invalidHandle = true;
Jeff Layton44772882010-10-15 15:34:03 -0400616 spin_unlock(&cifs_file_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000618 cFYI(1, "Closing uncompleted readdir with rc %d",
619 rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 /* not much we can do if it fails anyway, ignore rc */
621 rc = 0;
Steve Frenchddb4cbf2008-11-20 20:00:44 +0000622 } else
Jeff Layton44772882010-10-15 15:34:03 -0400623 spin_unlock(&cifs_file_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
625 if (ptmp) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000626 cFYI(1, "closedir free smb buf in srch struct");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000628 if (pCFileStruct->srch_inf.smallBuf)
Steve Frenchd47d7c12006-02-28 03:45:48 +0000629 cifs_small_buf_release(ptmp);
630 else
631 cifs_buf_release(ptmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 }
Jeff Layton13cfb732010-09-29 19:51:11 -0400633 cifs_put_tlink(pCFileStruct->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 kfree(file->private_data);
635 file->private_data = NULL;
636 }
637 /* BB can we lock the filestruct while this is going on? */
638 FreeXid(xid);
639 return rc;
640}
641
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000642static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
643 __u64 offset, __u8 lockType)
644{
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000645 struct cifsLockInfo *li =
646 kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000647 if (li == NULL)
648 return -ENOMEM;
649 li->offset = offset;
650 li->length = len;
651 li->type = lockType;
Roland Dreier796e5662007-05-03 04:33:45 +0000652 mutex_lock(&fid->lock_mutex);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000653 list_add(&li->llist, &fid->llist);
Roland Dreier796e5662007-05-03 04:33:45 +0000654 mutex_unlock(&fid->lock_mutex);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000655 return 0;
656}
657
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
659{
660 int rc, xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 __u32 numLock = 0;
662 __u32 numUnlock = 0;
663 __u64 length;
Steve French4b18f2a2008-04-29 00:06:05 +0000664 bool wait_flag = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000666 struct cifs_tcon *tcon;
Steve French08547b02006-02-28 22:39:25 +0000667 __u16 netfid;
668 __u8 lockType = LOCKING_ANDX_LARGE_FILES;
Steve French13a6e422008-12-02 17:24:33 +0000669 bool posix_locking = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670
671 length = 1 + pfLock->fl_end - pfLock->fl_start;
672 rc = -EACCES;
673 xid = GetXid();
674
Joe Perchesb6b38f72010-04-21 03:50:45 +0000675 cFYI(1, "Lock parm: 0x%x flockflags: "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 "0x%x flocktype: 0x%x start: %lld end: %lld",
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000677 cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000678 pfLock->fl_end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
680 if (pfLock->fl_flags & FL_POSIX)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000681 cFYI(1, "Posix");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 if (pfLock->fl_flags & FL_FLOCK)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000683 cFYI(1, "Flock");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 if (pfLock->fl_flags & FL_SLEEP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000685 cFYI(1, "Blocking lock");
Steve French4b18f2a2008-04-29 00:06:05 +0000686 wait_flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 }
688 if (pfLock->fl_flags & FL_ACCESS)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000689 cFYI(1, "Process suspended by mandatory locking - "
690 "not implemented yet");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 if (pfLock->fl_flags & FL_LEASE)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000692 cFYI(1, "Lease on file - not implemented yet");
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000693 if (pfLock->fl_flags &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
Joe Perchesb6b38f72010-04-21 03:50:45 +0000695 cFYI(1, "Unknown lock flags 0x%x", pfLock->fl_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
697 if (pfLock->fl_type == F_WRLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000698 cFYI(1, "F_WRLCK ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 numLock = 1;
700 } else if (pfLock->fl_type == F_UNLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000701 cFYI(1, "F_UNLCK");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 numUnlock = 1;
Steve Frenchd47d7c12006-02-28 03:45:48 +0000703 /* Check if unlock includes more than
704 one lock range */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 } else if (pfLock->fl_type == F_RDLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000706 cFYI(1, "F_RDLCK");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 lockType |= LOCKING_ANDX_SHARED_LOCK;
708 numLock = 1;
709 } else if (pfLock->fl_type == F_EXLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000710 cFYI(1, "F_EXLCK");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 numLock = 1;
712 } else if (pfLock->fl_type == F_SHLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000713 cFYI(1, "F_SHLCK");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 lockType |= LOCKING_ANDX_SHARED_LOCK;
715 numLock = 1;
716 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +0000717 cFYI(1, "Unknown type of lock");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -0800719 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Jeff Layton13cfb732010-09-29 19:51:11 -0400720 tcon = tlink_tcon(((struct cifsFileInfo *)file->private_data)->tlink);
Steve French08547b02006-02-28 22:39:25 +0000721 netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722
Steve French13a6e422008-12-02 17:24:33 +0000723 if ((tcon->ses->capabilities & CAP_UNIX) &&
724 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
Steve Frenchacc18aa2008-12-02 18:53:55 +0000725 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
Steve French13a6e422008-12-02 17:24:33 +0000726 posix_locking = 1;
Steve French08547b02006-02-28 22:39:25 +0000727 /* BB add code here to normalize offset and length to
728 account for negative length which we can not accept over the
729 wire */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 if (IS_GETLK(cmd)) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000731 if (posix_locking) {
Steve French08547b02006-02-28 22:39:25 +0000732 int posix_lock_type;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000733 if (lockType & LOCKING_ANDX_SHARED_LOCK)
Steve French08547b02006-02-28 22:39:25 +0000734 posix_lock_type = CIFS_RDLCK;
735 else
736 posix_lock_type = CIFS_WRLCK;
Steve French13a6e422008-12-02 17:24:33 +0000737 rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */,
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000738 length, pfLock, posix_lock_type,
739 wait_flag);
Steve French08547b02006-02-28 22:39:25 +0000740 FreeXid(xid);
741 return rc;
742 }
743
744 /* BB we could chain these into one lock request BB */
Steve French13a6e422008-12-02 17:24:33 +0000745 rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start,
Pavel Shilovsky12fed002011-01-17 20:15:44 +0300746 0, 1, lockType, 0 /* wait flag */, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 if (rc == 0) {
Steve French13a6e422008-12-02 17:24:33 +0000748 rc = CIFSSMBLock(xid, tcon, netfid, length,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 pfLock->fl_start, 1 /* numUnlock */ ,
750 0 /* numLock */ , lockType,
Pavel Shilovsky12fed002011-01-17 20:15:44 +0300751 0 /* wait flag */, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 pfLock->fl_type = F_UNLCK;
753 if (rc != 0)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000754 cERROR(1, "Error unlocking previously locked "
755 "range %d during test of lock", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 rc = 0;
757
758 } else {
759 /* if rc == ERR_SHARING_VIOLATION ? */
Pavel Shilovskyf05337c2010-04-05 09:59:14 +0400760 rc = 0;
761
762 if (lockType & LOCKING_ANDX_SHARED_LOCK) {
763 pfLock->fl_type = F_WRLCK;
764 } else {
765 rc = CIFSSMBLock(xid, tcon, netfid, length,
766 pfLock->fl_start, 0, 1,
767 lockType | LOCKING_ANDX_SHARED_LOCK,
Pavel Shilovsky12fed002011-01-17 20:15:44 +0300768 0 /* wait flag */, 0);
Pavel Shilovskyf05337c2010-04-05 09:59:14 +0400769 if (rc == 0) {
770 rc = CIFSSMBLock(xid, tcon, netfid,
771 length, pfLock->fl_start, 1, 0,
772 lockType |
773 LOCKING_ANDX_SHARED_LOCK,
Pavel Shilovsky12fed002011-01-17 20:15:44 +0300774 0 /* wait flag */, 0);
Pavel Shilovskyf05337c2010-04-05 09:59:14 +0400775 pfLock->fl_type = F_RDLCK;
776 if (rc != 0)
Steve Frenchf19159d2010-04-21 04:12:10 +0000777 cERROR(1, "Error unlocking "
Pavel Shilovskyf05337c2010-04-05 09:59:14 +0400778 "previously locked range %d "
Steve Frenchf19159d2010-04-21 04:12:10 +0000779 "during test of lock", rc);
Pavel Shilovskyf05337c2010-04-05 09:59:14 +0400780 rc = 0;
781 } else {
782 pfLock->fl_type = F_WRLCK;
783 rc = 0;
784 }
785 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 }
787
788 FreeXid(xid);
789 return rc;
790 }
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000791
792 if (!numLock && !numUnlock) {
793 /* if no lock or unlock then nothing
794 to do since we do not know what it is */
795 FreeXid(xid);
796 return -EOPNOTSUPP;
797 }
798
799 if (posix_locking) {
Steve French08547b02006-02-28 22:39:25 +0000800 int posix_lock_type;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000801 if (lockType & LOCKING_ANDX_SHARED_LOCK)
Steve French08547b02006-02-28 22:39:25 +0000802 posix_lock_type = CIFS_RDLCK;
803 else
804 posix_lock_type = CIFS_WRLCK;
Steve French50c2f752007-07-13 00:33:32 +0000805
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000806 if (numUnlock == 1)
Steve Frenchbeb84dc2006-03-03 23:36:34 +0000807 posix_lock_type = CIFS_UNLCK;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000808
Steve French13a6e422008-12-02 17:24:33 +0000809 rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */,
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000810 length, pfLock, posix_lock_type,
811 wait_flag);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000812 } else {
Joe Perchesc21dfb62010-07-12 13:50:14 -0700813 struct cifsFileInfo *fid = file->private_data;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000814
815 if (numLock) {
Steve French13a6e422008-12-02 17:24:33 +0000816 rc = CIFSSMBLock(xid, tcon, netfid, length,
Pavel Shilovsky12fed002011-01-17 20:15:44 +0300817 pfLock->fl_start, 0, numLock, lockType,
818 wait_flag, 0);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000819
820 if (rc == 0) {
821 /* For Windows locks we must store them. */
822 rc = store_file_lock(fid, length,
823 pfLock->fl_start, lockType);
824 }
825 } else if (numUnlock) {
826 /* For each stored lock that this unlock overlaps
827 completely, unlock it. */
828 int stored_rc = 0;
829 struct cifsLockInfo *li, *tmp;
830
Steve French6b70c952006-09-21 07:35:29 +0000831 rc = 0;
Roland Dreier796e5662007-05-03 04:33:45 +0000832 mutex_lock(&fid->lock_mutex);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000833 list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
834 if (pfLock->fl_start <= li->offset &&
Steve Frenchc19eb712007-08-24 03:22:48 +0000835 (pfLock->fl_start + length) >=
Jeff Layton39db8102007-08-24 03:16:51 +0000836 (li->offset + li->length)) {
Steve French13a6e422008-12-02 17:24:33 +0000837 stored_rc = CIFSSMBLock(xid, tcon,
Pavel Shilovsky12fed002011-01-17 20:15:44 +0300838 netfid, li->length,
839 li->offset, 1, 0,
840 li->type, false, 0);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000841 if (stored_rc)
842 rc = stored_rc;
Pavel Shilovsky2c964d12010-04-21 19:44:24 +0000843 else {
844 list_del(&li->llist);
845 kfree(li);
846 }
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000847 }
848 }
Roland Dreier796e5662007-05-03 04:33:45 +0000849 mutex_unlock(&fid->lock_mutex);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000850 }
851 }
852
Steve Frenchd634cc12005-08-26 14:42:59 -0500853 if (pfLock->fl_flags & FL_POSIX)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 posix_lock_file_wait(file, pfLock);
855 FreeXid(xid);
856 return rc;
857}
858
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400859/* update the file size (if needed) after a write */
Pavel Shilovsky72432ff2011-01-24 14:16:35 -0500860void
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400861cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
862 unsigned int bytes_written)
863{
864 loff_t end_of_write = offset + bytes_written;
865
866 if (end_of_write > cifsi->server_eof)
867 cifsi->server_eof = end_of_write;
868}
869
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +0400870static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
Jeff Layton7da4b492010-10-15 15:34:00 -0400871 const char *write_data, size_t write_size,
872 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873{
874 int rc = 0;
875 unsigned int bytes_written = 0;
876 unsigned int total_written;
877 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000878 struct cifs_tcon *pTcon;
Jeff Layton77499812011-01-11 07:24:23 -0500879 int xid;
Jeff Layton7da4b492010-10-15 15:34:00 -0400880 struct dentry *dentry = open_file->dentry;
881 struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +0400882 struct cifs_io_parms io_parms;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
Jeff Layton7da4b492010-10-15 15:34:00 -0400884 cifs_sb = CIFS_SB(dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
Joe Perchesb6b38f72010-04-21 03:50:45 +0000886 cFYI(1, "write %zd bytes to offset %lld of %s", write_size,
Jeff Layton7da4b492010-10-15 15:34:00 -0400887 *poffset, dentry->d_name.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888
Jeff Layton13cfb732010-09-29 19:51:11 -0400889 pTcon = tlink_tcon(open_file->tlink);
Steve French50c2f752007-07-13 00:33:32 +0000890
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 for (total_written = 0; write_size > total_written;
894 total_written += bytes_written) {
895 rc = -EAGAIN;
896 while (rc == -EAGAIN) {
Jeff Laytonca83ce32011-04-12 09:13:44 -0400897 struct kvec iov[2];
898 unsigned int len;
899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 if (open_file->invalidHandle) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 /* we could deadlock if we called
902 filemap_fdatawait from here so tell
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000903 reopen_file not to flush data to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 server now */
Jeff Layton15886172010-10-15 15:33:59 -0400905 rc = cifs_reopen_file(open_file, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 if (rc != 0)
907 break;
908 }
Steve French3e844692005-10-03 13:37:24 -0700909
Jeff Laytonca83ce32011-04-12 09:13:44 -0400910 len = min((size_t)cifs_sb->wsize,
911 write_size - total_written);
912 /* iov[0] is reserved for smb header */
913 iov[1].iov_base = (char *)write_data + total_written;
914 iov[1].iov_len = len;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +0400915 io_parms.netfid = open_file->netfid;
916 io_parms.pid = pid;
917 io_parms.tcon = pTcon;
918 io_parms.offset = *poffset;
919 io_parms.length = len;
920 rc = CIFSSMBWrite2(xid, &io_parms, &bytes_written, iov,
921 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 }
923 if (rc || (bytes_written == 0)) {
924 if (total_written)
925 break;
926 else {
927 FreeXid(xid);
928 return rc;
929 }
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400930 } else {
931 cifs_update_eof(cifsi, *poffset, bytes_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 *poffset += bytes_written;
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400933 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 }
935
Steve Frencha4544342005-08-24 13:59:35 -0700936 cifs_stats_bytes_written(pTcon, total_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937
Jeff Layton7da4b492010-10-15 15:34:00 -0400938 if (total_written > 0) {
939 spin_lock(&dentry->d_inode->i_lock);
940 if (*poffset > dentry->d_inode->i_size)
941 i_size_write(dentry->d_inode, *poffset);
942 spin_unlock(&dentry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 }
Jeff Layton7da4b492010-10-15 15:34:00 -0400944 mark_inode_dirty_sync(dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 FreeXid(xid);
946 return total_written;
947}
948
Jeff Layton6508d902010-09-29 19:51:11 -0400949struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
950 bool fsuid_only)
Steve French630f3f0c2007-10-25 21:17:17 +0000951{
952 struct cifsFileInfo *open_file = NULL;
Jeff Layton6508d902010-09-29 19:51:11 -0400953 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
954
955 /* only filter by fsuid on multiuser mounts */
956 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
957 fsuid_only = false;
Steve French630f3f0c2007-10-25 21:17:17 +0000958
Jeff Layton44772882010-10-15 15:34:03 -0400959 spin_lock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +0000960 /* we could simply get the first_list_entry since write-only entries
961 are always at the end of the list but since the first entry might
962 have a close pending, we go through the whole list */
963 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -0400964 if (fsuid_only && open_file->uid != current_fsuid())
965 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -0400966 if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
Steve French630f3f0c2007-10-25 21:17:17 +0000967 if (!open_file->invalidHandle) {
968 /* found a good file */
969 /* lock it so it will not be closed on us */
Dave Kleikamp6ab409b2009-08-31 11:07:12 -0400970 cifsFileInfo_get(open_file);
Jeff Layton44772882010-10-15 15:34:03 -0400971 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +0000972 return open_file;
973 } /* else might as well continue, and look for
974 another, or simply have the caller reopen it
975 again rather than trying to fix this handle */
976 } else /* write only file */
977 break; /* write only files are last so must be done */
978 }
Jeff Layton44772882010-10-15 15:34:03 -0400979 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +0000980 return NULL;
981}
Steve French630f3f0c2007-10-25 21:17:17 +0000982
Jeff Layton6508d902010-09-29 19:51:11 -0400983struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
984 bool fsuid_only)
Steve French6148a742005-10-05 12:23:19 -0700985{
986 struct cifsFileInfo *open_file;
Jeff Laytond3892292010-11-02 16:22:50 -0400987 struct cifs_sb_info *cifs_sb;
Jeff Layton2846d382008-09-22 21:33:33 -0400988 bool any_available = false;
Steve Frenchdd99cd82005-10-05 19:32:49 -0700989 int rc;
Steve French6148a742005-10-05 12:23:19 -0700990
Steve French60808232006-04-22 15:53:05 +0000991 /* Having a null inode here (because mapping->host was set to zero by
992 the VFS or MM) should not happen but we had reports of on oops (due to
993 it being zero) during stress testcases so we need to check for it */
994
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000995 if (cifs_inode == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000996 cERROR(1, "Null inode passed to cifs_writeable_file");
Steve French60808232006-04-22 15:53:05 +0000997 dump_stack();
998 return NULL;
999 }
1000
Jeff Laytond3892292010-11-02 16:22:50 -04001001 cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1002
Jeff Layton6508d902010-09-29 19:51:11 -04001003 /* only filter by fsuid on multiuser mounts */
1004 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1005 fsuid_only = false;
1006
Jeff Layton44772882010-10-15 15:34:03 -04001007 spin_lock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001008refind_writable:
Steve French6148a742005-10-05 12:23:19 -07001009 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001010 if (!any_available && open_file->pid != current->tgid)
1011 continue;
1012 if (fsuid_only && open_file->uid != current_fsuid())
1013 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001014 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001015 cifsFileInfo_get(open_file);
Steve French9b22b0b2007-10-02 01:11:08 +00001016
1017 if (!open_file->invalidHandle) {
1018 /* found a good writable file */
Jeff Layton44772882010-10-15 15:34:03 -04001019 spin_unlock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001020 return open_file;
1021 }
Steve French8840dee2007-11-16 23:05:52 +00001022
Jeff Layton44772882010-10-15 15:34:03 -04001023 spin_unlock(&cifs_file_list_lock);
Steve Frenchcdff08e2010-10-21 22:46:14 +00001024
Steve French9b22b0b2007-10-02 01:11:08 +00001025 /* Had to unlock since following call can block */
Jeff Layton15886172010-10-15 15:33:59 -04001026 rc = cifs_reopen_file(open_file, false);
Steve Frenchcdff08e2010-10-21 22:46:14 +00001027 if (!rc)
1028 return open_file;
Steve French9b22b0b2007-10-02 01:11:08 +00001029
Steve Frenchcdff08e2010-10-21 22:46:14 +00001030 /* if it fails, try another handle if possible */
Joe Perchesb6b38f72010-04-21 03:50:45 +00001031 cFYI(1, "wp failed on reopen file");
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001032 cifsFileInfo_put(open_file);
Steve French8840dee2007-11-16 23:05:52 +00001033
Steve Frenchcdff08e2010-10-21 22:46:14 +00001034 spin_lock(&cifs_file_list_lock);
1035
Steve French9b22b0b2007-10-02 01:11:08 +00001036 /* else we simply continue to the next entry. Thus
1037 we do not loop on reopen errors. If we
1038 can not reopen the file, for example if we
1039 reconnected to a server with another client
1040 racing to delete or lock the file we would not
1041 make progress if we restarted before the beginning
1042 of the loop here. */
Steve French6148a742005-10-05 12:23:19 -07001043 }
1044 }
Jeff Layton2846d382008-09-22 21:33:33 -04001045 /* couldn't find useable FH with same pid, try any available */
1046 if (!any_available) {
1047 any_available = true;
1048 goto refind_writable;
1049 }
Jeff Layton44772882010-10-15 15:34:03 -04001050 spin_unlock(&cifs_file_list_lock);
Steve French6148a742005-10-05 12:23:19 -07001051 return NULL;
1052}
1053
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1055{
1056 struct address_space *mapping = page->mapping;
1057 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1058 char *write_data;
1059 int rc = -EFAULT;
1060 int bytes_written = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 struct inode *inode;
Steve French6148a742005-10-05 12:23:19 -07001062 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
1064 if (!mapping || !mapping->host)
1065 return -EFAULT;
1066
1067 inode = page->mapping->host;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
1069 offset += (loff_t)from;
1070 write_data = kmap(page);
1071 write_data += from;
1072
1073 if ((to > PAGE_CACHE_SIZE) || (from > to)) {
1074 kunmap(page);
1075 return -EIO;
1076 }
1077
1078 /* racing with truncate? */
1079 if (offset > mapping->host->i_size) {
1080 kunmap(page);
1081 return 0; /* don't care */
1082 }
1083
1084 /* check to make sure that we are not extending the file */
1085 if (mapping->host->i_size - offset < (loff_t)to)
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001086 to = (unsigned)(mapping->host->i_size - offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
Jeff Layton6508d902010-09-29 19:51:11 -04001088 open_file = find_writable_file(CIFS_I(mapping->host), false);
Steve French6148a742005-10-05 12:23:19 -07001089 if (open_file) {
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001090 bytes_written = cifs_write(open_file, open_file->pid,
1091 write_data, to - from, &offset);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001092 cifsFileInfo_put(open_file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 /* Does mm or vfs already set times? */
Steve French6148a742005-10-05 12:23:19 -07001094 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001095 if ((bytes_written > 0) && (offset))
Steve French6148a742005-10-05 12:23:19 -07001096 rc = 0;
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001097 else if (bytes_written < 0)
1098 rc = bytes_written;
Steve French6148a742005-10-05 12:23:19 -07001099 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001100 cFYI(1, "No writeable filehandles for inode");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 rc = -EIO;
1102 }
1103
1104 kunmap(page);
1105 return rc;
1106}
1107
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108static int cifs_writepages(struct address_space *mapping,
Steve French37c0eb42005-10-05 14:50:29 -07001109 struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110{
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001111 struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb);
1112 bool done = false, scanned = false, range_whole = false;
1113 pgoff_t end, index;
1114 struct cifs_writedata *wdata;
Steve French37c0eb42005-10-05 14:50:29 -07001115 struct page *page;
Steve French37c0eb42005-10-05 14:50:29 -07001116 int rc = 0;
Steve French50c2f752007-07-13 00:33:32 +00001117
Steve French37c0eb42005-10-05 14:50:29 -07001118 /*
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001119 * If wsize is smaller than the page cache size, default to writing
Steve French37c0eb42005-10-05 14:50:29 -07001120 * one page at a time via cifs_writepage
1121 */
1122 if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1123 return generic_writepages(mapping, wbc);
1124
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001125 if (wbc->range_cyclic) {
Steve French37c0eb42005-10-05 14:50:29 -07001126 index = mapping->writeback_index; /* Start from prev offset */
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001127 end = -1;
1128 } else {
1129 index = wbc->range_start >> PAGE_CACHE_SHIFT;
1130 end = wbc->range_end >> PAGE_CACHE_SHIFT;
1131 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001132 range_whole = true;
1133 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001134 }
1135retry:
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001136 while (!done && index <= end) {
1137 unsigned int i, nr_pages, found_pages;
1138 pgoff_t next = 0, tofind;
1139 struct page **pages;
Steve French37c0eb42005-10-05 14:50:29 -07001140
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001141 tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1,
1142 end - index) + 1;
Steve French37c0eb42005-10-05 14:50:29 -07001143
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001144 wdata = cifs_writedata_alloc((unsigned int)tofind);
1145 if (!wdata) {
1146 rc = -ENOMEM;
1147 break;
1148 }
1149
1150 /*
1151 * find_get_pages_tag seems to return a max of 256 on each
1152 * iteration, so we must call it several times in order to
1153 * fill the array or the wsize is effectively limited to
1154 * 256 * PAGE_CACHE_SIZE.
1155 */
1156 found_pages = 0;
1157 pages = wdata->pages;
1158 do {
1159 nr_pages = find_get_pages_tag(mapping, &index,
1160 PAGECACHE_TAG_DIRTY,
1161 tofind, pages);
1162 found_pages += nr_pages;
1163 tofind -= nr_pages;
1164 pages += nr_pages;
1165 } while (nr_pages && tofind && index <= end);
1166
1167 if (found_pages == 0) {
1168 kref_put(&wdata->refcount, cifs_writedata_release);
1169 break;
1170 }
1171
1172 nr_pages = 0;
1173 for (i = 0; i < found_pages; i++) {
1174 page = wdata->pages[i];
Steve French37c0eb42005-10-05 14:50:29 -07001175 /*
1176 * At this point we hold neither mapping->tree_lock nor
1177 * lock on the page itself: the page may be truncated or
1178 * invalidated (changing page->mapping to NULL), or even
1179 * swizzled back from swapper_space to tmpfs file
1180 * mapping
1181 */
1182
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001183 if (nr_pages == 0)
Steve French37c0eb42005-10-05 14:50:29 -07001184 lock_page(page);
Nick Piggin529ae9a2008-08-02 12:01:03 +02001185 else if (!trylock_page(page))
Steve French37c0eb42005-10-05 14:50:29 -07001186 break;
1187
1188 if (unlikely(page->mapping != mapping)) {
1189 unlock_page(page);
1190 break;
1191 }
1192
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001193 if (!wbc->range_cyclic && page->index > end) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001194 done = true;
Steve French37c0eb42005-10-05 14:50:29 -07001195 unlock_page(page);
1196 break;
1197 }
1198
1199 if (next && (page->index != next)) {
1200 /* Not next consecutive page */
1201 unlock_page(page);
1202 break;
1203 }
1204
1205 if (wbc->sync_mode != WB_SYNC_NONE)
1206 wait_on_page_writeback(page);
1207
1208 if (PageWriteback(page) ||
Linus Torvaldscb876f42006-12-23 16:19:07 -08001209 !clear_page_dirty_for_io(page)) {
Steve French37c0eb42005-10-05 14:50:29 -07001210 unlock_page(page);
1211 break;
1212 }
Steve French84d2f072005-10-12 15:32:05 -07001213
Linus Torvaldscb876f42006-12-23 16:19:07 -08001214 /*
1215 * This actually clears the dirty bit in the radix tree.
1216 * See cifs_writepage() for more commentary.
1217 */
1218 set_page_writeback(page);
1219
Steve French84d2f072005-10-12 15:32:05 -07001220 if (page_offset(page) >= mapping->host->i_size) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001221 done = true;
Steve French84d2f072005-10-12 15:32:05 -07001222 unlock_page(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001223 end_page_writeback(page);
Steve French84d2f072005-10-12 15:32:05 -07001224 break;
1225 }
1226
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001227 wdata->pages[i] = page;
Steve French37c0eb42005-10-05 14:50:29 -07001228 next = page->index + 1;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001229 ++nr_pages;
Steve French37c0eb42005-10-05 14:50:29 -07001230 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001231
1232 /* reset index to refind any pages skipped */
1233 if (nr_pages == 0)
1234 index = wdata->pages[0]->index + 1;
1235
1236 /* put any pages we aren't going to use */
1237 for (i = nr_pages; i < found_pages; i++) {
1238 page_cache_release(wdata->pages[i]);
1239 wdata->pages[i] = NULL;
1240 }
1241
1242 /* nothing to write? */
1243 if (nr_pages == 0) {
1244 kref_put(&wdata->refcount, cifs_writedata_release);
1245 continue;
1246 }
1247
1248 wdata->sync_mode = wbc->sync_mode;
1249 wdata->nr_pages = nr_pages;
1250 wdata->offset = page_offset(wdata->pages[0]);
1251
1252 do {
1253 if (wdata->cfile != NULL)
1254 cifsFileInfo_put(wdata->cfile);
1255 wdata->cfile = find_writable_file(CIFS_I(mapping->host),
1256 false);
1257 if (!wdata->cfile) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001258 cERROR(1, "No writable handles for inode");
Steve French23e7dd72005-10-20 13:44:56 -07001259 rc = -EBADF;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001260 break;
Steve French37c0eb42005-10-05 14:50:29 -07001261 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001262 rc = cifs_async_writev(wdata);
1263 } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN);
Jeff Laytonf3983c22010-09-22 16:17:40 -07001264
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001265 for (i = 0; i < nr_pages; ++i)
1266 unlock_page(wdata->pages[i]);
Jeff Layton941b8532011-01-11 07:24:01 -05001267
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001268 /* send failure -- clean up the mess */
1269 if (rc != 0) {
1270 for (i = 0; i < nr_pages; ++i) {
Jeff Layton941b8532011-01-11 07:24:01 -05001271 if (rc == -EAGAIN)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001272 redirty_page_for_writepage(wbc,
1273 wdata->pages[i]);
1274 else
1275 SetPageError(wdata->pages[i]);
1276 end_page_writeback(wdata->pages[i]);
1277 page_cache_release(wdata->pages[i]);
Steve French37c0eb42005-10-05 14:50:29 -07001278 }
Jeff Layton941b8532011-01-11 07:24:01 -05001279 if (rc != -EAGAIN)
1280 mapping_set_error(mapping, rc);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001281 }
1282 kref_put(&wdata->refcount, cifs_writedata_release);
Jeff Layton941b8532011-01-11 07:24:01 -05001283
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001284 wbc->nr_to_write -= nr_pages;
1285 if (wbc->nr_to_write <= 0)
1286 done = true;
Dave Kleikampb066a482008-11-18 03:49:05 +00001287
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001288 index = next;
Steve French37c0eb42005-10-05 14:50:29 -07001289 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001290
Steve French37c0eb42005-10-05 14:50:29 -07001291 if (!scanned && !done) {
1292 /*
1293 * We hit the last page and there is more work to be done: wrap
1294 * back to the start of the file
1295 */
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001296 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001297 index = 0;
1298 goto retry;
1299 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001300
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001301 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
Steve French37c0eb42005-10-05 14:50:29 -07001302 mapping->writeback_index = index;
1303
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 return rc;
1305}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001307static int
1308cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309{
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001310 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 int xid;
1312
1313 xid = GetXid();
1314/* BB add check for wbc flags */
1315 page_cache_get(page);
Steve Frenchad7a2922008-02-07 23:25:02 +00001316 if (!PageUptodate(page))
Joe Perchesb6b38f72010-04-21 03:50:45 +00001317 cFYI(1, "ppw - page not up to date");
Linus Torvaldscb876f42006-12-23 16:19:07 -08001318
1319 /*
1320 * Set the "writeback" flag, and clear "dirty" in the radix tree.
1321 *
1322 * A writepage() implementation always needs to do either this,
1323 * or re-dirty the page with "redirty_page_for_writepage()" in
1324 * the case of a failure.
1325 *
1326 * Just unlocking the page will cause the radix tree tag-bits
1327 * to fail to update with the state of the page correctly.
1328 */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001329 set_page_writeback(page);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001330retry_write:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001332 if (rc == -EAGAIN && wbc->sync_mode == WB_SYNC_ALL)
1333 goto retry_write;
1334 else if (rc == -EAGAIN)
1335 redirty_page_for_writepage(wbc, page);
1336 else if (rc != 0)
1337 SetPageError(page);
1338 else
1339 SetPageUptodate(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001340 end_page_writeback(page);
1341 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 FreeXid(xid);
1343 return rc;
1344}
1345
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001346static int cifs_writepage(struct page *page, struct writeback_control *wbc)
1347{
1348 int rc = cifs_writepage_locked(page, wbc);
1349 unlock_page(page);
1350 return rc;
1351}
1352
Nick Piggind9414772008-09-24 11:32:59 -04001353static int cifs_write_end(struct file *file, struct address_space *mapping,
1354 loff_t pos, unsigned len, unsigned copied,
1355 struct page *page, void *fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356{
Nick Piggind9414772008-09-24 11:32:59 -04001357 int rc;
1358 struct inode *inode = mapping->host;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001359 struct cifsFileInfo *cfile = file->private_data;
1360 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
1361 __u32 pid;
1362
1363 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1364 pid = cfile->pid;
1365 else
1366 pid = current->tgid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367
Joe Perchesb6b38f72010-04-21 03:50:45 +00001368 cFYI(1, "write_end for page %p from pos %lld with %d bytes",
1369 page, pos, copied);
Steve Frenchad7a2922008-02-07 23:25:02 +00001370
Jeff Laytona98ee8c2008-11-26 19:32:33 +00001371 if (PageChecked(page)) {
1372 if (copied == len)
1373 SetPageUptodate(page);
1374 ClearPageChecked(page);
1375 } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
Nick Piggind9414772008-09-24 11:32:59 -04001376 SetPageUptodate(page);
1377
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 if (!PageUptodate(page)) {
Nick Piggind9414772008-09-24 11:32:59 -04001379 char *page_data;
1380 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
1381 int xid;
1382
1383 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 /* this is probably better than directly calling
1385 partialpage_write since in this function the file handle is
1386 known which we might as well leverage */
1387 /* BB check if anything else missing out of ppw
1388 such as updating last write time */
1389 page_data = kmap(page);
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001390 rc = cifs_write(cfile, pid, page_data + offset, copied, &pos);
Nick Piggind9414772008-09-24 11:32:59 -04001391 /* if (rc < 0) should we set writebehind rc? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 kunmap(page);
Nick Piggind9414772008-09-24 11:32:59 -04001393
1394 FreeXid(xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001395 } else {
Nick Piggind9414772008-09-24 11:32:59 -04001396 rc = copied;
1397 pos += copied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 set_page_dirty(page);
1399 }
1400
Nick Piggind9414772008-09-24 11:32:59 -04001401 if (rc > 0) {
1402 spin_lock(&inode->i_lock);
1403 if (pos > inode->i_size)
1404 i_size_write(inode, pos);
1405 spin_unlock(&inode->i_lock);
1406 }
1407
1408 unlock_page(page);
1409 page_cache_release(page);
1410
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 return rc;
1412}
1413
Josef Bacik02c24a82011-07-16 20:44:56 -04001414int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
1415 int datasync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416{
1417 int xid;
1418 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00001419 struct cifs_tcon *tcon;
Joe Perchesc21dfb62010-07-12 13:50:14 -07001420 struct cifsFileInfo *smbfile = file->private_data;
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08001421 struct inode *inode = file->f_path.dentry->d_inode;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001422 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
Josef Bacik02c24a82011-07-16 20:44:56 -04001424 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
1425 if (rc)
1426 return rc;
1427 mutex_lock(&inode->i_mutex);
1428
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 xid = GetXid();
1430
Joe Perchesb6b38f72010-04-21 03:50:45 +00001431 cFYI(1, "Sync file - name: %s datasync: 0x%x",
Christoph Hellwig7ea80852010-05-26 17:53:25 +02001432 file->f_path.dentry->d_name.name, datasync);
Steve French50c2f752007-07-13 00:33:32 +00001433
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001434 if (!CIFS_I(inode)->clientCanCacheRead) {
1435 rc = cifs_invalidate_mapping(inode);
1436 if (rc) {
1437 cFYI(1, "rc: %d during invalidate phase", rc);
1438 rc = 0; /* don't care about it in fsync */
1439 }
1440 }
Jeff Laytoneb4b7562010-10-22 14:52:29 -04001441
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001442 tcon = tlink_tcon(smbfile->tlink);
1443 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
1444 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
1445
1446 FreeXid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04001447 mutex_unlock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001448 return rc;
1449}
1450
Josef Bacik02c24a82011-07-16 20:44:56 -04001451int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001452{
1453 int xid;
1454 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00001455 struct cifs_tcon *tcon;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001456 struct cifsFileInfo *smbfile = file->private_data;
1457 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Josef Bacik02c24a82011-07-16 20:44:56 -04001458 struct inode *inode = file->f_mapping->host;
1459
1460 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
1461 if (rc)
1462 return rc;
1463 mutex_lock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001464
1465 xid = GetXid();
1466
1467 cFYI(1, "Sync file - name: %s datasync: 0x%x",
1468 file->f_path.dentry->d_name.name, datasync);
1469
1470 tcon = tlink_tcon(smbfile->tlink);
1471 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
1472 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
Steve Frenchb298f222009-02-21 21:17:43 +00001473
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 FreeXid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04001475 mutex_unlock(&inode->i_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 return rc;
1477}
1478
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479/*
1480 * As file closes, flush all cached write data for this inode checking
1481 * for write behind errors.
1482 */
Miklos Szeredi75e1fcc2006-06-23 02:05:12 -07001483int cifs_flush(struct file *file, fl_owner_t id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484{
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001485 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 int rc = 0;
1487
Jeff Laytoneb4b7562010-10-22 14:52:29 -04001488 if (file->f_mode & FMODE_WRITE)
Jeff Laytond3f13222010-10-15 15:34:07 -04001489 rc = filemap_write_and_wait(inode->i_mapping);
Steve French50c2f752007-07-13 00:33:32 +00001490
Joe Perchesb6b38f72010-04-21 03:50:45 +00001491 cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492
1493 return rc;
1494}
1495
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001496static int
1497cifs_write_allocate_pages(struct page **pages, unsigned long num_pages)
1498{
1499 int rc = 0;
1500 unsigned long i;
1501
1502 for (i = 0; i < num_pages; i++) {
1503 pages[i] = alloc_page(__GFP_HIGHMEM);
1504 if (!pages[i]) {
1505 /*
1506 * save number of pages we have already allocated and
1507 * return with ENOMEM error
1508 */
1509 num_pages = i;
1510 rc = -ENOMEM;
1511 goto error;
1512 }
1513 }
1514
1515 return rc;
1516
1517error:
1518 for (i = 0; i < num_pages; i++)
1519 put_page(pages[i]);
1520 return rc;
1521}
1522
1523static inline
1524size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
1525{
1526 size_t num_pages;
1527 size_t clen;
1528
1529 clen = min_t(const size_t, len, wsize);
1530 num_pages = clen / PAGE_CACHE_SIZE;
1531 if (clen % PAGE_CACHE_SIZE)
1532 num_pages++;
1533
1534 if (cur_len)
1535 *cur_len = clen;
1536
1537 return num_pages;
1538}
1539
1540static ssize_t
1541cifs_iovec_write(struct file *file, const struct iovec *iov,
1542 unsigned long nr_segs, loff_t *poffset)
1543{
Pavel Shilovsky76429c12011-01-31 16:03:08 +03001544 unsigned int written;
1545 unsigned long num_pages, npages, i;
1546 size_t copied, len, cur_len;
1547 ssize_t total_written = 0;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001548 struct kvec *to_send;
1549 struct page **pages;
1550 struct iov_iter it;
1551 struct inode *inode;
1552 struct cifsFileInfo *open_file;
Steve French96daf2b2011-05-27 04:34:02 +00001553 struct cifs_tcon *pTcon;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001554 struct cifs_sb_info *cifs_sb;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001555 struct cifs_io_parms io_parms;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001556 int xid, rc;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001557 __u32 pid;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001558
1559 len = iov_length(iov, nr_segs);
1560 if (!len)
1561 return 0;
1562
1563 rc = generic_write_checks(file, poffset, &len, 0);
1564 if (rc)
1565 return rc;
1566
1567 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1568 num_pages = get_numpages(cifs_sb->wsize, len, &cur_len);
1569
1570 pages = kmalloc(sizeof(struct pages *)*num_pages, GFP_KERNEL);
1571 if (!pages)
1572 return -ENOMEM;
1573
1574 to_send = kmalloc(sizeof(struct kvec)*(num_pages + 1), GFP_KERNEL);
1575 if (!to_send) {
1576 kfree(pages);
1577 return -ENOMEM;
1578 }
1579
1580 rc = cifs_write_allocate_pages(pages, num_pages);
1581 if (rc) {
1582 kfree(pages);
1583 kfree(to_send);
1584 return rc;
1585 }
1586
1587 xid = GetXid();
1588 open_file = file->private_data;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001589
1590 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1591 pid = open_file->pid;
1592 else
1593 pid = current->tgid;
1594
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001595 pTcon = tlink_tcon(open_file->tlink);
1596 inode = file->f_path.dentry->d_inode;
1597
1598 iov_iter_init(&it, iov, nr_segs, len, 0);
1599 npages = num_pages;
1600
1601 do {
1602 size_t save_len = cur_len;
1603 for (i = 0; i < npages; i++) {
1604 copied = min_t(const size_t, cur_len, PAGE_CACHE_SIZE);
1605 copied = iov_iter_copy_from_user(pages[i], &it, 0,
1606 copied);
1607 cur_len -= copied;
1608 iov_iter_advance(&it, copied);
1609 to_send[i+1].iov_base = kmap(pages[i]);
1610 to_send[i+1].iov_len = copied;
1611 }
1612
1613 cur_len = save_len - cur_len;
1614
1615 do {
1616 if (open_file->invalidHandle) {
1617 rc = cifs_reopen_file(open_file, false);
1618 if (rc != 0)
1619 break;
1620 }
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001621 io_parms.netfid = open_file->netfid;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001622 io_parms.pid = pid;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001623 io_parms.tcon = pTcon;
1624 io_parms.offset = *poffset;
1625 io_parms.length = cur_len;
1626 rc = CIFSSMBWrite2(xid, &io_parms, &written, to_send,
1627 npages, 0);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001628 } while (rc == -EAGAIN);
1629
1630 for (i = 0; i < npages; i++)
1631 kunmap(pages[i]);
1632
1633 if (written) {
1634 len -= written;
1635 total_written += written;
1636 cifs_update_eof(CIFS_I(inode), *poffset, written);
1637 *poffset += written;
1638 } else if (rc < 0) {
1639 if (!total_written)
1640 total_written = rc;
1641 break;
1642 }
1643
1644 /* get length and number of kvecs of the next write */
1645 npages = get_numpages(cifs_sb->wsize, len, &cur_len);
1646 } while (len > 0);
1647
1648 if (total_written > 0) {
1649 spin_lock(&inode->i_lock);
1650 if (*poffset > inode->i_size)
1651 i_size_write(inode, *poffset);
1652 spin_unlock(&inode->i_lock);
1653 }
1654
1655 cifs_stats_bytes_written(pTcon, total_written);
1656 mark_inode_dirty_sync(inode);
1657
1658 for (i = 0; i < num_pages; i++)
1659 put_page(pages[i]);
1660 kfree(to_send);
1661 kfree(pages);
1662 FreeXid(xid);
1663 return total_written;
1664}
1665
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03001666ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001667 unsigned long nr_segs, loff_t pos)
1668{
1669 ssize_t written;
1670 struct inode *inode;
1671
1672 inode = iocb->ki_filp->f_path.dentry->d_inode;
1673
1674 /*
1675 * BB - optimize the way when signing is disabled. We can drop this
1676 * extra memory-to-memory copying and use iovec buffers for constructing
1677 * write request.
1678 */
1679
1680 written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos);
1681 if (written > 0) {
1682 CIFS_I(inode)->invalid_mapping = true;
1683 iocb->ki_pos = pos;
1684 }
1685
1686 return written;
1687}
1688
1689ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
1690 unsigned long nr_segs, loff_t pos)
1691{
1692 struct inode *inode;
1693
1694 inode = iocb->ki_filp->f_path.dentry->d_inode;
1695
1696 if (CIFS_I(inode)->clientCanCacheAll)
1697 return generic_file_aio_write(iocb, iov, nr_segs, pos);
1698
1699 /*
1700 * In strict cache mode we need to write the data to the server exactly
1701 * from the pos to pos+len-1 rather than flush all affected pages
1702 * because it may cause a error with mandatory locks on these pages but
1703 * not on the region from pos to ppos+len-1.
1704 */
1705
1706 return cifs_user_writev(iocb, iov, nr_segs, pos);
1707}
1708
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001709static ssize_t
1710cifs_iovec_read(struct file *file, const struct iovec *iov,
1711 unsigned long nr_segs, loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712{
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001713 int rc;
1714 int xid;
Pavel Shilovsky76429c12011-01-31 16:03:08 +03001715 ssize_t total_read;
1716 unsigned int bytes_read = 0;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001717 size_t len, cur_len;
1718 int iov_offset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00001720 struct cifs_tcon *pTcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 struct smb_com_read_rsp *pSMBr;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001723 struct cifs_io_parms io_parms;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001724 char *read_data;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001725 __u32 pid;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001726
1727 if (!nr_segs)
1728 return 0;
1729
1730 len = iov_length(iov, nr_segs);
1731 if (!len)
1732 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733
1734 xid = GetXid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08001735 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736
Joe Perchesc21dfb62010-07-12 13:50:14 -07001737 open_file = file->private_data;
Jeff Layton13cfb732010-09-29 19:51:11 -04001738 pTcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001740 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1741 pid = open_file->pid;
1742 else
1743 pid = current->tgid;
1744
Steve Frenchad7a2922008-02-07 23:25:02 +00001745 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001746 cFYI(1, "attempting read on write only file instance");
Steve Frenchad7a2922008-02-07 23:25:02 +00001747
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001748 for (total_read = 0; total_read < len; total_read += bytes_read) {
1749 cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 rc = -EAGAIN;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001751 read_data = NULL;
1752
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 while (rc == -EAGAIN) {
Steve Frenchec637e32005-12-12 20:53:18 -08001754 int buf_type = CIFS_NO_BUFFER;
Steve Frenchcdff08e2010-10-21 22:46:14 +00001755 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04001756 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 if (rc != 0)
1758 break;
1759 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001760 io_parms.netfid = open_file->netfid;
1761 io_parms.pid = pid;
1762 io_parms.tcon = pTcon;
1763 io_parms.offset = *poffset;
Pavel Shilovsky2cebaa52011-07-20 18:24:09 +04001764 io_parms.length = cur_len;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001765 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001766 &read_data, &buf_type);
1767 pSMBr = (struct smb_com_read_rsp *)read_data;
1768 if (read_data) {
1769 char *data_offset = read_data + 4 +
1770 le16_to_cpu(pSMBr->DataOffset);
1771 if (memcpy_toiovecend(iov, data_offset,
1772 iov_offset, bytes_read))
Steve French93544cc2006-02-14 22:30:52 -06001773 rc = -EFAULT;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001774 if (buf_type == CIFS_SMALL_BUFFER)
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001775 cifs_small_buf_release(read_data);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001776 else if (buf_type == CIFS_LARGE_BUFFER)
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001777 cifs_buf_release(read_data);
1778 read_data = NULL;
1779 iov_offset += bytes_read;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 }
1781 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001782
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 if (rc || (bytes_read == 0)) {
1784 if (total_read) {
1785 break;
1786 } else {
1787 FreeXid(xid);
1788 return rc;
1789 }
1790 } else {
Steve Frencha4544342005-08-24 13:59:35 -07001791 cifs_stats_bytes_read(pTcon, bytes_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 *poffset += bytes_read;
1793 }
1794 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001795
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 FreeXid(xid);
1797 return total_read;
1798}
1799
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03001800ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001801 unsigned long nr_segs, loff_t pos)
1802{
1803 ssize_t read;
1804
1805 read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos);
1806 if (read > 0)
1807 iocb->ki_pos = pos;
1808
1809 return read;
1810}
1811
1812ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov,
1813 unsigned long nr_segs, loff_t pos)
1814{
1815 struct inode *inode;
1816
1817 inode = iocb->ki_filp->f_path.dentry->d_inode;
1818
1819 if (CIFS_I(inode)->clientCanCacheRead)
1820 return generic_file_aio_read(iocb, iov, nr_segs, pos);
1821
1822 /*
1823 * In strict cache mode we need to read from the server all the time
1824 * if we don't have level II oplock because the server can delay mtime
1825 * change - so we can't make a decision about inode invalidating.
1826 * And we can also fail with pagereading if there are mandatory locks
1827 * on pages affected by this read but not on the region from pos to
1828 * pos+len-1.
1829 */
1830
1831 return cifs_user_readv(iocb, iov, nr_segs, pos);
1832}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833
1834static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001835 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836{
1837 int rc = -EACCES;
1838 unsigned int bytes_read = 0;
1839 unsigned int total_read;
1840 unsigned int current_read_size;
1841 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00001842 struct cifs_tcon *pTcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 int xid;
1844 char *current_offset;
1845 struct cifsFileInfo *open_file;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001846 struct cifs_io_parms io_parms;
Steve Frenchec637e32005-12-12 20:53:18 -08001847 int buf_type = CIFS_NO_BUFFER;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001848 __u32 pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849
1850 xid = GetXid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08001851 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852
1853 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301854 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301856 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 }
Joe Perchesc21dfb62010-07-12 13:50:14 -07001858 open_file = file->private_data;
Jeff Layton13cfb732010-09-29 19:51:11 -04001859 pTcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001861 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1862 pid = open_file->pid;
1863 else
1864 pid = current->tgid;
1865
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001867 cFYI(1, "attempting read on write only file instance");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001869 for (total_read = 0, current_offset = read_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 read_size > total_read;
1871 total_read += bytes_read, current_offset += bytes_read) {
1872 current_read_size = min_t(const int, read_size - total_read,
1873 cifs_sb->rsize);
Steve Frenchf9f5c8172005-09-15 23:06:38 -07001874 /* For windows me and 9x we do not want to request more
1875 than it negotiated since it will refuse the read then */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001876 if ((pTcon->ses) &&
Steve Frenchf9f5c8172005-09-15 23:06:38 -07001877 !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
1878 current_read_size = min_t(const int, current_read_size,
Jeff Laytonc974bef2011-10-11 06:41:32 -04001879 CIFSMaxBufSize);
Steve Frenchf9f5c8172005-09-15 23:06:38 -07001880 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 rc = -EAGAIN;
1882 while (rc == -EAGAIN) {
Steve Frenchcdff08e2010-10-21 22:46:14 +00001883 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04001884 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 if (rc != 0)
1886 break;
1887 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001888 io_parms.netfid = open_file->netfid;
1889 io_parms.pid = pid;
1890 io_parms.tcon = pTcon;
1891 io_parms.offset = *poffset;
1892 io_parms.length = current_read_size;
1893 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
1894 &current_offset, &buf_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 }
1896 if (rc || (bytes_read == 0)) {
1897 if (total_read) {
1898 break;
1899 } else {
1900 FreeXid(xid);
1901 return rc;
1902 }
1903 } else {
Steve Frencha4544342005-08-24 13:59:35 -07001904 cifs_stats_bytes_read(pTcon, total_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 *poffset += bytes_read;
1906 }
1907 }
1908 FreeXid(xid);
1909 return total_read;
1910}
1911
Jeff Laytonca83ce32011-04-12 09:13:44 -04001912/*
1913 * If the page is mmap'ed into a process' page tables, then we need to make
1914 * sure that it doesn't change while being written back.
1915 */
1916static int
1917cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1918{
1919 struct page *page = vmf->page;
1920
1921 lock_page(page);
1922 return VM_FAULT_LOCKED;
1923}
1924
1925static struct vm_operations_struct cifs_file_vm_ops = {
1926 .fault = filemap_fault,
1927 .page_mkwrite = cifs_page_mkwrite,
1928};
1929
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03001930int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
1931{
1932 int rc, xid;
1933 struct inode *inode = file->f_path.dentry->d_inode;
1934
1935 xid = GetXid();
1936
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001937 if (!CIFS_I(inode)->clientCanCacheRead) {
1938 rc = cifs_invalidate_mapping(inode);
1939 if (rc)
1940 return rc;
1941 }
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03001942
1943 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04001944 if (rc == 0)
1945 vma->vm_ops = &cifs_file_vm_ops;
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03001946 FreeXid(xid);
1947 return rc;
1948}
1949
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1951{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 int rc, xid;
1953
1954 xid = GetXid();
Jeff Laytonabab0952010-02-12 07:44:18 -05001955 rc = cifs_revalidate_file(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001957 cFYI(1, "Validation prior to mmap failed, error=%d", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 FreeXid(xid);
1959 return rc;
1960 }
1961 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04001962 if (rc == 0)
1963 vma->vm_ops = &cifs_file_vm_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 FreeXid(xid);
1965 return rc;
1966}
1967
1968
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001969static void cifs_copy_cache_pages(struct address_space *mapping,
Nick Piggin315e9952010-04-21 03:18:28 +00001970 struct list_head *pages, int bytes_read, char *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971{
1972 struct page *page;
1973 char *target;
1974
1975 while (bytes_read > 0) {
1976 if (list_empty(pages))
1977 break;
1978
1979 page = list_entry(pages->prev, struct page, lru);
1980 list_del(&page->lru);
1981
Nick Piggin315e9952010-04-21 03:18:28 +00001982 if (add_to_page_cache_lru(page, mapping, page->index,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 GFP_KERNEL)) {
1984 page_cache_release(page);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001985 cFYI(1, "Add page cache failed");
Steve French3079ca62005-06-09 14:44:07 -07001986 data += PAGE_CACHE_SIZE;
1987 bytes_read -= PAGE_CACHE_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 continue;
1989 }
Jeff Layton06b43672010-06-01 10:54:45 -04001990 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001992 target = kmap_atomic(page, KM_USER0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993
1994 if (PAGE_CACHE_SIZE > bytes_read) {
1995 memcpy(target, data, bytes_read);
1996 /* zero the tail end of this partial page */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001997 memset(target + bytes_read, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 PAGE_CACHE_SIZE - bytes_read);
1999 bytes_read = 0;
2000 } else {
2001 memcpy(target, data, PAGE_CACHE_SIZE);
2002 bytes_read -= PAGE_CACHE_SIZE;
2003 }
2004 kunmap_atomic(target, KM_USER0);
2005
2006 flush_dcache_page(page);
2007 SetPageUptodate(page);
2008 unlock_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 data += PAGE_CACHE_SIZE;
Suresh Jayaraman9dc06552010-07-05 18:13:11 +05302010
2011 /* add page to FS-Cache */
2012 cifs_readpage_to_fscache(mapping->host, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 }
2014 return;
2015}
2016
2017static int cifs_readpages(struct file *file, struct address_space *mapping,
2018 struct list_head *page_list, unsigned num_pages)
2019{
2020 int rc = -EACCES;
2021 int xid;
2022 loff_t offset;
2023 struct page *page;
2024 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00002025 struct cifs_tcon *pTcon;
Steve French2c2130e2007-10-12 19:10:28 +00002026 unsigned int bytes_read = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002027 unsigned int read_size, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 char *smb_read_data = NULL;
2029 struct smb_com_read_rsp *pSMBr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 struct cifsFileInfo *open_file;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002031 struct cifs_io_parms io_parms;
Steve Frenchec637e32005-12-12 20:53:18 -08002032 int buf_type = CIFS_NO_BUFFER;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002033 __u32 pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034
2035 xid = GetXid();
2036 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302037 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302039 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 }
Joe Perchesc21dfb62010-07-12 13:50:14 -07002041 open_file = file->private_data;
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002042 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Jeff Layton13cfb732010-09-29 19:51:11 -04002043 pTcon = tlink_tcon(open_file->tlink);
Steve Frenchbfa0d752005-08-31 21:50:37 -07002044
Suresh Jayaraman56698232010-07-05 18:13:25 +05302045 /*
2046 * Reads as many pages as possible from fscache. Returns -ENOBUFS
2047 * immediately if the cookie is negative
2048 */
2049 rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
2050 &num_pages);
2051 if (rc == 0)
2052 goto read_complete;
2053
Steve Frenchf19159d2010-04-21 04:12:10 +00002054 cFYI(DBG2, "rpages: num pages %d", num_pages);
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002055 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2056 pid = open_file->pid;
2057 else
2058 pid = current->tgid;
2059
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 for (i = 0; i < num_pages; ) {
2061 unsigned contig_pages;
2062 struct page *tmp_page;
2063 unsigned long expected_index;
2064
2065 if (list_empty(page_list))
2066 break;
2067
2068 page = list_entry(page_list->prev, struct page, lru);
2069 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
2070
2071 /* count adjacent pages that we will read into */
2072 contig_pages = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002073 expected_index =
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 list_entry(page_list->prev, struct page, lru)->index;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002075 list_for_each_entry_reverse(tmp_page, page_list, lru) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 if (tmp_page->index == expected_index) {
2077 contig_pages++;
2078 expected_index++;
2079 } else
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002080 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 }
2082 if (contig_pages + i > num_pages)
2083 contig_pages = num_pages - i;
2084
2085 /* for reads over a certain size could initiate async
2086 read ahead */
2087
2088 read_size = contig_pages * PAGE_CACHE_SIZE;
2089 /* Read size needs to be in multiples of one page */
2090 read_size = min_t(const unsigned int, read_size,
2091 cifs_sb->rsize & PAGE_CACHE_MASK);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002092 cFYI(DBG2, "rpages: read size 0x%x contiguous pages %d",
2093 read_size, contig_pages);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 rc = -EAGAIN;
2095 while (rc == -EAGAIN) {
Steve Frenchcdff08e2010-10-21 22:46:14 +00002096 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04002097 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 if (rc != 0)
2099 break;
2100 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002101 io_parms.netfid = open_file->netfid;
2102 io_parms.pid = pid;
2103 io_parms.tcon = pTcon;
2104 io_parms.offset = offset;
2105 io_parms.length = read_size;
2106 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
2107 &smb_read_data, &buf_type);
Steve Frencha9d02ad2005-08-24 23:06:05 -07002108 /* BB more RC checks ? */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002109 if (rc == -EAGAIN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 if (smb_read_data) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002111 if (buf_type == CIFS_SMALL_BUFFER)
Steve Frenchec637e32005-12-12 20:53:18 -08002112 cifs_small_buf_release(smb_read_data);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002113 else if (buf_type == CIFS_LARGE_BUFFER)
Steve Frenchec637e32005-12-12 20:53:18 -08002114 cifs_buf_release(smb_read_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 smb_read_data = NULL;
2116 }
2117 }
2118 }
2119 if ((rc < 0) || (smb_read_data == NULL)) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002120 cFYI(1, "Read error in readpages: %d", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 break;
2122 } else if (bytes_read > 0) {
Andrew Morton6f88cc22006-12-10 02:19:44 -08002123 task_io_account_read(bytes_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
2125 cifs_copy_cache_pages(mapping, page_list, bytes_read,
2126 smb_read_data + 4 /* RFC1001 hdr */ +
Nick Piggin315e9952010-04-21 03:18:28 +00002127 le16_to_cpu(pSMBr->DataOffset));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128
2129 i += bytes_read >> PAGE_CACHE_SHIFT;
Steve Frencha4544342005-08-24 13:59:35 -07002130 cifs_stats_bytes_read(pTcon, bytes_read);
Steve French2c2130e2007-10-12 19:10:28 +00002131 if ((bytes_read & PAGE_CACHE_MASK) != bytes_read) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 i++; /* account for partial page */
2133
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002134 /* server copy of file can have smaller size
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 than client */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002136 /* BB do we need to verify this common case ?
2137 this case is ok - if we are at server EOF
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 we will hit it on next read */
2139
OGAWA Hirofumi05ac9d42006-11-02 22:07:08 -08002140 /* break; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 }
2142 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002143 cFYI(1, "No bytes read (%d) at offset %lld . "
Steve Frenchf19159d2010-04-21 04:12:10 +00002144 "Cleaning remaining pages from readahead list",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002145 bytes_read, offset);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002146 /* BB turn off caching and do new lookup on
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 file size at server? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 break;
2149 }
2150 if (smb_read_data) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002151 if (buf_type == CIFS_SMALL_BUFFER)
Steve Frenchec637e32005-12-12 20:53:18 -08002152 cifs_small_buf_release(smb_read_data);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002153 else if (buf_type == CIFS_LARGE_BUFFER)
Steve Frenchec637e32005-12-12 20:53:18 -08002154 cifs_buf_release(smb_read_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 smb_read_data = NULL;
2156 }
2157 bytes_read = 0;
2158 }
2159
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160/* need to free smb_read_data buf before exit */
2161 if (smb_read_data) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002162 if (buf_type == CIFS_SMALL_BUFFER)
Steve French47c886b2006-01-18 14:20:39 -08002163 cifs_small_buf_release(smb_read_data);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002164 else if (buf_type == CIFS_LARGE_BUFFER)
Steve French47c886b2006-01-18 14:20:39 -08002165 cifs_buf_release(smb_read_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 smb_read_data = NULL;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168
Suresh Jayaraman56698232010-07-05 18:13:25 +05302169read_complete:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 FreeXid(xid);
2171 return rc;
2172}
2173
2174static int cifs_readpage_worker(struct file *file, struct page *page,
2175 loff_t *poffset)
2176{
2177 char *read_data;
2178 int rc;
2179
Suresh Jayaraman56698232010-07-05 18:13:25 +05302180 /* Is the page cached? */
2181 rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page);
2182 if (rc == 0)
2183 goto read_complete;
2184
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 page_cache_get(page);
2186 read_data = kmap(page);
2187 /* for reads over a certain size could initiate async read ahead */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002188
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002190
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 if (rc < 0)
2192 goto io_error;
2193 else
Joe Perchesb6b38f72010-04-21 03:50:45 +00002194 cFYI(1, "Bytes read %d", rc);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002195
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002196 file->f_path.dentry->d_inode->i_atime =
2197 current_fs_time(file->f_path.dentry->d_inode->i_sb);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002198
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 if (PAGE_CACHE_SIZE > rc)
2200 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
2201
2202 flush_dcache_page(page);
2203 SetPageUptodate(page);
Suresh Jayaraman9dc06552010-07-05 18:13:11 +05302204
2205 /* send this page to the cache */
2206 cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page);
2207
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 rc = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002209
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210io_error:
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002211 kunmap(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 page_cache_release(page);
Suresh Jayaraman56698232010-07-05 18:13:25 +05302213
2214read_complete:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 return rc;
2216}
2217
2218static int cifs_readpage(struct file *file, struct page *page)
2219{
2220 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
2221 int rc = -EACCES;
2222 int xid;
2223
2224 xid = GetXid();
2225
2226 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302227 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302229 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 }
2231
Joe Perchesb6b38f72010-04-21 03:50:45 +00002232 cFYI(1, "readpage %p at offset %d 0x%x\n",
2233 page, (int)offset, (int)offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234
2235 rc = cifs_readpage_worker(file, page, &offset);
2236
2237 unlock_page(page);
2238
2239 FreeXid(xid);
2240 return rc;
2241}
2242
Steve Frencha403a0a2007-07-26 15:54:16 +00002243static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
2244{
2245 struct cifsFileInfo *open_file;
2246
Jeff Layton44772882010-10-15 15:34:03 -04002247 spin_lock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002248 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton2e396b82010-10-15 15:34:01 -04002249 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Jeff Layton44772882010-10-15 15:34:03 -04002250 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002251 return 1;
2252 }
2253 }
Jeff Layton44772882010-10-15 15:34:03 -04002254 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002255 return 0;
2256}
2257
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258/* We do not want to update the file size from server for inodes
2259 open for write - to avoid races with writepage extending
2260 the file - in the future we could consider allowing
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002261 refreshing the inode only on increases in the file size
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262 but this is tricky to do without racing with writebehind
2263 page caching in the current Linux kernel design */
Steve French4b18f2a2008-04-29 00:06:05 +00002264bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265{
Steve Frencha403a0a2007-07-26 15:54:16 +00002266 if (!cifsInode)
Steve French4b18f2a2008-04-29 00:06:05 +00002267 return true;
Steve French23e7dd72005-10-20 13:44:56 -07002268
Steve Frencha403a0a2007-07-26 15:54:16 +00002269 if (is_inode_writable(cifsInode)) {
2270 /* This inode is open for write at least once */
Steve Frenchc32a0b62006-01-12 14:41:28 -08002271 struct cifs_sb_info *cifs_sb;
2272
Steve Frenchc32a0b62006-01-12 14:41:28 -08002273 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
Steve Frenchad7a2922008-02-07 23:25:02 +00002274 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002275 /* since no page cache to corrupt on directio
Steve Frenchc32a0b62006-01-12 14:41:28 -08002276 we can change size safely */
Steve French4b18f2a2008-04-29 00:06:05 +00002277 return true;
Steve Frenchc32a0b62006-01-12 14:41:28 -08002278 }
2279
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002280 if (i_size_read(&cifsInode->vfs_inode) < end_of_file)
Steve French4b18f2a2008-04-29 00:06:05 +00002281 return true;
Steve French7ba52632007-02-08 18:14:13 +00002282
Steve French4b18f2a2008-04-29 00:06:05 +00002283 return false;
Steve French23e7dd72005-10-20 13:44:56 -07002284 } else
Steve French4b18f2a2008-04-29 00:06:05 +00002285 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286}
2287
Nick Piggind9414772008-09-24 11:32:59 -04002288static int cifs_write_begin(struct file *file, struct address_space *mapping,
2289 loff_t pos, unsigned len, unsigned flags,
2290 struct page **pagep, void **fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291{
Nick Piggind9414772008-09-24 11:32:59 -04002292 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
2293 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002294 loff_t page_start = pos & PAGE_MASK;
2295 loff_t i_size;
2296 struct page *page;
2297 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298
Joe Perchesb6b38f72010-04-21 03:50:45 +00002299 cFYI(1, "write_begin from %lld len %d", (long long)pos, len);
Nick Piggind9414772008-09-24 11:32:59 -04002300
Nick Piggin54566b22009-01-04 12:00:53 -08002301 page = grab_cache_page_write_begin(mapping, index, flags);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002302 if (!page) {
2303 rc = -ENOMEM;
2304 goto out;
2305 }
Nick Piggind9414772008-09-24 11:32:59 -04002306
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002307 if (PageUptodate(page))
2308 goto out;
Steve French8a236262007-03-06 00:31:00 +00002309
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002310 /*
2311 * If we write a full page it will be up to date, no need to read from
2312 * the server. If the write is short, we'll end up doing a sync write
2313 * instead.
2314 */
2315 if (len == PAGE_CACHE_SIZE)
2316 goto out;
2317
2318 /*
2319 * optimize away the read when we have an oplock, and we're not
2320 * expecting to use any of the data we'd be reading in. That
2321 * is, when the page lies beyond the EOF, or straddles the EOF
2322 * and the write will cover all of the existing data.
2323 */
2324 if (CIFS_I(mapping->host)->clientCanCacheRead) {
2325 i_size = i_size_read(mapping->host);
2326 if (page_start >= i_size ||
2327 (offset == 0 && (pos + len) >= i_size)) {
2328 zero_user_segments(page, 0, offset,
2329 offset + len,
2330 PAGE_CACHE_SIZE);
2331 /*
2332 * PageChecked means that the parts of the page
2333 * to which we're not writing are considered up
2334 * to date. Once the data is copied to the
2335 * page, it can be set uptodate.
2336 */
2337 SetPageChecked(page);
2338 goto out;
2339 }
2340 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341
Nick Piggind9414772008-09-24 11:32:59 -04002342 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002343 /*
2344 * might as well read a page, it is fast enough. If we get
2345 * an error, we don't need to return it. cifs_write_end will
2346 * do a sync write instead since PG_uptodate isn't set.
2347 */
2348 cifs_readpage_worker(file, page, &page_start);
Steve French8a236262007-03-06 00:31:00 +00002349 } else {
2350 /* we could try using another file handle if there is one -
2351 but how would we lock it to prevent close of that handle
2352 racing with this read? In any case
Nick Piggind9414772008-09-24 11:32:59 -04002353 this will be written out by write_end so is fine */
Steve French8a236262007-03-06 00:31:00 +00002354 }
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002355out:
2356 *pagep = page;
2357 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358}
2359
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302360static int cifs_release_page(struct page *page, gfp_t gfp)
2361{
2362 if (PagePrivate(page))
2363 return 0;
2364
2365 return cifs_fscache_release_page(page, gfp);
2366}
2367
2368static void cifs_invalidate_page(struct page *page, unsigned long offset)
2369{
2370 struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
2371
2372 if (offset == 0)
2373 cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
2374}
2375
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002376static int cifs_launder_page(struct page *page)
2377{
2378 int rc = 0;
2379 loff_t range_start = page_offset(page);
2380 loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
2381 struct writeback_control wbc = {
2382 .sync_mode = WB_SYNC_ALL,
2383 .nr_to_write = 0,
2384 .range_start = range_start,
2385 .range_end = range_end,
2386 };
2387
2388 cFYI(1, "Launder page: %p", page);
2389
2390 if (clear_page_dirty_for_io(page))
2391 rc = cifs_writepage_locked(page, &wbc);
2392
2393 cifs_fscache_invalidate_page(page, page->mapping->host);
2394 return rc;
2395}
2396
Tejun Heo9b646972010-07-20 22:09:02 +02002397void cifs_oplock_break(struct work_struct *work)
Jeff Layton3bc303c2009-09-21 06:47:50 -04002398{
2399 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
2400 oplock_break);
Jeff Laytona5e18bc2010-10-11 15:07:18 -04002401 struct inode *inode = cfile->dentry->d_inode;
Jeff Layton3bc303c2009-09-21 06:47:50 -04002402 struct cifsInodeInfo *cinode = CIFS_I(inode);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002403 int rc = 0;
Jeff Layton3bc303c2009-09-21 06:47:50 -04002404
2405 if (inode && S_ISREG(inode->i_mode)) {
Steve Frenchd54ff732010-04-27 04:38:15 +00002406 if (cinode->clientCanCacheRead)
Al Viro8737c932009-12-24 06:47:55 -05002407 break_lease(inode, O_RDONLY);
Steve Frenchd54ff732010-04-27 04:38:15 +00002408 else
Al Viro8737c932009-12-24 06:47:55 -05002409 break_lease(inode, O_WRONLY);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002410 rc = filemap_fdatawrite(inode->i_mapping);
2411 if (cinode->clientCanCacheRead == 0) {
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002412 rc = filemap_fdatawait(inode->i_mapping);
2413 mapping_set_error(inode->i_mapping, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002414 invalidate_remote_inode(inode);
2415 }
Joe Perchesb6b38f72010-04-21 03:50:45 +00002416 cFYI(1, "Oplock flush inode %p rc %d", inode, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002417 }
2418
2419 /*
2420 * releasing stale oplock after recent reconnect of smb session using
2421 * a now incorrect file handle is not a data integrity issue but do
2422 * not bother sending an oplock release if session to server still is
2423 * disconnected since oplock already released by the server
2424 */
Steve Frenchcdff08e2010-10-21 22:46:14 +00002425 if (!cfile->oplock_break_cancelled) {
Jeff Layton13cfb732010-09-29 19:51:11 -04002426 rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0,
Pavel Shilovsky12fed002011-01-17 20:15:44 +03002427 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false,
2428 cinode->clientCanCacheRead ? 1 : 0);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002429 cFYI(1, "Oplock release rc = %d", rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002430 }
Jeff Layton3bc303c2009-09-21 06:47:50 -04002431}
2432
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07002433const struct address_space_operations cifs_addr_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434 .readpage = cifs_readpage,
2435 .readpages = cifs_readpages,
2436 .writepage = cifs_writepage,
Steve French37c0eb42005-10-05 14:50:29 -07002437 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04002438 .write_begin = cifs_write_begin,
2439 .write_end = cifs_write_end,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302441 .releasepage = cifs_release_page,
2442 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002443 .launder_page = cifs_launder_page,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444};
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002445
2446/*
2447 * cifs_readpages requires the server to support a buffer large enough to
2448 * contain the header plus one complete page of data. Otherwise, we need
2449 * to leave cifs_readpages out of the address space operations.
2450 */
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07002451const struct address_space_operations cifs_addr_ops_smallbuf = {
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002452 .readpage = cifs_readpage,
2453 .writepage = cifs_writepage,
2454 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04002455 .write_begin = cifs_write_begin,
2456 .write_end = cifs_write_end,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002457 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302458 .releasepage = cifs_release_page,
2459 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002460 .launder_page = cifs_launder_page,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002461};