blob: 8f6917816fec4faf796353709a2c77d0144a04bb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/file.c
3 *
4 * vfs operations that deal with files
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005 *
Steve Frenchf19159d2010-04-21 04:12:10 +00006 * Copyright (C) International Business Machines Corp., 2002,2010
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 * Author(s): Steve French (sfrench@us.ibm.com)
Jeremy Allison7ee1af72006-08-02 21:56:33 +00008 * Jeremy Allison (jra@samba.org)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 *
10 * This library is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published
12 * by the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
18 * the GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24#include <linux/fs.h>
Steve French37c0eb42005-10-05 14:50:29 -070025#include <linux/backing-dev.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/stat.h>
27#include <linux/fcntl.h>
28#include <linux/pagemap.h>
29#include <linux/pagevec.h>
Steve French37c0eb42005-10-05 14:50:29 -070030#include <linux/writeback.h>
Andrew Morton6f88cc22006-12-10 02:19:44 -080031#include <linux/task_io_accounting_ops.h>
Steve French23e7dd72005-10-20 13:44:56 -070032#include <linux/delay.h>
Jeff Layton3bc303c2009-09-21 06:47:50 -040033#include <linux/mount.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090034#include <linux/slab.h>
Jeff Layton690c5e32011-10-19 15:30:16 -040035#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <asm/div64.h>
37#include "cifsfs.h"
38#include "cifspdu.h"
39#include "cifsglob.h"
40#include "cifsproto.h"
41#include "cifs_unicode.h"
42#include "cifs_debug.h"
43#include "cifs_fs_sb.h"
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +053044#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
Linus Torvalds1da177e2005-04-16 15:20:36 -070046static inline int cifs_convert_flags(unsigned int flags)
47{
48 if ((flags & O_ACCMODE) == O_RDONLY)
49 return GENERIC_READ;
50 else if ((flags & O_ACCMODE) == O_WRONLY)
51 return GENERIC_WRITE;
52 else if ((flags & O_ACCMODE) == O_RDWR) {
53 /* GENERIC_ALL is too much permission to request
54 can cause unnecessary access denied on create */
55 /* return GENERIC_ALL; */
56 return (GENERIC_READ | GENERIC_WRITE);
57 }
58
Jeff Laytone10f7b52008-05-14 10:21:33 -070059 return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
60 FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA |
61 FILE_READ_DATA);
Steve French7fc8f4e2009-02-23 20:43:11 +000062}
Jeff Laytone10f7b52008-05-14 10:21:33 -070063
Jeff Layton608712f2010-10-15 15:33:56 -040064static u32 cifs_posix_convert_flags(unsigned int flags)
Steve French7fc8f4e2009-02-23 20:43:11 +000065{
Jeff Layton608712f2010-10-15 15:33:56 -040066 u32 posix_flags = 0;
Jeff Laytone10f7b52008-05-14 10:21:33 -070067
Steve French7fc8f4e2009-02-23 20:43:11 +000068 if ((flags & O_ACCMODE) == O_RDONLY)
Jeff Layton608712f2010-10-15 15:33:56 -040069 posix_flags = SMB_O_RDONLY;
Steve French7fc8f4e2009-02-23 20:43:11 +000070 else if ((flags & O_ACCMODE) == O_WRONLY)
Jeff Layton608712f2010-10-15 15:33:56 -040071 posix_flags = SMB_O_WRONLY;
72 else if ((flags & O_ACCMODE) == O_RDWR)
73 posix_flags = SMB_O_RDWR;
74
75 if (flags & O_CREAT)
76 posix_flags |= SMB_O_CREAT;
77 if (flags & O_EXCL)
78 posix_flags |= SMB_O_EXCL;
79 if (flags & O_TRUNC)
80 posix_flags |= SMB_O_TRUNC;
81 /* be safe and imply O_SYNC for O_DSYNC */
Christoph Hellwig6b2f3d12009-10-27 11:05:28 +010082 if (flags & O_DSYNC)
Jeff Layton608712f2010-10-15 15:33:56 -040083 posix_flags |= SMB_O_SYNC;
Steve French7fc8f4e2009-02-23 20:43:11 +000084 if (flags & O_DIRECTORY)
Jeff Layton608712f2010-10-15 15:33:56 -040085 posix_flags |= SMB_O_DIRECTORY;
Steve French7fc8f4e2009-02-23 20:43:11 +000086 if (flags & O_NOFOLLOW)
Jeff Layton608712f2010-10-15 15:33:56 -040087 posix_flags |= SMB_O_NOFOLLOW;
Steve French7fc8f4e2009-02-23 20:43:11 +000088 if (flags & O_DIRECT)
Jeff Layton608712f2010-10-15 15:33:56 -040089 posix_flags |= SMB_O_DIRECT;
Steve French7fc8f4e2009-02-23 20:43:11 +000090
91 return posix_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -070092}
93
94static inline int cifs_get_disposition(unsigned int flags)
95{
96 if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
97 return FILE_CREATE;
98 else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
99 return FILE_OVERWRITE_IF;
100 else if ((flags & O_CREAT) == O_CREAT)
101 return FILE_OPEN_IF;
Steve French55aa2e02006-05-30 18:09:31 +0000102 else if ((flags & O_TRUNC) == O_TRUNC)
103 return FILE_OVERWRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 else
105 return FILE_OPEN;
106}
107
Jeff Layton608712f2010-10-15 15:33:56 -0400108int cifs_posix_open(char *full_path, struct inode **pinode,
109 struct super_block *sb, int mode, unsigned int f_flags,
110 __u32 *poplock, __u16 *pnetfid, int xid)
111{
112 int rc;
113 FILE_UNIX_BASIC_INFO *presp_data;
114 __u32 posix_flags = 0;
115 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
116 struct cifs_fattr fattr;
117 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000118 struct cifs_tcon *tcon;
Jeff Layton608712f2010-10-15 15:33:56 -0400119
120 cFYI(1, "posix open %s", full_path);
121
122 presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
123 if (presp_data == NULL)
124 return -ENOMEM;
125
126 tlink = cifs_sb_tlink(cifs_sb);
127 if (IS_ERR(tlink)) {
128 rc = PTR_ERR(tlink);
129 goto posix_open_ret;
130 }
131
132 tcon = tlink_tcon(tlink);
133 mode &= ~current_umask();
134
135 posix_flags = cifs_posix_convert_flags(f_flags);
136 rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data,
137 poplock, full_path, cifs_sb->local_nls,
138 cifs_sb->mnt_cifs_flags &
139 CIFS_MOUNT_MAP_SPECIAL_CHR);
140 cifs_put_tlink(tlink);
141
142 if (rc)
143 goto posix_open_ret;
144
145 if (presp_data->Type == cpu_to_le32(-1))
146 goto posix_open_ret; /* open ok, caller does qpathinfo */
147
148 if (!pinode)
149 goto posix_open_ret; /* caller does not need info */
150
151 cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
152
153 /* get new inode and set it up */
154 if (*pinode == NULL) {
155 cifs_fill_uniqueid(sb, &fattr);
156 *pinode = cifs_iget(sb, &fattr);
157 if (!*pinode) {
158 rc = -ENOMEM;
159 goto posix_open_ret;
160 }
161 } else {
162 cifs_fattr_to_inode(*pinode, &fattr);
163 }
164
165posix_open_ret:
166 kfree(presp_data);
167 return rc;
168}
169
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300170static int
171cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
Steve French96daf2b2011-05-27 04:34:02 +0000172 struct cifs_tcon *tcon, unsigned int f_flags, __u32 *poplock,
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300173 __u16 *pnetfid, int xid)
174{
175 int rc;
176 int desiredAccess;
177 int disposition;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500178 int create_options = CREATE_NOT_DIR;
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300179 FILE_ALL_INFO *buf;
180
181 desiredAccess = cifs_convert_flags(f_flags);
182
183/*********************************************************************
184 * open flag mapping table:
185 *
186 * POSIX Flag CIFS Disposition
187 * ---------- ----------------
188 * O_CREAT FILE_OPEN_IF
189 * O_CREAT | O_EXCL FILE_CREATE
190 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
191 * O_TRUNC FILE_OVERWRITE
192 * none of the above FILE_OPEN
193 *
194 * Note that there is not a direct match between disposition
195 * FILE_SUPERSEDE (ie create whether or not file exists although
196 * O_CREAT | O_TRUNC is similar but truncates the existing
197 * file rather than creating a new file as FILE_SUPERSEDE does
198 * (which uses the attributes / metadata passed in on open call)
199 *?
200 *? O_SYNC is a reasonable match to CIFS writethrough flag
201 *? and the read write flags match reasonably. O_LARGEFILE
202 *? is irrelevant because largefile support is always used
203 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
204 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
205 *********************************************************************/
206
207 disposition = cifs_get_disposition(f_flags);
208
209 /* BB pass O_SYNC flag through on file attributes .. BB */
210
211 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
212 if (!buf)
213 return -ENOMEM;
214
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500215 if (backup_cred(cifs_sb))
216 create_options |= CREATE_OPEN_BACKUP_INTENT;
217
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300218 if (tcon->ses->capabilities & CAP_NT_SMBS)
219 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500220 desiredAccess, create_options, pnetfid, poplock, buf,
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300221 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
222 & CIFS_MOUNT_MAP_SPECIAL_CHR);
223 else
224 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
225 desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf,
226 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
227 & CIFS_MOUNT_MAP_SPECIAL_CHR);
228
229 if (rc)
230 goto out;
231
232 if (tcon->unix_ext)
233 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
234 xid);
235 else
236 rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
237 xid, pnetfid);
238
239out:
240 kfree(buf);
241 return rc;
242}
243
Jeff Layton15ecb432010-10-15 15:34:02 -0400244struct cifsFileInfo *
245cifs_new_fileinfo(__u16 fileHandle, struct file *file,
246 struct tcon_link *tlink, __u32 oplock)
247{
248 struct dentry *dentry = file->f_path.dentry;
249 struct inode *inode = dentry->d_inode;
250 struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
251 struct cifsFileInfo *pCifsFile;
252
253 pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
254 if (pCifsFile == NULL)
255 return pCifsFile;
256
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400257 pCifsFile->count = 1;
Jeff Layton15ecb432010-10-15 15:34:02 -0400258 pCifsFile->netfid = fileHandle;
259 pCifsFile->pid = current->tgid;
260 pCifsFile->uid = current_fsuid();
261 pCifsFile->dentry = dget(dentry);
262 pCifsFile->f_flags = file->f_flags;
263 pCifsFile->invalidHandle = false;
Jeff Layton15ecb432010-10-15 15:34:02 -0400264 pCifsFile->tlink = cifs_get_tlink(tlink);
265 mutex_init(&pCifsFile->fh_mutex);
Jeff Layton15ecb432010-10-15 15:34:02 -0400266 INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
267
Jeff Layton44772882010-10-15 15:34:03 -0400268 spin_lock(&cifs_file_list_lock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400269 list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList));
270 /* if readable file instance put first in list*/
271 if (file->f_mode & FMODE_READ)
272 list_add(&pCifsFile->flist, &pCifsInode->openFileList);
273 else
274 list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList);
Jeff Layton44772882010-10-15 15:34:03 -0400275 spin_unlock(&cifs_file_list_lock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400276
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300277 cifs_set_oplock_level(pCifsInode, oplock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400278
279 file->private_data = pCifsFile;
280 return pCifsFile;
281}
282
Steve Frenchcdff08e2010-10-21 22:46:14 +0000283/*
284 * Release a reference on the file private data. This may involve closing
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400285 * the filehandle out on the server. Must be called without holding
286 * cifs_file_list_lock.
Steve Frenchcdff08e2010-10-21 22:46:14 +0000287 */
Jeff Laytonb33879a2010-10-15 15:34:04 -0400288void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
289{
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300290 struct inode *inode = cifs_file->dentry->d_inode;
Steve French96daf2b2011-05-27 04:34:02 +0000291 struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300292 struct cifsInodeInfo *cifsi = CIFS_I(inode);
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300293 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000294 struct cifsLockInfo *li, *tmp;
295
296 spin_lock(&cifs_file_list_lock);
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400297 if (--cifs_file->count > 0) {
Steve Frenchcdff08e2010-10-21 22:46:14 +0000298 spin_unlock(&cifs_file_list_lock);
299 return;
Jeff Laytonb33879a2010-10-15 15:34:04 -0400300 }
Steve Frenchcdff08e2010-10-21 22:46:14 +0000301
302 /* remove it from the lists */
303 list_del(&cifs_file->flist);
304 list_del(&cifs_file->tlist);
305
306 if (list_empty(&cifsi->openFileList)) {
307 cFYI(1, "closing last open instance for inode %p",
308 cifs_file->dentry->d_inode);
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300309
310 /* in strict cache mode we need invalidate mapping on the last
311 close because it may cause a error when we open this file
312 again and get at least level II oplock */
313 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
314 CIFS_I(inode)->invalid_mapping = true;
315
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300316 cifs_set_oplock_level(cifsi, 0);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000317 }
318 spin_unlock(&cifs_file_list_lock);
319
Jeff Laytonad635942011-07-26 12:20:17 -0400320 cancel_work_sync(&cifs_file->oplock_break);
321
Steve Frenchcdff08e2010-10-21 22:46:14 +0000322 if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
323 int xid, rc;
324
325 xid = GetXid();
326 rc = CIFSSMBClose(xid, tcon, cifs_file->netfid);
327 FreeXid(xid);
328 }
329
330 /* Delete any outstanding lock records. We'll lose them when the file
331 * is closed anyway.
332 */
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400333 mutex_lock(&cifsi->lock_mutex);
334 list_for_each_entry_safe(li, tmp, &cifsi->llist, llist) {
335 if (li->netfid != cifs_file->netfid)
336 continue;
Steve Frenchcdff08e2010-10-21 22:46:14 +0000337 list_del(&li->llist);
338 kfree(li);
339 }
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400340 mutex_unlock(&cifsi->lock_mutex);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000341
342 cifs_put_tlink(cifs_file->tlink);
343 dput(cifs_file->dentry);
344 kfree(cifs_file);
Jeff Laytonb33879a2010-10-15 15:34:04 -0400345}
346
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347int cifs_open(struct inode *inode, struct file *file)
348{
349 int rc = -EACCES;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400350 int xid;
351 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000353 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400354 struct tcon_link *tlink;
Jeff Layton6ca9f3b2010-06-16 13:40:16 -0400355 struct cifsFileInfo *pCifsFile = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 char *full_path = NULL;
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300357 bool posix_open_ok = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 __u16 netfid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
360 xid = GetXid();
361
362 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400363 tlink = cifs_sb_tlink(cifs_sb);
364 if (IS_ERR(tlink)) {
365 FreeXid(xid);
366 return PTR_ERR(tlink);
367 }
368 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -0800370 full_path = build_path_from_dentry(file->f_path.dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530372 rc = -ENOMEM;
Jeff Layton232341b2010-08-05 13:58:38 -0400373 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 }
375
Joe Perchesb6b38f72010-04-21 03:50:45 +0000376 cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
377 inode, file->f_flags, full_path);
Steve French276a74a2009-03-03 18:00:34 +0000378
Steve Frenche7504732011-10-12 17:47:03 -0500379 if (enable_oplocks)
Steve French276a74a2009-03-03 18:00:34 +0000380 oplock = REQ_OPLOCK;
381 else
382 oplock = 0;
383
Steve French64cc2c62009-03-04 19:54:08 +0000384 if (!tcon->broken_posix_open && tcon->unix_ext &&
385 (tcon->ses->capabilities & CAP_UNIX) &&
Steve French276a74a2009-03-03 18:00:34 +0000386 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
387 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Steve French276a74a2009-03-03 18:00:34 +0000388 /* can not refresh inode info since size could be stale */
Jeff Layton2422f672010-06-16 13:40:16 -0400389 rc = cifs_posix_open(full_path, &inode, inode->i_sb,
Steve Frenchfa588e02010-04-22 19:21:55 +0000390 cifs_sb->mnt_file_mode /* ignored */,
Jeff Layton608712f2010-10-15 15:33:56 -0400391 file->f_flags, &oplock, &netfid, xid);
Steve French276a74a2009-03-03 18:00:34 +0000392 if (rc == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000393 cFYI(1, "posix open succeeded");
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300394 posix_open_ok = true;
Steve French64cc2c62009-03-04 19:54:08 +0000395 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
396 if (tcon->ses->serverNOS)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000397 cERROR(1, "server %s of type %s returned"
Steve French64cc2c62009-03-04 19:54:08 +0000398 " unexpected error on SMB posix open"
399 ", disabling posix open support."
400 " Check if server update available.",
401 tcon->ses->serverName,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000402 tcon->ses->serverNOS);
Steve French64cc2c62009-03-04 19:54:08 +0000403 tcon->broken_posix_open = true;
Steve French276a74a2009-03-03 18:00:34 +0000404 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
405 (rc != -EOPNOTSUPP)) /* path not found or net err */
406 goto out;
Steve French64cc2c62009-03-04 19:54:08 +0000407 /* else fallthrough to retry open the old way on network i/o
408 or DFS errors */
Steve French276a74a2009-03-03 18:00:34 +0000409 }
410
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300411 if (!posix_open_ok) {
412 rc = cifs_nt_open(full_path, inode, cifs_sb, tcon,
413 file->f_flags, &oplock, &netfid, xid);
414 if (rc)
415 goto out;
416 }
Jeff Layton47c78b72010-06-16 13:40:17 -0400417
Jeff Laytonabfe1ee2010-10-15 15:33:58 -0400418 pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock);
Jeff Layton6ca9f3b2010-06-16 13:40:16 -0400419 if (pCifsFile == NULL) {
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300420 CIFSSMBClose(xid, tcon, netfid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 rc = -ENOMEM;
422 goto out;
423 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530425 cifs_fscache_set_inode_cookie(inode, file);
426
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300427 if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 /* time to set mode which we can not set earlier due to
429 problems creating new read-only files */
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300430 struct cifs_unix_set_info_args args = {
431 .mode = inode->i_mode,
432 .uid = NO_CHANGE_64,
433 .gid = NO_CHANGE_64,
434 .ctime = NO_CHANGE_64,
435 .atime = NO_CHANGE_64,
436 .mtime = NO_CHANGE_64,
437 .device = 0,
438 };
Jeff Laytond44a9fe2011-01-07 11:30:29 -0500439 CIFSSMBUnixSetFileInfo(xid, tcon, &args, netfid,
440 pCifsFile->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 }
442
443out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 kfree(full_path);
445 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400446 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 return rc;
448}
449
Adrian Bunk04187262006-06-30 18:23:04 +0200450/* Try to reacquire byte range locks that were released when session */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451/* to server was lost */
452static int cifs_relock_file(struct cifsFileInfo *cifsFile)
453{
454 int rc = 0;
455
456/* BB list all locks open on this file and relock */
457
458 return rc;
459}
460
Jeff Layton15886172010-10-15 15:33:59 -0400461static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462{
463 int rc = -EACCES;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400464 int xid;
465 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000467 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 struct cifsInodeInfo *pCifsInode;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000469 struct inode *inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 char *full_path = NULL;
471 int desiredAccess;
472 int disposition = FILE_OPEN;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500473 int create_options = CREATE_NOT_DIR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 __u16 netfid;
475
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 xid = GetXid();
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400477 mutex_lock(&pCifsFile->fh_mutex);
Steve French4b18f2a2008-04-29 00:06:05 +0000478 if (!pCifsFile->invalidHandle) {
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400479 mutex_unlock(&pCifsFile->fh_mutex);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530480 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530482 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 }
484
Jeff Layton15886172010-10-15 15:33:59 -0400485 inode = pCifsFile->dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton13cfb732010-09-29 19:51:11 -0400487 tcon = tlink_tcon(pCifsFile->tlink);
Steve French3a9f4622007-04-04 17:10:24 +0000488
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489/* can not grab rename sem here because various ops, including
490 those that already have the rename sem can end up causing writepage
491 to get called and if the server was down that means we end up here,
492 and we can never tell if the caller already has the rename_sem */
Jeff Layton15886172010-10-15 15:33:59 -0400493 full_path = build_path_from_dentry(pCifsFile->dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 if (full_path == NULL) {
Steve French3a9f4622007-04-04 17:10:24 +0000495 rc = -ENOMEM;
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400496 mutex_unlock(&pCifsFile->fh_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 FreeXid(xid);
Steve French3a9f4622007-04-04 17:10:24 +0000498 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 }
500
Joe Perchesb6b38f72010-04-21 03:50:45 +0000501 cFYI(1, "inode = 0x%p file flags 0x%x for %s",
Jeff Layton15886172010-10-15 15:33:59 -0400502 inode, pCifsFile->f_flags, full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
Steve Frenche7504732011-10-12 17:47:03 -0500504 if (enable_oplocks)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 oplock = REQ_OPLOCK;
506 else
Steve French4b18f2a2008-04-29 00:06:05 +0000507 oplock = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
Steve French7fc8f4e2009-02-23 20:43:11 +0000509 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
510 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
511 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton608712f2010-10-15 15:33:56 -0400512
513 /*
514 * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
515 * original open. Must mask them off for a reopen.
516 */
Jeff Layton15886172010-10-15 15:33:59 -0400517 unsigned int oflags = pCifsFile->f_flags &
518 ~(O_CREAT | O_EXCL | O_TRUNC);
Jeff Layton608712f2010-10-15 15:33:56 -0400519
Jeff Layton2422f672010-06-16 13:40:16 -0400520 rc = cifs_posix_open(full_path, NULL, inode->i_sb,
Steve Frenchfa588e02010-04-22 19:21:55 +0000521 cifs_sb->mnt_file_mode /* ignored */,
522 oflags, &oplock, &netfid, xid);
Steve French7fc8f4e2009-02-23 20:43:11 +0000523 if (rc == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000524 cFYI(1, "posix reopen succeeded");
Steve French7fc8f4e2009-02-23 20:43:11 +0000525 goto reopen_success;
526 }
527 /* fallthrough to retry open the old way on errors, especially
528 in the reconnect path it is important to retry hard */
529 }
530
Jeff Layton15886172010-10-15 15:33:59 -0400531 desiredAccess = cifs_convert_flags(pCifsFile->f_flags);
Steve French7fc8f4e2009-02-23 20:43:11 +0000532
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500533 if (backup_cred(cifs_sb))
534 create_options |= CREATE_OPEN_BACKUP_INTENT;
535
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 /* Can not refresh inode by passing in file_info buf to be returned
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000537 by SMBOpen and then calling get_inode_info with returned buf
538 since file might have write behind data that needs to be flushed
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 and server version of file size can be stale. If we knew for sure
540 that inode was not dirty locally we could do this */
541
Steve French7fc8f4e2009-02-23 20:43:11 +0000542 rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess,
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500543 create_options, &netfid, &oplock, NULL,
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000544 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
Steve French737b7582005-04-28 22:41:06 -0700545 CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 if (rc) {
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400547 mutex_unlock(&pCifsFile->fh_mutex);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000548 cFYI(1, "cifs_open returned 0x%x", rc);
549 cFYI(1, "oplock: %d", oplock);
Jeff Layton15886172010-10-15 15:33:59 -0400550 goto reopen_error_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 }
Jeff Layton15886172010-10-15 15:33:59 -0400552
553reopen_success:
554 pCifsFile->netfid = netfid;
555 pCifsFile->invalidHandle = false;
556 mutex_unlock(&pCifsFile->fh_mutex);
557 pCifsInode = CIFS_I(inode);
558
559 if (can_flush) {
560 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -0400561 mapping_set_error(inode->i_mapping, rc);
Jeff Layton15886172010-10-15 15:33:59 -0400562
Jeff Layton15886172010-10-15 15:33:59 -0400563 if (tcon->unix_ext)
564 rc = cifs_get_inode_info_unix(&inode,
565 full_path, inode->i_sb, xid);
566 else
567 rc = cifs_get_inode_info(&inode,
568 full_path, NULL, inode->i_sb,
569 xid, NULL);
570 } /* else we are writing out data to server already
571 and could deadlock if we tried to flush data, and
572 since we do not know if we have data that would
573 invalidate the current end of file on the server
574 we can not go to the server to get the new inod
575 info */
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300576
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300577 cifs_set_oplock_level(pCifsInode, oplock);
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300578
Jeff Layton15886172010-10-15 15:33:59 -0400579 cifs_relock_file(pCifsFile);
580
581reopen_error_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 kfree(full_path);
583 FreeXid(xid);
584 return rc;
585}
586
587int cifs_close(struct inode *inode, struct file *file)
588{
Jeff Layton77970692011-04-05 16:23:47 -0700589 if (file->private_data != NULL) {
590 cifsFileInfo_put(file->private_data);
591 file->private_data = NULL;
592 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593
Steve Frenchcdff08e2010-10-21 22:46:14 +0000594 /* return code from the ->release op is always ignored */
595 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596}
597
598int cifs_closedir(struct inode *inode, struct file *file)
599{
600 int rc = 0;
601 int xid;
Joe Perchesc21dfb62010-07-12 13:50:14 -0700602 struct cifsFileInfo *pCFileStruct = file->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 char *ptmp;
604
Joe Perchesb6b38f72010-04-21 03:50:45 +0000605 cFYI(1, "Closedir inode = 0x%p", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
607 xid = GetXid();
608
609 if (pCFileStruct) {
Steve French96daf2b2011-05-27 04:34:02 +0000610 struct cifs_tcon *pTcon = tlink_tcon(pCFileStruct->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
Joe Perchesb6b38f72010-04-21 03:50:45 +0000612 cFYI(1, "Freeing private data in close dir");
Jeff Layton44772882010-10-15 15:34:03 -0400613 spin_lock(&cifs_file_list_lock);
Steve French4b18f2a2008-04-29 00:06:05 +0000614 if (!pCFileStruct->srch_inf.endOfSearch &&
615 !pCFileStruct->invalidHandle) {
616 pCFileStruct->invalidHandle = true;
Jeff Layton44772882010-10-15 15:34:03 -0400617 spin_unlock(&cifs_file_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000619 cFYI(1, "Closing uncompleted readdir with rc %d",
620 rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 /* not much we can do if it fails anyway, ignore rc */
622 rc = 0;
Steve Frenchddb4cbf2008-11-20 20:00:44 +0000623 } else
Jeff Layton44772882010-10-15 15:34:03 -0400624 spin_unlock(&cifs_file_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
626 if (ptmp) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000627 cFYI(1, "closedir free smb buf in srch struct");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000629 if (pCFileStruct->srch_inf.smallBuf)
Steve Frenchd47d7c12006-02-28 03:45:48 +0000630 cifs_small_buf_release(ptmp);
631 else
632 cifs_buf_release(ptmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 }
Jeff Layton13cfb732010-09-29 19:51:11 -0400634 cifs_put_tlink(pCFileStruct->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 kfree(file->private_data);
636 file->private_data = NULL;
637 }
638 /* BB can we lock the filestruct while this is going on? */
639 FreeXid(xid);
640 return rc;
641}
642
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400643static int store_file_lock(struct cifsInodeInfo *cinode, __u64 len,
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400644 __u64 offset, __u8 type, __u16 netfid)
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000645{
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000646 struct cifsLockInfo *li =
647 kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000648 if (li == NULL)
649 return -ENOMEM;
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400650 li->netfid = netfid;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000651 li->offset = offset;
652 li->length = len;
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400653 li->type = type;
654 li->pid = current->tgid;
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400655 mutex_lock(&cinode->lock_mutex);
656 list_add_tail(&li->llist, &cinode->llist);
657 mutex_unlock(&cinode->lock_mutex);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000658 return 0;
659}
660
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400661static void
662cifs_read_flock(struct file_lock *flock, __u8 *type, int *lock, int *unlock,
663 bool *wait_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664{
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400665 if (flock->fl_flags & FL_POSIX)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000666 cFYI(1, "Posix");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400667 if (flock->fl_flags & FL_FLOCK)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000668 cFYI(1, "Flock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400669 if (flock->fl_flags & FL_SLEEP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000670 cFYI(1, "Blocking lock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400671 *wait_flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 }
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400673 if (flock->fl_flags & FL_ACCESS)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000674 cFYI(1, "Process suspended by mandatory locking - "
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400675 "not implemented yet");
676 if (flock->fl_flags & FL_LEASE)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000677 cFYI(1, "Lease on file - not implemented yet");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400678 if (flock->fl_flags &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400680 cFYI(1, "Unknown lock flags 0x%x", flock->fl_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400682 *type = LOCKING_ANDX_LARGE_FILES;
683 if (flock->fl_type == F_WRLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000684 cFYI(1, "F_WRLCK ");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400685 *lock = 1;
686 } else if (flock->fl_type == F_UNLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000687 cFYI(1, "F_UNLCK");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400688 *unlock = 1;
689 /* Check if unlock includes more than one lock range */
690 } else if (flock->fl_type == F_RDLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000691 cFYI(1, "F_RDLCK");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400692 *type |= LOCKING_ANDX_SHARED_LOCK;
693 *lock = 1;
694 } else if (flock->fl_type == F_EXLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000695 cFYI(1, "F_EXLCK");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400696 *lock = 1;
697 } else if (flock->fl_type == F_SHLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000698 cFYI(1, "F_SHLCK");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400699 *type |= LOCKING_ANDX_SHARED_LOCK;
700 *lock = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +0000702 cFYI(1, "Unknown type of lock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400703}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400705static int
706cifs_getlk(struct cifsFileInfo *cfile, struct file_lock *flock, __u8 type,
707 bool wait_flag, bool posix_lck, int xid)
708{
709 int rc = 0;
710 __u64 length = 1 + flock->fl_end - flock->fl_start;
711 __u16 netfid = cfile->netfid;
712 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400714 if (posix_lck) {
715 int posix_lock_type;
716 if (type & LOCKING_ANDX_SHARED_LOCK)
717 posix_lock_type = CIFS_RDLCK;
718 else
719 posix_lock_type = CIFS_WRLCK;
720 rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */,
721 length, flock, posix_lock_type,
722 wait_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 return rc;
724 }
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000725
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400726 /* BB we could chain these into one lock request BB */
727 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length,
728 flock->fl_start, 0, 1, type, 0, 0);
729 if (rc == 0) {
730 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid,
731 length, flock->fl_start, 1, 0,
732 type, 0, 0);
733 flock->fl_type = F_UNLCK;
734 if (rc != 0)
735 cERROR(1, "Error unlocking previously locked "
736 "range %d during test of lock", rc);
737 rc = 0;
738 return rc;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000739 }
740
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400741 if (type & LOCKING_ANDX_SHARED_LOCK) {
742 flock->fl_type = F_WRLCK;
743 rc = 0;
744 return rc;
745 }
746
747 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length,
748 flock->fl_start, 0, 1,
749 type | LOCKING_ANDX_SHARED_LOCK, 0, 0);
750 if (rc == 0) {
751 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid,
752 length, flock->fl_start, 1, 0,
753 type | LOCKING_ANDX_SHARED_LOCK,
754 0, 0);
755 flock->fl_type = F_RDLCK;
756 if (rc != 0)
757 cERROR(1, "Error unlocking previously locked "
758 "range %d during test of lock", rc);
759 } else
760 flock->fl_type = F_WRLCK;
761
762 rc = 0;
763 return rc;
764}
765
766static int
767cifs_setlk(struct file *file, struct file_lock *flock, __u8 type,
768 bool wait_flag, bool posix_lck, int lock, int unlock, int xid)
769{
770 int rc = 0;
771 __u64 length = 1 + flock->fl_end - flock->fl_start;
772 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
773 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400774 struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode);
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400775 __u16 netfid = cfile->netfid;
776
777 if (posix_lck) {
Steve French08547b02006-02-28 22:39:25 +0000778 int posix_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400779 if (type & LOCKING_ANDX_SHARED_LOCK)
Steve French08547b02006-02-28 22:39:25 +0000780 posix_lock_type = CIFS_RDLCK;
781 else
782 posix_lock_type = CIFS_WRLCK;
Steve French50c2f752007-07-13 00:33:32 +0000783
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400784 if (unlock == 1)
Steve Frenchbeb84dc2006-03-03 23:36:34 +0000785 posix_lock_type = CIFS_UNLCK;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000786
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400787 rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */, length,
788 flock, posix_lock_type, wait_flag);
789 goto out;
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000790 }
791
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400792 if (lock) {
793 rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length,
794 flock->fl_start, 0, lock, type, wait_flag, 0);
795 if (rc == 0) {
796 /* For Windows locks we must store them. */
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400797 rc = store_file_lock(cinode, length, flock->fl_start,
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400798 type, netfid);
799 }
800 } else if (unlock) {
801 /*
802 * For each stored lock that this unlock overlaps completely,
803 * unlock it.
804 */
805 int stored_rc = 0;
806 struct cifsLockInfo *li, *tmp;
807
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400808 mutex_lock(&cinode->lock_mutex);
809 list_for_each_entry_safe(li, tmp, &cinode->llist, llist) {
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400810 if (flock->fl_start > li->offset ||
811 (flock->fl_start + length) <
812 (li->offset + li->length))
813 continue;
814 if (current->tgid != li->pid)
815 continue;
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400816 if (cfile->netfid != li->netfid)
817 continue;
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400818
819 stored_rc = CIFSSMBLock(xid, tcon, netfid,
820 current->tgid, li->length,
821 li->offset, 1, 0, li->type,
822 0, 0);
823 if (stored_rc)
824 rc = stored_rc;
825 else {
826 list_del(&li->llist);
827 kfree(li);
828 }
829 }
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400830 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky03776f42010-08-17 11:26:00 +0400831 }
832out:
833 if (flock->fl_flags & FL_POSIX)
834 posix_lock_file_wait(file, flock);
835 return rc;
836}
837
838int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
839{
840 int rc, xid;
841 int lock = 0, unlock = 0;
842 bool wait_flag = false;
843 bool posix_lck = false;
844 struct cifs_sb_info *cifs_sb;
845 struct cifs_tcon *tcon;
846 struct cifsInodeInfo *cinode;
847 struct cifsFileInfo *cfile;
848 __u16 netfid;
849 __u8 type;
850
851 rc = -EACCES;
852 xid = GetXid();
853
854 cFYI(1, "Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld "
855 "end: %lld", cmd, flock->fl_flags, flock->fl_type,
856 flock->fl_start, flock->fl_end);
857
858 cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag);
859
860 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
861 cfile = (struct cifsFileInfo *)file->private_data;
862 tcon = tlink_tcon(cfile->tlink);
863 netfid = cfile->netfid;
864 cinode = CIFS_I(file->f_path.dentry->d_inode);
865
866 if ((tcon->ses->capabilities & CAP_UNIX) &&
867 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
868 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
869 posix_lck = true;
870 /*
871 * BB add code here to normalize offset and length to account for
872 * negative length which we can not accept over the wire.
873 */
874 if (IS_GETLK(cmd)) {
875 rc = cifs_getlk(cfile, flock, type, wait_flag, posix_lck, xid);
876 FreeXid(xid);
877 return rc;
878 }
879
880 if (!lock && !unlock) {
881 /*
882 * if no lock or unlock then nothing to do since we do not
883 * know what it is
884 */
885 FreeXid(xid);
886 return -EOPNOTSUPP;
887 }
888
889 rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock,
890 xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 FreeXid(xid);
892 return rc;
893}
894
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400895/* update the file size (if needed) after a write */
Pavel Shilovsky72432ff2011-01-24 14:16:35 -0500896void
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400897cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
898 unsigned int bytes_written)
899{
900 loff_t end_of_write = offset + bytes_written;
901
902 if (end_of_write > cifsi->server_eof)
903 cifsi->server_eof = end_of_write;
904}
905
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +0400906static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
Jeff Layton7da4b492010-10-15 15:34:00 -0400907 const char *write_data, size_t write_size,
908 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909{
910 int rc = 0;
911 unsigned int bytes_written = 0;
912 unsigned int total_written;
913 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000914 struct cifs_tcon *pTcon;
Jeff Layton77499812011-01-11 07:24:23 -0500915 int xid;
Jeff Layton7da4b492010-10-15 15:34:00 -0400916 struct dentry *dentry = open_file->dentry;
917 struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +0400918 struct cifs_io_parms io_parms;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
Jeff Layton7da4b492010-10-15 15:34:00 -0400920 cifs_sb = CIFS_SB(dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921
Joe Perchesb6b38f72010-04-21 03:50:45 +0000922 cFYI(1, "write %zd bytes to offset %lld of %s", write_size,
Jeff Layton7da4b492010-10-15 15:34:00 -0400923 *poffset, dentry->d_name.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
Jeff Layton13cfb732010-09-29 19:51:11 -0400925 pTcon = tlink_tcon(open_file->tlink);
Steve French50c2f752007-07-13 00:33:32 +0000926
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 for (total_written = 0; write_size > total_written;
930 total_written += bytes_written) {
931 rc = -EAGAIN;
932 while (rc == -EAGAIN) {
Jeff Laytonca83ce32011-04-12 09:13:44 -0400933 struct kvec iov[2];
934 unsigned int len;
935
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 if (open_file->invalidHandle) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 /* we could deadlock if we called
938 filemap_fdatawait from here so tell
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000939 reopen_file not to flush data to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 server now */
Jeff Layton15886172010-10-15 15:33:59 -0400941 rc = cifs_reopen_file(open_file, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 if (rc != 0)
943 break;
944 }
Steve French3e844692005-10-03 13:37:24 -0700945
Jeff Laytonca83ce32011-04-12 09:13:44 -0400946 len = min((size_t)cifs_sb->wsize,
947 write_size - total_written);
948 /* iov[0] is reserved for smb header */
949 iov[1].iov_base = (char *)write_data + total_written;
950 iov[1].iov_len = len;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +0400951 io_parms.netfid = open_file->netfid;
952 io_parms.pid = pid;
953 io_parms.tcon = pTcon;
954 io_parms.offset = *poffset;
955 io_parms.length = len;
956 rc = CIFSSMBWrite2(xid, &io_parms, &bytes_written, iov,
957 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 }
959 if (rc || (bytes_written == 0)) {
960 if (total_written)
961 break;
962 else {
963 FreeXid(xid);
964 return rc;
965 }
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400966 } else {
967 cifs_update_eof(cifsi, *poffset, bytes_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 *poffset += bytes_written;
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400969 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 }
971
Steve Frencha4544342005-08-24 13:59:35 -0700972 cifs_stats_bytes_written(pTcon, total_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973
Jeff Layton7da4b492010-10-15 15:34:00 -0400974 if (total_written > 0) {
975 spin_lock(&dentry->d_inode->i_lock);
976 if (*poffset > dentry->d_inode->i_size)
977 i_size_write(dentry->d_inode, *poffset);
978 spin_unlock(&dentry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 }
Jeff Layton7da4b492010-10-15 15:34:00 -0400980 mark_inode_dirty_sync(dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 FreeXid(xid);
982 return total_written;
983}
984
Jeff Layton6508d902010-09-29 19:51:11 -0400985struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
986 bool fsuid_only)
Steve French630f3f0c2007-10-25 21:17:17 +0000987{
988 struct cifsFileInfo *open_file = NULL;
Jeff Layton6508d902010-09-29 19:51:11 -0400989 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
990
991 /* only filter by fsuid on multiuser mounts */
992 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
993 fsuid_only = false;
Steve French630f3f0c2007-10-25 21:17:17 +0000994
Jeff Layton44772882010-10-15 15:34:03 -0400995 spin_lock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +0000996 /* we could simply get the first_list_entry since write-only entries
997 are always at the end of the list but since the first entry might
998 have a close pending, we go through the whole list */
999 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001000 if (fsuid_only && open_file->uid != current_fsuid())
1001 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001002 if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
Steve French630f3f0c2007-10-25 21:17:17 +00001003 if (!open_file->invalidHandle) {
1004 /* found a good file */
1005 /* lock it so it will not be closed on us */
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001006 cifsFileInfo_get(open_file);
Jeff Layton44772882010-10-15 15:34:03 -04001007 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001008 return open_file;
1009 } /* else might as well continue, and look for
1010 another, or simply have the caller reopen it
1011 again rather than trying to fix this handle */
1012 } else /* write only file */
1013 break; /* write only files are last so must be done */
1014 }
Jeff Layton44772882010-10-15 15:34:03 -04001015 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001016 return NULL;
1017}
Steve French630f3f0c2007-10-25 21:17:17 +00001018
Jeff Layton6508d902010-09-29 19:51:11 -04001019struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1020 bool fsuid_only)
Steve French6148a742005-10-05 12:23:19 -07001021{
1022 struct cifsFileInfo *open_file;
Jeff Laytond3892292010-11-02 16:22:50 -04001023 struct cifs_sb_info *cifs_sb;
Jeff Layton2846d382008-09-22 21:33:33 -04001024 bool any_available = false;
Steve Frenchdd99cd82005-10-05 19:32:49 -07001025 int rc;
Steve French6148a742005-10-05 12:23:19 -07001026
Steve French60808232006-04-22 15:53:05 +00001027 /* Having a null inode here (because mapping->host was set to zero by
1028 the VFS or MM) should not happen but we had reports of on oops (due to
1029 it being zero) during stress testcases so we need to check for it */
1030
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001031 if (cifs_inode == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001032 cERROR(1, "Null inode passed to cifs_writeable_file");
Steve French60808232006-04-22 15:53:05 +00001033 dump_stack();
1034 return NULL;
1035 }
1036
Jeff Laytond3892292010-11-02 16:22:50 -04001037 cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1038
Jeff Layton6508d902010-09-29 19:51:11 -04001039 /* only filter by fsuid on multiuser mounts */
1040 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1041 fsuid_only = false;
1042
Jeff Layton44772882010-10-15 15:34:03 -04001043 spin_lock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001044refind_writable:
Steve French6148a742005-10-05 12:23:19 -07001045 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001046 if (!any_available && open_file->pid != current->tgid)
1047 continue;
1048 if (fsuid_only && open_file->uid != current_fsuid())
1049 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001050 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001051 cifsFileInfo_get(open_file);
Steve French9b22b0b2007-10-02 01:11:08 +00001052
1053 if (!open_file->invalidHandle) {
1054 /* found a good writable file */
Jeff Layton44772882010-10-15 15:34:03 -04001055 spin_unlock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001056 return open_file;
1057 }
Steve French8840dee2007-11-16 23:05:52 +00001058
Jeff Layton44772882010-10-15 15:34:03 -04001059 spin_unlock(&cifs_file_list_lock);
Steve Frenchcdff08e2010-10-21 22:46:14 +00001060
Steve French9b22b0b2007-10-02 01:11:08 +00001061 /* Had to unlock since following call can block */
Jeff Layton15886172010-10-15 15:33:59 -04001062 rc = cifs_reopen_file(open_file, false);
Steve Frenchcdff08e2010-10-21 22:46:14 +00001063 if (!rc)
1064 return open_file;
Steve French9b22b0b2007-10-02 01:11:08 +00001065
Steve Frenchcdff08e2010-10-21 22:46:14 +00001066 /* if it fails, try another handle if possible */
Joe Perchesb6b38f72010-04-21 03:50:45 +00001067 cFYI(1, "wp failed on reopen file");
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001068 cifsFileInfo_put(open_file);
Steve French8840dee2007-11-16 23:05:52 +00001069
Steve Frenchcdff08e2010-10-21 22:46:14 +00001070 spin_lock(&cifs_file_list_lock);
1071
Steve French9b22b0b2007-10-02 01:11:08 +00001072 /* else we simply continue to the next entry. Thus
1073 we do not loop on reopen errors. If we
1074 can not reopen the file, for example if we
1075 reconnected to a server with another client
1076 racing to delete or lock the file we would not
1077 make progress if we restarted before the beginning
1078 of the loop here. */
Steve French6148a742005-10-05 12:23:19 -07001079 }
1080 }
Jeff Layton2846d382008-09-22 21:33:33 -04001081 /* couldn't find useable FH with same pid, try any available */
1082 if (!any_available) {
1083 any_available = true;
1084 goto refind_writable;
1085 }
Jeff Layton44772882010-10-15 15:34:03 -04001086 spin_unlock(&cifs_file_list_lock);
Steve French6148a742005-10-05 12:23:19 -07001087 return NULL;
1088}
1089
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1091{
1092 struct address_space *mapping = page->mapping;
1093 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1094 char *write_data;
1095 int rc = -EFAULT;
1096 int bytes_written = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 struct inode *inode;
Steve French6148a742005-10-05 12:23:19 -07001098 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
1100 if (!mapping || !mapping->host)
1101 return -EFAULT;
1102
1103 inode = page->mapping->host;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104
1105 offset += (loff_t)from;
1106 write_data = kmap(page);
1107 write_data += from;
1108
1109 if ((to > PAGE_CACHE_SIZE) || (from > to)) {
1110 kunmap(page);
1111 return -EIO;
1112 }
1113
1114 /* racing with truncate? */
1115 if (offset > mapping->host->i_size) {
1116 kunmap(page);
1117 return 0; /* don't care */
1118 }
1119
1120 /* check to make sure that we are not extending the file */
1121 if (mapping->host->i_size - offset < (loff_t)to)
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001122 to = (unsigned)(mapping->host->i_size - offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
Jeff Layton6508d902010-09-29 19:51:11 -04001124 open_file = find_writable_file(CIFS_I(mapping->host), false);
Steve French6148a742005-10-05 12:23:19 -07001125 if (open_file) {
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001126 bytes_written = cifs_write(open_file, open_file->pid,
1127 write_data, to - from, &offset);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001128 cifsFileInfo_put(open_file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 /* Does mm or vfs already set times? */
Steve French6148a742005-10-05 12:23:19 -07001130 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001131 if ((bytes_written > 0) && (offset))
Steve French6148a742005-10-05 12:23:19 -07001132 rc = 0;
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001133 else if (bytes_written < 0)
1134 rc = bytes_written;
Steve French6148a742005-10-05 12:23:19 -07001135 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001136 cFYI(1, "No writeable filehandles for inode");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 rc = -EIO;
1138 }
1139
1140 kunmap(page);
1141 return rc;
1142}
1143
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144static int cifs_writepages(struct address_space *mapping,
Steve French37c0eb42005-10-05 14:50:29 -07001145 struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146{
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001147 struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb);
1148 bool done = false, scanned = false, range_whole = false;
1149 pgoff_t end, index;
1150 struct cifs_writedata *wdata;
Steve French37c0eb42005-10-05 14:50:29 -07001151 struct page *page;
Steve French37c0eb42005-10-05 14:50:29 -07001152 int rc = 0;
Steve French50c2f752007-07-13 00:33:32 +00001153
Steve French37c0eb42005-10-05 14:50:29 -07001154 /*
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001155 * If wsize is smaller than the page cache size, default to writing
Steve French37c0eb42005-10-05 14:50:29 -07001156 * one page at a time via cifs_writepage
1157 */
1158 if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1159 return generic_writepages(mapping, wbc);
1160
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001161 if (wbc->range_cyclic) {
Steve French37c0eb42005-10-05 14:50:29 -07001162 index = mapping->writeback_index; /* Start from prev offset */
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001163 end = -1;
1164 } else {
1165 index = wbc->range_start >> PAGE_CACHE_SHIFT;
1166 end = wbc->range_end >> PAGE_CACHE_SHIFT;
1167 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001168 range_whole = true;
1169 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001170 }
1171retry:
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001172 while (!done && index <= end) {
1173 unsigned int i, nr_pages, found_pages;
1174 pgoff_t next = 0, tofind;
1175 struct page **pages;
Steve French37c0eb42005-10-05 14:50:29 -07001176
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001177 tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1,
1178 end - index) + 1;
Steve French37c0eb42005-10-05 14:50:29 -07001179
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001180 wdata = cifs_writedata_alloc((unsigned int)tofind);
1181 if (!wdata) {
1182 rc = -ENOMEM;
1183 break;
1184 }
1185
1186 /*
1187 * find_get_pages_tag seems to return a max of 256 on each
1188 * iteration, so we must call it several times in order to
1189 * fill the array or the wsize is effectively limited to
1190 * 256 * PAGE_CACHE_SIZE.
1191 */
1192 found_pages = 0;
1193 pages = wdata->pages;
1194 do {
1195 nr_pages = find_get_pages_tag(mapping, &index,
1196 PAGECACHE_TAG_DIRTY,
1197 tofind, pages);
1198 found_pages += nr_pages;
1199 tofind -= nr_pages;
1200 pages += nr_pages;
1201 } while (nr_pages && tofind && index <= end);
1202
1203 if (found_pages == 0) {
1204 kref_put(&wdata->refcount, cifs_writedata_release);
1205 break;
1206 }
1207
1208 nr_pages = 0;
1209 for (i = 0; i < found_pages; i++) {
1210 page = wdata->pages[i];
Steve French37c0eb42005-10-05 14:50:29 -07001211 /*
1212 * At this point we hold neither mapping->tree_lock nor
1213 * lock on the page itself: the page may be truncated or
1214 * invalidated (changing page->mapping to NULL), or even
1215 * swizzled back from swapper_space to tmpfs file
1216 * mapping
1217 */
1218
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001219 if (nr_pages == 0)
Steve French37c0eb42005-10-05 14:50:29 -07001220 lock_page(page);
Nick Piggin529ae9a2008-08-02 12:01:03 +02001221 else if (!trylock_page(page))
Steve French37c0eb42005-10-05 14:50:29 -07001222 break;
1223
1224 if (unlikely(page->mapping != mapping)) {
1225 unlock_page(page);
1226 break;
1227 }
1228
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001229 if (!wbc->range_cyclic && page->index > end) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001230 done = true;
Steve French37c0eb42005-10-05 14:50:29 -07001231 unlock_page(page);
1232 break;
1233 }
1234
1235 if (next && (page->index != next)) {
1236 /* Not next consecutive page */
1237 unlock_page(page);
1238 break;
1239 }
1240
1241 if (wbc->sync_mode != WB_SYNC_NONE)
1242 wait_on_page_writeback(page);
1243
1244 if (PageWriteback(page) ||
Linus Torvaldscb876f42006-12-23 16:19:07 -08001245 !clear_page_dirty_for_io(page)) {
Steve French37c0eb42005-10-05 14:50:29 -07001246 unlock_page(page);
1247 break;
1248 }
Steve French84d2f072005-10-12 15:32:05 -07001249
Linus Torvaldscb876f42006-12-23 16:19:07 -08001250 /*
1251 * This actually clears the dirty bit in the radix tree.
1252 * See cifs_writepage() for more commentary.
1253 */
1254 set_page_writeback(page);
1255
Steve French84d2f072005-10-12 15:32:05 -07001256 if (page_offset(page) >= mapping->host->i_size) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001257 done = true;
Steve French84d2f072005-10-12 15:32:05 -07001258 unlock_page(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001259 end_page_writeback(page);
Steve French84d2f072005-10-12 15:32:05 -07001260 break;
1261 }
1262
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001263 wdata->pages[i] = page;
Steve French37c0eb42005-10-05 14:50:29 -07001264 next = page->index + 1;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001265 ++nr_pages;
Steve French37c0eb42005-10-05 14:50:29 -07001266 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001267
1268 /* reset index to refind any pages skipped */
1269 if (nr_pages == 0)
1270 index = wdata->pages[0]->index + 1;
1271
1272 /* put any pages we aren't going to use */
1273 for (i = nr_pages; i < found_pages; i++) {
1274 page_cache_release(wdata->pages[i]);
1275 wdata->pages[i] = NULL;
1276 }
1277
1278 /* nothing to write? */
1279 if (nr_pages == 0) {
1280 kref_put(&wdata->refcount, cifs_writedata_release);
1281 continue;
1282 }
1283
1284 wdata->sync_mode = wbc->sync_mode;
1285 wdata->nr_pages = nr_pages;
1286 wdata->offset = page_offset(wdata->pages[0]);
1287
1288 do {
1289 if (wdata->cfile != NULL)
1290 cifsFileInfo_put(wdata->cfile);
1291 wdata->cfile = find_writable_file(CIFS_I(mapping->host),
1292 false);
1293 if (!wdata->cfile) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001294 cERROR(1, "No writable handles for inode");
Steve French23e7dd72005-10-20 13:44:56 -07001295 rc = -EBADF;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001296 break;
Steve French37c0eb42005-10-05 14:50:29 -07001297 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001298 rc = cifs_async_writev(wdata);
1299 } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN);
Jeff Laytonf3983c22010-09-22 16:17:40 -07001300
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001301 for (i = 0; i < nr_pages; ++i)
1302 unlock_page(wdata->pages[i]);
Jeff Layton941b8532011-01-11 07:24:01 -05001303
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001304 /* send failure -- clean up the mess */
1305 if (rc != 0) {
1306 for (i = 0; i < nr_pages; ++i) {
Jeff Layton941b8532011-01-11 07:24:01 -05001307 if (rc == -EAGAIN)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001308 redirty_page_for_writepage(wbc,
1309 wdata->pages[i]);
1310 else
1311 SetPageError(wdata->pages[i]);
1312 end_page_writeback(wdata->pages[i]);
1313 page_cache_release(wdata->pages[i]);
Steve French37c0eb42005-10-05 14:50:29 -07001314 }
Jeff Layton941b8532011-01-11 07:24:01 -05001315 if (rc != -EAGAIN)
1316 mapping_set_error(mapping, rc);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001317 }
1318 kref_put(&wdata->refcount, cifs_writedata_release);
Jeff Layton941b8532011-01-11 07:24:01 -05001319
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001320 wbc->nr_to_write -= nr_pages;
1321 if (wbc->nr_to_write <= 0)
1322 done = true;
Dave Kleikampb066a482008-11-18 03:49:05 +00001323
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001324 index = next;
Steve French37c0eb42005-10-05 14:50:29 -07001325 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001326
Steve French37c0eb42005-10-05 14:50:29 -07001327 if (!scanned && !done) {
1328 /*
1329 * We hit the last page and there is more work to be done: wrap
1330 * back to the start of the file
1331 */
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001332 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001333 index = 0;
1334 goto retry;
1335 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001336
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001337 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
Steve French37c0eb42005-10-05 14:50:29 -07001338 mapping->writeback_index = index;
1339
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 return rc;
1341}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001343static int
1344cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345{
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001346 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 int xid;
1348
1349 xid = GetXid();
1350/* BB add check for wbc flags */
1351 page_cache_get(page);
Steve Frenchad7a2922008-02-07 23:25:02 +00001352 if (!PageUptodate(page))
Joe Perchesb6b38f72010-04-21 03:50:45 +00001353 cFYI(1, "ppw - page not up to date");
Linus Torvaldscb876f42006-12-23 16:19:07 -08001354
1355 /*
1356 * Set the "writeback" flag, and clear "dirty" in the radix tree.
1357 *
1358 * A writepage() implementation always needs to do either this,
1359 * or re-dirty the page with "redirty_page_for_writepage()" in
1360 * the case of a failure.
1361 *
1362 * Just unlocking the page will cause the radix tree tag-bits
1363 * to fail to update with the state of the page correctly.
1364 */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001365 set_page_writeback(page);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001366retry_write:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001368 if (rc == -EAGAIN && wbc->sync_mode == WB_SYNC_ALL)
1369 goto retry_write;
1370 else if (rc == -EAGAIN)
1371 redirty_page_for_writepage(wbc, page);
1372 else if (rc != 0)
1373 SetPageError(page);
1374 else
1375 SetPageUptodate(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001376 end_page_writeback(page);
1377 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 FreeXid(xid);
1379 return rc;
1380}
1381
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001382static int cifs_writepage(struct page *page, struct writeback_control *wbc)
1383{
1384 int rc = cifs_writepage_locked(page, wbc);
1385 unlock_page(page);
1386 return rc;
1387}
1388
Nick Piggind9414772008-09-24 11:32:59 -04001389static int cifs_write_end(struct file *file, struct address_space *mapping,
1390 loff_t pos, unsigned len, unsigned copied,
1391 struct page *page, void *fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392{
Nick Piggind9414772008-09-24 11:32:59 -04001393 int rc;
1394 struct inode *inode = mapping->host;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001395 struct cifsFileInfo *cfile = file->private_data;
1396 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
1397 __u32 pid;
1398
1399 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1400 pid = cfile->pid;
1401 else
1402 pid = current->tgid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
Joe Perchesb6b38f72010-04-21 03:50:45 +00001404 cFYI(1, "write_end for page %p from pos %lld with %d bytes",
1405 page, pos, copied);
Steve Frenchad7a2922008-02-07 23:25:02 +00001406
Jeff Laytona98ee8c2008-11-26 19:32:33 +00001407 if (PageChecked(page)) {
1408 if (copied == len)
1409 SetPageUptodate(page);
1410 ClearPageChecked(page);
1411 } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
Nick Piggind9414772008-09-24 11:32:59 -04001412 SetPageUptodate(page);
1413
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 if (!PageUptodate(page)) {
Nick Piggind9414772008-09-24 11:32:59 -04001415 char *page_data;
1416 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
1417 int xid;
1418
1419 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 /* this is probably better than directly calling
1421 partialpage_write since in this function the file handle is
1422 known which we might as well leverage */
1423 /* BB check if anything else missing out of ppw
1424 such as updating last write time */
1425 page_data = kmap(page);
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001426 rc = cifs_write(cfile, pid, page_data + offset, copied, &pos);
Nick Piggind9414772008-09-24 11:32:59 -04001427 /* if (rc < 0) should we set writebehind rc? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 kunmap(page);
Nick Piggind9414772008-09-24 11:32:59 -04001429
1430 FreeXid(xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001431 } else {
Nick Piggind9414772008-09-24 11:32:59 -04001432 rc = copied;
1433 pos += copied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 set_page_dirty(page);
1435 }
1436
Nick Piggind9414772008-09-24 11:32:59 -04001437 if (rc > 0) {
1438 spin_lock(&inode->i_lock);
1439 if (pos > inode->i_size)
1440 i_size_write(inode, pos);
1441 spin_unlock(&inode->i_lock);
1442 }
1443
1444 unlock_page(page);
1445 page_cache_release(page);
1446
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 return rc;
1448}
1449
Josef Bacik02c24a82011-07-16 20:44:56 -04001450int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
1451 int datasync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452{
1453 int xid;
1454 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00001455 struct cifs_tcon *tcon;
Joe Perchesc21dfb62010-07-12 13:50:14 -07001456 struct cifsFileInfo *smbfile = file->private_data;
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08001457 struct inode *inode = file->f_path.dentry->d_inode;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001458 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
Josef Bacik02c24a82011-07-16 20:44:56 -04001460 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
1461 if (rc)
1462 return rc;
1463 mutex_lock(&inode->i_mutex);
1464
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 xid = GetXid();
1466
Joe Perchesb6b38f72010-04-21 03:50:45 +00001467 cFYI(1, "Sync file - name: %s datasync: 0x%x",
Christoph Hellwig7ea80852010-05-26 17:53:25 +02001468 file->f_path.dentry->d_name.name, datasync);
Steve French50c2f752007-07-13 00:33:32 +00001469
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001470 if (!CIFS_I(inode)->clientCanCacheRead) {
1471 rc = cifs_invalidate_mapping(inode);
1472 if (rc) {
1473 cFYI(1, "rc: %d during invalidate phase", rc);
1474 rc = 0; /* don't care about it in fsync */
1475 }
1476 }
Jeff Laytoneb4b7562010-10-22 14:52:29 -04001477
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001478 tcon = tlink_tcon(smbfile->tlink);
1479 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
1480 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
1481
1482 FreeXid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04001483 mutex_unlock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001484 return rc;
1485}
1486
Josef Bacik02c24a82011-07-16 20:44:56 -04001487int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001488{
1489 int xid;
1490 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00001491 struct cifs_tcon *tcon;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001492 struct cifsFileInfo *smbfile = file->private_data;
1493 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Josef Bacik02c24a82011-07-16 20:44:56 -04001494 struct inode *inode = file->f_mapping->host;
1495
1496 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
1497 if (rc)
1498 return rc;
1499 mutex_lock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03001500
1501 xid = GetXid();
1502
1503 cFYI(1, "Sync file - name: %s datasync: 0x%x",
1504 file->f_path.dentry->d_name.name, datasync);
1505
1506 tcon = tlink_tcon(smbfile->tlink);
1507 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
1508 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
Steve Frenchb298f222009-02-21 21:17:43 +00001509
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 FreeXid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04001511 mutex_unlock(&inode->i_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 return rc;
1513}
1514
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515/*
1516 * As file closes, flush all cached write data for this inode checking
1517 * for write behind errors.
1518 */
Miklos Szeredi75e1fcc2006-06-23 02:05:12 -07001519int cifs_flush(struct file *file, fl_owner_t id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520{
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001521 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 int rc = 0;
1523
Jeff Laytoneb4b7562010-10-22 14:52:29 -04001524 if (file->f_mode & FMODE_WRITE)
Jeff Laytond3f13222010-10-15 15:34:07 -04001525 rc = filemap_write_and_wait(inode->i_mapping);
Steve French50c2f752007-07-13 00:33:32 +00001526
Joe Perchesb6b38f72010-04-21 03:50:45 +00001527 cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528
1529 return rc;
1530}
1531
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001532static int
1533cifs_write_allocate_pages(struct page **pages, unsigned long num_pages)
1534{
1535 int rc = 0;
1536 unsigned long i;
1537
1538 for (i = 0; i < num_pages; i++) {
1539 pages[i] = alloc_page(__GFP_HIGHMEM);
1540 if (!pages[i]) {
1541 /*
1542 * save number of pages we have already allocated and
1543 * return with ENOMEM error
1544 */
1545 num_pages = i;
1546 rc = -ENOMEM;
1547 goto error;
1548 }
1549 }
1550
1551 return rc;
1552
1553error:
1554 for (i = 0; i < num_pages; i++)
1555 put_page(pages[i]);
1556 return rc;
1557}
1558
1559static inline
1560size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
1561{
1562 size_t num_pages;
1563 size_t clen;
1564
1565 clen = min_t(const size_t, len, wsize);
1566 num_pages = clen / PAGE_CACHE_SIZE;
1567 if (clen % PAGE_CACHE_SIZE)
1568 num_pages++;
1569
1570 if (cur_len)
1571 *cur_len = clen;
1572
1573 return num_pages;
1574}
1575
1576static ssize_t
1577cifs_iovec_write(struct file *file, const struct iovec *iov,
1578 unsigned long nr_segs, loff_t *poffset)
1579{
Pavel Shilovsky76429c12011-01-31 16:03:08 +03001580 unsigned int written;
1581 unsigned long num_pages, npages, i;
1582 size_t copied, len, cur_len;
1583 ssize_t total_written = 0;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001584 struct kvec *to_send;
1585 struct page **pages;
1586 struct iov_iter it;
1587 struct inode *inode;
1588 struct cifsFileInfo *open_file;
Steve French96daf2b2011-05-27 04:34:02 +00001589 struct cifs_tcon *pTcon;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001590 struct cifs_sb_info *cifs_sb;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001591 struct cifs_io_parms io_parms;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001592 int xid, rc;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001593 __u32 pid;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001594
1595 len = iov_length(iov, nr_segs);
1596 if (!len)
1597 return 0;
1598
1599 rc = generic_write_checks(file, poffset, &len, 0);
1600 if (rc)
1601 return rc;
1602
1603 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1604 num_pages = get_numpages(cifs_sb->wsize, len, &cur_len);
1605
1606 pages = kmalloc(sizeof(struct pages *)*num_pages, GFP_KERNEL);
1607 if (!pages)
1608 return -ENOMEM;
1609
1610 to_send = kmalloc(sizeof(struct kvec)*(num_pages + 1), GFP_KERNEL);
1611 if (!to_send) {
1612 kfree(pages);
1613 return -ENOMEM;
1614 }
1615
1616 rc = cifs_write_allocate_pages(pages, num_pages);
1617 if (rc) {
1618 kfree(pages);
1619 kfree(to_send);
1620 return rc;
1621 }
1622
1623 xid = GetXid();
1624 open_file = file->private_data;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001625
1626 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1627 pid = open_file->pid;
1628 else
1629 pid = current->tgid;
1630
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001631 pTcon = tlink_tcon(open_file->tlink);
1632 inode = file->f_path.dentry->d_inode;
1633
1634 iov_iter_init(&it, iov, nr_segs, len, 0);
1635 npages = num_pages;
1636
1637 do {
1638 size_t save_len = cur_len;
1639 for (i = 0; i < npages; i++) {
1640 copied = min_t(const size_t, cur_len, PAGE_CACHE_SIZE);
1641 copied = iov_iter_copy_from_user(pages[i], &it, 0,
1642 copied);
1643 cur_len -= copied;
1644 iov_iter_advance(&it, copied);
1645 to_send[i+1].iov_base = kmap(pages[i]);
1646 to_send[i+1].iov_len = copied;
1647 }
1648
1649 cur_len = save_len - cur_len;
1650
1651 do {
1652 if (open_file->invalidHandle) {
1653 rc = cifs_reopen_file(open_file, false);
1654 if (rc != 0)
1655 break;
1656 }
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001657 io_parms.netfid = open_file->netfid;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001658 io_parms.pid = pid;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001659 io_parms.tcon = pTcon;
1660 io_parms.offset = *poffset;
1661 io_parms.length = cur_len;
1662 rc = CIFSSMBWrite2(xid, &io_parms, &written, to_send,
1663 npages, 0);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001664 } while (rc == -EAGAIN);
1665
1666 for (i = 0; i < npages; i++)
1667 kunmap(pages[i]);
1668
1669 if (written) {
1670 len -= written;
1671 total_written += written;
1672 cifs_update_eof(CIFS_I(inode), *poffset, written);
1673 *poffset += written;
1674 } else if (rc < 0) {
1675 if (!total_written)
1676 total_written = rc;
1677 break;
1678 }
1679
1680 /* get length and number of kvecs of the next write */
1681 npages = get_numpages(cifs_sb->wsize, len, &cur_len);
1682 } while (len > 0);
1683
1684 if (total_written > 0) {
1685 spin_lock(&inode->i_lock);
1686 if (*poffset > inode->i_size)
1687 i_size_write(inode, *poffset);
1688 spin_unlock(&inode->i_lock);
1689 }
1690
1691 cifs_stats_bytes_written(pTcon, total_written);
1692 mark_inode_dirty_sync(inode);
1693
1694 for (i = 0; i < num_pages; i++)
1695 put_page(pages[i]);
1696 kfree(to_send);
1697 kfree(pages);
1698 FreeXid(xid);
1699 return total_written;
1700}
1701
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03001702ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001703 unsigned long nr_segs, loff_t pos)
1704{
1705 ssize_t written;
1706 struct inode *inode;
1707
1708 inode = iocb->ki_filp->f_path.dentry->d_inode;
1709
1710 /*
1711 * BB - optimize the way when signing is disabled. We can drop this
1712 * extra memory-to-memory copying and use iovec buffers for constructing
1713 * write request.
1714 */
1715
1716 written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos);
1717 if (written > 0) {
1718 CIFS_I(inode)->invalid_mapping = true;
1719 iocb->ki_pos = pos;
1720 }
1721
1722 return written;
1723}
1724
1725ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
1726 unsigned long nr_segs, loff_t pos)
1727{
1728 struct inode *inode;
1729
1730 inode = iocb->ki_filp->f_path.dentry->d_inode;
1731
1732 if (CIFS_I(inode)->clientCanCacheAll)
1733 return generic_file_aio_write(iocb, iov, nr_segs, pos);
1734
1735 /*
1736 * In strict cache mode we need to write the data to the server exactly
1737 * from the pos to pos+len-1 rather than flush all affected pages
1738 * because it may cause a error with mandatory locks on these pages but
1739 * not on the region from pos to ppos+len-1.
1740 */
1741
1742 return cifs_user_writev(iocb, iov, nr_segs, pos);
1743}
1744
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001745static ssize_t
1746cifs_iovec_read(struct file *file, const struct iovec *iov,
1747 unsigned long nr_segs, loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748{
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001749 int rc;
1750 int xid;
Pavel Shilovsky76429c12011-01-31 16:03:08 +03001751 ssize_t total_read;
1752 unsigned int bytes_read = 0;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001753 size_t len, cur_len;
1754 int iov_offset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00001756 struct cifs_tcon *pTcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 struct smb_com_read_rsp *pSMBr;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001759 struct cifs_io_parms io_parms;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001760 char *read_data;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001761 __u32 pid;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001762
1763 if (!nr_segs)
1764 return 0;
1765
1766 len = iov_length(iov, nr_segs);
1767 if (!len)
1768 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769
1770 xid = GetXid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08001771 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772
Joe Perchesc21dfb62010-07-12 13:50:14 -07001773 open_file = file->private_data;
Jeff Layton13cfb732010-09-29 19:51:11 -04001774 pTcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001776 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1777 pid = open_file->pid;
1778 else
1779 pid = current->tgid;
1780
Steve Frenchad7a2922008-02-07 23:25:02 +00001781 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001782 cFYI(1, "attempting read on write only file instance");
Steve Frenchad7a2922008-02-07 23:25:02 +00001783
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001784 for (total_read = 0; total_read < len; total_read += bytes_read) {
1785 cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 rc = -EAGAIN;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001787 read_data = NULL;
1788
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 while (rc == -EAGAIN) {
Steve Frenchec637e32005-12-12 20:53:18 -08001790 int buf_type = CIFS_NO_BUFFER;
Steve Frenchcdff08e2010-10-21 22:46:14 +00001791 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04001792 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 if (rc != 0)
1794 break;
1795 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001796 io_parms.netfid = open_file->netfid;
1797 io_parms.pid = pid;
1798 io_parms.tcon = pTcon;
1799 io_parms.offset = *poffset;
Pavel Shilovsky2cebaa52011-07-20 18:24:09 +04001800 io_parms.length = cur_len;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001801 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001802 &read_data, &buf_type);
1803 pSMBr = (struct smb_com_read_rsp *)read_data;
1804 if (read_data) {
1805 char *data_offset = read_data + 4 +
1806 le16_to_cpu(pSMBr->DataOffset);
1807 if (memcpy_toiovecend(iov, data_offset,
1808 iov_offset, bytes_read))
Steve French93544cc2006-02-14 22:30:52 -06001809 rc = -EFAULT;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001810 if (buf_type == CIFS_SMALL_BUFFER)
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001811 cifs_small_buf_release(read_data);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001812 else if (buf_type == CIFS_LARGE_BUFFER)
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001813 cifs_buf_release(read_data);
1814 read_data = NULL;
1815 iov_offset += bytes_read;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 }
1817 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001818
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 if (rc || (bytes_read == 0)) {
1820 if (total_read) {
1821 break;
1822 } else {
1823 FreeXid(xid);
1824 return rc;
1825 }
1826 } else {
Steve Frencha4544342005-08-24 13:59:35 -07001827 cifs_stats_bytes_read(pTcon, bytes_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 *poffset += bytes_read;
1829 }
1830 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001831
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 FreeXid(xid);
1833 return total_read;
1834}
1835
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03001836ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001837 unsigned long nr_segs, loff_t pos)
1838{
1839 ssize_t read;
1840
1841 read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos);
1842 if (read > 0)
1843 iocb->ki_pos = pos;
1844
1845 return read;
1846}
1847
1848ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov,
1849 unsigned long nr_segs, loff_t pos)
1850{
1851 struct inode *inode;
1852
1853 inode = iocb->ki_filp->f_path.dentry->d_inode;
1854
1855 if (CIFS_I(inode)->clientCanCacheRead)
1856 return generic_file_aio_read(iocb, iov, nr_segs, pos);
1857
1858 /*
1859 * In strict cache mode we need to read from the server all the time
1860 * if we don't have level II oplock because the server can delay mtime
1861 * change - so we can't make a decision about inode invalidating.
1862 * And we can also fail with pagereading if there are mandatory locks
1863 * on pages affected by this read but not on the region from pos to
1864 * pos+len-1.
1865 */
1866
1867 return cifs_user_readv(iocb, iov, nr_segs, pos);
1868}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869
1870static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03001871 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872{
1873 int rc = -EACCES;
1874 unsigned int bytes_read = 0;
1875 unsigned int total_read;
1876 unsigned int current_read_size;
1877 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00001878 struct cifs_tcon *pTcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 int xid;
1880 char *current_offset;
1881 struct cifsFileInfo *open_file;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001882 struct cifs_io_parms io_parms;
Steve Frenchec637e32005-12-12 20:53:18 -08001883 int buf_type = CIFS_NO_BUFFER;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001884 __u32 pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885
1886 xid = GetXid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08001887 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888
1889 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301890 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301892 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 }
Joe Perchesc21dfb62010-07-12 13:50:14 -07001894 open_file = file->private_data;
Jeff Layton13cfb732010-09-29 19:51:11 -04001895 pTcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001897 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1898 pid = open_file->pid;
1899 else
1900 pid = current->tgid;
1901
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001903 cFYI(1, "attempting read on write only file instance");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001905 for (total_read = 0, current_offset = read_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 read_size > total_read;
1907 total_read += bytes_read, current_offset += bytes_read) {
Dan Carpenter7748dd62011-10-18 12:41:35 +03001908 current_read_size = min_t(uint, read_size - total_read,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 cifs_sb->rsize);
Steve Frenchf9f5c8172005-09-15 23:06:38 -07001910 /* For windows me and 9x we do not want to request more
1911 than it negotiated since it will refuse the read then */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001912 if ((pTcon->ses) &&
Steve Frenchf9f5c8172005-09-15 23:06:38 -07001913 !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
Dan Carpenter7748dd62011-10-18 12:41:35 +03001914 current_read_size = min_t(uint, current_read_size,
Jeff Laytonc974bef2011-10-11 06:41:32 -04001915 CIFSMaxBufSize);
Steve Frenchf9f5c8172005-09-15 23:06:38 -07001916 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 rc = -EAGAIN;
1918 while (rc == -EAGAIN) {
Steve Frenchcdff08e2010-10-21 22:46:14 +00001919 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04001920 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 if (rc != 0)
1922 break;
1923 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001924 io_parms.netfid = open_file->netfid;
1925 io_parms.pid = pid;
1926 io_parms.tcon = pTcon;
1927 io_parms.offset = *poffset;
1928 io_parms.length = current_read_size;
1929 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
1930 &current_offset, &buf_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 }
1932 if (rc || (bytes_read == 0)) {
1933 if (total_read) {
1934 break;
1935 } else {
1936 FreeXid(xid);
1937 return rc;
1938 }
1939 } else {
Steve Frencha4544342005-08-24 13:59:35 -07001940 cifs_stats_bytes_read(pTcon, total_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 *poffset += bytes_read;
1942 }
1943 }
1944 FreeXid(xid);
1945 return total_read;
1946}
1947
Jeff Laytonca83ce32011-04-12 09:13:44 -04001948/*
1949 * If the page is mmap'ed into a process' page tables, then we need to make
1950 * sure that it doesn't change while being written back.
1951 */
1952static int
1953cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1954{
1955 struct page *page = vmf->page;
1956
1957 lock_page(page);
1958 return VM_FAULT_LOCKED;
1959}
1960
1961static struct vm_operations_struct cifs_file_vm_ops = {
1962 .fault = filemap_fault,
1963 .page_mkwrite = cifs_page_mkwrite,
1964};
1965
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03001966int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
1967{
1968 int rc, xid;
1969 struct inode *inode = file->f_path.dentry->d_inode;
1970
1971 xid = GetXid();
1972
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001973 if (!CIFS_I(inode)->clientCanCacheRead) {
1974 rc = cifs_invalidate_mapping(inode);
1975 if (rc)
1976 return rc;
1977 }
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03001978
1979 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04001980 if (rc == 0)
1981 vma->vm_ops = &cifs_file_vm_ops;
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03001982 FreeXid(xid);
1983 return rc;
1984}
1985
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1987{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 int rc, xid;
1989
1990 xid = GetXid();
Jeff Laytonabab0952010-02-12 07:44:18 -05001991 rc = cifs_revalidate_file(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001993 cFYI(1, "Validation prior to mmap failed, error=%d", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 FreeXid(xid);
1995 return rc;
1996 }
1997 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04001998 if (rc == 0)
1999 vma->vm_ops = &cifs_file_vm_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 FreeXid(xid);
2001 return rc;
2002}
2003
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004static int cifs_readpages(struct file *file, struct address_space *mapping,
2005 struct list_head *page_list, unsigned num_pages)
2006{
Jeff Layton690c5e32011-10-19 15:30:16 -04002007 int rc;
2008 struct list_head tmplist;
2009 struct cifsFileInfo *open_file = file->private_data;
2010 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
2011 unsigned int rsize = cifs_sb->rsize;
2012 pid_t pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013
Jeff Layton690c5e32011-10-19 15:30:16 -04002014 /*
2015 * Give up immediately if rsize is too small to read an entire page.
2016 * The VFS will fall back to readpage. We should never reach this
2017 * point however since we set ra_pages to 0 when the rsize is smaller
2018 * than a cache page.
2019 */
2020 if (unlikely(rsize < PAGE_CACHE_SIZE))
2021 return 0;
Steve Frenchbfa0d752005-08-31 21:50:37 -07002022
Suresh Jayaraman56698232010-07-05 18:13:25 +05302023 /*
2024 * Reads as many pages as possible from fscache. Returns -ENOBUFS
2025 * immediately if the cookie is negative
2026 */
2027 rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
2028 &num_pages);
2029 if (rc == 0)
Jeff Layton690c5e32011-10-19 15:30:16 -04002030 return rc;
Suresh Jayaraman56698232010-07-05 18:13:25 +05302031
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002032 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2033 pid = open_file->pid;
2034 else
2035 pid = current->tgid;
2036
Jeff Layton690c5e32011-10-19 15:30:16 -04002037 rc = 0;
2038 INIT_LIST_HEAD(&tmplist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039
Jeff Layton690c5e32011-10-19 15:30:16 -04002040 cFYI(1, "%s: file=%p mapping=%p num_pages=%u", __func__, file,
2041 mapping, num_pages);
2042
2043 /*
2044 * Start with the page at end of list and move it to private
2045 * list. Do the same with any following pages until we hit
2046 * the rsize limit, hit an index discontinuity, or run out of
2047 * pages. Issue the async read and then start the loop again
2048 * until the list is empty.
2049 *
2050 * Note that list order is important. The page_list is in
2051 * the order of declining indexes. When we put the pages in
2052 * the rdata->pages, then we want them in increasing order.
2053 */
2054 while (!list_empty(page_list)) {
2055 unsigned int bytes = PAGE_CACHE_SIZE;
2056 unsigned int expected_index;
2057 unsigned int nr_pages = 1;
2058 loff_t offset;
2059 struct page *page, *tpage;
2060 struct cifs_readdata *rdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061
2062 page = list_entry(page_list->prev, struct page, lru);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063
Jeff Layton690c5e32011-10-19 15:30:16 -04002064 /*
2065 * Lock the page and put it in the cache. Since no one else
2066 * should have access to this page, we're safe to simply set
2067 * PG_locked without checking it first.
2068 */
2069 __set_page_locked(page);
2070 rc = add_to_page_cache_locked(page, mapping,
2071 page->index, GFP_KERNEL);
2072
2073 /* give up if we can't stick it in the cache */
2074 if (rc) {
2075 __clear_page_locked(page);
2076 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078
Jeff Layton690c5e32011-10-19 15:30:16 -04002079 /* move first page to the tmplist */
2080 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
2081 list_move_tail(&page->lru, &tmplist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082
Jeff Layton690c5e32011-10-19 15:30:16 -04002083 /* now try and add more pages onto the request */
2084 expected_index = page->index + 1;
2085 list_for_each_entry_safe_reverse(page, tpage, page_list, lru) {
2086 /* discontinuity ? */
2087 if (page->index != expected_index)
2088 break;
2089
2090 /* would this page push the read over the rsize? */
2091 if (bytes + PAGE_CACHE_SIZE > rsize)
2092 break;
2093
2094 __set_page_locked(page);
2095 if (add_to_page_cache_locked(page, mapping,
2096 page->index, GFP_KERNEL)) {
2097 __clear_page_locked(page);
2098 break;
2099 }
2100 list_move_tail(&page->lru, &tmplist);
2101 bytes += PAGE_CACHE_SIZE;
2102 expected_index++;
2103 nr_pages++;
2104 }
2105
2106 rdata = cifs_readdata_alloc(nr_pages);
2107 if (!rdata) {
2108 /* best to give up if we're out of mem */
2109 list_for_each_entry_safe(page, tpage, &tmplist, lru) {
2110 list_del(&page->lru);
2111 lru_cache_add_file(page);
2112 unlock_page(page);
2113 page_cache_release(page);
2114 }
2115 rc = -ENOMEM;
2116 break;
2117 }
2118
2119 spin_lock(&cifs_file_list_lock);
2120 cifsFileInfo_get(open_file);
2121 spin_unlock(&cifs_file_list_lock);
2122 rdata->cfile = open_file;
2123 rdata->mapping = mapping;
2124 rdata->offset = offset;
2125 rdata->bytes = bytes;
2126 rdata->pid = pid;
2127 list_splice_init(&tmplist, &rdata->pages);
2128
2129 do {
Steve Frenchcdff08e2010-10-21 22:46:14 +00002130 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04002131 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 if (rc != 0)
Jeff Layton690c5e32011-10-19 15:30:16 -04002133 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 }
Jeff Layton690c5e32011-10-19 15:30:16 -04002135 rc = cifs_async_readv(rdata);
2136 } while (rc == -EAGAIN);
2137
2138 if (rc != 0) {
2139 list_for_each_entry_safe(page, tpage, &rdata->pages,
2140 lru) {
2141 list_del(&page->lru);
2142 lru_cache_add_file(page);
2143 unlock_page(page);
2144 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 }
Jeff Layton690c5e32011-10-19 15:30:16 -04002146 cifs_readdata_free(rdata);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 break;
2148 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 }
2150
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 return rc;
2152}
2153
2154static int cifs_readpage_worker(struct file *file, struct page *page,
2155 loff_t *poffset)
2156{
2157 char *read_data;
2158 int rc;
2159
Suresh Jayaraman56698232010-07-05 18:13:25 +05302160 /* Is the page cached? */
2161 rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page);
2162 if (rc == 0)
2163 goto read_complete;
2164
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 page_cache_get(page);
2166 read_data = kmap(page);
2167 /* for reads over a certain size could initiate async read ahead */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002168
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002170
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 if (rc < 0)
2172 goto io_error;
2173 else
Joe Perchesb6b38f72010-04-21 03:50:45 +00002174 cFYI(1, "Bytes read %d", rc);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002175
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002176 file->f_path.dentry->d_inode->i_atime =
2177 current_fs_time(file->f_path.dentry->d_inode->i_sb);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002178
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 if (PAGE_CACHE_SIZE > rc)
2180 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
2181
2182 flush_dcache_page(page);
2183 SetPageUptodate(page);
Suresh Jayaraman9dc06552010-07-05 18:13:11 +05302184
2185 /* send this page to the cache */
2186 cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page);
2187
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 rc = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002189
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190io_error:
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002191 kunmap(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 page_cache_release(page);
Suresh Jayaraman56698232010-07-05 18:13:25 +05302193
2194read_complete:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 return rc;
2196}
2197
2198static int cifs_readpage(struct file *file, struct page *page)
2199{
2200 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
2201 int rc = -EACCES;
2202 int xid;
2203
2204 xid = GetXid();
2205
2206 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302207 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302209 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 }
2211
Joe Perchesb6b38f72010-04-21 03:50:45 +00002212 cFYI(1, "readpage %p at offset %d 0x%x\n",
2213 page, (int)offset, (int)offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214
2215 rc = cifs_readpage_worker(file, page, &offset);
2216
2217 unlock_page(page);
2218
2219 FreeXid(xid);
2220 return rc;
2221}
2222
Steve Frencha403a0a2007-07-26 15:54:16 +00002223static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
2224{
2225 struct cifsFileInfo *open_file;
2226
Jeff Layton44772882010-10-15 15:34:03 -04002227 spin_lock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002228 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton2e396b82010-10-15 15:34:01 -04002229 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Jeff Layton44772882010-10-15 15:34:03 -04002230 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002231 return 1;
2232 }
2233 }
Jeff Layton44772882010-10-15 15:34:03 -04002234 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00002235 return 0;
2236}
2237
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238/* We do not want to update the file size from server for inodes
2239 open for write - to avoid races with writepage extending
2240 the file - in the future we could consider allowing
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002241 refreshing the inode only on increases in the file size
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 but this is tricky to do without racing with writebehind
2243 page caching in the current Linux kernel design */
Steve French4b18f2a2008-04-29 00:06:05 +00002244bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245{
Steve Frencha403a0a2007-07-26 15:54:16 +00002246 if (!cifsInode)
Steve French4b18f2a2008-04-29 00:06:05 +00002247 return true;
Steve French23e7dd72005-10-20 13:44:56 -07002248
Steve Frencha403a0a2007-07-26 15:54:16 +00002249 if (is_inode_writable(cifsInode)) {
2250 /* This inode is open for write at least once */
Steve Frenchc32a0b62006-01-12 14:41:28 -08002251 struct cifs_sb_info *cifs_sb;
2252
Steve Frenchc32a0b62006-01-12 14:41:28 -08002253 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
Steve Frenchad7a2922008-02-07 23:25:02 +00002254 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002255 /* since no page cache to corrupt on directio
Steve Frenchc32a0b62006-01-12 14:41:28 -08002256 we can change size safely */
Steve French4b18f2a2008-04-29 00:06:05 +00002257 return true;
Steve Frenchc32a0b62006-01-12 14:41:28 -08002258 }
2259
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002260 if (i_size_read(&cifsInode->vfs_inode) < end_of_file)
Steve French4b18f2a2008-04-29 00:06:05 +00002261 return true;
Steve French7ba52632007-02-08 18:14:13 +00002262
Steve French4b18f2a2008-04-29 00:06:05 +00002263 return false;
Steve French23e7dd72005-10-20 13:44:56 -07002264 } else
Steve French4b18f2a2008-04-29 00:06:05 +00002265 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266}
2267
Nick Piggind9414772008-09-24 11:32:59 -04002268static int cifs_write_begin(struct file *file, struct address_space *mapping,
2269 loff_t pos, unsigned len, unsigned flags,
2270 struct page **pagep, void **fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271{
Nick Piggind9414772008-09-24 11:32:59 -04002272 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
2273 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002274 loff_t page_start = pos & PAGE_MASK;
2275 loff_t i_size;
2276 struct page *page;
2277 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278
Joe Perchesb6b38f72010-04-21 03:50:45 +00002279 cFYI(1, "write_begin from %lld len %d", (long long)pos, len);
Nick Piggind9414772008-09-24 11:32:59 -04002280
Nick Piggin54566b22009-01-04 12:00:53 -08002281 page = grab_cache_page_write_begin(mapping, index, flags);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002282 if (!page) {
2283 rc = -ENOMEM;
2284 goto out;
2285 }
Nick Piggind9414772008-09-24 11:32:59 -04002286
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002287 if (PageUptodate(page))
2288 goto out;
Steve French8a236262007-03-06 00:31:00 +00002289
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002290 /*
2291 * If we write a full page it will be up to date, no need to read from
2292 * the server. If the write is short, we'll end up doing a sync write
2293 * instead.
2294 */
2295 if (len == PAGE_CACHE_SIZE)
2296 goto out;
2297
2298 /*
2299 * optimize away the read when we have an oplock, and we're not
2300 * expecting to use any of the data we'd be reading in. That
2301 * is, when the page lies beyond the EOF, or straddles the EOF
2302 * and the write will cover all of the existing data.
2303 */
2304 if (CIFS_I(mapping->host)->clientCanCacheRead) {
2305 i_size = i_size_read(mapping->host);
2306 if (page_start >= i_size ||
2307 (offset == 0 && (pos + len) >= i_size)) {
2308 zero_user_segments(page, 0, offset,
2309 offset + len,
2310 PAGE_CACHE_SIZE);
2311 /*
2312 * PageChecked means that the parts of the page
2313 * to which we're not writing are considered up
2314 * to date. Once the data is copied to the
2315 * page, it can be set uptodate.
2316 */
2317 SetPageChecked(page);
2318 goto out;
2319 }
2320 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321
Nick Piggind9414772008-09-24 11:32:59 -04002322 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002323 /*
2324 * might as well read a page, it is fast enough. If we get
2325 * an error, we don't need to return it. cifs_write_end will
2326 * do a sync write instead since PG_uptodate isn't set.
2327 */
2328 cifs_readpage_worker(file, page, &page_start);
Steve French8a236262007-03-06 00:31:00 +00002329 } else {
2330 /* we could try using another file handle if there is one -
2331 but how would we lock it to prevent close of that handle
2332 racing with this read? In any case
Nick Piggind9414772008-09-24 11:32:59 -04002333 this will be written out by write_end so is fine */
Steve French8a236262007-03-06 00:31:00 +00002334 }
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002335out:
2336 *pagep = page;
2337 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338}
2339
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302340static int cifs_release_page(struct page *page, gfp_t gfp)
2341{
2342 if (PagePrivate(page))
2343 return 0;
2344
2345 return cifs_fscache_release_page(page, gfp);
2346}
2347
2348static void cifs_invalidate_page(struct page *page, unsigned long offset)
2349{
2350 struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
2351
2352 if (offset == 0)
2353 cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
2354}
2355
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002356static int cifs_launder_page(struct page *page)
2357{
2358 int rc = 0;
2359 loff_t range_start = page_offset(page);
2360 loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
2361 struct writeback_control wbc = {
2362 .sync_mode = WB_SYNC_ALL,
2363 .nr_to_write = 0,
2364 .range_start = range_start,
2365 .range_end = range_end,
2366 };
2367
2368 cFYI(1, "Launder page: %p", page);
2369
2370 if (clear_page_dirty_for_io(page))
2371 rc = cifs_writepage_locked(page, &wbc);
2372
2373 cifs_fscache_invalidate_page(page, page->mapping->host);
2374 return rc;
2375}
2376
Tejun Heo9b646972010-07-20 22:09:02 +02002377void cifs_oplock_break(struct work_struct *work)
Jeff Layton3bc303c2009-09-21 06:47:50 -04002378{
2379 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
2380 oplock_break);
Jeff Laytona5e18bc2010-10-11 15:07:18 -04002381 struct inode *inode = cfile->dentry->d_inode;
Jeff Layton3bc303c2009-09-21 06:47:50 -04002382 struct cifsInodeInfo *cinode = CIFS_I(inode);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002383 int rc = 0;
Jeff Layton3bc303c2009-09-21 06:47:50 -04002384
2385 if (inode && S_ISREG(inode->i_mode)) {
Steve Frenchd54ff732010-04-27 04:38:15 +00002386 if (cinode->clientCanCacheRead)
Al Viro8737c932009-12-24 06:47:55 -05002387 break_lease(inode, O_RDONLY);
Steve Frenchd54ff732010-04-27 04:38:15 +00002388 else
Al Viro8737c932009-12-24 06:47:55 -05002389 break_lease(inode, O_WRONLY);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002390 rc = filemap_fdatawrite(inode->i_mapping);
2391 if (cinode->clientCanCacheRead == 0) {
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002392 rc = filemap_fdatawait(inode->i_mapping);
2393 mapping_set_error(inode->i_mapping, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002394 invalidate_remote_inode(inode);
2395 }
Joe Perchesb6b38f72010-04-21 03:50:45 +00002396 cFYI(1, "Oplock flush inode %p rc %d", inode, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002397 }
2398
2399 /*
2400 * releasing stale oplock after recent reconnect of smb session using
2401 * a now incorrect file handle is not a data integrity issue but do
2402 * not bother sending an oplock release if session to server still is
2403 * disconnected since oplock already released by the server
2404 */
Steve Frenchcdff08e2010-10-21 22:46:14 +00002405 if (!cfile->oplock_break_cancelled) {
Pavel Shilovsky03776f42010-08-17 11:26:00 +04002406 rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid,
2407 current->tgid, 0, 0, 0, 0,
2408 LOCKING_ANDX_OPLOCK_RELEASE, false,
Pavel Shilovsky12fed002011-01-17 20:15:44 +03002409 cinode->clientCanCacheRead ? 1 : 0);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002410 cFYI(1, "Oplock release rc = %d", rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04002411 }
Jeff Layton3bc303c2009-09-21 06:47:50 -04002412}
2413
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07002414const struct address_space_operations cifs_addr_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 .readpage = cifs_readpage,
2416 .readpages = cifs_readpages,
2417 .writepage = cifs_writepage,
Steve French37c0eb42005-10-05 14:50:29 -07002418 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04002419 .write_begin = cifs_write_begin,
2420 .write_end = cifs_write_end,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302422 .releasepage = cifs_release_page,
2423 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002424 .launder_page = cifs_launder_page,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425};
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002426
2427/*
2428 * cifs_readpages requires the server to support a buffer large enough to
2429 * contain the header plus one complete page of data. Otherwise, we need
2430 * to leave cifs_readpages out of the address space operations.
2431 */
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07002432const struct address_space_operations cifs_addr_ops_smallbuf = {
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002433 .readpage = cifs_readpage,
2434 .writepage = cifs_writepage,
2435 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04002436 .write_begin = cifs_write_begin,
2437 .write_end = cifs_write_end,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002438 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05302439 .releasepage = cifs_release_page,
2440 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002441 .launder_page = cifs_launder_page,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00002442};