blob: 513adbc211d7029d1c8b1d6670a1a37d9029cac6 [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);
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300267 INIT_LIST_HEAD(&pCifsFile->llist);
Jeff Layton15ecb432010-10-15 15:34:02 -0400268
Jeff Layton44772882010-10-15 15:34:03 -0400269 spin_lock(&cifs_file_list_lock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400270 list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList));
271 /* if readable file instance put first in list*/
272 if (file->f_mode & FMODE_READ)
273 list_add(&pCifsFile->flist, &pCifsInode->openFileList);
274 else
275 list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList);
Jeff Layton44772882010-10-15 15:34:03 -0400276 spin_unlock(&cifs_file_list_lock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400277
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300278 cifs_set_oplock_level(pCifsInode, oplock);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400279 pCifsInode->can_cache_brlcks = pCifsInode->clientCanCacheAll;
Jeff Layton15ecb432010-10-15 15:34:02 -0400280
281 file->private_data = pCifsFile;
282 return pCifsFile;
283}
284
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400285static void cifs_del_lock_waiters(struct cifsLockInfo *lock);
286
Steve Frenchcdff08e2010-10-21 22:46:14 +0000287/*
288 * Release a reference on the file private data. This may involve closing
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400289 * the filehandle out on the server. Must be called without holding
290 * cifs_file_list_lock.
Steve Frenchcdff08e2010-10-21 22:46:14 +0000291 */
Jeff Laytonb33879a2010-10-15 15:34:04 -0400292void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
293{
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300294 struct inode *inode = cifs_file->dentry->d_inode;
Steve French96daf2b2011-05-27 04:34:02 +0000295 struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300296 struct cifsInodeInfo *cifsi = CIFS_I(inode);
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300297 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000298 struct cifsLockInfo *li, *tmp;
299
300 spin_lock(&cifs_file_list_lock);
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400301 if (--cifs_file->count > 0) {
Steve Frenchcdff08e2010-10-21 22:46:14 +0000302 spin_unlock(&cifs_file_list_lock);
303 return;
Jeff Laytonb33879a2010-10-15 15:34:04 -0400304 }
Steve Frenchcdff08e2010-10-21 22:46:14 +0000305
306 /* remove it from the lists */
307 list_del(&cifs_file->flist);
308 list_del(&cifs_file->tlist);
309
310 if (list_empty(&cifsi->openFileList)) {
311 cFYI(1, "closing last open instance for inode %p",
312 cifs_file->dentry->d_inode);
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300313
314 /* in strict cache mode we need invalidate mapping on the last
315 close because it may cause a error when we open this file
316 again and get at least level II oplock */
317 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
318 CIFS_I(inode)->invalid_mapping = true;
319
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300320 cifs_set_oplock_level(cifsi, 0);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000321 }
322 spin_unlock(&cifs_file_list_lock);
323
Jeff Laytonad635942011-07-26 12:20:17 -0400324 cancel_work_sync(&cifs_file->oplock_break);
325
Steve Frenchcdff08e2010-10-21 22:46:14 +0000326 if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
327 int xid, rc;
328
329 xid = GetXid();
330 rc = CIFSSMBClose(xid, tcon, cifs_file->netfid);
331 FreeXid(xid);
332 }
333
334 /* Delete any outstanding lock records. We'll lose them when the file
335 * is closed anyway.
336 */
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400337 mutex_lock(&cifsi->lock_mutex);
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300338 list_for_each_entry_safe(li, tmp, &cifs_file->llist, llist) {
Steve Frenchcdff08e2010-10-21 22:46:14 +0000339 list_del(&li->llist);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400340 cifs_del_lock_waiters(li);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000341 kfree(li);
342 }
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400343 mutex_unlock(&cifsi->lock_mutex);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000344
345 cifs_put_tlink(cifs_file->tlink);
346 dput(cifs_file->dentry);
347 kfree(cifs_file);
Jeff Laytonb33879a2010-10-15 15:34:04 -0400348}
349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350int cifs_open(struct inode *inode, struct file *file)
351{
352 int rc = -EACCES;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400353 int xid;
354 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000356 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400357 struct tcon_link *tlink;
Jeff Layton6ca9f3b2010-06-16 13:40:16 -0400358 struct cifsFileInfo *pCifsFile = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 char *full_path = NULL;
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300360 bool posix_open_ok = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 __u16 netfid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362
363 xid = GetXid();
364
365 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400366 tlink = cifs_sb_tlink(cifs_sb);
367 if (IS_ERR(tlink)) {
368 FreeXid(xid);
369 return PTR_ERR(tlink);
370 }
371 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -0800373 full_path = build_path_from_dentry(file->f_path.dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530375 rc = -ENOMEM;
Jeff Layton232341b2010-08-05 13:58:38 -0400376 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 }
378
Joe Perchesb6b38f72010-04-21 03:50:45 +0000379 cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
380 inode, file->f_flags, full_path);
Steve French276a74a2009-03-03 18:00:34 +0000381
Pavel Shilovsky10b9b982012-03-20 12:55:09 +0300382 if (tcon->ses->server->oplocks)
Steve French276a74a2009-03-03 18:00:34 +0000383 oplock = REQ_OPLOCK;
384 else
385 oplock = 0;
386
Steve French64cc2c62009-03-04 19:54:08 +0000387 if (!tcon->broken_posix_open && tcon->unix_ext &&
388 (tcon->ses->capabilities & CAP_UNIX) &&
Steve French276a74a2009-03-03 18:00:34 +0000389 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
390 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Steve French276a74a2009-03-03 18:00:34 +0000391 /* can not refresh inode info since size could be stale */
Jeff Layton2422f672010-06-16 13:40:16 -0400392 rc = cifs_posix_open(full_path, &inode, inode->i_sb,
Steve Frenchfa588e02010-04-22 19:21:55 +0000393 cifs_sb->mnt_file_mode /* ignored */,
Jeff Layton608712f2010-10-15 15:33:56 -0400394 file->f_flags, &oplock, &netfid, xid);
Steve French276a74a2009-03-03 18:00:34 +0000395 if (rc == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000396 cFYI(1, "posix open succeeded");
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300397 posix_open_ok = true;
Steve French64cc2c62009-03-04 19:54:08 +0000398 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
399 if (tcon->ses->serverNOS)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000400 cERROR(1, "server %s of type %s returned"
Steve French64cc2c62009-03-04 19:54:08 +0000401 " unexpected error on SMB posix open"
402 ", disabling posix open support."
403 " Check if server update available.",
404 tcon->ses->serverName,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000405 tcon->ses->serverNOS);
Steve French64cc2c62009-03-04 19:54:08 +0000406 tcon->broken_posix_open = true;
Steve French276a74a2009-03-03 18:00:34 +0000407 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
408 (rc != -EOPNOTSUPP)) /* path not found or net err */
409 goto out;
Steve French64cc2c62009-03-04 19:54:08 +0000410 /* else fallthrough to retry open the old way on network i/o
411 or DFS errors */
Steve French276a74a2009-03-03 18:00:34 +0000412 }
413
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300414 if (!posix_open_ok) {
415 rc = cifs_nt_open(full_path, inode, cifs_sb, tcon,
416 file->f_flags, &oplock, &netfid, xid);
417 if (rc)
418 goto out;
419 }
Jeff Layton47c78b72010-06-16 13:40:17 -0400420
Jeff Laytonabfe1ee2010-10-15 15:33:58 -0400421 pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock);
Jeff Layton6ca9f3b2010-06-16 13:40:16 -0400422 if (pCifsFile == NULL) {
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300423 CIFSSMBClose(xid, tcon, netfid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 rc = -ENOMEM;
425 goto out;
426 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530428 cifs_fscache_set_inode_cookie(inode, file);
429
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300430 if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 /* time to set mode which we can not set earlier due to
432 problems creating new read-only files */
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300433 struct cifs_unix_set_info_args args = {
434 .mode = inode->i_mode,
435 .uid = NO_CHANGE_64,
436 .gid = NO_CHANGE_64,
437 .ctime = NO_CHANGE_64,
438 .atime = NO_CHANGE_64,
439 .mtime = NO_CHANGE_64,
440 .device = 0,
441 };
Jeff Laytond44a9fe2011-01-07 11:30:29 -0500442 CIFSSMBUnixSetFileInfo(xid, tcon, &args, netfid,
443 pCifsFile->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 }
445
446out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 kfree(full_path);
448 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400449 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 return rc;
451}
452
Adrian Bunk04187262006-06-30 18:23:04 +0200453/* Try to reacquire byte range locks that were released when session */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454/* to server was lost */
455static int cifs_relock_file(struct cifsFileInfo *cifsFile)
456{
457 int rc = 0;
458
459/* BB list all locks open on this file and relock */
460
461 return rc;
462}
463
Jeff Layton15886172010-10-15 15:33:59 -0400464static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465{
466 int rc = -EACCES;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400467 int xid;
468 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000470 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 struct cifsInodeInfo *pCifsInode;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000472 struct inode *inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 char *full_path = NULL;
474 int desiredAccess;
475 int disposition = FILE_OPEN;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500476 int create_options = CREATE_NOT_DIR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 __u16 netfid;
478
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 xid = GetXid();
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400480 mutex_lock(&pCifsFile->fh_mutex);
Steve French4b18f2a2008-04-29 00:06:05 +0000481 if (!pCifsFile->invalidHandle) {
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400482 mutex_unlock(&pCifsFile->fh_mutex);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530483 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530485 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 }
487
Jeff Layton15886172010-10-15 15:33:59 -0400488 inode = pCifsFile->dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton13cfb732010-09-29 19:51:11 -0400490 tcon = tlink_tcon(pCifsFile->tlink);
Steve French3a9f4622007-04-04 17:10:24 +0000491
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492/* can not grab rename sem here because various ops, including
493 those that already have the rename sem can end up causing writepage
494 to get called and if the server was down that means we end up here,
495 and we can never tell if the caller already has the rename_sem */
Jeff Layton15886172010-10-15 15:33:59 -0400496 full_path = build_path_from_dentry(pCifsFile->dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 if (full_path == NULL) {
Steve French3a9f4622007-04-04 17:10:24 +0000498 rc = -ENOMEM;
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400499 mutex_unlock(&pCifsFile->fh_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 FreeXid(xid);
Steve French3a9f4622007-04-04 17:10:24 +0000501 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 }
503
Joe Perchesb6b38f72010-04-21 03:50:45 +0000504 cFYI(1, "inode = 0x%p file flags 0x%x for %s",
Jeff Layton15886172010-10-15 15:33:59 -0400505 inode, pCifsFile->f_flags, full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
Pavel Shilovsky10b9b982012-03-20 12:55:09 +0300507 if (tcon->ses->server->oplocks)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 oplock = REQ_OPLOCK;
509 else
Steve French4b18f2a2008-04-29 00:06:05 +0000510 oplock = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511
Steve French7fc8f4e2009-02-23 20:43:11 +0000512 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
513 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
514 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton608712f2010-10-15 15:33:56 -0400515
516 /*
517 * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
518 * original open. Must mask them off for a reopen.
519 */
Jeff Layton15886172010-10-15 15:33:59 -0400520 unsigned int oflags = pCifsFile->f_flags &
521 ~(O_CREAT | O_EXCL | O_TRUNC);
Jeff Layton608712f2010-10-15 15:33:56 -0400522
Jeff Layton2422f672010-06-16 13:40:16 -0400523 rc = cifs_posix_open(full_path, NULL, inode->i_sb,
Steve Frenchfa588e02010-04-22 19:21:55 +0000524 cifs_sb->mnt_file_mode /* ignored */,
525 oflags, &oplock, &netfid, xid);
Steve French7fc8f4e2009-02-23 20:43:11 +0000526 if (rc == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000527 cFYI(1, "posix reopen succeeded");
Steve French7fc8f4e2009-02-23 20:43:11 +0000528 goto reopen_success;
529 }
530 /* fallthrough to retry open the old way on errors, especially
531 in the reconnect path it is important to retry hard */
532 }
533
Jeff Layton15886172010-10-15 15:33:59 -0400534 desiredAccess = cifs_convert_flags(pCifsFile->f_flags);
Steve French7fc8f4e2009-02-23 20:43:11 +0000535
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500536 if (backup_cred(cifs_sb))
537 create_options |= CREATE_OPEN_BACKUP_INTENT;
538
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 /* Can not refresh inode by passing in file_info buf to be returned
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000540 by SMBOpen and then calling get_inode_info with returned buf
541 since file might have write behind data that needs to be flushed
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 and server version of file size can be stale. If we knew for sure
543 that inode was not dirty locally we could do this */
544
Steve French7fc8f4e2009-02-23 20:43:11 +0000545 rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess,
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500546 create_options, &netfid, &oplock, NULL,
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000547 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
Steve French737b7582005-04-28 22:41:06 -0700548 CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 if (rc) {
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400550 mutex_unlock(&pCifsFile->fh_mutex);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000551 cFYI(1, "cifs_open returned 0x%x", rc);
552 cFYI(1, "oplock: %d", oplock);
Jeff Layton15886172010-10-15 15:33:59 -0400553 goto reopen_error_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 }
Jeff Layton15886172010-10-15 15:33:59 -0400555
556reopen_success:
557 pCifsFile->netfid = netfid;
558 pCifsFile->invalidHandle = false;
559 mutex_unlock(&pCifsFile->fh_mutex);
560 pCifsInode = CIFS_I(inode);
561
562 if (can_flush) {
563 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -0400564 mapping_set_error(inode->i_mapping, rc);
Jeff Layton15886172010-10-15 15:33:59 -0400565
Jeff Layton15886172010-10-15 15:33:59 -0400566 if (tcon->unix_ext)
567 rc = cifs_get_inode_info_unix(&inode,
568 full_path, inode->i_sb, xid);
569 else
570 rc = cifs_get_inode_info(&inode,
571 full_path, NULL, inode->i_sb,
572 xid, NULL);
573 } /* else we are writing out data to server already
574 and could deadlock if we tried to flush data, and
575 since we do not know if we have data that would
576 invalidate the current end of file on the server
577 we can not go to the server to get the new inod
578 info */
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300579
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300580 cifs_set_oplock_level(pCifsInode, oplock);
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300581
Jeff Layton15886172010-10-15 15:33:59 -0400582 cifs_relock_file(pCifsFile);
583
584reopen_error_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 kfree(full_path);
586 FreeXid(xid);
587 return rc;
588}
589
590int cifs_close(struct inode *inode, struct file *file)
591{
Jeff Layton77970692011-04-05 16:23:47 -0700592 if (file->private_data != NULL) {
593 cifsFileInfo_put(file->private_data);
594 file->private_data = NULL;
595 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
Steve Frenchcdff08e2010-10-21 22:46:14 +0000597 /* return code from the ->release op is always ignored */
598 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599}
600
601int cifs_closedir(struct inode *inode, struct file *file)
602{
603 int rc = 0;
604 int xid;
Joe Perchesc21dfb62010-07-12 13:50:14 -0700605 struct cifsFileInfo *pCFileStruct = file->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 char *ptmp;
607
Joe Perchesb6b38f72010-04-21 03:50:45 +0000608 cFYI(1, "Closedir inode = 0x%p", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
610 xid = GetXid();
611
612 if (pCFileStruct) {
Steve French96daf2b2011-05-27 04:34:02 +0000613 struct cifs_tcon *pTcon = tlink_tcon(pCFileStruct->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
Joe Perchesb6b38f72010-04-21 03:50:45 +0000615 cFYI(1, "Freeing private data in close dir");
Jeff Layton44772882010-10-15 15:34:03 -0400616 spin_lock(&cifs_file_list_lock);
Steve French4b18f2a2008-04-29 00:06:05 +0000617 if (!pCFileStruct->srch_inf.endOfSearch &&
618 !pCFileStruct->invalidHandle) {
619 pCFileStruct->invalidHandle = true;
Jeff Layton44772882010-10-15 15:34:03 -0400620 spin_unlock(&cifs_file_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000622 cFYI(1, "Closing uncompleted readdir with rc %d",
623 rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 /* not much we can do if it fails anyway, ignore rc */
625 rc = 0;
Steve Frenchddb4cbf2008-11-20 20:00:44 +0000626 } else
Jeff Layton44772882010-10-15 15:34:03 -0400627 spin_unlock(&cifs_file_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
629 if (ptmp) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000630 cFYI(1, "closedir free smb buf in srch struct");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000632 if (pCFileStruct->srch_inf.smallBuf)
Steve Frenchd47d7c12006-02-28 03:45:48 +0000633 cifs_small_buf_release(ptmp);
634 else
635 cifs_buf_release(ptmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 }
Jeff Layton13cfb732010-09-29 19:51:11 -0400637 cifs_put_tlink(pCFileStruct->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 kfree(file->private_data);
639 file->private_data = NULL;
640 }
641 /* BB can we lock the filestruct while this is going on? */
642 FreeXid(xid);
643 return rc;
644}
645
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400646static struct cifsLockInfo *
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300647cifs_lock_init(__u64 offset, __u64 length, __u8 type)
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000648{
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400649 struct cifsLockInfo *lock =
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000650 kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400651 if (!lock)
652 return lock;
653 lock->offset = offset;
654 lock->length = length;
655 lock->type = type;
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400656 lock->pid = current->tgid;
657 INIT_LIST_HEAD(&lock->blist);
658 init_waitqueue_head(&lock->block_q);
659 return lock;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400660}
661
662static void
663cifs_del_lock_waiters(struct cifsLockInfo *lock)
664{
665 struct cifsLockInfo *li, *tmp;
666 list_for_each_entry_safe(li, tmp, &lock->blist, blist) {
667 list_del_init(&li->blist);
668 wake_up(&li->block_q);
669 }
670}
671
672static bool
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300673cifs_find_fid_lock_conflict(struct cifsFileInfo *cfile, __u64 offset,
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300674 __u64 length, __u8 type, struct cifsFileInfo *cur,
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300675 struct cifsLockInfo **conf_lock)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400676{
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300677 struct cifsLockInfo *li;
Pavel Shilovsky106dc532012-02-28 14:23:34 +0300678 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400679
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300680 list_for_each_entry(li, &cfile->llist, llist) {
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400681 if (offset + length <= li->offset ||
682 offset >= li->offset + li->length)
683 continue;
Pavel Shilovsky106dc532012-02-28 14:23:34 +0300684 else if ((type & server->vals->shared_lock_type) &&
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300685 ((server->ops->compare_fids(cur, cfile) &&
686 current->tgid == li->pid) || type == li->type))
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400687 continue;
688 else {
689 *conf_lock = li;
690 return true;
691 }
692 }
693 return false;
694}
695
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400696static bool
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300697cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
698 __u8 type, struct cifsLockInfo **conf_lock)
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400699{
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300700 bool rc = false;
701 struct cifsFileInfo *fid, *tmp;
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300702 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300703
704 spin_lock(&cifs_file_list_lock);
705 list_for_each_entry_safe(fid, tmp, &cinode->openFileList, flist) {
706 rc = cifs_find_fid_lock_conflict(fid, offset, length, type,
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300707 cfile, conf_lock);
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300708 if (rc)
709 break;
710 }
711 spin_unlock(&cifs_file_list_lock);
712
713 return rc;
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400714}
715
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300716/*
717 * Check if there is another lock that prevents us to set the lock (mandatory
718 * style). If such a lock exists, update the flock structure with its
719 * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks
720 * or leave it the same if we can't. Returns 0 if we don't need to request to
721 * the server or 1 otherwise.
722 */
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400723static int
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300724cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
725 __u8 type, struct file_lock *flock)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400726{
727 int rc = 0;
728 struct cifsLockInfo *conf_lock;
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300729 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovsky106dc532012-02-28 14:23:34 +0300730 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400731 bool exist;
732
733 mutex_lock(&cinode->lock_mutex);
734
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300735 exist = cifs_find_lock_conflict(cfile, offset, length, type,
736 &conf_lock);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400737 if (exist) {
738 flock->fl_start = conf_lock->offset;
739 flock->fl_end = conf_lock->offset + conf_lock->length - 1;
740 flock->fl_pid = conf_lock->pid;
Pavel Shilovsky106dc532012-02-28 14:23:34 +0300741 if (conf_lock->type & server->vals->shared_lock_type)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400742 flock->fl_type = F_RDLCK;
743 else
744 flock->fl_type = F_WRLCK;
745 } else if (!cinode->can_cache_brlcks)
746 rc = 1;
747 else
748 flock->fl_type = F_UNLCK;
749
750 mutex_unlock(&cinode->lock_mutex);
751 return rc;
752}
753
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400754static void
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300755cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400756{
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300757 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400758 mutex_lock(&cinode->lock_mutex);
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300759 list_add_tail(&lock->llist, &cfile->llist);
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400760 mutex_unlock(&cinode->lock_mutex);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000761}
762
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300763/*
764 * Set the byte-range lock (mandatory style). Returns:
765 * 1) 0, if we set the lock and don't need to request to the server;
766 * 2) 1, if no locks prevent us but we need to request to the server;
767 * 3) -EACCESS, if there is a lock that prevents us and wait is false.
768 */
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400769static int
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300770cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock,
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400771 bool wait)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400772{
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400773 struct cifsLockInfo *conf_lock;
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300774 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400775 bool exist;
776 int rc = 0;
777
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400778try_again:
779 exist = false;
780 mutex_lock(&cinode->lock_mutex);
781
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300782 exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length,
783 lock->type, &conf_lock);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400784 if (!exist && cinode->can_cache_brlcks) {
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300785 list_add_tail(&lock->llist, &cfile->llist);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400786 mutex_unlock(&cinode->lock_mutex);
787 return rc;
788 }
789
790 if (!exist)
791 rc = 1;
792 else if (!wait)
793 rc = -EACCES;
794 else {
795 list_add_tail(&lock->blist, &conf_lock->blist);
796 mutex_unlock(&cinode->lock_mutex);
797 rc = wait_event_interruptible(lock->block_q,
798 (lock->blist.prev == &lock->blist) &&
799 (lock->blist.next == &lock->blist));
800 if (!rc)
801 goto try_again;
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400802 mutex_lock(&cinode->lock_mutex);
803 list_del_init(&lock->blist);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400804 }
805
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400806 mutex_unlock(&cinode->lock_mutex);
807 return rc;
808}
809
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300810/*
811 * Check if there is another lock that prevents us to set the lock (posix
812 * style). If such a lock exists, update the flock structure with its
813 * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks
814 * or leave it the same if we can't. Returns 0 if we don't need to request to
815 * the server or 1 otherwise.
816 */
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400817static int
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400818cifs_posix_lock_test(struct file *file, struct file_lock *flock)
819{
820 int rc = 0;
821 struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode);
822 unsigned char saved_type = flock->fl_type;
823
Pavel Shilovsky50792762011-10-29 17:17:57 +0400824 if ((flock->fl_flags & FL_POSIX) == 0)
825 return 1;
826
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400827 mutex_lock(&cinode->lock_mutex);
828 posix_test_lock(file, flock);
829
830 if (flock->fl_type == F_UNLCK && !cinode->can_cache_brlcks) {
831 flock->fl_type = saved_type;
832 rc = 1;
833 }
834
835 mutex_unlock(&cinode->lock_mutex);
836 return rc;
837}
838
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300839/*
840 * Set the byte-range lock (posix style). Returns:
841 * 1) 0, if we set the lock and don't need to request to the server;
842 * 2) 1, if we need to request to the server;
843 * 3) <0, if the error occurs while setting the lock.
844 */
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400845static int
846cifs_posix_lock_set(struct file *file, struct file_lock *flock)
847{
848 struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode);
Pavel Shilovsky50792762011-10-29 17:17:57 +0400849 int rc = 1;
850
851 if ((flock->fl_flags & FL_POSIX) == 0)
852 return rc;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400853
Pavel Shilovsky66189be2012-03-28 21:56:19 +0400854try_again:
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400855 mutex_lock(&cinode->lock_mutex);
856 if (!cinode->can_cache_brlcks) {
857 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky50792762011-10-29 17:17:57 +0400858 return rc;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400859 }
Pavel Shilovsky66189be2012-03-28 21:56:19 +0400860
861 rc = posix_lock_file(file, flock, NULL);
Steve French9ebb3892012-04-01 13:52:54 -0500862 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky66189be2012-03-28 21:56:19 +0400863 if (rc == FILE_LOCK_DEFERRED) {
864 rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next);
865 if (!rc)
866 goto try_again;
867 locks_delete_block(flock);
868 }
Steve French9ebb3892012-04-01 13:52:54 -0500869 return rc;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400870}
871
872static int
873cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400874{
875 int xid, rc = 0, stored_rc;
876 struct cifsLockInfo *li, *tmp;
877 struct cifs_tcon *tcon;
878 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovsky0013fb42012-05-31 13:03:26 +0400879 unsigned int num, max_num, max_buf;
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400880 LOCKING_ANDX_RANGE *buf, *cur;
881 int types[] = {LOCKING_ANDX_LARGE_FILES,
882 LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
883 int i;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400884
885 xid = GetXid();
886 tcon = tlink_tcon(cfile->tlink);
887
888 mutex_lock(&cinode->lock_mutex);
889 if (!cinode->can_cache_brlcks) {
890 mutex_unlock(&cinode->lock_mutex);
891 FreeXid(xid);
892 return rc;
893 }
894
Pavel Shilovsky0013fb42012-05-31 13:03:26 +0400895 /*
896 * Accessing maxBuf is racy with cifs_reconnect - need to store value
897 * and check it for zero before using.
898 */
899 max_buf = tcon->ses->server->maxBuf;
900 if (!max_buf) {
901 mutex_unlock(&cinode->lock_mutex);
902 FreeXid(xid);
903 return -EINVAL;
904 }
905
906 max_num = (max_buf - sizeof(struct smb_hdr)) /
907 sizeof(LOCKING_ANDX_RANGE);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400908 buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
909 if (!buf) {
910 mutex_unlock(&cinode->lock_mutex);
911 FreeXid(xid);
912 return rc;
913 }
914
915 for (i = 0; i < 2; i++) {
916 cur = buf;
917 num = 0;
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300918 list_for_each_entry_safe(li, tmp, &cfile->llist, llist) {
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400919 if (li->type != types[i])
920 continue;
921 cur->Pid = cpu_to_le16(li->pid);
922 cur->LengthLow = cpu_to_le32((u32)li->length);
923 cur->LengthHigh = cpu_to_le32((u32)(li->length>>32));
924 cur->OffsetLow = cpu_to_le32((u32)li->offset);
925 cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
926 if (++num == max_num) {
927 stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +0300928 (__u8)li->type, 0, num,
929 buf);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400930 if (stored_rc)
931 rc = stored_rc;
932 cur = buf;
933 num = 0;
934 } else
935 cur++;
936 }
937
938 if (num) {
939 stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +0300940 (__u8)types[i], 0, num, buf);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400941 if (stored_rc)
942 rc = stored_rc;
943 }
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400944 }
945
946 cinode->can_cache_brlcks = false;
947 mutex_unlock(&cinode->lock_mutex);
948
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400949 kfree(buf);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400950 FreeXid(xid);
951 return rc;
952}
953
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400954/* copied from fs/locks.c with a name change */
955#define cifs_for_each_lock(inode, lockp) \
956 for (lockp = &inode->i_flock; *lockp != NULL; \
957 lockp = &(*lockp)->fl_next)
958
Pavel Shilovskyd5751462012-03-05 09:39:20 +0300959struct lock_to_push {
960 struct list_head llist;
961 __u64 offset;
962 __u64 length;
963 __u32 pid;
964 __u16 netfid;
965 __u8 type;
966};
967
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400968static int
969cifs_push_posix_locks(struct cifsFileInfo *cfile)
970{
971 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
972 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
973 struct file_lock *flock, **before;
Pavel Shilovskyd5751462012-03-05 09:39:20 +0300974 unsigned int count = 0, i = 0;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400975 int rc = 0, xid, type;
Pavel Shilovskyd5751462012-03-05 09:39:20 +0300976 struct list_head locks_to_send, *el;
977 struct lock_to_push *lck, *tmp;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400978 __u64 length;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400979
980 xid = GetXid();
981
982 mutex_lock(&cinode->lock_mutex);
983 if (!cinode->can_cache_brlcks) {
984 mutex_unlock(&cinode->lock_mutex);
985 FreeXid(xid);
986 return rc;
987 }
988
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400989 lock_flocks();
990 cifs_for_each_lock(cfile->dentry->d_inode, before) {
Pavel Shilovskyd5751462012-03-05 09:39:20 +0300991 if ((*before)->fl_flags & FL_POSIX)
992 count++;
993 }
994 unlock_flocks();
995
996 INIT_LIST_HEAD(&locks_to_send);
997
998 /*
Pavel Shilovskyce858522012-03-17 09:46:55 +0300999 * Allocating count locks is enough because no FL_POSIX locks can be
1000 * added to the list while we are holding cinode->lock_mutex that
1001 * protects locking operations of this inode.
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001002 */
1003 for (; i < count; i++) {
1004 lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL);
1005 if (!lck) {
1006 rc = -ENOMEM;
1007 goto err_out;
1008 }
1009 list_add_tail(&lck->llist, &locks_to_send);
1010 }
1011
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001012 el = locks_to_send.next;
1013 lock_flocks();
1014 cifs_for_each_lock(cfile->dentry->d_inode, before) {
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001015 flock = *before;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001016 if ((flock->fl_flags & FL_POSIX) == 0)
1017 continue;
Pavel Shilovskyce858522012-03-17 09:46:55 +03001018 if (el == &locks_to_send) {
1019 /*
1020 * The list ended. We don't have enough allocated
1021 * structures - something is really wrong.
1022 */
1023 cERROR(1, "Can't push all brlocks!");
1024 break;
1025 }
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001026 length = 1 + flock->fl_end - flock->fl_start;
1027 if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK)
1028 type = CIFS_RDLCK;
1029 else
1030 type = CIFS_WRLCK;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001031 lck = list_entry(el, struct lock_to_push, llist);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001032 lck->pid = flock->fl_pid;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001033 lck->netfid = cfile->netfid;
1034 lck->length = length;
1035 lck->type = type;
1036 lck->offset = flock->fl_start;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001037 el = el->next;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001038 }
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001039 unlock_flocks();
1040
1041 list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
1042 struct file_lock tmp_lock;
1043 int stored_rc;
1044
1045 tmp_lock.fl_start = lck->offset;
1046 stored_rc = CIFSSMBPosixLock(xid, tcon, lck->netfid, lck->pid,
1047 0, lck->length, &tmp_lock,
1048 lck->type, 0);
1049 if (stored_rc)
1050 rc = stored_rc;
1051 list_del(&lck->llist);
1052 kfree(lck);
1053 }
1054
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001055out:
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001056 cinode->can_cache_brlcks = false;
1057 mutex_unlock(&cinode->lock_mutex);
1058
1059 FreeXid(xid);
1060 return rc;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001061err_out:
1062 list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
1063 list_del(&lck->llist);
1064 kfree(lck);
1065 }
1066 goto out;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001067}
1068
1069static int
1070cifs_push_locks(struct cifsFileInfo *cfile)
1071{
1072 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
1073 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1074
1075 if ((tcon->ses->capabilities & CAP_UNIX) &&
1076 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
1077 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
1078 return cifs_push_posix_locks(cfile);
1079
1080 return cifs_push_mandatory_locks(cfile);
1081}
1082
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001083static void
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001084cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock,
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001085 bool *wait_flag, struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086{
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001087 if (flock->fl_flags & FL_POSIX)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001088 cFYI(1, "Posix");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001089 if (flock->fl_flags & FL_FLOCK)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001090 cFYI(1, "Flock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001091 if (flock->fl_flags & FL_SLEEP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001092 cFYI(1, "Blocking lock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001093 *wait_flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 }
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001095 if (flock->fl_flags & FL_ACCESS)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001096 cFYI(1, "Process suspended by mandatory locking - "
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001097 "not implemented yet");
1098 if (flock->fl_flags & FL_LEASE)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001099 cFYI(1, "Lease on file - not implemented yet");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001100 if (flock->fl_flags &
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001102 cFYI(1, "Unknown lock flags 0x%x", flock->fl_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001104 *type = server->vals->large_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001105 if (flock->fl_type == F_WRLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001106 cFYI(1, "F_WRLCK ");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001107 *type |= server->vals->exclusive_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001108 *lock = 1;
1109 } else if (flock->fl_type == F_UNLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001110 cFYI(1, "F_UNLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001111 *type |= server->vals->unlock_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001112 *unlock = 1;
1113 /* Check if unlock includes more than one lock range */
1114 } else if (flock->fl_type == F_RDLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001115 cFYI(1, "F_RDLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001116 *type |= server->vals->shared_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001117 *lock = 1;
1118 } else if (flock->fl_type == F_EXLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001119 cFYI(1, "F_EXLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001120 *type |= server->vals->exclusive_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001121 *lock = 1;
1122 } else if (flock->fl_type == F_SHLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001123 cFYI(1, "F_SHLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001124 *type |= server->vals->shared_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001125 *lock = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +00001127 cFYI(1, "Unknown type of lock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001128}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001130static int
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001131cifs_mandatory_lock(int xid, struct cifsFileInfo *cfile, __u64 offset,
1132 __u64 length, __u32 type, int lock, int unlock, bool wait)
1133{
1134 return CIFSSMBLock(xid, tlink_tcon(cfile->tlink), cfile->netfid,
1135 current->tgid, length, offset, unlock, lock,
1136 (__u8)type, wait, 0);
1137}
1138
1139static int
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001140cifs_getlk(struct file *file, struct file_lock *flock, __u32 type,
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001141 bool wait_flag, bool posix_lck, int xid)
1142{
1143 int rc = 0;
1144 __u64 length = 1 + flock->fl_end - flock->fl_start;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001145 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
1146 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001147 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001148 __u16 netfid = cfile->netfid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001150 if (posix_lck) {
1151 int posix_lock_type;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001152
1153 rc = cifs_posix_lock_test(file, flock);
1154 if (!rc)
1155 return rc;
1156
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001157 if (type & server->vals->shared_lock_type)
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001158 posix_lock_type = CIFS_RDLCK;
1159 else
1160 posix_lock_type = CIFS_WRLCK;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001161 rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid,
1162 1 /* get */, length, flock,
1163 posix_lock_type, wait_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 return rc;
1165 }
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001166
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001167 rc = cifs_lock_test(cfile, flock->fl_start, length, type, flock);
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001168 if (!rc)
1169 return rc;
1170
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001171 /* BB we could chain these into one lock request BB */
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001172 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length, type,
1173 1, 0, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001174 if (rc == 0) {
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001175 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1176 type, 0, 1, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001177 flock->fl_type = F_UNLCK;
1178 if (rc != 0)
1179 cERROR(1, "Error unlocking previously locked "
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001180 "range %d during test of lock", rc);
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001181 return 0;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001182 }
1183
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001184 if (type & server->vals->shared_lock_type) {
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001185 flock->fl_type = F_WRLCK;
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001186 return 0;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001187 }
1188
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001189 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1190 type | server->vals->shared_lock_type, 1, 0,
1191 false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001192 if (rc == 0) {
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001193 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1194 type | server->vals->shared_lock_type,
1195 0, 1, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001196 flock->fl_type = F_RDLCK;
1197 if (rc != 0)
1198 cERROR(1, "Error unlocking previously locked "
1199 "range %d during test of lock", rc);
1200 } else
1201 flock->fl_type = F_WRLCK;
1202
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001203 return 0;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001204}
1205
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001206static void
1207cifs_move_llist(struct list_head *source, struct list_head *dest)
1208{
1209 struct list_head *li, *tmp;
1210 list_for_each_safe(li, tmp, source)
1211 list_move(li, dest);
1212}
1213
1214static void
1215cifs_free_llist(struct list_head *llist)
1216{
1217 struct cifsLockInfo *li, *tmp;
1218 list_for_each_entry_safe(li, tmp, llist, llist) {
1219 cifs_del_lock_waiters(li);
1220 list_del(&li->llist);
1221 kfree(li);
1222 }
1223}
1224
1225static int
1226cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid)
1227{
1228 int rc = 0, stored_rc;
1229 int types[] = {LOCKING_ANDX_LARGE_FILES,
1230 LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
1231 unsigned int i;
Pavel Shilovsky0013fb42012-05-31 13:03:26 +04001232 unsigned int max_num, num, max_buf;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001233 LOCKING_ANDX_RANGE *buf, *cur;
1234 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1235 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
1236 struct cifsLockInfo *li, *tmp;
1237 __u64 length = 1 + flock->fl_end - flock->fl_start;
1238 struct list_head tmp_llist;
1239
1240 INIT_LIST_HEAD(&tmp_llist);
1241
Pavel Shilovsky0013fb42012-05-31 13:03:26 +04001242 /*
1243 * Accessing maxBuf is racy with cifs_reconnect - need to store value
1244 * and check it for zero before using.
1245 */
1246 max_buf = tcon->ses->server->maxBuf;
1247 if (!max_buf)
1248 return -EINVAL;
1249
1250 max_num = (max_buf - sizeof(struct smb_hdr)) /
1251 sizeof(LOCKING_ANDX_RANGE);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001252 buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
1253 if (!buf)
1254 return -ENOMEM;
1255
1256 mutex_lock(&cinode->lock_mutex);
1257 for (i = 0; i < 2; i++) {
1258 cur = buf;
1259 num = 0;
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001260 list_for_each_entry_safe(li, tmp, &cfile->llist, llist) {
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001261 if (flock->fl_start > li->offset ||
1262 (flock->fl_start + length) <
1263 (li->offset + li->length))
1264 continue;
1265 if (current->tgid != li->pid)
1266 continue;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001267 if (types[i] != li->type)
1268 continue;
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001269 if (cinode->can_cache_brlcks) {
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001270 /*
1271 * We can cache brlock requests - simply remove
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001272 * a lock from the file's list.
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001273 */
1274 list_del(&li->llist);
1275 cifs_del_lock_waiters(li);
1276 kfree(li);
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001277 continue;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001278 }
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001279 cur->Pid = cpu_to_le16(li->pid);
1280 cur->LengthLow = cpu_to_le32((u32)li->length);
1281 cur->LengthHigh = cpu_to_le32((u32)(li->length>>32));
1282 cur->OffsetLow = cpu_to_le32((u32)li->offset);
1283 cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
1284 /*
1285 * We need to save a lock here to let us add it again to
1286 * the file's list if the unlock range request fails on
1287 * the server.
1288 */
1289 list_move(&li->llist, &tmp_llist);
1290 if (++num == max_num) {
1291 stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
1292 li->type, num, 0, buf);
1293 if (stored_rc) {
1294 /*
1295 * We failed on the unlock range
1296 * request - add all locks from the tmp
1297 * list to the head of the file's list.
1298 */
1299 cifs_move_llist(&tmp_llist,
1300 &cfile->llist);
1301 rc = stored_rc;
1302 } else
1303 /*
1304 * The unlock range request succeed -
1305 * free the tmp list.
1306 */
1307 cifs_free_llist(&tmp_llist);
1308 cur = buf;
1309 num = 0;
1310 } else
1311 cur++;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001312 }
1313 if (num) {
1314 stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
1315 types[i], num, 0, buf);
1316 if (stored_rc) {
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001317 cifs_move_llist(&tmp_llist, &cfile->llist);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001318 rc = stored_rc;
1319 } else
1320 cifs_free_llist(&tmp_llist);
1321 }
1322 }
1323
1324 mutex_unlock(&cinode->lock_mutex);
1325 kfree(buf);
1326 return rc;
1327}
1328
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001329static int
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001330cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001331 bool wait_flag, bool posix_lck, int lock, int unlock, int xid)
1332{
1333 int rc = 0;
1334 __u64 length = 1 + flock->fl_end - flock->fl_start;
1335 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
1336 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001337 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001338 __u16 netfid = cfile->netfid;
1339
1340 if (posix_lck) {
Steve French08547b02006-02-28 22:39:25 +00001341 int posix_lock_type;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001342
1343 rc = cifs_posix_lock_set(file, flock);
1344 if (!rc || rc < 0)
1345 return rc;
1346
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001347 if (type & server->vals->shared_lock_type)
Steve French08547b02006-02-28 22:39:25 +00001348 posix_lock_type = CIFS_RDLCK;
1349 else
1350 posix_lock_type = CIFS_WRLCK;
Steve French50c2f752007-07-13 00:33:32 +00001351
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001352 if (unlock == 1)
Steve Frenchbeb84dc2006-03-03 23:36:34 +00001353 posix_lock_type = CIFS_UNLCK;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001354
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001355 rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid,
1356 0 /* set */, length, flock,
1357 posix_lock_type, wait_flag);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001358 goto out;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001359 }
1360
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001361 if (lock) {
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001362 struct cifsLockInfo *lock;
1363
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001364 lock = cifs_lock_init(flock->fl_start, length, type);
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001365 if (!lock)
1366 return -ENOMEM;
1367
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001368 rc = cifs_lock_add_if(cfile, lock, wait_flag);
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001369 if (rc < 0)
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001370 kfree(lock);
1371 if (rc <= 0)
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001372 goto out;
1373
Pavel Shilovsky7f924472012-03-28 17:10:25 +04001374 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1375 type, 1, 0, wait_flag);
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001376 if (rc) {
1377 kfree(lock);
1378 goto out;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001379 }
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001380
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001381 cifs_lock_add(cfile, lock);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001382 } else if (unlock)
1383 rc = cifs_unlock_range(cfile, flock, xid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001384
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001385out:
1386 if (flock->fl_flags & FL_POSIX)
Steve French9ebb3892012-04-01 13:52:54 -05001387 posix_lock_file_wait(file, flock);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001388 return rc;
1389}
1390
1391int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
1392{
1393 int rc, xid;
1394 int lock = 0, unlock = 0;
1395 bool wait_flag = false;
1396 bool posix_lck = false;
1397 struct cifs_sb_info *cifs_sb;
1398 struct cifs_tcon *tcon;
1399 struct cifsInodeInfo *cinode;
1400 struct cifsFileInfo *cfile;
1401 __u16 netfid;
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001402 __u32 type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001403
1404 rc = -EACCES;
1405 xid = GetXid();
1406
1407 cFYI(1, "Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld "
1408 "end: %lld", cmd, flock->fl_flags, flock->fl_type,
1409 flock->fl_start, flock->fl_end);
1410
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001411 cfile = (struct cifsFileInfo *)file->private_data;
1412 tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001413
1414 cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag,
1415 tcon->ses->server);
1416
1417 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001418 netfid = cfile->netfid;
1419 cinode = CIFS_I(file->f_path.dentry->d_inode);
1420
1421 if ((tcon->ses->capabilities & CAP_UNIX) &&
1422 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
1423 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
1424 posix_lck = true;
1425 /*
1426 * BB add code here to normalize offset and length to account for
1427 * negative length which we can not accept over the wire.
1428 */
1429 if (IS_GETLK(cmd)) {
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001430 rc = cifs_getlk(file, flock, type, wait_flag, posix_lck, xid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001431 FreeXid(xid);
1432 return rc;
1433 }
1434
1435 if (!lock && !unlock) {
1436 /*
1437 * if no lock or unlock then nothing to do since we do not
1438 * know what it is
1439 */
1440 FreeXid(xid);
1441 return -EOPNOTSUPP;
1442 }
1443
1444 rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock,
1445 xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 FreeXid(xid);
1447 return rc;
1448}
1449
Jeff Layton597b0272012-03-23 14:40:56 -04001450/*
1451 * update the file size (if needed) after a write. Should be called with
1452 * the inode->i_lock held
1453 */
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001454void
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001455cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
1456 unsigned int bytes_written)
1457{
1458 loff_t end_of_write = offset + bytes_written;
1459
1460 if (end_of_write > cifsi->server_eof)
1461 cifsi->server_eof = end_of_write;
1462}
1463
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001464static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
Jeff Layton7da4b492010-10-15 15:34:00 -04001465 const char *write_data, size_t write_size,
1466 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467{
1468 int rc = 0;
1469 unsigned int bytes_written = 0;
1470 unsigned int total_written;
1471 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00001472 struct cifs_tcon *pTcon;
Jeff Layton77499812011-01-11 07:24:23 -05001473 int xid;
Jeff Layton7da4b492010-10-15 15:34:00 -04001474 struct dentry *dentry = open_file->dentry;
1475 struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001476 struct cifs_io_parms io_parms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
Jeff Layton7da4b492010-10-15 15:34:00 -04001478 cifs_sb = CIFS_SB(dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479
Joe Perchesb6b38f72010-04-21 03:50:45 +00001480 cFYI(1, "write %zd bytes to offset %lld of %s", write_size,
Jeff Layton7da4b492010-10-15 15:34:00 -04001481 *poffset, dentry->d_name.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
Jeff Layton13cfb732010-09-29 19:51:11 -04001483 pTcon = tlink_tcon(open_file->tlink);
Steve French50c2f752007-07-13 00:33:32 +00001484
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 for (total_written = 0; write_size > total_written;
1488 total_written += bytes_written) {
1489 rc = -EAGAIN;
1490 while (rc == -EAGAIN) {
Jeff Laytonca83ce32011-04-12 09:13:44 -04001491 struct kvec iov[2];
1492 unsigned int len;
1493
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 if (open_file->invalidHandle) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 /* we could deadlock if we called
1496 filemap_fdatawait from here so tell
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001497 reopen_file not to flush data to
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 server now */
Jeff Layton15886172010-10-15 15:33:59 -04001499 rc = cifs_reopen_file(open_file, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 if (rc != 0)
1501 break;
1502 }
Steve French3e844692005-10-03 13:37:24 -07001503
Jeff Laytonca83ce32011-04-12 09:13:44 -04001504 len = min((size_t)cifs_sb->wsize,
1505 write_size - total_written);
1506 /* iov[0] is reserved for smb header */
1507 iov[1].iov_base = (char *)write_data + total_written;
1508 iov[1].iov_len = len;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001509 io_parms.netfid = open_file->netfid;
1510 io_parms.pid = pid;
1511 io_parms.tcon = pTcon;
1512 io_parms.offset = *poffset;
1513 io_parms.length = len;
1514 rc = CIFSSMBWrite2(xid, &io_parms, &bytes_written, iov,
1515 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 }
1517 if (rc || (bytes_written == 0)) {
1518 if (total_written)
1519 break;
1520 else {
1521 FreeXid(xid);
1522 return rc;
1523 }
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001524 } else {
Jeff Layton597b0272012-03-23 14:40:56 -04001525 spin_lock(&dentry->d_inode->i_lock);
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001526 cifs_update_eof(cifsi, *poffset, bytes_written);
Jeff Layton597b0272012-03-23 14:40:56 -04001527 spin_unlock(&dentry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 *poffset += bytes_written;
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001529 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 }
1531
Steve Frencha4544342005-08-24 13:59:35 -07001532 cifs_stats_bytes_written(pTcon, total_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533
Jeff Layton7da4b492010-10-15 15:34:00 -04001534 if (total_written > 0) {
1535 spin_lock(&dentry->d_inode->i_lock);
1536 if (*poffset > dentry->d_inode->i_size)
1537 i_size_write(dentry->d_inode, *poffset);
1538 spin_unlock(&dentry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 }
Jeff Layton7da4b492010-10-15 15:34:00 -04001540 mark_inode_dirty_sync(dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 FreeXid(xid);
1542 return total_written;
1543}
1544
Jeff Layton6508d902010-09-29 19:51:11 -04001545struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1546 bool fsuid_only)
Steve French630f3f0c2007-10-25 21:17:17 +00001547{
1548 struct cifsFileInfo *open_file = NULL;
Jeff Layton6508d902010-09-29 19:51:11 -04001549 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1550
1551 /* only filter by fsuid on multiuser mounts */
1552 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1553 fsuid_only = false;
Steve French630f3f0c2007-10-25 21:17:17 +00001554
Jeff Layton44772882010-10-15 15:34:03 -04001555 spin_lock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001556 /* we could simply get the first_list_entry since write-only entries
1557 are always at the end of the list but since the first entry might
1558 have a close pending, we go through the whole list */
1559 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001560 if (fsuid_only && open_file->uid != current_fsuid())
1561 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001562 if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
Steve French630f3f0c2007-10-25 21:17:17 +00001563 if (!open_file->invalidHandle) {
1564 /* found a good file */
1565 /* lock it so it will not be closed on us */
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001566 cifsFileInfo_get(open_file);
Jeff Layton44772882010-10-15 15:34:03 -04001567 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001568 return open_file;
1569 } /* else might as well continue, and look for
1570 another, or simply have the caller reopen it
1571 again rather than trying to fix this handle */
1572 } else /* write only file */
1573 break; /* write only files are last so must be done */
1574 }
Jeff Layton44772882010-10-15 15:34:03 -04001575 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001576 return NULL;
1577}
Steve French630f3f0c2007-10-25 21:17:17 +00001578
Jeff Layton6508d902010-09-29 19:51:11 -04001579struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1580 bool fsuid_only)
Steve French6148a742005-10-05 12:23:19 -07001581{
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001582 struct cifsFileInfo *open_file, *inv_file = NULL;
Jeff Laytond3892292010-11-02 16:22:50 -04001583 struct cifs_sb_info *cifs_sb;
Jeff Layton2846d382008-09-22 21:33:33 -04001584 bool any_available = false;
Steve Frenchdd99cd82005-10-05 19:32:49 -07001585 int rc;
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001586 unsigned int refind = 0;
Steve French6148a742005-10-05 12:23:19 -07001587
Steve French60808232006-04-22 15:53:05 +00001588 /* Having a null inode here (because mapping->host was set to zero by
1589 the VFS or MM) should not happen but we had reports of on oops (due to
1590 it being zero) during stress testcases so we need to check for it */
1591
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001592 if (cifs_inode == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001593 cERROR(1, "Null inode passed to cifs_writeable_file");
Steve French60808232006-04-22 15:53:05 +00001594 dump_stack();
1595 return NULL;
1596 }
1597
Jeff Laytond3892292010-11-02 16:22:50 -04001598 cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1599
Jeff Layton6508d902010-09-29 19:51:11 -04001600 /* only filter by fsuid on multiuser mounts */
1601 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1602 fsuid_only = false;
1603
Jeff Layton44772882010-10-15 15:34:03 -04001604 spin_lock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001605refind_writable:
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001606 if (refind > MAX_REOPEN_ATT) {
1607 spin_unlock(&cifs_file_list_lock);
1608 return NULL;
1609 }
Steve French6148a742005-10-05 12:23:19 -07001610 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001611 if (!any_available && open_file->pid != current->tgid)
1612 continue;
1613 if (fsuid_only && open_file->uid != current_fsuid())
1614 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001615 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Steve French9b22b0b2007-10-02 01:11:08 +00001616 if (!open_file->invalidHandle) {
1617 /* found a good writable file */
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001618 cifsFileInfo_get(open_file);
Jeff Layton44772882010-10-15 15:34:03 -04001619 spin_unlock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001620 return open_file;
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001621 } else {
1622 if (!inv_file)
1623 inv_file = open_file;
Steve French9b22b0b2007-10-02 01:11:08 +00001624 }
Steve French6148a742005-10-05 12:23:19 -07001625 }
1626 }
Jeff Layton2846d382008-09-22 21:33:33 -04001627 /* couldn't find useable FH with same pid, try any available */
1628 if (!any_available) {
1629 any_available = true;
1630 goto refind_writable;
1631 }
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001632
1633 if (inv_file) {
1634 any_available = false;
1635 cifsFileInfo_get(inv_file);
1636 }
1637
Jeff Layton44772882010-10-15 15:34:03 -04001638 spin_unlock(&cifs_file_list_lock);
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001639
1640 if (inv_file) {
1641 rc = cifs_reopen_file(inv_file, false);
1642 if (!rc)
1643 return inv_file;
1644 else {
1645 spin_lock(&cifs_file_list_lock);
1646 list_move_tail(&inv_file->flist,
1647 &cifs_inode->openFileList);
1648 spin_unlock(&cifs_file_list_lock);
1649 cifsFileInfo_put(inv_file);
1650 spin_lock(&cifs_file_list_lock);
1651 ++refind;
1652 goto refind_writable;
1653 }
1654 }
1655
Steve French6148a742005-10-05 12:23:19 -07001656 return NULL;
1657}
1658
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1660{
1661 struct address_space *mapping = page->mapping;
1662 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1663 char *write_data;
1664 int rc = -EFAULT;
1665 int bytes_written = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 struct inode *inode;
Steve French6148a742005-10-05 12:23:19 -07001667 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
1669 if (!mapping || !mapping->host)
1670 return -EFAULT;
1671
1672 inode = page->mapping->host;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
1674 offset += (loff_t)from;
1675 write_data = kmap(page);
1676 write_data += from;
1677
1678 if ((to > PAGE_CACHE_SIZE) || (from > to)) {
1679 kunmap(page);
1680 return -EIO;
1681 }
1682
1683 /* racing with truncate? */
1684 if (offset > mapping->host->i_size) {
1685 kunmap(page);
1686 return 0; /* don't care */
1687 }
1688
1689 /* check to make sure that we are not extending the file */
1690 if (mapping->host->i_size - offset < (loff_t)to)
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001691 to = (unsigned)(mapping->host->i_size - offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692
Jeff Layton6508d902010-09-29 19:51:11 -04001693 open_file = find_writable_file(CIFS_I(mapping->host), false);
Steve French6148a742005-10-05 12:23:19 -07001694 if (open_file) {
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001695 bytes_written = cifs_write(open_file, open_file->pid,
1696 write_data, to - from, &offset);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001697 cifsFileInfo_put(open_file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 /* Does mm or vfs already set times? */
Steve French6148a742005-10-05 12:23:19 -07001699 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001700 if ((bytes_written > 0) && (offset))
Steve French6148a742005-10-05 12:23:19 -07001701 rc = 0;
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001702 else if (bytes_written < 0)
1703 rc = bytes_written;
Steve French6148a742005-10-05 12:23:19 -07001704 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001705 cFYI(1, "No writeable filehandles for inode");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 rc = -EIO;
1707 }
1708
1709 kunmap(page);
1710 return rc;
1711}
1712
Jeff Laytone9492872012-03-23 14:40:56 -04001713/*
1714 * Marshal up the iov array, reserving the first one for the header. Also,
1715 * set wdata->bytes.
1716 */
1717static void
1718cifs_writepages_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
1719{
1720 int i;
1721 struct inode *inode = wdata->cfile->dentry->d_inode;
1722 loff_t size = i_size_read(inode);
1723
1724 /* marshal up the pages into iov array */
1725 wdata->bytes = 0;
1726 for (i = 0; i < wdata->nr_pages; i++) {
1727 iov[i + 1].iov_len = min(size - page_offset(wdata->pages[i]),
1728 (loff_t)PAGE_CACHE_SIZE);
1729 iov[i + 1].iov_base = kmap(wdata->pages[i]);
1730 wdata->bytes += iov[i + 1].iov_len;
1731 }
1732}
1733
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734static int cifs_writepages(struct address_space *mapping,
Steve French37c0eb42005-10-05 14:50:29 -07001735 struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736{
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001737 struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb);
1738 bool done = false, scanned = false, range_whole = false;
1739 pgoff_t end, index;
1740 struct cifs_writedata *wdata;
Steve French37c0eb42005-10-05 14:50:29 -07001741 struct page *page;
Steve French37c0eb42005-10-05 14:50:29 -07001742 int rc = 0;
Steve French50c2f752007-07-13 00:33:32 +00001743
Steve French37c0eb42005-10-05 14:50:29 -07001744 /*
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001745 * If wsize is smaller than the page cache size, default to writing
Steve French37c0eb42005-10-05 14:50:29 -07001746 * one page at a time via cifs_writepage
1747 */
1748 if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1749 return generic_writepages(mapping, wbc);
1750
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001751 if (wbc->range_cyclic) {
Steve French37c0eb42005-10-05 14:50:29 -07001752 index = mapping->writeback_index; /* Start from prev offset */
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001753 end = -1;
1754 } else {
1755 index = wbc->range_start >> PAGE_CACHE_SHIFT;
1756 end = wbc->range_end >> PAGE_CACHE_SHIFT;
1757 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001758 range_whole = true;
1759 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001760 }
1761retry:
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001762 while (!done && index <= end) {
1763 unsigned int i, nr_pages, found_pages;
1764 pgoff_t next = 0, tofind;
1765 struct page **pages;
Steve French37c0eb42005-10-05 14:50:29 -07001766
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001767 tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1,
1768 end - index) + 1;
Steve French37c0eb42005-10-05 14:50:29 -07001769
Jeff Laytonc2e87642012-03-23 14:40:55 -04001770 wdata = cifs_writedata_alloc((unsigned int)tofind,
1771 cifs_writev_complete);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001772 if (!wdata) {
1773 rc = -ENOMEM;
1774 break;
1775 }
1776
1777 /*
1778 * find_get_pages_tag seems to return a max of 256 on each
1779 * iteration, so we must call it several times in order to
1780 * fill the array or the wsize is effectively limited to
1781 * 256 * PAGE_CACHE_SIZE.
1782 */
1783 found_pages = 0;
1784 pages = wdata->pages;
1785 do {
1786 nr_pages = find_get_pages_tag(mapping, &index,
1787 PAGECACHE_TAG_DIRTY,
1788 tofind, pages);
1789 found_pages += nr_pages;
1790 tofind -= nr_pages;
1791 pages += nr_pages;
1792 } while (nr_pages && tofind && index <= end);
1793
1794 if (found_pages == 0) {
1795 kref_put(&wdata->refcount, cifs_writedata_release);
1796 break;
1797 }
1798
1799 nr_pages = 0;
1800 for (i = 0; i < found_pages; i++) {
1801 page = wdata->pages[i];
Steve French37c0eb42005-10-05 14:50:29 -07001802 /*
1803 * At this point we hold neither mapping->tree_lock nor
1804 * lock on the page itself: the page may be truncated or
1805 * invalidated (changing page->mapping to NULL), or even
1806 * swizzled back from swapper_space to tmpfs file
1807 * mapping
1808 */
1809
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001810 if (nr_pages == 0)
Steve French37c0eb42005-10-05 14:50:29 -07001811 lock_page(page);
Nick Piggin529ae9a2008-08-02 12:01:03 +02001812 else if (!trylock_page(page))
Steve French37c0eb42005-10-05 14:50:29 -07001813 break;
1814
1815 if (unlikely(page->mapping != mapping)) {
1816 unlock_page(page);
1817 break;
1818 }
1819
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001820 if (!wbc->range_cyclic && page->index > end) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001821 done = true;
Steve French37c0eb42005-10-05 14:50:29 -07001822 unlock_page(page);
1823 break;
1824 }
1825
1826 if (next && (page->index != next)) {
1827 /* Not next consecutive page */
1828 unlock_page(page);
1829 break;
1830 }
1831
1832 if (wbc->sync_mode != WB_SYNC_NONE)
1833 wait_on_page_writeback(page);
1834
1835 if (PageWriteback(page) ||
Linus Torvaldscb876f42006-12-23 16:19:07 -08001836 !clear_page_dirty_for_io(page)) {
Steve French37c0eb42005-10-05 14:50:29 -07001837 unlock_page(page);
1838 break;
1839 }
Steve French84d2f072005-10-12 15:32:05 -07001840
Linus Torvaldscb876f42006-12-23 16:19:07 -08001841 /*
1842 * This actually clears the dirty bit in the radix tree.
1843 * See cifs_writepage() for more commentary.
1844 */
1845 set_page_writeback(page);
1846
Steve French84d2f072005-10-12 15:32:05 -07001847 if (page_offset(page) >= mapping->host->i_size) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001848 done = true;
Steve French84d2f072005-10-12 15:32:05 -07001849 unlock_page(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001850 end_page_writeback(page);
Steve French84d2f072005-10-12 15:32:05 -07001851 break;
1852 }
1853
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001854 wdata->pages[i] = page;
Steve French37c0eb42005-10-05 14:50:29 -07001855 next = page->index + 1;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001856 ++nr_pages;
Steve French37c0eb42005-10-05 14:50:29 -07001857 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001858
1859 /* reset index to refind any pages skipped */
1860 if (nr_pages == 0)
1861 index = wdata->pages[0]->index + 1;
1862
1863 /* put any pages we aren't going to use */
1864 for (i = nr_pages; i < found_pages; i++) {
1865 page_cache_release(wdata->pages[i]);
1866 wdata->pages[i] = NULL;
1867 }
1868
1869 /* nothing to write? */
1870 if (nr_pages == 0) {
1871 kref_put(&wdata->refcount, cifs_writedata_release);
1872 continue;
1873 }
1874
1875 wdata->sync_mode = wbc->sync_mode;
1876 wdata->nr_pages = nr_pages;
1877 wdata->offset = page_offset(wdata->pages[0]);
Jeff Laytone9492872012-03-23 14:40:56 -04001878 wdata->marshal_iov = cifs_writepages_marshal_iov;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001879
1880 do {
1881 if (wdata->cfile != NULL)
1882 cifsFileInfo_put(wdata->cfile);
1883 wdata->cfile = find_writable_file(CIFS_I(mapping->host),
1884 false);
1885 if (!wdata->cfile) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001886 cERROR(1, "No writable handles for inode");
Steve French23e7dd72005-10-20 13:44:56 -07001887 rc = -EBADF;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001888 break;
Steve French37c0eb42005-10-05 14:50:29 -07001889 }
Jeff Laytonfe5f5d22012-03-23 14:40:55 -04001890 wdata->pid = wdata->cfile->pid;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001891 rc = cifs_async_writev(wdata);
1892 } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN);
Jeff Laytonf3983c22010-09-22 16:17:40 -07001893
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001894 for (i = 0; i < nr_pages; ++i)
1895 unlock_page(wdata->pages[i]);
Jeff Layton941b8532011-01-11 07:24:01 -05001896
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001897 /* send failure -- clean up the mess */
1898 if (rc != 0) {
1899 for (i = 0; i < nr_pages; ++i) {
Jeff Layton941b8532011-01-11 07:24:01 -05001900 if (rc == -EAGAIN)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001901 redirty_page_for_writepage(wbc,
1902 wdata->pages[i]);
1903 else
1904 SetPageError(wdata->pages[i]);
1905 end_page_writeback(wdata->pages[i]);
1906 page_cache_release(wdata->pages[i]);
Steve French37c0eb42005-10-05 14:50:29 -07001907 }
Jeff Layton941b8532011-01-11 07:24:01 -05001908 if (rc != -EAGAIN)
1909 mapping_set_error(mapping, rc);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001910 }
1911 kref_put(&wdata->refcount, cifs_writedata_release);
Jeff Layton941b8532011-01-11 07:24:01 -05001912
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001913 wbc->nr_to_write -= nr_pages;
1914 if (wbc->nr_to_write <= 0)
1915 done = true;
Dave Kleikampb066a482008-11-18 03:49:05 +00001916
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001917 index = next;
Steve French37c0eb42005-10-05 14:50:29 -07001918 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001919
Steve French37c0eb42005-10-05 14:50:29 -07001920 if (!scanned && !done) {
1921 /*
1922 * We hit the last page and there is more work to be done: wrap
1923 * back to the start of the file
1924 */
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001925 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001926 index = 0;
1927 goto retry;
1928 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001929
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001930 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
Steve French37c0eb42005-10-05 14:50:29 -07001931 mapping->writeback_index = index;
1932
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 return rc;
1934}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001936static int
1937cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938{
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001939 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 int xid;
1941
1942 xid = GetXid();
1943/* BB add check for wbc flags */
1944 page_cache_get(page);
Steve Frenchad7a2922008-02-07 23:25:02 +00001945 if (!PageUptodate(page))
Joe Perchesb6b38f72010-04-21 03:50:45 +00001946 cFYI(1, "ppw - page not up to date");
Linus Torvaldscb876f42006-12-23 16:19:07 -08001947
1948 /*
1949 * Set the "writeback" flag, and clear "dirty" in the radix tree.
1950 *
1951 * A writepage() implementation always needs to do either this,
1952 * or re-dirty the page with "redirty_page_for_writepage()" in
1953 * the case of a failure.
1954 *
1955 * Just unlocking the page will cause the radix tree tag-bits
1956 * to fail to update with the state of the page correctly.
1957 */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001958 set_page_writeback(page);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001959retry_write:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001961 if (rc == -EAGAIN && wbc->sync_mode == WB_SYNC_ALL)
1962 goto retry_write;
1963 else if (rc == -EAGAIN)
1964 redirty_page_for_writepage(wbc, page);
1965 else if (rc != 0)
1966 SetPageError(page);
1967 else
1968 SetPageUptodate(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001969 end_page_writeback(page);
1970 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 FreeXid(xid);
1972 return rc;
1973}
1974
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001975static int cifs_writepage(struct page *page, struct writeback_control *wbc)
1976{
1977 int rc = cifs_writepage_locked(page, wbc);
1978 unlock_page(page);
1979 return rc;
1980}
1981
Nick Piggind9414772008-09-24 11:32:59 -04001982static int cifs_write_end(struct file *file, struct address_space *mapping,
1983 loff_t pos, unsigned len, unsigned copied,
1984 struct page *page, void *fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985{
Nick Piggind9414772008-09-24 11:32:59 -04001986 int rc;
1987 struct inode *inode = mapping->host;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001988 struct cifsFileInfo *cfile = file->private_data;
1989 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
1990 __u32 pid;
1991
1992 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1993 pid = cfile->pid;
1994 else
1995 pid = current->tgid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996
Joe Perchesb6b38f72010-04-21 03:50:45 +00001997 cFYI(1, "write_end for page %p from pos %lld with %d bytes",
1998 page, pos, copied);
Steve Frenchad7a2922008-02-07 23:25:02 +00001999
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002000 if (PageChecked(page)) {
2001 if (copied == len)
2002 SetPageUptodate(page);
2003 ClearPageChecked(page);
2004 } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
Nick Piggind9414772008-09-24 11:32:59 -04002005 SetPageUptodate(page);
2006
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 if (!PageUptodate(page)) {
Nick Piggind9414772008-09-24 11:32:59 -04002008 char *page_data;
2009 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
2010 int xid;
2011
2012 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 /* this is probably better than directly calling
2014 partialpage_write since in this function the file handle is
2015 known which we might as well leverage */
2016 /* BB check if anything else missing out of ppw
2017 such as updating last write time */
2018 page_data = kmap(page);
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002019 rc = cifs_write(cfile, pid, page_data + offset, copied, &pos);
Nick Piggind9414772008-09-24 11:32:59 -04002020 /* if (rc < 0) should we set writebehind rc? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 kunmap(page);
Nick Piggind9414772008-09-24 11:32:59 -04002022
2023 FreeXid(xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002024 } else {
Nick Piggind9414772008-09-24 11:32:59 -04002025 rc = copied;
2026 pos += copied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 set_page_dirty(page);
2028 }
2029
Nick Piggind9414772008-09-24 11:32:59 -04002030 if (rc > 0) {
2031 spin_lock(&inode->i_lock);
2032 if (pos > inode->i_size)
2033 i_size_write(inode, pos);
2034 spin_unlock(&inode->i_lock);
2035 }
2036
2037 unlock_page(page);
2038 page_cache_release(page);
2039
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 return rc;
2041}
2042
Josef Bacik02c24a82011-07-16 20:44:56 -04002043int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
2044 int datasync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045{
2046 int xid;
2047 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00002048 struct cifs_tcon *tcon;
Joe Perchesc21dfb62010-07-12 13:50:14 -07002049 struct cifsFileInfo *smbfile = file->private_data;
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002050 struct inode *inode = file->f_path.dentry->d_inode;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002051 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052
Josef Bacik02c24a82011-07-16 20:44:56 -04002053 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
2054 if (rc)
2055 return rc;
2056 mutex_lock(&inode->i_mutex);
2057
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 xid = GetXid();
2059
Joe Perchesb6b38f72010-04-21 03:50:45 +00002060 cFYI(1, "Sync file - name: %s datasync: 0x%x",
Christoph Hellwig7ea80852010-05-26 17:53:25 +02002061 file->f_path.dentry->d_name.name, datasync);
Steve French50c2f752007-07-13 00:33:32 +00002062
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002063 if (!CIFS_I(inode)->clientCanCacheRead) {
2064 rc = cifs_invalidate_mapping(inode);
2065 if (rc) {
2066 cFYI(1, "rc: %d during invalidate phase", rc);
2067 rc = 0; /* don't care about it in fsync */
2068 }
2069 }
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002070
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002071 tcon = tlink_tcon(smbfile->tlink);
2072 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
2073 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
2074
2075 FreeXid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04002076 mutex_unlock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002077 return rc;
2078}
2079
Josef Bacik02c24a82011-07-16 20:44:56 -04002080int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002081{
2082 int xid;
2083 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00002084 struct cifs_tcon *tcon;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002085 struct cifsFileInfo *smbfile = file->private_data;
2086 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Josef Bacik02c24a82011-07-16 20:44:56 -04002087 struct inode *inode = file->f_mapping->host;
2088
2089 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
2090 if (rc)
2091 return rc;
2092 mutex_lock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002093
2094 xid = GetXid();
2095
2096 cFYI(1, "Sync file - name: %s datasync: 0x%x",
2097 file->f_path.dentry->d_name.name, datasync);
2098
2099 tcon = tlink_tcon(smbfile->tlink);
2100 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
2101 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
Steve Frenchb298f222009-02-21 21:17:43 +00002102
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 FreeXid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04002104 mutex_unlock(&inode->i_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 return rc;
2106}
2107
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108/*
2109 * As file closes, flush all cached write data for this inode checking
2110 * for write behind errors.
2111 */
Miklos Szeredi75e1fcc2006-06-23 02:05:12 -07002112int cifs_flush(struct file *file, fl_owner_t id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113{
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002114 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 int rc = 0;
2116
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002117 if (file->f_mode & FMODE_WRITE)
Jeff Laytond3f13222010-10-15 15:34:07 -04002118 rc = filemap_write_and_wait(inode->i_mapping);
Steve French50c2f752007-07-13 00:33:32 +00002119
Joe Perchesb6b38f72010-04-21 03:50:45 +00002120 cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121
2122 return rc;
2123}
2124
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002125static int
2126cifs_write_allocate_pages(struct page **pages, unsigned long num_pages)
2127{
2128 int rc = 0;
2129 unsigned long i;
2130
2131 for (i = 0; i < num_pages; i++) {
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002132 pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002133 if (!pages[i]) {
2134 /*
2135 * save number of pages we have already allocated and
2136 * return with ENOMEM error
2137 */
2138 num_pages = i;
2139 rc = -ENOMEM;
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002140 break;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002141 }
2142 }
2143
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002144 if (rc) {
2145 for (i = 0; i < num_pages; i++)
2146 put_page(pages[i]);
2147 }
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002148 return rc;
2149}
2150
2151static inline
2152size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
2153{
2154 size_t num_pages;
2155 size_t clen;
2156
2157 clen = min_t(const size_t, len, wsize);
Jeff Laytona7103b92012-03-23 14:40:56 -04002158 num_pages = DIV_ROUND_UP(clen, PAGE_SIZE);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002159
2160 if (cur_len)
2161 *cur_len = clen;
2162
2163 return num_pages;
2164}
2165
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002166static void
2167cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
2168{
2169 int i;
2170 size_t bytes = wdata->bytes;
2171
2172 /* marshal up the pages into iov array */
2173 for (i = 0; i < wdata->nr_pages; i++) {
Steve Frenchc7ad42b2012-03-23 16:30:56 -05002174 iov[i + 1].iov_len = min_t(size_t, bytes, PAGE_SIZE);
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002175 iov[i + 1].iov_base = kmap(wdata->pages[i]);
2176 bytes -= iov[i + 1].iov_len;
2177 }
2178}
2179
2180static void
2181cifs_uncached_writev_complete(struct work_struct *work)
2182{
2183 int i;
2184 struct cifs_writedata *wdata = container_of(work,
2185 struct cifs_writedata, work);
2186 struct inode *inode = wdata->cfile->dentry->d_inode;
2187 struct cifsInodeInfo *cifsi = CIFS_I(inode);
2188
2189 spin_lock(&inode->i_lock);
2190 cifs_update_eof(cifsi, wdata->offset, wdata->bytes);
2191 if (cifsi->server_eof > inode->i_size)
2192 i_size_write(inode, cifsi->server_eof);
2193 spin_unlock(&inode->i_lock);
2194
2195 complete(&wdata->done);
2196
2197 if (wdata->result != -EAGAIN) {
2198 for (i = 0; i < wdata->nr_pages; i++)
2199 put_page(wdata->pages[i]);
2200 }
2201
2202 kref_put(&wdata->refcount, cifs_writedata_release);
2203}
2204
2205/* attempt to send write to server, retry on any -EAGAIN errors */
2206static int
2207cifs_uncached_retry_writev(struct cifs_writedata *wdata)
2208{
2209 int rc;
2210
2211 do {
2212 if (wdata->cfile->invalidHandle) {
2213 rc = cifs_reopen_file(wdata->cfile, false);
2214 if (rc != 0)
2215 continue;
2216 }
2217 rc = cifs_async_writev(wdata);
2218 } while (rc == -EAGAIN);
2219
2220 return rc;
2221}
2222
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002223static ssize_t
2224cifs_iovec_write(struct file *file, const struct iovec *iov,
2225 unsigned long nr_segs, loff_t *poffset)
2226{
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002227 unsigned long nr_pages, i;
Pavel Shilovsky76429c12011-01-31 16:03:08 +03002228 size_t copied, len, cur_len;
2229 ssize_t total_written = 0;
Jeff Layton3af9d8f2012-04-13 17:16:59 -04002230 loff_t offset;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002231 struct iov_iter it;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002232 struct cifsFileInfo *open_file;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002233 struct cifs_tcon *tcon;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002234 struct cifs_sb_info *cifs_sb;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002235 struct cifs_writedata *wdata, *tmp;
2236 struct list_head wdata_list;
2237 int rc;
2238 pid_t pid;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002239
2240 len = iov_length(iov, nr_segs);
2241 if (!len)
2242 return 0;
2243
2244 rc = generic_write_checks(file, poffset, &len, 0);
2245 if (rc)
2246 return rc;
2247
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002248 INIT_LIST_HEAD(&wdata_list);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002249 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002250 open_file = file->private_data;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002251 tcon = tlink_tcon(open_file->tlink);
Jeff Layton3af9d8f2012-04-13 17:16:59 -04002252 offset = *poffset;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002253
2254 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2255 pid = open_file->pid;
2256 else
2257 pid = current->tgid;
2258
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002259 iov_iter_init(&it, iov, nr_segs, len, 0);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002260 do {
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002261 size_t save_len;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002262
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002263 nr_pages = get_numpages(cifs_sb->wsize, len, &cur_len);
2264 wdata = cifs_writedata_alloc(nr_pages,
2265 cifs_uncached_writev_complete);
2266 if (!wdata) {
2267 rc = -ENOMEM;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002268 break;
2269 }
2270
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002271 rc = cifs_write_allocate_pages(wdata->pages, nr_pages);
2272 if (rc) {
2273 kfree(wdata);
2274 break;
2275 }
2276
2277 save_len = cur_len;
2278 for (i = 0; i < nr_pages; i++) {
2279 copied = min_t(const size_t, cur_len, PAGE_SIZE);
2280 copied = iov_iter_copy_from_user(wdata->pages[i], &it,
2281 0, copied);
2282 cur_len -= copied;
2283 iov_iter_advance(&it, copied);
2284 }
2285 cur_len = save_len - cur_len;
2286
2287 wdata->sync_mode = WB_SYNC_ALL;
2288 wdata->nr_pages = nr_pages;
2289 wdata->offset = (__u64)offset;
2290 wdata->cfile = cifsFileInfo_get(open_file);
2291 wdata->pid = pid;
2292 wdata->bytes = cur_len;
2293 wdata->marshal_iov = cifs_uncached_marshal_iov;
2294 rc = cifs_uncached_retry_writev(wdata);
2295 if (rc) {
2296 kref_put(&wdata->refcount, cifs_writedata_release);
2297 break;
2298 }
2299
2300 list_add_tail(&wdata->list, &wdata_list);
2301 offset += cur_len;
2302 len -= cur_len;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002303 } while (len > 0);
2304
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002305 /*
2306 * If at least one write was successfully sent, then discard any rc
2307 * value from the later writes. If the other write succeeds, then
2308 * we'll end up returning whatever was written. If it fails, then
2309 * we'll get a new rc value from that.
2310 */
2311 if (!list_empty(&wdata_list))
2312 rc = 0;
2313
2314 /*
2315 * Wait for and collect replies for any successful sends in order of
2316 * increasing offset. Once an error is hit or we get a fatal signal
2317 * while waiting, then return without waiting for any more replies.
2318 */
2319restart_loop:
2320 list_for_each_entry_safe(wdata, tmp, &wdata_list, list) {
2321 if (!rc) {
2322 /* FIXME: freezable too? */
2323 rc = wait_for_completion_killable(&wdata->done);
2324 if (rc)
2325 rc = -EINTR;
2326 else if (wdata->result)
2327 rc = wdata->result;
2328 else
2329 total_written += wdata->bytes;
2330
2331 /* resend call if it's a retryable error */
2332 if (rc == -EAGAIN) {
2333 rc = cifs_uncached_retry_writev(wdata);
2334 goto restart_loop;
2335 }
2336 }
2337 list_del_init(&wdata->list);
2338 kref_put(&wdata->refcount, cifs_writedata_release);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002339 }
2340
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002341 if (total_written > 0)
2342 *poffset += total_written;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002343
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002344 cifs_stats_bytes_written(tcon, total_written);
2345 return total_written ? total_written : (ssize_t)rc;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002346}
2347
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03002348ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002349 unsigned long nr_segs, loff_t pos)
2350{
2351 ssize_t written;
2352 struct inode *inode;
2353
2354 inode = iocb->ki_filp->f_path.dentry->d_inode;
2355
2356 /*
2357 * BB - optimize the way when signing is disabled. We can drop this
2358 * extra memory-to-memory copying and use iovec buffers for constructing
2359 * write request.
2360 */
2361
2362 written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos);
2363 if (written > 0) {
2364 CIFS_I(inode)->invalid_mapping = true;
2365 iocb->ki_pos = pos;
2366 }
2367
2368 return written;
2369}
2370
2371ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
2372 unsigned long nr_segs, loff_t pos)
2373{
2374 struct inode *inode;
2375
2376 inode = iocb->ki_filp->f_path.dentry->d_inode;
2377
2378 if (CIFS_I(inode)->clientCanCacheAll)
2379 return generic_file_aio_write(iocb, iov, nr_segs, pos);
2380
2381 /*
2382 * In strict cache mode we need to write the data to the server exactly
2383 * from the pos to pos+len-1 rather than flush all affected pages
2384 * because it may cause a error with mandatory locks on these pages but
2385 * not on the region from pos to ppos+len-1.
2386 */
2387
2388 return cifs_user_writev(iocb, iov, nr_segs, pos);
2389}
2390
Jeff Layton0471ca32012-05-16 07:13:16 -04002391static struct cifs_readdata *
2392cifs_readdata_alloc(unsigned int nr_vecs, work_func_t complete)
2393{
2394 struct cifs_readdata *rdata;
2395
2396 rdata = kzalloc(sizeof(*rdata) +
2397 sizeof(struct kvec) * nr_vecs, GFP_KERNEL);
2398 if (rdata != NULL) {
Jeff Layton6993f742012-05-16 07:13:17 -04002399 kref_init(&rdata->refcount);
Jeff Layton1c892542012-05-16 07:13:17 -04002400 INIT_LIST_HEAD(&rdata->list);
2401 init_completion(&rdata->done);
Jeff Layton0471ca32012-05-16 07:13:16 -04002402 INIT_WORK(&rdata->work, complete);
2403 INIT_LIST_HEAD(&rdata->pages);
2404 }
2405 return rdata;
2406}
2407
Jeff Layton6993f742012-05-16 07:13:17 -04002408void
2409cifs_readdata_release(struct kref *refcount)
Jeff Layton0471ca32012-05-16 07:13:16 -04002410{
Jeff Layton6993f742012-05-16 07:13:17 -04002411 struct cifs_readdata *rdata = container_of(refcount,
2412 struct cifs_readdata, refcount);
2413
2414 if (rdata->cfile)
2415 cifsFileInfo_put(rdata->cfile);
2416
Jeff Layton0471ca32012-05-16 07:13:16 -04002417 kfree(rdata);
2418}
2419
Jeff Layton2a1bb132012-05-16 07:13:17 -04002420static int
Jeff Layton1c892542012-05-16 07:13:17 -04002421cifs_read_allocate_pages(struct list_head *list, unsigned int npages)
2422{
2423 int rc = 0;
2424 struct page *page, *tpage;
2425 unsigned int i;
2426
2427 for (i = 0; i < npages; i++) {
2428 page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
2429 if (!page) {
2430 rc = -ENOMEM;
2431 break;
2432 }
2433 list_add(&page->lru, list);
2434 }
2435
2436 if (rc) {
2437 list_for_each_entry_safe(page, tpage, list, lru) {
2438 list_del(&page->lru);
2439 put_page(page);
2440 }
2441 }
2442 return rc;
2443}
2444
2445static void
2446cifs_uncached_readdata_release(struct kref *refcount)
2447{
2448 struct page *page, *tpage;
2449 struct cifs_readdata *rdata = container_of(refcount,
2450 struct cifs_readdata, refcount);
2451
2452 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2453 list_del(&page->lru);
2454 put_page(page);
2455 }
2456 cifs_readdata_release(refcount);
2457}
2458
2459static int
Jeff Layton2a1bb132012-05-16 07:13:17 -04002460cifs_retry_async_readv(struct cifs_readdata *rdata)
2461{
2462 int rc;
2463
2464 do {
2465 if (rdata->cfile->invalidHandle) {
2466 rc = cifs_reopen_file(rdata->cfile, true);
2467 if (rc != 0)
2468 continue;
2469 }
2470 rc = cifs_async_readv(rdata);
2471 } while (rc == -EAGAIN);
2472
2473 return rc;
2474}
2475
Jeff Layton1c892542012-05-16 07:13:17 -04002476/**
2477 * cifs_readdata_to_iov - copy data from pages in response to an iovec
2478 * @rdata: the readdata response with list of pages holding data
2479 * @iov: vector in which we should copy the data
2480 * @nr_segs: number of segments in vector
2481 * @offset: offset into file of the first iovec
2482 * @copied: used to return the amount of data copied to the iov
2483 *
2484 * This function copies data from a list of pages in a readdata response into
2485 * an array of iovecs. It will first calculate where the data should go
2486 * based on the info in the readdata and then copy the data into that spot.
2487 */
2488static ssize_t
2489cifs_readdata_to_iov(struct cifs_readdata *rdata, const struct iovec *iov,
2490 unsigned long nr_segs, loff_t offset, ssize_t *copied)
2491{
2492 int rc = 0;
2493 struct iov_iter ii;
2494 size_t pos = rdata->offset - offset;
2495 struct page *page, *tpage;
2496 ssize_t remaining = rdata->bytes;
2497 unsigned char *pdata;
2498
2499 /* set up iov_iter and advance to the correct offset */
2500 iov_iter_init(&ii, iov, nr_segs, iov_length(iov, nr_segs), 0);
2501 iov_iter_advance(&ii, pos);
2502
2503 *copied = 0;
2504 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2505 ssize_t copy;
2506
2507 /* copy a whole page or whatever's left */
2508 copy = min_t(ssize_t, remaining, PAGE_SIZE);
2509
2510 /* ...but limit it to whatever space is left in the iov */
2511 copy = min_t(ssize_t, copy, iov_iter_count(&ii));
2512
2513 /* go while there's data to be copied and no errors */
2514 if (copy && !rc) {
2515 pdata = kmap(page);
2516 rc = memcpy_toiovecend(ii.iov, pdata, ii.iov_offset,
2517 (int)copy);
2518 kunmap(page);
2519 if (!rc) {
2520 *copied += copy;
2521 remaining -= copy;
2522 iov_iter_advance(&ii, copy);
2523 }
2524 }
2525
2526 list_del(&page->lru);
2527 put_page(page);
2528 }
2529
2530 return rc;
2531}
2532
2533static void
2534cifs_uncached_readv_complete(struct work_struct *work)
2535{
2536 struct cifs_readdata *rdata = container_of(work,
2537 struct cifs_readdata, work);
2538
2539 /* if the result is non-zero then the pages weren't kmapped */
2540 if (rdata->result == 0) {
2541 struct page *page;
2542
2543 list_for_each_entry(page, &rdata->pages, lru)
2544 kunmap(page);
2545 }
2546
2547 complete(&rdata->done);
2548 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
2549}
2550
2551static int
2552cifs_uncached_read_marshal_iov(struct cifs_readdata *rdata,
2553 unsigned int remaining)
2554{
2555 int len = 0;
2556 struct page *page, *tpage;
2557
2558 rdata->nr_iov = 1;
2559 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2560 if (remaining >= PAGE_SIZE) {
2561 /* enough data to fill the page */
2562 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2563 rdata->iov[rdata->nr_iov].iov_len = PAGE_SIZE;
2564 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2565 rdata->nr_iov, page->index,
2566 rdata->iov[rdata->nr_iov].iov_base,
2567 rdata->iov[rdata->nr_iov].iov_len);
2568 ++rdata->nr_iov;
2569 len += PAGE_SIZE;
2570 remaining -= PAGE_SIZE;
2571 } else if (remaining > 0) {
2572 /* enough for partial page, fill and zero the rest */
2573 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2574 rdata->iov[rdata->nr_iov].iov_len = remaining;
2575 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2576 rdata->nr_iov, page->index,
2577 rdata->iov[rdata->nr_iov].iov_base,
2578 rdata->iov[rdata->nr_iov].iov_len);
2579 memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
2580 '\0', PAGE_SIZE - remaining);
2581 ++rdata->nr_iov;
2582 len += remaining;
2583 remaining = 0;
2584 } else {
2585 /* no need to hold page hostage */
2586 list_del(&page->lru);
2587 put_page(page);
2588 }
2589 }
2590
2591 return len;
2592}
2593
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002594static ssize_t
2595cifs_iovec_read(struct file *file, const struct iovec *iov,
2596 unsigned long nr_segs, loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597{
Jeff Layton1c892542012-05-16 07:13:17 -04002598 ssize_t rc;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002599 size_t len, cur_len;
Jeff Layton1c892542012-05-16 07:13:17 -04002600 ssize_t total_read = 0;
2601 loff_t offset = *poffset;
2602 unsigned int npages;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 struct cifs_sb_info *cifs_sb;
Jeff Layton1c892542012-05-16 07:13:17 -04002604 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605 struct cifsFileInfo *open_file;
Jeff Layton1c892542012-05-16 07:13:17 -04002606 struct cifs_readdata *rdata, *tmp;
2607 struct list_head rdata_list;
2608 pid_t pid;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002609
2610 if (!nr_segs)
2611 return 0;
2612
2613 len = iov_length(iov, nr_segs);
2614 if (!len)
2615 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616
Jeff Layton1c892542012-05-16 07:13:17 -04002617 INIT_LIST_HEAD(&rdata_list);
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002618 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -07002619 open_file = file->private_data;
Jeff Layton1c892542012-05-16 07:13:17 -04002620 tcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002622 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2623 pid = open_file->pid;
2624 else
2625 pid = current->tgid;
2626
Steve Frenchad7a2922008-02-07 23:25:02 +00002627 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002628 cFYI(1, "attempting read on write only file instance");
Steve Frenchad7a2922008-02-07 23:25:02 +00002629
Jeff Layton1c892542012-05-16 07:13:17 -04002630 do {
2631 cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize);
2632 npages = DIV_ROUND_UP(cur_len, PAGE_SIZE);
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002633
Jeff Layton1c892542012-05-16 07:13:17 -04002634 /* allocate a readdata struct */
2635 rdata = cifs_readdata_alloc(npages,
2636 cifs_uncached_readv_complete);
2637 if (!rdata) {
2638 rc = -ENOMEM;
2639 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002641
Jeff Layton1c892542012-05-16 07:13:17 -04002642 rc = cifs_read_allocate_pages(&rdata->pages, npages);
2643 if (rc)
2644 goto error;
2645
2646 rdata->cfile = cifsFileInfo_get(open_file);
2647 rdata->offset = offset;
2648 rdata->bytes = cur_len;
2649 rdata->pid = pid;
2650 rdata->marshal_iov = cifs_uncached_read_marshal_iov;
2651
2652 rc = cifs_retry_async_readv(rdata);
2653error:
2654 if (rc) {
2655 kref_put(&rdata->refcount,
2656 cifs_uncached_readdata_release);
2657 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 }
Jeff Layton1c892542012-05-16 07:13:17 -04002659
2660 list_add_tail(&rdata->list, &rdata_list);
2661 offset += cur_len;
2662 len -= cur_len;
2663 } while (len > 0);
2664
2665 /* if at least one read request send succeeded, then reset rc */
2666 if (!list_empty(&rdata_list))
2667 rc = 0;
2668
2669 /* the loop below should proceed in the order of increasing offsets */
2670restart_loop:
2671 list_for_each_entry_safe(rdata, tmp, &rdata_list, list) {
2672 if (!rc) {
2673 ssize_t copied;
2674
2675 /* FIXME: freezable sleep too? */
2676 rc = wait_for_completion_killable(&rdata->done);
2677 if (rc)
2678 rc = -EINTR;
2679 else if (rdata->result)
2680 rc = rdata->result;
2681 else {
2682 rc = cifs_readdata_to_iov(rdata, iov,
2683 nr_segs, *poffset,
2684 &copied);
2685 total_read += copied;
2686 }
2687
2688 /* resend call if it's a retryable error */
2689 if (rc == -EAGAIN) {
2690 rc = cifs_retry_async_readv(rdata);
2691 goto restart_loop;
2692 }
2693 }
2694 list_del_init(&rdata->list);
2695 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002697
Jeff Layton1c892542012-05-16 07:13:17 -04002698 cifs_stats_bytes_read(tcon, total_read);
2699 *poffset += total_read;
2700
2701 return total_read ? total_read : rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702}
2703
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03002704ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002705 unsigned long nr_segs, loff_t pos)
2706{
2707 ssize_t read;
2708
2709 read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos);
2710 if (read > 0)
2711 iocb->ki_pos = pos;
2712
2713 return read;
2714}
2715
2716ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov,
2717 unsigned long nr_segs, loff_t pos)
2718{
2719 struct inode *inode;
2720
2721 inode = iocb->ki_filp->f_path.dentry->d_inode;
2722
2723 if (CIFS_I(inode)->clientCanCacheRead)
2724 return generic_file_aio_read(iocb, iov, nr_segs, pos);
2725
2726 /*
2727 * In strict cache mode we need to read from the server all the time
2728 * if we don't have level II oplock because the server can delay mtime
2729 * change - so we can't make a decision about inode invalidating.
2730 * And we can also fail with pagereading if there are mandatory locks
2731 * on pages affected by this read but not on the region from pos to
2732 * pos+len-1.
2733 */
2734
2735 return cifs_user_readv(iocb, iov, nr_segs, pos);
2736}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737
2738static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002739 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740{
2741 int rc = -EACCES;
2742 unsigned int bytes_read = 0;
2743 unsigned int total_read;
2744 unsigned int current_read_size;
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002745 unsigned int rsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00002747 struct cifs_tcon *pTcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 int xid;
2749 char *current_offset;
2750 struct cifsFileInfo *open_file;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002751 struct cifs_io_parms io_parms;
Steve Frenchec637e32005-12-12 20:53:18 -08002752 int buf_type = CIFS_NO_BUFFER;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002753 __u32 pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754
2755 xid = GetXid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002756 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002758 /* FIXME: set up handlers for larger reads and/or convert to async */
2759 rsize = min_t(unsigned int, cifs_sb->rsize, CIFSMaxBufSize);
2760
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302762 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302764 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 }
Joe Perchesc21dfb62010-07-12 13:50:14 -07002766 open_file = file->private_data;
Jeff Layton13cfb732010-09-29 19:51:11 -04002767 pTcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002769 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2770 pid = open_file->pid;
2771 else
2772 pid = current->tgid;
2773
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002775 cFYI(1, "attempting read on write only file instance");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002777 for (total_read = 0, current_offset = read_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 read_size > total_read;
2779 total_read += bytes_read, current_offset += bytes_read) {
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002780 current_read_size = min_t(uint, read_size - total_read, rsize);
2781
Steve Frenchf9f5c8172005-09-15 23:06:38 -07002782 /* For windows me and 9x we do not want to request more
2783 than it negotiated since it will refuse the read then */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002784 if ((pTcon->ses) &&
Steve Frenchf9f5c8172005-09-15 23:06:38 -07002785 !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
Dan Carpenter7748dd62011-10-18 12:41:35 +03002786 current_read_size = min_t(uint, current_read_size,
Jeff Laytonc974bef2011-10-11 06:41:32 -04002787 CIFSMaxBufSize);
Steve Frenchf9f5c8172005-09-15 23:06:38 -07002788 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 rc = -EAGAIN;
2790 while (rc == -EAGAIN) {
Steve Frenchcdff08e2010-10-21 22:46:14 +00002791 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04002792 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 if (rc != 0)
2794 break;
2795 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002796 io_parms.netfid = open_file->netfid;
2797 io_parms.pid = pid;
2798 io_parms.tcon = pTcon;
2799 io_parms.offset = *poffset;
2800 io_parms.length = current_read_size;
2801 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
2802 &current_offset, &buf_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 }
2804 if (rc || (bytes_read == 0)) {
2805 if (total_read) {
2806 break;
2807 } else {
2808 FreeXid(xid);
2809 return rc;
2810 }
2811 } else {
Steve Frencha4544342005-08-24 13:59:35 -07002812 cifs_stats_bytes_read(pTcon, total_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 *poffset += bytes_read;
2814 }
2815 }
2816 FreeXid(xid);
2817 return total_read;
2818}
2819
Jeff Laytonca83ce32011-04-12 09:13:44 -04002820/*
2821 * If the page is mmap'ed into a process' page tables, then we need to make
2822 * sure that it doesn't change while being written back.
2823 */
2824static int
2825cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
2826{
2827 struct page *page = vmf->page;
2828
2829 lock_page(page);
2830 return VM_FAULT_LOCKED;
2831}
2832
2833static struct vm_operations_struct cifs_file_vm_ops = {
2834 .fault = filemap_fault,
2835 .page_mkwrite = cifs_page_mkwrite,
2836};
2837
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002838int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
2839{
2840 int rc, xid;
2841 struct inode *inode = file->f_path.dentry->d_inode;
2842
2843 xid = GetXid();
2844
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002845 if (!CIFS_I(inode)->clientCanCacheRead) {
2846 rc = cifs_invalidate_mapping(inode);
2847 if (rc)
2848 return rc;
2849 }
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002850
2851 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04002852 if (rc == 0)
2853 vma->vm_ops = &cifs_file_vm_ops;
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002854 FreeXid(xid);
2855 return rc;
2856}
2857
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
2859{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 int rc, xid;
2861
2862 xid = GetXid();
Jeff Laytonabab0952010-02-12 07:44:18 -05002863 rc = cifs_revalidate_file(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002865 cFYI(1, "Validation prior to mmap failed, error=%d", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866 FreeXid(xid);
2867 return rc;
2868 }
2869 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04002870 if (rc == 0)
2871 vma->vm_ops = &cifs_file_vm_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872 FreeXid(xid);
2873 return rc;
2874}
2875
Jeff Layton0471ca32012-05-16 07:13:16 -04002876static void
2877cifs_readv_complete(struct work_struct *work)
2878{
2879 struct cifs_readdata *rdata = container_of(work,
2880 struct cifs_readdata, work);
2881 struct page *page, *tpage;
2882
2883 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2884 list_del(&page->lru);
2885 lru_cache_add_file(page);
2886
2887 if (rdata->result == 0) {
2888 kunmap(page);
2889 flush_dcache_page(page);
2890 SetPageUptodate(page);
2891 }
2892
2893 unlock_page(page);
2894
2895 if (rdata->result == 0)
2896 cifs_readpage_to_fscache(rdata->mapping->host, page);
2897
2898 page_cache_release(page);
2899 }
Jeff Layton6993f742012-05-16 07:13:17 -04002900 kref_put(&rdata->refcount, cifs_readdata_release);
Jeff Layton0471ca32012-05-16 07:13:16 -04002901}
2902
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04002903static int
2904cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining)
2905{
2906 int len = 0;
2907 struct page *page, *tpage;
2908 u64 eof;
2909 pgoff_t eof_index;
2910
2911 /* determine the eof that the server (probably) has */
2912 eof = CIFS_I(rdata->mapping->host)->server_eof;
2913 eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
2914 cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
2915
2916 rdata->nr_iov = 1;
2917 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2918 if (remaining >= PAGE_CACHE_SIZE) {
2919 /* enough data to fill the page */
2920 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2921 rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE;
2922 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2923 rdata->nr_iov, page->index,
2924 rdata->iov[rdata->nr_iov].iov_base,
2925 rdata->iov[rdata->nr_iov].iov_len);
2926 ++rdata->nr_iov;
2927 len += PAGE_CACHE_SIZE;
2928 remaining -= PAGE_CACHE_SIZE;
2929 } else if (remaining > 0) {
2930 /* enough for partial page, fill and zero the rest */
2931 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2932 rdata->iov[rdata->nr_iov].iov_len = remaining;
2933 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2934 rdata->nr_iov, page->index,
2935 rdata->iov[rdata->nr_iov].iov_base,
2936 rdata->iov[rdata->nr_iov].iov_len);
2937 memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
2938 '\0', PAGE_CACHE_SIZE - remaining);
2939 ++rdata->nr_iov;
2940 len += remaining;
2941 remaining = 0;
2942 } else if (page->index > eof_index) {
2943 /*
2944 * The VFS will not try to do readahead past the
2945 * i_size, but it's possible that we have outstanding
2946 * writes with gaps in the middle and the i_size hasn't
2947 * caught up yet. Populate those with zeroed out pages
2948 * to prevent the VFS from repeatedly attempting to
2949 * fill them until the writes are flushed.
2950 */
2951 zero_user(page, 0, PAGE_CACHE_SIZE);
2952 list_del(&page->lru);
2953 lru_cache_add_file(page);
2954 flush_dcache_page(page);
2955 SetPageUptodate(page);
2956 unlock_page(page);
2957 page_cache_release(page);
2958 } else {
2959 /* no need to hold page hostage */
2960 list_del(&page->lru);
2961 lru_cache_add_file(page);
2962 unlock_page(page);
2963 page_cache_release(page);
2964 }
2965 }
2966
2967 return len;
2968}
2969
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970static int cifs_readpages(struct file *file, struct address_space *mapping,
2971 struct list_head *page_list, unsigned num_pages)
2972{
Jeff Layton690c5e32011-10-19 15:30:16 -04002973 int rc;
2974 struct list_head tmplist;
2975 struct cifsFileInfo *open_file = file->private_data;
2976 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
2977 unsigned int rsize = cifs_sb->rsize;
2978 pid_t pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979
Jeff Layton690c5e32011-10-19 15:30:16 -04002980 /*
2981 * Give up immediately if rsize is too small to read an entire page.
2982 * The VFS will fall back to readpage. We should never reach this
2983 * point however since we set ra_pages to 0 when the rsize is smaller
2984 * than a cache page.
2985 */
2986 if (unlikely(rsize < PAGE_CACHE_SIZE))
2987 return 0;
Steve Frenchbfa0d752005-08-31 21:50:37 -07002988
Suresh Jayaraman56698232010-07-05 18:13:25 +05302989 /*
2990 * Reads as many pages as possible from fscache. Returns -ENOBUFS
2991 * immediately if the cookie is negative
2992 */
2993 rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
2994 &num_pages);
2995 if (rc == 0)
Jeff Layton690c5e32011-10-19 15:30:16 -04002996 return rc;
Suresh Jayaraman56698232010-07-05 18:13:25 +05302997
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002998 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2999 pid = open_file->pid;
3000 else
3001 pid = current->tgid;
3002
Jeff Layton690c5e32011-10-19 15:30:16 -04003003 rc = 0;
3004 INIT_LIST_HEAD(&tmplist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005
Jeff Layton690c5e32011-10-19 15:30:16 -04003006 cFYI(1, "%s: file=%p mapping=%p num_pages=%u", __func__, file,
3007 mapping, num_pages);
3008
3009 /*
3010 * Start with the page at end of list and move it to private
3011 * list. Do the same with any following pages until we hit
3012 * the rsize limit, hit an index discontinuity, or run out of
3013 * pages. Issue the async read and then start the loop again
3014 * until the list is empty.
3015 *
3016 * Note that list order is important. The page_list is in
3017 * the order of declining indexes. When we put the pages in
3018 * the rdata->pages, then we want them in increasing order.
3019 */
3020 while (!list_empty(page_list)) {
3021 unsigned int bytes = PAGE_CACHE_SIZE;
3022 unsigned int expected_index;
3023 unsigned int nr_pages = 1;
3024 loff_t offset;
3025 struct page *page, *tpage;
3026 struct cifs_readdata *rdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027
3028 page = list_entry(page_list->prev, struct page, lru);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029
Jeff Layton690c5e32011-10-19 15:30:16 -04003030 /*
3031 * Lock the page and put it in the cache. Since no one else
3032 * should have access to this page, we're safe to simply set
3033 * PG_locked without checking it first.
3034 */
3035 __set_page_locked(page);
3036 rc = add_to_page_cache_locked(page, mapping,
3037 page->index, GFP_KERNEL);
3038
3039 /* give up if we can't stick it in the cache */
3040 if (rc) {
3041 __clear_page_locked(page);
3042 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044
Jeff Layton690c5e32011-10-19 15:30:16 -04003045 /* move first page to the tmplist */
3046 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
3047 list_move_tail(&page->lru, &tmplist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048
Jeff Layton690c5e32011-10-19 15:30:16 -04003049 /* now try and add more pages onto the request */
3050 expected_index = page->index + 1;
3051 list_for_each_entry_safe_reverse(page, tpage, page_list, lru) {
3052 /* discontinuity ? */
3053 if (page->index != expected_index)
3054 break;
3055
3056 /* would this page push the read over the rsize? */
3057 if (bytes + PAGE_CACHE_SIZE > rsize)
3058 break;
3059
3060 __set_page_locked(page);
3061 if (add_to_page_cache_locked(page, mapping,
3062 page->index, GFP_KERNEL)) {
3063 __clear_page_locked(page);
3064 break;
3065 }
3066 list_move_tail(&page->lru, &tmplist);
3067 bytes += PAGE_CACHE_SIZE;
3068 expected_index++;
3069 nr_pages++;
3070 }
3071
Jeff Layton0471ca32012-05-16 07:13:16 -04003072 rdata = cifs_readdata_alloc(nr_pages, cifs_readv_complete);
Jeff Layton690c5e32011-10-19 15:30:16 -04003073 if (!rdata) {
3074 /* best to give up if we're out of mem */
3075 list_for_each_entry_safe(page, tpage, &tmplist, lru) {
3076 list_del(&page->lru);
3077 lru_cache_add_file(page);
3078 unlock_page(page);
3079 page_cache_release(page);
3080 }
3081 rc = -ENOMEM;
3082 break;
3083 }
3084
3085 spin_lock(&cifs_file_list_lock);
Jeff Layton690c5e32011-10-19 15:30:16 -04003086 spin_unlock(&cifs_file_list_lock);
Jeff Layton6993f742012-05-16 07:13:17 -04003087 rdata->cfile = cifsFileInfo_get(open_file);
Jeff Layton690c5e32011-10-19 15:30:16 -04003088 rdata->mapping = mapping;
3089 rdata->offset = offset;
3090 rdata->bytes = bytes;
3091 rdata->pid = pid;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003092 rdata->marshal_iov = cifs_readpages_marshal_iov;
Jeff Layton690c5e32011-10-19 15:30:16 -04003093 list_splice_init(&tmplist, &rdata->pages);
3094
Jeff Layton2a1bb132012-05-16 07:13:17 -04003095 rc = cifs_retry_async_readv(rdata);
Jeff Layton690c5e32011-10-19 15:30:16 -04003096 if (rc != 0) {
3097 list_for_each_entry_safe(page, tpage, &rdata->pages,
3098 lru) {
3099 list_del(&page->lru);
3100 lru_cache_add_file(page);
3101 unlock_page(page);
3102 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103 }
Jeff Layton6993f742012-05-16 07:13:17 -04003104 kref_put(&rdata->refcount, cifs_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 break;
3106 }
Jeff Layton6993f742012-05-16 07:13:17 -04003107
3108 kref_put(&rdata->refcount, cifs_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 }
3110
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111 return rc;
3112}
3113
3114static int cifs_readpage_worker(struct file *file, struct page *page,
3115 loff_t *poffset)
3116{
3117 char *read_data;
3118 int rc;
3119
Suresh Jayaraman56698232010-07-05 18:13:25 +05303120 /* Is the page cached? */
3121 rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page);
3122 if (rc == 0)
3123 goto read_complete;
3124
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125 page_cache_get(page);
3126 read_data = kmap(page);
3127 /* for reads over a certain size could initiate async read ahead */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003128
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003130
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131 if (rc < 0)
3132 goto io_error;
3133 else
Joe Perchesb6b38f72010-04-21 03:50:45 +00003134 cFYI(1, "Bytes read %d", rc);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003135
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08003136 file->f_path.dentry->d_inode->i_atime =
3137 current_fs_time(file->f_path.dentry->d_inode->i_sb);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003138
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 if (PAGE_CACHE_SIZE > rc)
3140 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
3141
3142 flush_dcache_page(page);
3143 SetPageUptodate(page);
Suresh Jayaraman9dc06552010-07-05 18:13:11 +05303144
3145 /* send this page to the cache */
3146 cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page);
3147
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 rc = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003149
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150io_error:
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003151 kunmap(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152 page_cache_release(page);
Suresh Jayaraman56698232010-07-05 18:13:25 +05303153
3154read_complete:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 return rc;
3156}
3157
3158static int cifs_readpage(struct file *file, struct page *page)
3159{
3160 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
3161 int rc = -EACCES;
3162 int xid;
3163
3164 xid = GetXid();
3165
3166 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05303167 rc = -EBADF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05303169 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170 }
3171
Joe Perchesb6b38f72010-04-21 03:50:45 +00003172 cFYI(1, "readpage %p at offset %d 0x%x\n",
3173 page, (int)offset, (int)offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174
3175 rc = cifs_readpage_worker(file, page, &offset);
3176
3177 unlock_page(page);
3178
3179 FreeXid(xid);
3180 return rc;
3181}
3182
Steve Frencha403a0a2007-07-26 15:54:16 +00003183static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
3184{
3185 struct cifsFileInfo *open_file;
3186
Jeff Layton44772882010-10-15 15:34:03 -04003187 spin_lock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003188 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton2e396b82010-10-15 15:34:01 -04003189 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Jeff Layton44772882010-10-15 15:34:03 -04003190 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003191 return 1;
3192 }
3193 }
Jeff Layton44772882010-10-15 15:34:03 -04003194 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003195 return 0;
3196}
3197
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198/* We do not want to update the file size from server for inodes
3199 open for write - to avoid races with writepage extending
3200 the file - in the future we could consider allowing
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003201 refreshing the inode only on increases in the file size
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202 but this is tricky to do without racing with writebehind
3203 page caching in the current Linux kernel design */
Steve French4b18f2a2008-04-29 00:06:05 +00003204bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205{
Steve Frencha403a0a2007-07-26 15:54:16 +00003206 if (!cifsInode)
Steve French4b18f2a2008-04-29 00:06:05 +00003207 return true;
Steve French23e7dd72005-10-20 13:44:56 -07003208
Steve Frencha403a0a2007-07-26 15:54:16 +00003209 if (is_inode_writable(cifsInode)) {
3210 /* This inode is open for write at least once */
Steve Frenchc32a0b62006-01-12 14:41:28 -08003211 struct cifs_sb_info *cifs_sb;
3212
Steve Frenchc32a0b62006-01-12 14:41:28 -08003213 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
Steve Frenchad7a2922008-02-07 23:25:02 +00003214 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003215 /* since no page cache to corrupt on directio
Steve Frenchc32a0b62006-01-12 14:41:28 -08003216 we can change size safely */
Steve French4b18f2a2008-04-29 00:06:05 +00003217 return true;
Steve Frenchc32a0b62006-01-12 14:41:28 -08003218 }
3219
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003220 if (i_size_read(&cifsInode->vfs_inode) < end_of_file)
Steve French4b18f2a2008-04-29 00:06:05 +00003221 return true;
Steve French7ba52632007-02-08 18:14:13 +00003222
Steve French4b18f2a2008-04-29 00:06:05 +00003223 return false;
Steve French23e7dd72005-10-20 13:44:56 -07003224 } else
Steve French4b18f2a2008-04-29 00:06:05 +00003225 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226}
3227
Nick Piggind9414772008-09-24 11:32:59 -04003228static int cifs_write_begin(struct file *file, struct address_space *mapping,
3229 loff_t pos, unsigned len, unsigned flags,
3230 struct page **pagep, void **fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231{
Nick Piggind9414772008-09-24 11:32:59 -04003232 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
3233 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003234 loff_t page_start = pos & PAGE_MASK;
3235 loff_t i_size;
3236 struct page *page;
3237 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238
Joe Perchesb6b38f72010-04-21 03:50:45 +00003239 cFYI(1, "write_begin from %lld len %d", (long long)pos, len);
Nick Piggind9414772008-09-24 11:32:59 -04003240
Nick Piggin54566b22009-01-04 12:00:53 -08003241 page = grab_cache_page_write_begin(mapping, index, flags);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003242 if (!page) {
3243 rc = -ENOMEM;
3244 goto out;
3245 }
Nick Piggind9414772008-09-24 11:32:59 -04003246
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003247 if (PageUptodate(page))
3248 goto out;
Steve French8a236262007-03-06 00:31:00 +00003249
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003250 /*
3251 * If we write a full page it will be up to date, no need to read from
3252 * the server. If the write is short, we'll end up doing a sync write
3253 * instead.
3254 */
3255 if (len == PAGE_CACHE_SIZE)
3256 goto out;
3257
3258 /*
3259 * optimize away the read when we have an oplock, and we're not
3260 * expecting to use any of the data we'd be reading in. That
3261 * is, when the page lies beyond the EOF, or straddles the EOF
3262 * and the write will cover all of the existing data.
3263 */
3264 if (CIFS_I(mapping->host)->clientCanCacheRead) {
3265 i_size = i_size_read(mapping->host);
3266 if (page_start >= i_size ||
3267 (offset == 0 && (pos + len) >= i_size)) {
3268 zero_user_segments(page, 0, offset,
3269 offset + len,
3270 PAGE_CACHE_SIZE);
3271 /*
3272 * PageChecked means that the parts of the page
3273 * to which we're not writing are considered up
3274 * to date. Once the data is copied to the
3275 * page, it can be set uptodate.
3276 */
3277 SetPageChecked(page);
3278 goto out;
3279 }
3280 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281
Nick Piggind9414772008-09-24 11:32:59 -04003282 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003283 /*
3284 * might as well read a page, it is fast enough. If we get
3285 * an error, we don't need to return it. cifs_write_end will
3286 * do a sync write instead since PG_uptodate isn't set.
3287 */
3288 cifs_readpage_worker(file, page, &page_start);
Steve French8a236262007-03-06 00:31:00 +00003289 } else {
3290 /* we could try using another file handle if there is one -
3291 but how would we lock it to prevent close of that handle
3292 racing with this read? In any case
Nick Piggind9414772008-09-24 11:32:59 -04003293 this will be written out by write_end so is fine */
Steve French8a236262007-03-06 00:31:00 +00003294 }
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003295out:
3296 *pagep = page;
3297 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298}
3299
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303300static int cifs_release_page(struct page *page, gfp_t gfp)
3301{
3302 if (PagePrivate(page))
3303 return 0;
3304
3305 return cifs_fscache_release_page(page, gfp);
3306}
3307
3308static void cifs_invalidate_page(struct page *page, unsigned long offset)
3309{
3310 struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
3311
3312 if (offset == 0)
3313 cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
3314}
3315
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003316static int cifs_launder_page(struct page *page)
3317{
3318 int rc = 0;
3319 loff_t range_start = page_offset(page);
3320 loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
3321 struct writeback_control wbc = {
3322 .sync_mode = WB_SYNC_ALL,
3323 .nr_to_write = 0,
3324 .range_start = range_start,
3325 .range_end = range_end,
3326 };
3327
3328 cFYI(1, "Launder page: %p", page);
3329
3330 if (clear_page_dirty_for_io(page))
3331 rc = cifs_writepage_locked(page, &wbc);
3332
3333 cifs_fscache_invalidate_page(page, page->mapping->host);
3334 return rc;
3335}
3336
Tejun Heo9b646972010-07-20 22:09:02 +02003337void cifs_oplock_break(struct work_struct *work)
Jeff Layton3bc303c2009-09-21 06:47:50 -04003338{
3339 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
3340 oplock_break);
Jeff Laytona5e18bc2010-10-11 15:07:18 -04003341 struct inode *inode = cfile->dentry->d_inode;
Jeff Layton3bc303c2009-09-21 06:47:50 -04003342 struct cifsInodeInfo *cinode = CIFS_I(inode);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04003343 int rc = 0;
Jeff Layton3bc303c2009-09-21 06:47:50 -04003344
3345 if (inode && S_ISREG(inode->i_mode)) {
Steve Frenchd54ff732010-04-27 04:38:15 +00003346 if (cinode->clientCanCacheRead)
Al Viro8737c932009-12-24 06:47:55 -05003347 break_lease(inode, O_RDONLY);
Steve Frenchd54ff732010-04-27 04:38:15 +00003348 else
Al Viro8737c932009-12-24 06:47:55 -05003349 break_lease(inode, O_WRONLY);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003350 rc = filemap_fdatawrite(inode->i_mapping);
3351 if (cinode->clientCanCacheRead == 0) {
Jeff Laytoneb4b7562010-10-22 14:52:29 -04003352 rc = filemap_fdatawait(inode->i_mapping);
3353 mapping_set_error(inode->i_mapping, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003354 invalidate_remote_inode(inode);
3355 }
Joe Perchesb6b38f72010-04-21 03:50:45 +00003356 cFYI(1, "Oplock flush inode %p rc %d", inode, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003357 }
3358
Pavel Shilovsky85160e02011-10-22 15:33:29 +04003359 rc = cifs_push_locks(cfile);
3360 if (rc)
3361 cERROR(1, "Push locks rc = %d", rc);
3362
Jeff Layton3bc303c2009-09-21 06:47:50 -04003363 /*
3364 * releasing stale oplock after recent reconnect of smb session using
3365 * a now incorrect file handle is not a data integrity issue but do
3366 * not bother sending an oplock release if session to server still is
3367 * disconnected since oplock already released by the server
3368 */
Steve Frenchcdff08e2010-10-21 22:46:14 +00003369 if (!cfile->oplock_break_cancelled) {
Pavel Shilovsky03776f42010-08-17 11:26:00 +04003370 rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid,
3371 current->tgid, 0, 0, 0, 0,
3372 LOCKING_ANDX_OPLOCK_RELEASE, false,
Pavel Shilovsky12fed002011-01-17 20:15:44 +03003373 cinode->clientCanCacheRead ? 1 : 0);
Joe Perchesb6b38f72010-04-21 03:50:45 +00003374 cFYI(1, "Oplock release rc = %d", rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003375 }
Jeff Layton3bc303c2009-09-21 06:47:50 -04003376}
3377
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07003378const struct address_space_operations cifs_addr_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379 .readpage = cifs_readpage,
3380 .readpages = cifs_readpages,
3381 .writepage = cifs_writepage,
Steve French37c0eb42005-10-05 14:50:29 -07003382 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04003383 .write_begin = cifs_write_begin,
3384 .write_end = cifs_write_end,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303386 .releasepage = cifs_release_page,
3387 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003388 .launder_page = cifs_launder_page,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389};
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003390
3391/*
3392 * cifs_readpages requires the server to support a buffer large enough to
3393 * contain the header plus one complete page of data. Otherwise, we need
3394 * to leave cifs_readpages out of the address space operations.
3395 */
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07003396const struct address_space_operations cifs_addr_ops_smallbuf = {
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003397 .readpage = cifs_readpage,
3398 .writepage = cifs_writepage,
3399 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04003400 .write_begin = cifs_write_begin,
3401 .write_end = cifs_write_end,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003402 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303403 .releasepage = cifs_release_page,
3404 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003405 .launder_page = cifs_launder_page,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003406};