blob: ab85699c565346663fd515cb45d598804e75dc9f [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
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400642static int store_file_lock(struct cifsFileInfo *cfile, __u64 len,
643 __u64 offset, __u8 type, __u16 netfid)
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000644{
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;
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400651 li->type = type;
652 li->pid = current->tgid;
653 mutex_lock(&cfile->lock_mutex);
654 list_add_tail(&li->llist, &cfile->llist);
655 mutex_unlock(&cfile->lock_mutex);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000656 return 0;
657}
658
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400659static void
660cifs_read_flock(struct file_lock *flock, __u8 *type, int *lock, int *unlock,
661 bool *wait_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662{
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400663 if (flock->fl_flags & FL_POSIX)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000664 cFYI(1, "Posix");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400665 if (flock->fl_flags & FL_FLOCK)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000666 cFYI(1, "Flock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400667 if (flock->fl_flags & FL_SLEEP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000668 cFYI(1, "Blocking lock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400669 *wait_flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 }
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400671 if (flock->fl_flags & FL_ACCESS)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000672 cFYI(1, "Process suspended by mandatory locking - "
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400673 "not implemented yet");
674 if (flock->fl_flags & FL_LEASE)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000675 cFYI(1, "Lease on file - not implemented yet");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400676 if (flock->fl_flags &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400678 cFYI(1, "Unknown lock flags 0x%x", flock->fl_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400680 *type = LOCKING_ANDX_LARGE_FILES;
681 if (flock->fl_type == F_WRLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000682 cFYI(1, "F_WRLCK ");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400683 *lock = 1;
684 } else if (flock->fl_type == F_UNLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000685 cFYI(1, "F_UNLCK");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400686 *unlock = 1;
687 /* Check if unlock includes more than one lock range */
688 } else if (flock->fl_type == F_RDLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000689 cFYI(1, "F_RDLCK");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400690 *type |= LOCKING_ANDX_SHARED_LOCK;
691 *lock = 1;
692 } else if (flock->fl_type == F_EXLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000693 cFYI(1, "F_EXLCK");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400694 *lock = 1;
695 } else if (flock->fl_type == F_SHLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000696 cFYI(1, "F_SHLCK");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400697 *type |= LOCKING_ANDX_SHARED_LOCK;
698 *lock = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +0000700 cFYI(1, "Unknown type of lock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400701}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400703static int
704cifs_getlk(struct cifsFileInfo *cfile, struct file_lock *flock, __u8 type,
705 bool wait_flag, bool posix_lck, int xid)
706{
707 int rc = 0;
708 __u64 length = 1 + flock->fl_end - flock->fl_start;
709 __u16 netfid = cfile->netfid;
710 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400712 if (posix_lck) {
713 int posix_lock_type;
714 if (type & LOCKING_ANDX_SHARED_LOCK)
715 posix_lock_type = CIFS_RDLCK;
716 else
717 posix_lock_type = CIFS_WRLCK;
718 rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */,
719 length, flock, posix_lock_type,
720 wait_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 return rc;
722 }
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000723
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400724 /* BB we could chain these into one lock request BB */
725 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length,
726 flock->fl_start, 0, 1, type, 0, 0);
727 if (rc == 0) {
728 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid,
729 length, flock->fl_start, 1, 0,
730 type, 0, 0);
731 flock->fl_type = F_UNLCK;
732 if (rc != 0)
733 cERROR(1, "Error unlocking previously locked "
734 "range %d during test of lock", rc);
735 rc = 0;
736 return rc;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000737 }
738
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400739 if (type & LOCKING_ANDX_SHARED_LOCK) {
740 flock->fl_type = F_WRLCK;
741 rc = 0;
742 return rc;
743 }
744
745 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length,
746 flock->fl_start, 0, 1,
747 type | LOCKING_ANDX_SHARED_LOCK, 0, 0);
748 if (rc == 0) {
749 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid,
750 length, flock->fl_start, 1, 0,
751 type | LOCKING_ANDX_SHARED_LOCK,
752 0, 0);
753 flock->fl_type = F_RDLCK;
754 if (rc != 0)
755 cERROR(1, "Error unlocking previously locked "
756 "range %d during test of lock", rc);
757 } else
758 flock->fl_type = F_WRLCK;
759
760 rc = 0;
761 return rc;
762}
763
764static int
765cifs_setlk(struct file *file, struct file_lock *flock, __u8 type,
766 bool wait_flag, bool posix_lck, int lock, int unlock, int xid)
767{
768 int rc = 0;
769 __u64 length = 1 + flock->fl_end - flock->fl_start;
770 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
771 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
772 __u16 netfid = cfile->netfid;
773
774 if (posix_lck) {
Steve French08547b02006-02-28 22:39:25 +0000775 int posix_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400776 if (type & LOCKING_ANDX_SHARED_LOCK)
Steve French08547b02006-02-28 22:39:25 +0000777 posix_lock_type = CIFS_RDLCK;
778 else
779 posix_lock_type = CIFS_WRLCK;
Steve French50c2f752007-07-13 00:33:32 +0000780
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400781 if (unlock == 1)
Steve Frenchbeb84dc2006-03-03 23:36:34 +0000782 posix_lock_type = CIFS_UNLCK;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000783
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400784 rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */, length,
785 flock, posix_lock_type, wait_flag);
786 goto out;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000787 }
788
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400789 if (lock) {
790 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length,
791 flock->fl_start, 0, lock, type, wait_flag, 0);
792 if (rc == 0) {
793 /* For Windows locks we must store them. */
794 rc = store_file_lock(cfile, length, flock->fl_start,
795 type, netfid);
796 }
797 } else if (unlock) {
798 /*
799 * For each stored lock that this unlock overlaps completely,
800 * unlock it.
801 */
802 int stored_rc = 0;
803 struct cifsLockInfo *li, *tmp;
804
805 mutex_lock(&cfile->lock_mutex);
806 list_for_each_entry_safe(li, tmp, &cfile->llist, llist) {
807 if (flock->fl_start > li->offset ||
808 (flock->fl_start + length) <
809 (li->offset + li->length))
810 continue;
811 if (current->tgid != li->pid)
812 continue;
813
814 stored_rc = CIFSSMBLock(xid, tcon, netfid,
815 current->tgid, li->length,
816 li->offset, 1, 0, li->type,
817 0, 0);
818 if (stored_rc)
819 rc = stored_rc;
820 else {
821 list_del(&li->llist);
822 kfree(li);
823 }
824 }
825 mutex_unlock(&cfile->lock_mutex);
826 }
827out:
828 if (flock->fl_flags & FL_POSIX)
829 posix_lock_file_wait(file, flock);
830 return rc;
831}
832
833int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
834{
835 int rc, xid;
836 int lock = 0, unlock = 0;
837 bool wait_flag = false;
838 bool posix_lck = false;
839 struct cifs_sb_info *cifs_sb;
840 struct cifs_tcon *tcon;
841 struct cifsInodeInfo *cinode;
842 struct cifsFileInfo *cfile;
843 __u16 netfid;
844 __u8 type;
845
846 rc = -EACCES;
847 xid = GetXid();
848
849 cFYI(1, "Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld "
850 "end: %lld", cmd, flock->fl_flags, flock->fl_type,
851 flock->fl_start, flock->fl_end);
852
853 cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag);
854
855 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
856 cfile = (struct cifsFileInfo *)file->private_data;
857 tcon = tlink_tcon(cfile->tlink);
858 netfid = cfile->netfid;
859 cinode = CIFS_I(file->f_path.dentry->d_inode);
860
861 if ((tcon->ses->capabilities & CAP_UNIX) &&
862 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
863 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
864 posix_lck = true;
865 /*
866 * BB add code here to normalize offset and length to account for
867 * negative length which we can not accept over the wire.
868 */
869 if (IS_GETLK(cmd)) {
870 rc = cifs_getlk(cfile, flock, type, wait_flag, posix_lck, xid);
871 FreeXid(xid);
872 return rc;
873 }
874
875 if (!lock && !unlock) {
876 /*
877 * if no lock or unlock then nothing to do since we do not
878 * know what it is
879 */
880 FreeXid(xid);
881 return -EOPNOTSUPP;
882 }
883
884 rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock,
885 xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 FreeXid(xid);
887 return rc;
888}
889
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400890/* update the file size (if needed) after a write */
Pavel Shilovsky72432ff2011-01-24 14:16:35 -0500891void
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400892cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
893 unsigned int bytes_written)
894{
895 loff_t end_of_write = offset + bytes_written;
896
897 if (end_of_write > cifsi->server_eof)
898 cifsi->server_eof = end_of_write;
899}
900
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +0400901static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
Jeff Layton7da4b492010-10-15 15:34:00 -0400902 const char *write_data, size_t write_size,
903 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904{
905 int rc = 0;
906 unsigned int bytes_written = 0;
907 unsigned int total_written;
908 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000909 struct cifs_tcon *pTcon;
Jeff Layton77499812011-01-11 07:24:23 -0500910 int xid;
Jeff Layton7da4b492010-10-15 15:34:00 -0400911 struct dentry *dentry = open_file->dentry;
912 struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +0400913 struct cifs_io_parms io_parms;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914
Jeff Layton7da4b492010-10-15 15:34:00 -0400915 cifs_sb = CIFS_SB(dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916
Joe Perchesb6b38f72010-04-21 03:50:45 +0000917 cFYI(1, "write %zd bytes to offset %lld of %s", write_size,
Jeff Layton7da4b492010-10-15 15:34:00 -0400918 *poffset, dentry->d_name.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
Jeff Layton13cfb732010-09-29 19:51:11 -0400920 pTcon = tlink_tcon(open_file->tlink);
Steve French50c2f752007-07-13 00:33:32 +0000921
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 for (total_written = 0; write_size > total_written;
925 total_written += bytes_written) {
926 rc = -EAGAIN;
927 while (rc == -EAGAIN) {
Jeff Laytonca83ce32011-04-12 09:13:44 -0400928 struct kvec iov[2];
929 unsigned int len;
930
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 if (open_file->invalidHandle) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 /* we could deadlock if we called
933 filemap_fdatawait from here so tell
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000934 reopen_file not to flush data to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 server now */
Jeff Layton15886172010-10-15 15:33:59 -0400936 rc = cifs_reopen_file(open_file, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 if (rc != 0)
938 break;
939 }
Steve French3e844692005-10-03 13:37:24 -0700940
Jeff Laytonca83ce32011-04-12 09:13:44 -0400941 len = min((size_t)cifs_sb->wsize,
942 write_size - total_written);
943 /* iov[0] is reserved for smb header */
944 iov[1].iov_base = (char *)write_data + total_written;
945 iov[1].iov_len = len;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +0400946 io_parms.netfid = open_file->netfid;
947 io_parms.pid = pid;
948 io_parms.tcon = pTcon;
949 io_parms.offset = *poffset;
950 io_parms.length = len;
951 rc = CIFSSMBWrite2(xid, &io_parms, &bytes_written, iov,
952 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 }
954 if (rc || (bytes_written == 0)) {
955 if (total_written)
956 break;
957 else {
958 FreeXid(xid);
959 return rc;
960 }
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400961 } else {
962 cifs_update_eof(cifsi, *poffset, bytes_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 *poffset += bytes_written;
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400964 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 }
966
Steve Frencha4544342005-08-24 13:59:35 -0700967 cifs_stats_bytes_written(pTcon, total_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968
Jeff Layton7da4b492010-10-15 15:34:00 -0400969 if (total_written > 0) {
970 spin_lock(&dentry->d_inode->i_lock);
971 if (*poffset > dentry->d_inode->i_size)
972 i_size_write(dentry->d_inode, *poffset);
973 spin_unlock(&dentry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 }
Jeff Layton7da4b492010-10-15 15:34:00 -0400975 mark_inode_dirty_sync(dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 FreeXid(xid);
977 return total_written;
978}
979
Jeff Layton6508d902010-09-29 19:51:11 -0400980struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
981 bool fsuid_only)
Steve French630f3f0c2007-10-25 21:17:17 +0000982{
983 struct cifsFileInfo *open_file = NULL;
Jeff Layton6508d902010-09-29 19:51:11 -0400984 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
985
986 /* only filter by fsuid on multiuser mounts */
987 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
988 fsuid_only = false;
Steve French630f3f0c2007-10-25 21:17:17 +0000989
Jeff Layton44772882010-10-15 15:34:03 -0400990 spin_lock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +0000991 /* we could simply get the first_list_entry since write-only entries
992 are always at the end of the list but since the first entry might
993 have a close pending, we go through the whole list */
994 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -0400995 if (fsuid_only && open_file->uid != current_fsuid())
996 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -0400997 if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
Steve French630f3f0c2007-10-25 21:17:17 +0000998 if (!open_file->invalidHandle) {
999 /* found a good file */
1000 /* lock it so it will not be closed on us */
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001001 cifsFileInfo_get(open_file);
Jeff Layton44772882010-10-15 15:34:03 -04001002 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001003 return open_file;
1004 } /* else might as well continue, and look for
1005 another, or simply have the caller reopen it
1006 again rather than trying to fix this handle */
1007 } else /* write only file */
1008 break; /* write only files are last so must be done */
1009 }
Jeff Layton44772882010-10-15 15:34:03 -04001010 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001011 return NULL;
1012}
Steve French630f3f0c2007-10-25 21:17:17 +00001013
Jeff Layton6508d902010-09-29 19:51:11 -04001014struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1015 bool fsuid_only)
Steve French6148a742005-10-05 12:23:19 -07001016{
1017 struct cifsFileInfo *open_file;
Jeff Laytond3892292010-11-02 16:22:50 -04001018 struct cifs_sb_info *cifs_sb;
Jeff Layton2846d382008-09-22 21:33:33 -04001019 bool any_available = false;
Steve Frenchdd99cd82005-10-05 19:32:49 -07001020 int rc;
Steve French6148a742005-10-05 12:23:19 -07001021
Steve French60808232006-04-22 15:53:05 +00001022 /* Having a null inode here (because mapping->host was set to zero by
1023 the VFS or MM) should not happen but we had reports of on oops (due to
1024 it being zero) during stress testcases so we need to check for it */
1025
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001026 if (cifs_inode == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001027 cERROR(1, "Null inode passed to cifs_writeable_file");
Steve French60808232006-04-22 15:53:05 +00001028 dump_stack();
1029 return NULL;
1030 }
1031
Jeff Laytond3892292010-11-02 16:22:50 -04001032 cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1033
Jeff Layton6508d902010-09-29 19:51:11 -04001034 /* only filter by fsuid on multiuser mounts */
1035 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1036 fsuid_only = false;
1037
Jeff Layton44772882010-10-15 15:34:03 -04001038 spin_lock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001039refind_writable:
Steve French6148a742005-10-05 12:23:19 -07001040 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001041 if (!any_available && open_file->pid != current->tgid)
1042 continue;
1043 if (fsuid_only && open_file->uid != current_fsuid())
1044 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001045 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001046 cifsFileInfo_get(open_file);
Steve French9b22b0b2007-10-02 01:11:08 +00001047
1048 if (!open_file->invalidHandle) {
1049 /* found a good writable file */
Jeff Layton44772882010-10-15 15:34:03 -04001050 spin_unlock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001051 return open_file;
1052 }
Steve French8840dee2007-11-16 23:05:52 +00001053
Jeff Layton44772882010-10-15 15:34:03 -04001054 spin_unlock(&cifs_file_list_lock);
Steve Frenchcdff08e2010-10-21 22:46:14 +00001055
Steve French9b22b0b2007-10-02 01:11:08 +00001056 /* Had to unlock since following call can block */
Jeff Layton15886172010-10-15 15:33:59 -04001057 rc = cifs_reopen_file(open_file, false);
Steve Frenchcdff08e2010-10-21 22:46:14 +00001058 if (!rc)
1059 return open_file;
Steve French9b22b0b2007-10-02 01:11:08 +00001060
Steve Frenchcdff08e2010-10-21 22:46:14 +00001061 /* if it fails, try another handle if possible */
Joe Perchesb6b38f72010-04-21 03:50:45 +00001062 cFYI(1, "wp failed on reopen file");
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001063 cifsFileInfo_put(open_file);
Steve French8840dee2007-11-16 23:05:52 +00001064
Steve Frenchcdff08e2010-10-21 22:46:14 +00001065 spin_lock(&cifs_file_list_lock);
1066
Steve French9b22b0b2007-10-02 01:11:08 +00001067 /* else we simply continue to the next entry. Thus
1068 we do not loop on reopen errors. If we
1069 can not reopen the file, for example if we
1070 reconnected to a server with another client
1071 racing to delete or lock the file we would not
1072 make progress if we restarted before the beginning
1073 of the loop here. */
Steve French6148a742005-10-05 12:23:19 -07001074 }
1075 }
Jeff Layton2846d382008-09-22 21:33:33 -04001076 /* couldn't find useable FH with same pid, try any available */
1077 if (!any_available) {
1078 any_available = true;
1079 goto refind_writable;
1080 }
Jeff Layton44772882010-10-15 15:34:03 -04001081 spin_unlock(&cifs_file_list_lock);
Steve French6148a742005-10-05 12:23:19 -07001082 return NULL;
1083}
1084
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1086{
1087 struct address_space *mapping = page->mapping;
1088 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1089 char *write_data;
1090 int rc = -EFAULT;
1091 int bytes_written = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 struct inode *inode;
Steve French6148a742005-10-05 12:23:19 -07001093 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
1095 if (!mapping || !mapping->host)
1096 return -EFAULT;
1097
1098 inode = page->mapping->host;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
1100 offset += (loff_t)from;
1101 write_data = kmap(page);
1102 write_data += from;
1103
1104 if ((to > PAGE_CACHE_SIZE) || (from > to)) {
1105 kunmap(page);
1106 return -EIO;
1107 }
1108
1109 /* racing with truncate? */
1110 if (offset > mapping->host->i_size) {
1111 kunmap(page);
1112 return 0; /* don't care */
1113 }
1114
1115 /* check to make sure that we are not extending the file */
1116 if (mapping->host->i_size - offset < (loff_t)to)
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001117 to = (unsigned)(mapping->host->i_size - offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118
Jeff Layton6508d902010-09-29 19:51:11 -04001119 open_file = find_writable_file(CIFS_I(mapping->host), false);
Steve French6148a742005-10-05 12:23:19 -07001120 if (open_file) {
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001121 bytes_written = cifs_write(open_file, open_file->pid,
1122 write_data, to - from, &offset);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001123 cifsFileInfo_put(open_file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 /* Does mm or vfs already set times? */
Steve French6148a742005-10-05 12:23:19 -07001125 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001126 if ((bytes_written > 0) && (offset))
Steve French6148a742005-10-05 12:23:19 -07001127 rc = 0;
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001128 else if (bytes_written < 0)
1129 rc = bytes_written;
Steve French6148a742005-10-05 12:23:19 -07001130 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001131 cFYI(1, "No writeable filehandles for inode");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 rc = -EIO;
1133 }
1134
1135 kunmap(page);
1136 return rc;
1137}
1138
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139static int cifs_writepages(struct address_space *mapping,
Steve French37c0eb42005-10-05 14:50:29 -07001140 struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141{
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001142 struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb);
1143 bool done = false, scanned = false, range_whole = false;
1144 pgoff_t end, index;
1145 struct cifs_writedata *wdata;
Steve French37c0eb42005-10-05 14:50:29 -07001146 struct page *page;
Steve French37c0eb42005-10-05 14:50:29 -07001147 int rc = 0;
Steve French50c2f752007-07-13 00:33:32 +00001148
Steve French37c0eb42005-10-05 14:50:29 -07001149 /*
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001150 * If wsize is smaller than the page cache size, default to writing
Steve French37c0eb42005-10-05 14:50:29 -07001151 * one page at a time via cifs_writepage
1152 */
1153 if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1154 return generic_writepages(mapping, wbc);
1155
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001156 if (wbc->range_cyclic) {
Steve French37c0eb42005-10-05 14:50:29 -07001157 index = mapping->writeback_index; /* Start from prev offset */
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001158 end = -1;
1159 } else {
1160 index = wbc->range_start >> PAGE_CACHE_SHIFT;
1161 end = wbc->range_end >> PAGE_CACHE_SHIFT;
1162 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001163 range_whole = true;
1164 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001165 }
1166retry:
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001167 while (!done && index <= end) {
1168 unsigned int i, nr_pages, found_pages;
1169 pgoff_t next = 0, tofind;
1170 struct page **pages;
Steve French37c0eb42005-10-05 14:50:29 -07001171
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001172 tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1,
1173 end - index) + 1;
Steve French37c0eb42005-10-05 14:50:29 -07001174
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001175 wdata = cifs_writedata_alloc((unsigned int)tofind);
1176 if (!wdata) {
1177 rc = -ENOMEM;
1178 break;
1179 }
1180
1181 /*
1182 * find_get_pages_tag seems to return a max of 256 on each
1183 * iteration, so we must call it several times in order to
1184 * fill the array or the wsize is effectively limited to
1185 * 256 * PAGE_CACHE_SIZE.
1186 */
1187 found_pages = 0;
1188 pages = wdata->pages;
1189 do {
1190 nr_pages = find_get_pages_tag(mapping, &index,
1191 PAGECACHE_TAG_DIRTY,
1192 tofind, pages);
1193 found_pages += nr_pages;
1194 tofind -= nr_pages;
1195 pages += nr_pages;
1196 } while (nr_pages && tofind && index <= end);
1197
1198 if (found_pages == 0) {
1199 kref_put(&wdata->refcount, cifs_writedata_release);
1200 break;
1201 }
1202
1203 nr_pages = 0;
1204 for (i = 0; i < found_pages; i++) {
1205 page = wdata->pages[i];
Steve French37c0eb42005-10-05 14:50:29 -07001206 /*
1207 * At this point we hold neither mapping->tree_lock nor
1208 * lock on the page itself: the page may be truncated or
1209 * invalidated (changing page->mapping to NULL), or even
1210 * swizzled back from swapper_space to tmpfs file
1211 * mapping
1212 */
1213
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001214 if (nr_pages == 0)
Steve French37c0eb42005-10-05 14:50:29 -07001215 lock_page(page);
Nick Piggin529ae9a2008-08-02 12:01:03 +02001216 else if (!trylock_page(page))
Steve French37c0eb42005-10-05 14:50:29 -07001217 break;
1218
1219 if (unlikely(page->mapping != mapping)) {
1220 unlock_page(page);
1221 break;
1222 }
1223
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001224 if (!wbc->range_cyclic && page->index > end) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001225 done = true;
Steve French37c0eb42005-10-05 14:50:29 -07001226 unlock_page(page);
1227 break;
1228 }
1229
1230 if (next && (page->index != next)) {
1231 /* Not next consecutive page */
1232 unlock_page(page);
1233 break;
1234 }
1235
1236 if (wbc->sync_mode != WB_SYNC_NONE)
1237 wait_on_page_writeback(page);
1238
1239 if (PageWriteback(page) ||
Linus Torvaldscb876f42006-12-23 16:19:07 -08001240 !clear_page_dirty_for_io(page)) {
Steve French37c0eb42005-10-05 14:50:29 -07001241 unlock_page(page);
1242 break;
1243 }
Steve French84d2f072005-10-12 15:32:05 -07001244
Linus Torvaldscb876f42006-12-23 16:19:07 -08001245 /*
1246 * This actually clears the dirty bit in the radix tree.
1247 * See cifs_writepage() for more commentary.
1248 */
1249 set_page_writeback(page);
1250
Steve French84d2f072005-10-12 15:32:05 -07001251 if (page_offset(page) >= mapping->host->i_size) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001252 done = true;
Steve French84d2f072005-10-12 15:32:05 -07001253 unlock_page(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001254 end_page_writeback(page);
Steve French84d2f072005-10-12 15:32:05 -07001255 break;
1256 }
1257
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001258 wdata->pages[i] = page;
Steve French37c0eb42005-10-05 14:50:29 -07001259 next = page->index + 1;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001260 ++nr_pages;
Steve French37c0eb42005-10-05 14:50:29 -07001261 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001262
1263 /* reset index to refind any pages skipped */
1264 if (nr_pages == 0)
1265 index = wdata->pages[0]->index + 1;
1266
1267 /* put any pages we aren't going to use */
1268 for (i = nr_pages; i < found_pages; i++) {
1269 page_cache_release(wdata->pages[i]);
1270 wdata->pages[i] = NULL;
1271 }
1272
1273 /* nothing to write? */
1274 if (nr_pages == 0) {
1275 kref_put(&wdata->refcount, cifs_writedata_release);
1276 continue;
1277 }
1278
1279 wdata->sync_mode = wbc->sync_mode;
1280 wdata->nr_pages = nr_pages;
1281 wdata->offset = page_offset(wdata->pages[0]);
1282
1283 do {
1284 if (wdata->cfile != NULL)
1285 cifsFileInfo_put(wdata->cfile);
1286 wdata->cfile = find_writable_file(CIFS_I(mapping->host),
1287 false);
1288 if (!wdata->cfile) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001289 cERROR(1, "No writable handles for inode");
Steve French23e7dd72005-10-20 13:44:56 -07001290 rc = -EBADF;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001291 break;
Steve French37c0eb42005-10-05 14:50:29 -07001292 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001293 rc = cifs_async_writev(wdata);
1294 } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN);
Jeff Laytonf3983c22010-09-22 16:17:40 -07001295
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001296 for (i = 0; i < nr_pages; ++i)
1297 unlock_page(wdata->pages[i]);
Jeff Layton941b8532011-01-11 07:24:01 -05001298
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001299 /* send failure -- clean up the mess */
1300 if (rc != 0) {
1301 for (i = 0; i < nr_pages; ++i) {
Jeff Layton941b8532011-01-11 07:24:01 -05001302 if (rc == -EAGAIN)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001303 redirty_page_for_writepage(wbc,
1304 wdata->pages[i]);
1305 else
1306 SetPageError(wdata->pages[i]);
1307 end_page_writeback(wdata->pages[i]);
1308 page_cache_release(wdata->pages[i]);
Steve French37c0eb42005-10-05 14:50:29 -07001309 }
Jeff Layton941b8532011-01-11 07:24:01 -05001310 if (rc != -EAGAIN)
1311 mapping_set_error(mapping, rc);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001312 }
1313 kref_put(&wdata->refcount, cifs_writedata_release);
Jeff Layton941b8532011-01-11 07:24:01 -05001314
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001315 wbc->nr_to_write -= nr_pages;
1316 if (wbc->nr_to_write <= 0)
1317 done = true;
Dave Kleikampb066a482008-11-18 03:49:05 +00001318
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001319 index = next;
Steve French37c0eb42005-10-05 14:50:29 -07001320 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001321
Steve French37c0eb42005-10-05 14:50:29 -07001322 if (!scanned && !done) {
1323 /*
1324 * We hit the last page and there is more work to be done: wrap
1325 * back to the start of the file
1326 */
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001327 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001328 index = 0;
1329 goto retry;
1330 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001331
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001332 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
Steve French37c0eb42005-10-05 14:50:29 -07001333 mapping->writeback_index = index;
1334
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 return rc;
1336}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001338static int
1339cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340{
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001341 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 int xid;
1343
1344 xid = GetXid();
1345/* BB add check for wbc flags */
1346 page_cache_get(page);
Steve Frenchad7a2922008-02-07 23:25:02 +00001347 if (!PageUptodate(page))
Joe Perchesb6b38f72010-04-21 03:50:45 +00001348 cFYI(1, "ppw - page not up to date");
Linus Torvaldscb876f42006-12-23 16:19:07 -08001349
1350 /*
1351 * Set the "writeback" flag, and clear "dirty" in the radix tree.
1352 *
1353 * A writepage() implementation always needs to do either this,
1354 * or re-dirty the page with "redirty_page_for_writepage()" in
1355 * the case of a failure.
1356 *
1357 * Just unlocking the page will cause the radix tree tag-bits
1358 * to fail to update with the state of the page correctly.
1359 */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001360 set_page_writeback(page);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001361retry_write:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001363 if (rc == -EAGAIN && wbc->sync_mode == WB_SYNC_ALL)
1364 goto retry_write;
1365 else if (rc == -EAGAIN)
1366 redirty_page_for_writepage(wbc, page);
1367 else if (rc != 0)
1368 SetPageError(page);
1369 else
1370 SetPageUptodate(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001371 end_page_writeback(page);
1372 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 FreeXid(xid);
1374 return rc;
1375}
1376
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001377static int cifs_writepage(struct page *page, struct writeback_control *wbc)
1378{
1379 int rc = cifs_writepage_locked(page, wbc);
1380 unlock_page(page);
1381 return rc;
1382}
1383
Nick Piggind9414772008-09-24 11:32:59 -04001384static int cifs_write_end(struct file *file, struct address_space *mapping,
1385 loff_t pos, unsigned len, unsigned copied,
1386 struct page *page, void *fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387{
Nick Piggind9414772008-09-24 11:32:59 -04001388 int rc;
1389 struct inode *inode = mapping->host;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001390 struct cifsFileInfo *cfile = file->private_data;
1391 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
1392 __u32 pid;
1393
1394 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1395 pid = cfile->pid;
1396 else
1397 pid = current->tgid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
Joe Perchesb6b38f72010-04-21 03:50:45 +00001399 cFYI(1, "write_end for page %p from pos %lld with %d bytes",
1400 page, pos, copied);
Steve Frenchad7a2922008-02-07 23:25:02 +00001401
Jeff Laytona98ee8c2008-11-26 19:32:33 +00001402 if (PageChecked(page)) {
1403 if (copied == len)
1404 SetPageUptodate(page);
1405 ClearPageChecked(page);
1406 } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
Nick Piggind9414772008-09-24 11:32:59 -04001407 SetPageUptodate(page);
1408
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 if (!PageUptodate(page)) {
Nick Piggind9414772008-09-24 11:32:59 -04001410 char *page_data;
1411 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
1412 int xid;
1413
1414 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 /* this is probably better than directly calling
1416 partialpage_write since in this function the file handle is
1417 known which we might as well leverage */
1418 /* BB check if anything else missing out of ppw
1419 such as updating last write time */
1420 page_data = kmap(page);
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001421 rc = cifs_write(cfile, pid, page_data + offset, copied, &pos);
Nick Piggind9414772008-09-24 11:32:59 -04001422 /* if (rc < 0) should we set writebehind rc? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 kunmap(page);
Nick Piggind9414772008-09-24 11:32:59 -04001424
1425 FreeXid(xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001426 } else {
Nick Piggind9414772008-09-24 11:32:59 -04001427 rc = copied;
1428 pos += copied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 set_page_dirty(page);
1430 }
1431
Nick Piggind9414772008-09-24 11:32:59 -04001432 if (rc > 0) {
1433 spin_lock(&inode->i_lock);
1434 if (pos > inode->i_size)
1435 i_size_write(inode, pos);
1436 spin_unlock(&inode->i_lock);
1437 }
1438
1439 unlock_page(page);
1440 page_cache_release(page);
1441
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 return rc;
1443}
1444
Josef Bacik02c24a82011-07-16 20:44:56 -04001445int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
1446 int datasync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447{
1448 int xid;
1449 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00001450 struct cifs_tcon *tcon;
Joe Perchesc21dfb62010-07-12 13:50:14 -07001451 struct cifsFileInfo *smbfile = file->private_data;
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08001452 struct inode *inode = file->f_path.dentry->d_inode;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001453 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
Josef Bacik02c24a82011-07-16 20:44:56 -04001455 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
1456 if (rc)
1457 return rc;
1458 mutex_lock(&inode->i_mutex);
1459
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 xid = GetXid();
1461
Joe Perchesb6b38f72010-04-21 03:50:45 +00001462 cFYI(1, "Sync file - name: %s datasync: 0x%x",
Christoph Hellwig7ea80852010-05-26 17:53:25 +02001463 file->f_path.dentry->d_name.name, datasync);
Steve French50c2f752007-07-13 00:33:32 +00001464
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001465 if (!CIFS_I(inode)->clientCanCacheRead) {
1466 rc = cifs_invalidate_mapping(inode);
1467 if (rc) {
1468 cFYI(1, "rc: %d during invalidate phase", rc);
1469 rc = 0; /* don't care about it in fsync */
1470 }
1471 }
Jeff Laytoneb4b7562010-10-22 14:52:29 -04001472
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001473 tcon = tlink_tcon(smbfile->tlink);
1474 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
1475 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
1476
1477 FreeXid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04001478 mutex_unlock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001479 return rc;
1480}
1481
Josef Bacik02c24a82011-07-16 20:44:56 -04001482int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001483{
1484 int xid;
1485 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00001486 struct cifs_tcon *tcon;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001487 struct cifsFileInfo *smbfile = file->private_data;
1488 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Josef Bacik02c24a82011-07-16 20:44:56 -04001489 struct inode *inode = file->f_mapping->host;
1490
1491 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
1492 if (rc)
1493 return rc;
1494 mutex_lock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001495
1496 xid = GetXid();
1497
1498 cFYI(1, "Sync file - name: %s datasync: 0x%x",
1499 file->f_path.dentry->d_name.name, datasync);
1500
1501 tcon = tlink_tcon(smbfile->tlink);
1502 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
1503 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
Steve Frenchb298f222009-02-21 21:17:43 +00001504
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 FreeXid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04001506 mutex_unlock(&inode->i_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 return rc;
1508}
1509
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510/*
1511 * As file closes, flush all cached write data for this inode checking
1512 * for write behind errors.
1513 */
Miklos Szeredi75e1fcc2006-06-23 02:05:12 -07001514int cifs_flush(struct file *file, fl_owner_t id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515{
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001516 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 int rc = 0;
1518
Jeff Laytoneb4b7562010-10-22 14:52:29 -04001519 if (file->f_mode & FMODE_WRITE)
Jeff Laytond3f13222010-10-15 15:34:07 -04001520 rc = filemap_write_and_wait(inode->i_mapping);
Steve French50c2f752007-07-13 00:33:32 +00001521
Joe Perchesb6b38f72010-04-21 03:50:45 +00001522 cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
1524 return rc;
1525}
1526
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001527static int
1528cifs_write_allocate_pages(struct page **pages, unsigned long num_pages)
1529{
1530 int rc = 0;
1531 unsigned long i;
1532
1533 for (i = 0; i < num_pages; i++) {
1534 pages[i] = alloc_page(__GFP_HIGHMEM);
1535 if (!pages[i]) {
1536 /*
1537 * save number of pages we have already allocated and
1538 * return with ENOMEM error
1539 */
1540 num_pages = i;
1541 rc = -ENOMEM;
1542 goto error;
1543 }
1544 }
1545
1546 return rc;
1547
1548error:
1549 for (i = 0; i < num_pages; i++)
1550 put_page(pages[i]);
1551 return rc;
1552}
1553
1554static inline
1555size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
1556{
1557 size_t num_pages;
1558 size_t clen;
1559
1560 clen = min_t(const size_t, len, wsize);
1561 num_pages = clen / PAGE_CACHE_SIZE;
1562 if (clen % PAGE_CACHE_SIZE)
1563 num_pages++;
1564
1565 if (cur_len)
1566 *cur_len = clen;
1567
1568 return num_pages;
1569}
1570
1571static ssize_t
1572cifs_iovec_write(struct file *file, const struct iovec *iov,
1573 unsigned long nr_segs, loff_t *poffset)
1574{
Pavel Shilovsky76429c12011-01-31 16:03:08 +03001575 unsigned int written;
1576 unsigned long num_pages, npages, i;
1577 size_t copied, len, cur_len;
1578 ssize_t total_written = 0;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001579 struct kvec *to_send;
1580 struct page **pages;
1581 struct iov_iter it;
1582 struct inode *inode;
1583 struct cifsFileInfo *open_file;
Steve French96daf2b2011-05-27 04:34:02 +00001584 struct cifs_tcon *pTcon;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001585 struct cifs_sb_info *cifs_sb;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001586 struct cifs_io_parms io_parms;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001587 int xid, rc;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001588 __u32 pid;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001589
1590 len = iov_length(iov, nr_segs);
1591 if (!len)
1592 return 0;
1593
1594 rc = generic_write_checks(file, poffset, &len, 0);
1595 if (rc)
1596 return rc;
1597
1598 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1599 num_pages = get_numpages(cifs_sb->wsize, len, &cur_len);
1600
1601 pages = kmalloc(sizeof(struct pages *)*num_pages, GFP_KERNEL);
1602 if (!pages)
1603 return -ENOMEM;
1604
1605 to_send = kmalloc(sizeof(struct kvec)*(num_pages + 1), GFP_KERNEL);
1606 if (!to_send) {
1607 kfree(pages);
1608 return -ENOMEM;
1609 }
1610
1611 rc = cifs_write_allocate_pages(pages, num_pages);
1612 if (rc) {
1613 kfree(pages);
1614 kfree(to_send);
1615 return rc;
1616 }
1617
1618 xid = GetXid();
1619 open_file = file->private_data;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001620
1621 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1622 pid = open_file->pid;
1623 else
1624 pid = current->tgid;
1625
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001626 pTcon = tlink_tcon(open_file->tlink);
1627 inode = file->f_path.dentry->d_inode;
1628
1629 iov_iter_init(&it, iov, nr_segs, len, 0);
1630 npages = num_pages;
1631
1632 do {
1633 size_t save_len = cur_len;
1634 for (i = 0; i < npages; i++) {
1635 copied = min_t(const size_t, cur_len, PAGE_CACHE_SIZE);
1636 copied = iov_iter_copy_from_user(pages[i], &it, 0,
1637 copied);
1638 cur_len -= copied;
1639 iov_iter_advance(&it, copied);
1640 to_send[i+1].iov_base = kmap(pages[i]);
1641 to_send[i+1].iov_len = copied;
1642 }
1643
1644 cur_len = save_len - cur_len;
1645
1646 do {
1647 if (open_file->invalidHandle) {
1648 rc = cifs_reopen_file(open_file, false);
1649 if (rc != 0)
1650 break;
1651 }
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001652 io_parms.netfid = open_file->netfid;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001653 io_parms.pid = pid;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001654 io_parms.tcon = pTcon;
1655 io_parms.offset = *poffset;
1656 io_parms.length = cur_len;
1657 rc = CIFSSMBWrite2(xid, &io_parms, &written, to_send,
1658 npages, 0);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001659 } while (rc == -EAGAIN);
1660
1661 for (i = 0; i < npages; i++)
1662 kunmap(pages[i]);
1663
1664 if (written) {
1665 len -= written;
1666 total_written += written;
1667 cifs_update_eof(CIFS_I(inode), *poffset, written);
1668 *poffset += written;
1669 } else if (rc < 0) {
1670 if (!total_written)
1671 total_written = rc;
1672 break;
1673 }
1674
1675 /* get length and number of kvecs of the next write */
1676 npages = get_numpages(cifs_sb->wsize, len, &cur_len);
1677 } while (len > 0);
1678
1679 if (total_written > 0) {
1680 spin_lock(&inode->i_lock);
1681 if (*poffset > inode->i_size)
1682 i_size_write(inode, *poffset);
1683 spin_unlock(&inode->i_lock);
1684 }
1685
1686 cifs_stats_bytes_written(pTcon, total_written);
1687 mark_inode_dirty_sync(inode);
1688
1689 for (i = 0; i < num_pages; i++)
1690 put_page(pages[i]);
1691 kfree(to_send);
1692 kfree(pages);
1693 FreeXid(xid);
1694 return total_written;
1695}
1696
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03001697ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001698 unsigned long nr_segs, loff_t pos)
1699{
1700 ssize_t written;
1701 struct inode *inode;
1702
1703 inode = iocb->ki_filp->f_path.dentry->d_inode;
1704
1705 /*
1706 * BB - optimize the way when signing is disabled. We can drop this
1707 * extra memory-to-memory copying and use iovec buffers for constructing
1708 * write request.
1709 */
1710
1711 written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos);
1712 if (written > 0) {
1713 CIFS_I(inode)->invalid_mapping = true;
1714 iocb->ki_pos = pos;
1715 }
1716
1717 return written;
1718}
1719
1720ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
1721 unsigned long nr_segs, loff_t pos)
1722{
1723 struct inode *inode;
1724
1725 inode = iocb->ki_filp->f_path.dentry->d_inode;
1726
1727 if (CIFS_I(inode)->clientCanCacheAll)
1728 return generic_file_aio_write(iocb, iov, nr_segs, pos);
1729
1730 /*
1731 * In strict cache mode we need to write the data to the server exactly
1732 * from the pos to pos+len-1 rather than flush all affected pages
1733 * because it may cause a error with mandatory locks on these pages but
1734 * not on the region from pos to ppos+len-1.
1735 */
1736
1737 return cifs_user_writev(iocb, iov, nr_segs, pos);
1738}
1739
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001740static ssize_t
1741cifs_iovec_read(struct file *file, const struct iovec *iov,
1742 unsigned long nr_segs, loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743{
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001744 int rc;
1745 int xid;
Pavel Shilovsky76429c12011-01-31 16:03:08 +03001746 ssize_t total_read;
1747 unsigned int bytes_read = 0;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001748 size_t len, cur_len;
1749 int iov_offset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00001751 struct cifs_tcon *pTcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 struct smb_com_read_rsp *pSMBr;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001754 struct cifs_io_parms io_parms;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001755 char *read_data;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001756 __u32 pid;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001757
1758 if (!nr_segs)
1759 return 0;
1760
1761 len = iov_length(iov, nr_segs);
1762 if (!len)
1763 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764
1765 xid = GetXid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08001766 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767
Joe Perchesc21dfb62010-07-12 13:50:14 -07001768 open_file = file->private_data;
Jeff Layton13cfb732010-09-29 19:51:11 -04001769 pTcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001771 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1772 pid = open_file->pid;
1773 else
1774 pid = current->tgid;
1775
Steve Frenchad7a2922008-02-07 23:25:02 +00001776 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001777 cFYI(1, "attempting read on write only file instance");
Steve Frenchad7a2922008-02-07 23:25:02 +00001778
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001779 for (total_read = 0; total_read < len; total_read += bytes_read) {
1780 cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 rc = -EAGAIN;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001782 read_data = NULL;
1783
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 while (rc == -EAGAIN) {
Steve Frenchec637e32005-12-12 20:53:18 -08001785 int buf_type = CIFS_NO_BUFFER;
Steve Frenchcdff08e2010-10-21 22:46:14 +00001786 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04001787 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 if (rc != 0)
1789 break;
1790 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001791 io_parms.netfid = open_file->netfid;
1792 io_parms.pid = pid;
1793 io_parms.tcon = pTcon;
1794 io_parms.offset = *poffset;
Pavel Shilovsky2cebaa52011-07-20 18:24:09 +04001795 io_parms.length = cur_len;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001796 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001797 &read_data, &buf_type);
1798 pSMBr = (struct smb_com_read_rsp *)read_data;
1799 if (read_data) {
1800 char *data_offset = read_data + 4 +
1801 le16_to_cpu(pSMBr->DataOffset);
1802 if (memcpy_toiovecend(iov, data_offset,
1803 iov_offset, bytes_read))
Steve French93544cc2006-02-14 22:30:52 -06001804 rc = -EFAULT;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001805 if (buf_type == CIFS_SMALL_BUFFER)
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001806 cifs_small_buf_release(read_data);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001807 else if (buf_type == CIFS_LARGE_BUFFER)
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001808 cifs_buf_release(read_data);
1809 read_data = NULL;
1810 iov_offset += bytes_read;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 }
1812 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001813
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 if (rc || (bytes_read == 0)) {
1815 if (total_read) {
1816 break;
1817 } else {
1818 FreeXid(xid);
1819 return rc;
1820 }
1821 } else {
Steve Frencha4544342005-08-24 13:59:35 -07001822 cifs_stats_bytes_read(pTcon, bytes_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 *poffset += bytes_read;
1824 }
1825 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001826
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 FreeXid(xid);
1828 return total_read;
1829}
1830
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03001831ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001832 unsigned long nr_segs, loff_t pos)
1833{
1834 ssize_t read;
1835
1836 read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos);
1837 if (read > 0)
1838 iocb->ki_pos = pos;
1839
1840 return read;
1841}
1842
1843ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov,
1844 unsigned long nr_segs, loff_t pos)
1845{
1846 struct inode *inode;
1847
1848 inode = iocb->ki_filp->f_path.dentry->d_inode;
1849
1850 if (CIFS_I(inode)->clientCanCacheRead)
1851 return generic_file_aio_read(iocb, iov, nr_segs, pos);
1852
1853 /*
1854 * In strict cache mode we need to read from the server all the time
1855 * if we don't have level II oplock because the server can delay mtime
1856 * change - so we can't make a decision about inode invalidating.
1857 * And we can also fail with pagereading if there are mandatory locks
1858 * on pages affected by this read but not on the region from pos to
1859 * pos+len-1.
1860 */
1861
1862 return cifs_user_readv(iocb, iov, nr_segs, pos);
1863}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
1865static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001866 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867{
1868 int rc = -EACCES;
1869 unsigned int bytes_read = 0;
1870 unsigned int total_read;
1871 unsigned int current_read_size;
1872 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00001873 struct cifs_tcon *pTcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 int xid;
1875 char *current_offset;
1876 struct cifsFileInfo *open_file;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001877 struct cifs_io_parms io_parms;
Steve Frenchec637e32005-12-12 20:53:18 -08001878 int buf_type = CIFS_NO_BUFFER;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001879 __u32 pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880
1881 xid = GetXid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08001882 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883
1884 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301885 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301887 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 }
Joe Perchesc21dfb62010-07-12 13:50:14 -07001889 open_file = file->private_data;
Jeff Layton13cfb732010-09-29 19:51:11 -04001890 pTcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001892 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1893 pid = open_file->pid;
1894 else
1895 pid = current->tgid;
1896
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001898 cFYI(1, "attempting read on write only file instance");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001900 for (total_read = 0, current_offset = read_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 read_size > total_read;
1902 total_read += bytes_read, current_offset += bytes_read) {
1903 current_read_size = min_t(const int, read_size - total_read,
1904 cifs_sb->rsize);
Steve Frenchf9f5c8172005-09-15 23:06:38 -07001905 /* For windows me and 9x we do not want to request more
1906 than it negotiated since it will refuse the read then */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001907 if ((pTcon->ses) &&
Steve Frenchf9f5c8172005-09-15 23:06:38 -07001908 !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
1909 current_read_size = min_t(const int, current_read_size,
Jeff Laytonc974bef2011-10-11 06:41:32 -04001910 CIFSMaxBufSize);
Steve Frenchf9f5c8172005-09-15 23:06:38 -07001911 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 rc = -EAGAIN;
1913 while (rc == -EAGAIN) {
Steve Frenchcdff08e2010-10-21 22:46:14 +00001914 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04001915 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 if (rc != 0)
1917 break;
1918 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001919 io_parms.netfid = open_file->netfid;
1920 io_parms.pid = pid;
1921 io_parms.tcon = pTcon;
1922 io_parms.offset = *poffset;
1923 io_parms.length = current_read_size;
1924 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
1925 &current_offset, &buf_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 }
1927 if (rc || (bytes_read == 0)) {
1928 if (total_read) {
1929 break;
1930 } else {
1931 FreeXid(xid);
1932 return rc;
1933 }
1934 } else {
Steve Frencha4544342005-08-24 13:59:35 -07001935 cifs_stats_bytes_read(pTcon, total_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 *poffset += bytes_read;
1937 }
1938 }
1939 FreeXid(xid);
1940 return total_read;
1941}
1942
Jeff Laytonca83ce32011-04-12 09:13:44 -04001943/*
1944 * If the page is mmap'ed into a process' page tables, then we need to make
1945 * sure that it doesn't change while being written back.
1946 */
1947static int
1948cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1949{
1950 struct page *page = vmf->page;
1951
1952 lock_page(page);
1953 return VM_FAULT_LOCKED;
1954}
1955
1956static struct vm_operations_struct cifs_file_vm_ops = {
1957 .fault = filemap_fault,
1958 .page_mkwrite = cifs_page_mkwrite,
1959};
1960
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03001961int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
1962{
1963 int rc, xid;
1964 struct inode *inode = file->f_path.dentry->d_inode;
1965
1966 xid = GetXid();
1967
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001968 if (!CIFS_I(inode)->clientCanCacheRead) {
1969 rc = cifs_invalidate_mapping(inode);
1970 if (rc)
1971 return rc;
1972 }
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03001973
1974 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04001975 if (rc == 0)
1976 vma->vm_ops = &cifs_file_vm_ops;
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03001977 FreeXid(xid);
1978 return rc;
1979}
1980
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1982{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 int rc, xid;
1984
1985 xid = GetXid();
Jeff Laytonabab0952010-02-12 07:44:18 -05001986 rc = cifs_revalidate_file(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001988 cFYI(1, "Validation prior to mmap failed, error=%d", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 FreeXid(xid);
1990 return rc;
1991 }
1992 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04001993 if (rc == 0)
1994 vma->vm_ops = &cifs_file_vm_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 FreeXid(xid);
1996 return rc;
1997}
1998
1999
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002000static void cifs_copy_cache_pages(struct address_space *mapping,
Nick Piggin315e9952010-04-21 03:18:28 +00002001 struct list_head *pages, int bytes_read, char *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002{
2003 struct page *page;
2004 char *target;
2005
2006 while (bytes_read > 0) {
2007 if (list_empty(pages))
2008 break;
2009
2010 page = list_entry(pages->prev, struct page, lru);
2011 list_del(&page->lru);
2012
Nick Piggin315e9952010-04-21 03:18:28 +00002013 if (add_to_page_cache_lru(page, mapping, page->index,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 GFP_KERNEL)) {
2015 page_cache_release(page);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002016 cFYI(1, "Add page cache failed");
Steve French3079ca62005-06-09 14:44:07 -07002017 data += PAGE_CACHE_SIZE;
2018 bytes_read -= PAGE_CACHE_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 continue;
2020 }
Jeff Layton06b43672010-06-01 10:54:45 -04002021 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002023 target = kmap_atomic(page, KM_USER0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024
2025 if (PAGE_CACHE_SIZE > bytes_read) {
2026 memcpy(target, data, bytes_read);
2027 /* zero the tail end of this partial page */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002028 memset(target + bytes_read, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 PAGE_CACHE_SIZE - bytes_read);
2030 bytes_read = 0;
2031 } else {
2032 memcpy(target, data, PAGE_CACHE_SIZE);
2033 bytes_read -= PAGE_CACHE_SIZE;
2034 }
2035 kunmap_atomic(target, KM_USER0);
2036
2037 flush_dcache_page(page);
2038 SetPageUptodate(page);
2039 unlock_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 data += PAGE_CACHE_SIZE;
Suresh Jayaraman9dc06552010-07-05 18:13:11 +05302041
2042 /* add page to FS-Cache */
2043 cifs_readpage_to_fscache(mapping->host, page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 }
2045 return;
2046}
2047
2048static int cifs_readpages(struct file *file, struct address_space *mapping,
2049 struct list_head *page_list, unsigned num_pages)
2050{
2051 int rc = -EACCES;
2052 int xid;
2053 loff_t offset;
2054 struct page *page;
2055 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00002056 struct cifs_tcon *pTcon;
Steve French2c2130e2007-10-12 19:10:28 +00002057 unsigned int bytes_read = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002058 unsigned int read_size, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 char *smb_read_data = NULL;
2060 struct smb_com_read_rsp *pSMBr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 struct cifsFileInfo *open_file;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002062 struct cifs_io_parms io_parms;
Steve Frenchec637e32005-12-12 20:53:18 -08002063 int buf_type = CIFS_NO_BUFFER;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002064 __u32 pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065
2066 xid = GetXid();
2067 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302068 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302070 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 }
Joe Perchesc21dfb62010-07-12 13:50:14 -07002072 open_file = file->private_data;
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002073 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Jeff Layton13cfb732010-09-29 19:51:11 -04002074 pTcon = tlink_tcon(open_file->tlink);
Steve Frenchbfa0d752005-08-31 21:50:37 -07002075
Suresh Jayaraman56698232010-07-05 18:13:25 +05302076 /*
2077 * Reads as many pages as possible from fscache. Returns -ENOBUFS
2078 * immediately if the cookie is negative
2079 */
2080 rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
2081 &num_pages);
2082 if (rc == 0)
2083 goto read_complete;
2084
Steve Frenchf19159d2010-04-21 04:12:10 +00002085 cFYI(DBG2, "rpages: num pages %d", num_pages);
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002086 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2087 pid = open_file->pid;
2088 else
2089 pid = current->tgid;
2090
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 for (i = 0; i < num_pages; ) {
2092 unsigned contig_pages;
2093 struct page *tmp_page;
2094 unsigned long expected_index;
2095
2096 if (list_empty(page_list))
2097 break;
2098
2099 page = list_entry(page_list->prev, struct page, lru);
2100 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
2101
2102 /* count adjacent pages that we will read into */
2103 contig_pages = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002104 expected_index =
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 list_entry(page_list->prev, struct page, lru)->index;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002106 list_for_each_entry_reverse(tmp_page, page_list, lru) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 if (tmp_page->index == expected_index) {
2108 contig_pages++;
2109 expected_index++;
2110 } else
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002111 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 }
2113 if (contig_pages + i > num_pages)
2114 contig_pages = num_pages - i;
2115
2116 /* for reads over a certain size could initiate async
2117 read ahead */
2118
2119 read_size = contig_pages * PAGE_CACHE_SIZE;
2120 /* Read size needs to be in multiples of one page */
2121 read_size = min_t(const unsigned int, read_size,
2122 cifs_sb->rsize & PAGE_CACHE_MASK);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002123 cFYI(DBG2, "rpages: read size 0x%x contiguous pages %d",
2124 read_size, contig_pages);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 rc = -EAGAIN;
2126 while (rc == -EAGAIN) {
Steve Frenchcdff08e2010-10-21 22:46:14 +00002127 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04002128 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 if (rc != 0)
2130 break;
2131 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002132 io_parms.netfid = open_file->netfid;
2133 io_parms.pid = pid;
2134 io_parms.tcon = pTcon;
2135 io_parms.offset = offset;
2136 io_parms.length = read_size;
2137 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
2138 &smb_read_data, &buf_type);
Steve Frencha9d02ad2005-08-24 23:06:05 -07002139 /* BB more RC checks ? */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002140 if (rc == -EAGAIN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 if (smb_read_data) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002142 if (buf_type == CIFS_SMALL_BUFFER)
Steve Frenchec637e32005-12-12 20:53:18 -08002143 cifs_small_buf_release(smb_read_data);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002144 else if (buf_type == CIFS_LARGE_BUFFER)
Steve Frenchec637e32005-12-12 20:53:18 -08002145 cifs_buf_release(smb_read_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 smb_read_data = NULL;
2147 }
2148 }
2149 }
2150 if ((rc < 0) || (smb_read_data == NULL)) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002151 cFYI(1, "Read error in readpages: %d", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 break;
2153 } else if (bytes_read > 0) {
Andrew Morton6f88cc22006-12-10 02:19:44 -08002154 task_io_account_read(bytes_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
2156 cifs_copy_cache_pages(mapping, page_list, bytes_read,
2157 smb_read_data + 4 /* RFC1001 hdr */ +
Nick Piggin315e9952010-04-21 03:18:28 +00002158 le16_to_cpu(pSMBr->DataOffset));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159
2160 i += bytes_read >> PAGE_CACHE_SHIFT;
Steve Frencha4544342005-08-24 13:59:35 -07002161 cifs_stats_bytes_read(pTcon, bytes_read);
Steve French2c2130e2007-10-12 19:10:28 +00002162 if ((bytes_read & PAGE_CACHE_MASK) != bytes_read) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 i++; /* account for partial page */
2164
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002165 /* server copy of file can have smaller size
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 than client */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002167 /* BB do we need to verify this common case ?
2168 this case is ok - if we are at server EOF
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 we will hit it on next read */
2170
OGAWA Hirofumi05ac9d42006-11-02 22:07:08 -08002171 /* break; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 }
2173 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002174 cFYI(1, "No bytes read (%d) at offset %lld . "
Steve Frenchf19159d2010-04-21 04:12:10 +00002175 "Cleaning remaining pages from readahead list",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002176 bytes_read, offset);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002177 /* BB turn off caching and do new lookup on
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 file size at server? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 break;
2180 }
2181 if (smb_read_data) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002182 if (buf_type == CIFS_SMALL_BUFFER)
Steve Frenchec637e32005-12-12 20:53:18 -08002183 cifs_small_buf_release(smb_read_data);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002184 else if (buf_type == CIFS_LARGE_BUFFER)
Steve Frenchec637e32005-12-12 20:53:18 -08002185 cifs_buf_release(smb_read_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 smb_read_data = NULL;
2187 }
2188 bytes_read = 0;
2189 }
2190
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191/* need to free smb_read_data buf before exit */
2192 if (smb_read_data) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002193 if (buf_type == CIFS_SMALL_BUFFER)
Steve French47c886b2006-01-18 14:20:39 -08002194 cifs_small_buf_release(smb_read_data);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002195 else if (buf_type == CIFS_LARGE_BUFFER)
Steve French47c886b2006-01-18 14:20:39 -08002196 cifs_buf_release(smb_read_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 smb_read_data = NULL;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002198 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199
Suresh Jayaraman56698232010-07-05 18:13:25 +05302200read_complete:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 FreeXid(xid);
2202 return rc;
2203}
2204
2205static int cifs_readpage_worker(struct file *file, struct page *page,
2206 loff_t *poffset)
2207{
2208 char *read_data;
2209 int rc;
2210
Suresh Jayaraman56698232010-07-05 18:13:25 +05302211 /* Is the page cached? */
2212 rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page);
2213 if (rc == 0)
2214 goto read_complete;
2215
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 page_cache_get(page);
2217 read_data = kmap(page);
2218 /* for reads over a certain size could initiate async read ahead */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002219
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002221
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 if (rc < 0)
2223 goto io_error;
2224 else
Joe Perchesb6b38f72010-04-21 03:50:45 +00002225 cFYI(1, "Bytes read %d", rc);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002226
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002227 file->f_path.dentry->d_inode->i_atime =
2228 current_fs_time(file->f_path.dentry->d_inode->i_sb);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002229
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 if (PAGE_CACHE_SIZE > rc)
2231 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
2232
2233 flush_dcache_page(page);
2234 SetPageUptodate(page);
Suresh Jayaraman9dc06552010-07-05 18:13:11 +05302235
2236 /* send this page to the cache */
2237 cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page);
2238
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 rc = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002240
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241io_error:
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002242 kunmap(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 page_cache_release(page);
Suresh Jayaraman56698232010-07-05 18:13:25 +05302244
2245read_complete:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 return rc;
2247}
2248
2249static int cifs_readpage(struct file *file, struct page *page)
2250{
2251 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
2252 int rc = -EACCES;
2253 int xid;
2254
2255 xid = GetXid();
2256
2257 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302258 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302260 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 }
2262
Joe Perchesb6b38f72010-04-21 03:50:45 +00002263 cFYI(1, "readpage %p at offset %d 0x%x\n",
2264 page, (int)offset, (int)offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265
2266 rc = cifs_readpage_worker(file, page, &offset);
2267
2268 unlock_page(page);
2269
2270 FreeXid(xid);
2271 return rc;
2272}
2273
Steve Frencha403a0a2007-07-26 15:54:16 +00002274static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
2275{
2276 struct cifsFileInfo *open_file;
2277
Jeff Layton44772882010-10-15 15:34:03 -04002278 spin_lock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002279 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton2e396b82010-10-15 15:34:01 -04002280 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Jeff Layton44772882010-10-15 15:34:03 -04002281 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002282 return 1;
2283 }
2284 }
Jeff Layton44772882010-10-15 15:34:03 -04002285 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002286 return 0;
2287}
2288
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289/* We do not want to update the file size from server for inodes
2290 open for write - to avoid races with writepage extending
2291 the file - in the future we could consider allowing
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002292 refreshing the inode only on increases in the file size
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 but this is tricky to do without racing with writebehind
2294 page caching in the current Linux kernel design */
Steve French4b18f2a2008-04-29 00:06:05 +00002295bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296{
Steve Frencha403a0a2007-07-26 15:54:16 +00002297 if (!cifsInode)
Steve French4b18f2a2008-04-29 00:06:05 +00002298 return true;
Steve French23e7dd72005-10-20 13:44:56 -07002299
Steve Frencha403a0a2007-07-26 15:54:16 +00002300 if (is_inode_writable(cifsInode)) {
2301 /* This inode is open for write at least once */
Steve Frenchc32a0b62006-01-12 14:41:28 -08002302 struct cifs_sb_info *cifs_sb;
2303
Steve Frenchc32a0b62006-01-12 14:41:28 -08002304 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
Steve Frenchad7a2922008-02-07 23:25:02 +00002305 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002306 /* since no page cache to corrupt on directio
Steve Frenchc32a0b62006-01-12 14:41:28 -08002307 we can change size safely */
Steve French4b18f2a2008-04-29 00:06:05 +00002308 return true;
Steve Frenchc32a0b62006-01-12 14:41:28 -08002309 }
2310
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002311 if (i_size_read(&cifsInode->vfs_inode) < end_of_file)
Steve French4b18f2a2008-04-29 00:06:05 +00002312 return true;
Steve French7ba52632007-02-08 18:14:13 +00002313
Steve French4b18f2a2008-04-29 00:06:05 +00002314 return false;
Steve French23e7dd72005-10-20 13:44:56 -07002315 } else
Steve French4b18f2a2008-04-29 00:06:05 +00002316 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317}
2318
Nick Piggind9414772008-09-24 11:32:59 -04002319static int cifs_write_begin(struct file *file, struct address_space *mapping,
2320 loff_t pos, unsigned len, unsigned flags,
2321 struct page **pagep, void **fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322{
Nick Piggind9414772008-09-24 11:32:59 -04002323 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
2324 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002325 loff_t page_start = pos & PAGE_MASK;
2326 loff_t i_size;
2327 struct page *page;
2328 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329
Joe Perchesb6b38f72010-04-21 03:50:45 +00002330 cFYI(1, "write_begin from %lld len %d", (long long)pos, len);
Nick Piggind9414772008-09-24 11:32:59 -04002331
Nick Piggin54566b22009-01-04 12:00:53 -08002332 page = grab_cache_page_write_begin(mapping, index, flags);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002333 if (!page) {
2334 rc = -ENOMEM;
2335 goto out;
2336 }
Nick Piggind9414772008-09-24 11:32:59 -04002337
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002338 if (PageUptodate(page))
2339 goto out;
Steve French8a236262007-03-06 00:31:00 +00002340
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002341 /*
2342 * If we write a full page it will be up to date, no need to read from
2343 * the server. If the write is short, we'll end up doing a sync write
2344 * instead.
2345 */
2346 if (len == PAGE_CACHE_SIZE)
2347 goto out;
2348
2349 /*
2350 * optimize away the read when we have an oplock, and we're not
2351 * expecting to use any of the data we'd be reading in. That
2352 * is, when the page lies beyond the EOF, or straddles the EOF
2353 * and the write will cover all of the existing data.
2354 */
2355 if (CIFS_I(mapping->host)->clientCanCacheRead) {
2356 i_size = i_size_read(mapping->host);
2357 if (page_start >= i_size ||
2358 (offset == 0 && (pos + len) >= i_size)) {
2359 zero_user_segments(page, 0, offset,
2360 offset + len,
2361 PAGE_CACHE_SIZE);
2362 /*
2363 * PageChecked means that the parts of the page
2364 * to which we're not writing are considered up
2365 * to date. Once the data is copied to the
2366 * page, it can be set uptodate.
2367 */
2368 SetPageChecked(page);
2369 goto out;
2370 }
2371 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372
Nick Piggind9414772008-09-24 11:32:59 -04002373 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002374 /*
2375 * might as well read a page, it is fast enough. If we get
2376 * an error, we don't need to return it. cifs_write_end will
2377 * do a sync write instead since PG_uptodate isn't set.
2378 */
2379 cifs_readpage_worker(file, page, &page_start);
Steve French8a236262007-03-06 00:31:00 +00002380 } else {
2381 /* we could try using another file handle if there is one -
2382 but how would we lock it to prevent close of that handle
2383 racing with this read? In any case
Nick Piggind9414772008-09-24 11:32:59 -04002384 this will be written out by write_end so is fine */
Steve French8a236262007-03-06 00:31:00 +00002385 }
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002386out:
2387 *pagep = page;
2388 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389}
2390
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302391static int cifs_release_page(struct page *page, gfp_t gfp)
2392{
2393 if (PagePrivate(page))
2394 return 0;
2395
2396 return cifs_fscache_release_page(page, gfp);
2397}
2398
2399static void cifs_invalidate_page(struct page *page, unsigned long offset)
2400{
2401 struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
2402
2403 if (offset == 0)
2404 cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
2405}
2406
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002407static int cifs_launder_page(struct page *page)
2408{
2409 int rc = 0;
2410 loff_t range_start = page_offset(page);
2411 loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
2412 struct writeback_control wbc = {
2413 .sync_mode = WB_SYNC_ALL,
2414 .nr_to_write = 0,
2415 .range_start = range_start,
2416 .range_end = range_end,
2417 };
2418
2419 cFYI(1, "Launder page: %p", page);
2420
2421 if (clear_page_dirty_for_io(page))
2422 rc = cifs_writepage_locked(page, &wbc);
2423
2424 cifs_fscache_invalidate_page(page, page->mapping->host);
2425 return rc;
2426}
2427
Tejun Heo9b646972010-07-20 22:09:02 +02002428void cifs_oplock_break(struct work_struct *work)
Jeff Layton3bc303c2009-09-21 06:47:50 -04002429{
2430 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
2431 oplock_break);
Jeff Laytona5e18bc2010-10-11 15:07:18 -04002432 struct inode *inode = cfile->dentry->d_inode;
Jeff Layton3bc303c2009-09-21 06:47:50 -04002433 struct cifsInodeInfo *cinode = CIFS_I(inode);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002434 int rc = 0;
Jeff Layton3bc303c2009-09-21 06:47:50 -04002435
2436 if (inode && S_ISREG(inode->i_mode)) {
Steve Frenchd54ff732010-04-27 04:38:15 +00002437 if (cinode->clientCanCacheRead)
Al Viro8737c932009-12-24 06:47:55 -05002438 break_lease(inode, O_RDONLY);
Steve Frenchd54ff732010-04-27 04:38:15 +00002439 else
Al Viro8737c932009-12-24 06:47:55 -05002440 break_lease(inode, O_WRONLY);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002441 rc = filemap_fdatawrite(inode->i_mapping);
2442 if (cinode->clientCanCacheRead == 0) {
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002443 rc = filemap_fdatawait(inode->i_mapping);
2444 mapping_set_error(inode->i_mapping, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002445 invalidate_remote_inode(inode);
2446 }
Joe Perchesb6b38f72010-04-21 03:50:45 +00002447 cFYI(1, "Oplock flush inode %p rc %d", inode, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002448 }
2449
2450 /*
2451 * releasing stale oplock after recent reconnect of smb session using
2452 * a now incorrect file handle is not a data integrity issue but do
2453 * not bother sending an oplock release if session to server still is
2454 * disconnected since oplock already released by the server
2455 */
Steve Frenchcdff08e2010-10-21 22:46:14 +00002456 if (!cfile->oplock_break_cancelled) {
Pavel Shilovsky03776f42010-08-17 11:26:00 +04002457 rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid,
2458 current->tgid, 0, 0, 0, 0,
2459 LOCKING_ANDX_OPLOCK_RELEASE, false,
Pavel Shilovsky12fed002011-01-17 20:15:44 +03002460 cinode->clientCanCacheRead ? 1 : 0);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002461 cFYI(1, "Oplock release rc = %d", rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002462 }
Jeff Layton3bc303c2009-09-21 06:47:50 -04002463}
2464
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07002465const struct address_space_operations cifs_addr_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 .readpage = cifs_readpage,
2467 .readpages = cifs_readpages,
2468 .writepage = cifs_writepage,
Steve French37c0eb42005-10-05 14:50:29 -07002469 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04002470 .write_begin = cifs_write_begin,
2471 .write_end = cifs_write_end,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302473 .releasepage = cifs_release_page,
2474 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002475 .launder_page = cifs_launder_page,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476};
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002477
2478/*
2479 * cifs_readpages requires the server to support a buffer large enough to
2480 * contain the header plus one complete page of data. Otherwise, we need
2481 * to leave cifs_readpages out of the address space operations.
2482 */
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07002483const struct address_space_operations cifs_addr_ops_smallbuf = {
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002484 .readpage = cifs_readpage,
2485 .writepage = cifs_writepage,
2486 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04002487 .write_begin = cifs_write_begin,
2488 .write_end = cifs_write_end,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002489 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302490 .releasepage = cifs_release_page,
2491 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002492 .launder_page = cifs_launder_page,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002493};