blob: 93b3b1358409b02a2f36815920bae54e3eafd9b1 [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,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400110 __u32 *poplock, __u16 *pnetfid, unsigned int xid)
Jeff Layton608712f2010-10-15 15:33:56 -0400111{
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 Shilovsky6d5786a2012-06-20 11:21:16 +0400173 __u16 *pnetfid, unsigned int xid)
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300174{
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) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400327 unsigned int xid;
328 int rc;
329 xid = get_xid();
Steve Frenchcdff08e2010-10-21 22:46:14 +0000330 rc = CIFSSMBClose(xid, tcon, cifs_file->netfid);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400331 free_xid(xid);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000332 }
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;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400353 unsigned int xid;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400354 __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
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400363 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
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)) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400368 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400369 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);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400448 free_xid(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;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400467 unsigned int xid;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400468 __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
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400479 xid = get_xid();
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;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400484 free_xid(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);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400500 free_xid(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);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400586 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 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;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400604 unsigned 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
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400610 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
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? */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400642 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 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{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400875 unsigned int xid;
876 int rc = 0, stored_rc;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400877 struct cifsLockInfo *li, *tmp;
878 struct cifs_tcon *tcon;
879 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovsky0013fb42012-05-31 13:03:26 +0400880 unsigned int num, max_num, max_buf;
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400881 LOCKING_ANDX_RANGE *buf, *cur;
882 int types[] = {LOCKING_ANDX_LARGE_FILES,
883 LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
884 int i;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400885
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400886 xid = get_xid();
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400887 tcon = tlink_tcon(cfile->tlink);
888
889 mutex_lock(&cinode->lock_mutex);
890 if (!cinode->can_cache_brlcks) {
891 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400892 free_xid(xid);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400893 return rc;
894 }
895
Pavel Shilovsky0013fb42012-05-31 13:03:26 +0400896 /*
897 * Accessing maxBuf is racy with cifs_reconnect - need to store value
898 * and check it for zero before using.
899 */
900 max_buf = tcon->ses->server->maxBuf;
901 if (!max_buf) {
902 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400903 free_xid(xid);
Pavel Shilovsky0013fb42012-05-31 13:03:26 +0400904 return -EINVAL;
905 }
906
907 max_num = (max_buf - sizeof(struct smb_hdr)) /
908 sizeof(LOCKING_ANDX_RANGE);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400909 buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
910 if (!buf) {
911 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400912 free_xid(xid);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400913 return rc;
914 }
915
916 for (i = 0; i < 2; i++) {
917 cur = buf;
918 num = 0;
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300919 list_for_each_entry_safe(li, tmp, &cfile->llist, llist) {
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400920 if (li->type != types[i])
921 continue;
922 cur->Pid = cpu_to_le16(li->pid);
923 cur->LengthLow = cpu_to_le32((u32)li->length);
924 cur->LengthHigh = cpu_to_le32((u32)(li->length>>32));
925 cur->OffsetLow = cpu_to_le32((u32)li->offset);
926 cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
927 if (++num == max_num) {
928 stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +0300929 (__u8)li->type, 0, num,
930 buf);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400931 if (stored_rc)
932 rc = stored_rc;
933 cur = buf;
934 num = 0;
935 } else
936 cur++;
937 }
938
939 if (num) {
940 stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +0300941 (__u8)types[i], 0, num, buf);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400942 if (stored_rc)
943 rc = stored_rc;
944 }
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400945 }
946
947 cinode->can_cache_brlcks = false;
948 mutex_unlock(&cinode->lock_mutex);
949
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400950 kfree(buf);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400951 free_xid(xid);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400952 return rc;
953}
954
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400955/* copied from fs/locks.c with a name change */
956#define cifs_for_each_lock(inode, lockp) \
957 for (lockp = &inode->i_flock; *lockp != NULL; \
958 lockp = &(*lockp)->fl_next)
959
Pavel Shilovskyd5751462012-03-05 09:39:20 +0300960struct lock_to_push {
961 struct list_head llist;
962 __u64 offset;
963 __u64 length;
964 __u32 pid;
965 __u16 netfid;
966 __u8 type;
967};
968
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400969static int
970cifs_push_posix_locks(struct cifsFileInfo *cfile)
971{
972 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
973 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
974 struct file_lock *flock, **before;
Pavel Shilovskyd5751462012-03-05 09:39:20 +0300975 unsigned int count = 0, i = 0;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400976 int rc = 0, xid, type;
Pavel Shilovskyd5751462012-03-05 09:39:20 +0300977 struct list_head locks_to_send, *el;
978 struct lock_to_push *lck, *tmp;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400979 __u64 length;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400980
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400981 xid = get_xid();
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400982
983 mutex_lock(&cinode->lock_mutex);
984 if (!cinode->can_cache_brlcks) {
985 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400986 free_xid(xid);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400987 return rc;
988 }
989
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400990 lock_flocks();
991 cifs_for_each_lock(cfile->dentry->d_inode, before) {
Pavel Shilovskyd5751462012-03-05 09:39:20 +0300992 if ((*before)->fl_flags & FL_POSIX)
993 count++;
994 }
995 unlock_flocks();
996
997 INIT_LIST_HEAD(&locks_to_send);
998
999 /*
Pavel Shilovskyce858522012-03-17 09:46:55 +03001000 * Allocating count locks is enough because no FL_POSIX locks can be
1001 * added to the list while we are holding cinode->lock_mutex that
1002 * protects locking operations of this inode.
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001003 */
1004 for (; i < count; i++) {
1005 lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL);
1006 if (!lck) {
1007 rc = -ENOMEM;
1008 goto err_out;
1009 }
1010 list_add_tail(&lck->llist, &locks_to_send);
1011 }
1012
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001013 el = locks_to_send.next;
1014 lock_flocks();
1015 cifs_for_each_lock(cfile->dentry->d_inode, before) {
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001016 flock = *before;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001017 if ((flock->fl_flags & FL_POSIX) == 0)
1018 continue;
Pavel Shilovskyce858522012-03-17 09:46:55 +03001019 if (el == &locks_to_send) {
1020 /*
1021 * The list ended. We don't have enough allocated
1022 * structures - something is really wrong.
1023 */
1024 cERROR(1, "Can't push all brlocks!");
1025 break;
1026 }
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001027 length = 1 + flock->fl_end - flock->fl_start;
1028 if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK)
1029 type = CIFS_RDLCK;
1030 else
1031 type = CIFS_WRLCK;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001032 lck = list_entry(el, struct lock_to_push, llist);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001033 lck->pid = flock->fl_pid;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001034 lck->netfid = cfile->netfid;
1035 lck->length = length;
1036 lck->type = type;
1037 lck->offset = flock->fl_start;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001038 el = el->next;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001039 }
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001040 unlock_flocks();
1041
1042 list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001043 int stored_rc;
1044
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001045 stored_rc = CIFSSMBPosixLock(xid, tcon, lck->netfid, lck->pid,
Jeff Laytonc5fd3632012-07-23 13:28:37 -04001046 lck->offset, lck->length, NULL,
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001047 lck->type, 0);
1048 if (stored_rc)
1049 rc = stored_rc;
1050 list_del(&lck->llist);
1051 kfree(lck);
1052 }
1053
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001054out:
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001055 cinode->can_cache_brlcks = false;
1056 mutex_unlock(&cinode->lock_mutex);
1057
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001058 free_xid(xid);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001059 return rc;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001060err_out:
1061 list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
1062 list_del(&lck->llist);
1063 kfree(lck);
1064 }
1065 goto out;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001066}
1067
1068static int
1069cifs_push_locks(struct cifsFileInfo *cfile)
1070{
1071 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
1072 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1073
1074 if ((tcon->ses->capabilities & CAP_UNIX) &&
1075 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
1076 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
1077 return cifs_push_posix_locks(cfile);
1078
1079 return cifs_push_mandatory_locks(cfile);
1080}
1081
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001082static void
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001083cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock,
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001084 bool *wait_flag, struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085{
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001086 if (flock->fl_flags & FL_POSIX)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001087 cFYI(1, "Posix");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001088 if (flock->fl_flags & FL_FLOCK)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001089 cFYI(1, "Flock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001090 if (flock->fl_flags & FL_SLEEP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001091 cFYI(1, "Blocking lock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001092 *wait_flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 }
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001094 if (flock->fl_flags & FL_ACCESS)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001095 cFYI(1, "Process suspended by mandatory locking - "
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001096 "not implemented yet");
1097 if (flock->fl_flags & FL_LEASE)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001098 cFYI(1, "Lease on file - not implemented yet");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001099 if (flock->fl_flags &
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001101 cFYI(1, "Unknown lock flags 0x%x", flock->fl_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001103 *type = server->vals->large_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001104 if (flock->fl_type == F_WRLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001105 cFYI(1, "F_WRLCK ");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001106 *type |= server->vals->exclusive_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001107 *lock = 1;
1108 } else if (flock->fl_type == F_UNLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001109 cFYI(1, "F_UNLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001110 *type |= server->vals->unlock_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001111 *unlock = 1;
1112 /* Check if unlock includes more than one lock range */
1113 } else if (flock->fl_type == F_RDLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001114 cFYI(1, "F_RDLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001115 *type |= server->vals->shared_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001116 *lock = 1;
1117 } else if (flock->fl_type == F_EXLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001118 cFYI(1, "F_EXLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001119 *type |= server->vals->exclusive_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001120 *lock = 1;
1121 } else if (flock->fl_type == F_SHLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001122 cFYI(1, "F_SHLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001123 *type |= server->vals->shared_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001124 *lock = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +00001126 cFYI(1, "Unknown type of lock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001127}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001129static int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001130cifs_mandatory_lock(unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001131 __u64 length, __u32 type, int lock, int unlock, bool wait)
1132{
1133 return CIFSSMBLock(xid, tlink_tcon(cfile->tlink), cfile->netfid,
1134 current->tgid, length, offset, unlock, lock,
1135 (__u8)type, wait, 0);
1136}
1137
1138static int
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001139cifs_getlk(struct file *file, struct file_lock *flock, __u32 type,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001140 bool wait_flag, bool posix_lck, unsigned int xid)
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001141{
1142 int rc = 0;
1143 __u64 length = 1 + flock->fl_end - flock->fl_start;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001144 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
1145 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001146 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001147 __u16 netfid = cfile->netfid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001149 if (posix_lck) {
1150 int posix_lock_type;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001151
1152 rc = cifs_posix_lock_test(file, flock);
1153 if (!rc)
1154 return rc;
1155
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001156 if (type & server->vals->shared_lock_type)
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001157 posix_lock_type = CIFS_RDLCK;
1158 else
1159 posix_lock_type = CIFS_WRLCK;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001160 rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid,
Jeff Laytonc5fd3632012-07-23 13:28:37 -04001161 flock->fl_start, length, flock,
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001162 posix_lock_type, wait_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 return rc;
1164 }
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001165
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001166 rc = cifs_lock_test(cfile, flock->fl_start, length, type, flock);
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001167 if (!rc)
1168 return rc;
1169
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001170 /* BB we could chain these into one lock request BB */
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001171 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length, type,
1172 1, 0, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001173 if (rc == 0) {
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001174 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1175 type, 0, 1, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001176 flock->fl_type = F_UNLCK;
1177 if (rc != 0)
1178 cERROR(1, "Error unlocking previously locked "
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001179 "range %d during test of lock", rc);
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001180 return 0;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001181 }
1182
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001183 if (type & server->vals->shared_lock_type) {
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001184 flock->fl_type = F_WRLCK;
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001185 return 0;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001186 }
1187
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001188 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1189 type | server->vals->shared_lock_type, 1, 0,
1190 false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001191 if (rc == 0) {
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001192 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1193 type | server->vals->shared_lock_type,
1194 0, 1, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001195 flock->fl_type = F_RDLCK;
1196 if (rc != 0)
1197 cERROR(1, "Error unlocking previously locked "
1198 "range %d during test of lock", rc);
1199 } else
1200 flock->fl_type = F_WRLCK;
1201
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001202 return 0;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001203}
1204
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001205static void
1206cifs_move_llist(struct list_head *source, struct list_head *dest)
1207{
1208 struct list_head *li, *tmp;
1209 list_for_each_safe(li, tmp, source)
1210 list_move(li, dest);
1211}
1212
1213static void
1214cifs_free_llist(struct list_head *llist)
1215{
1216 struct cifsLockInfo *li, *tmp;
1217 list_for_each_entry_safe(li, tmp, llist, llist) {
1218 cifs_del_lock_waiters(li);
1219 list_del(&li->llist);
1220 kfree(li);
1221 }
1222}
1223
1224static int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001225cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
1226 unsigned int xid)
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001227{
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 Shilovsky6d5786a2012-06-20 11:21:16 +04001331 bool wait_flag, bool posix_lck, int lock, int unlock,
1332 unsigned int xid)
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001333{
1334 int rc = 0;
1335 __u64 length = 1 + flock->fl_end - flock->fl_start;
1336 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
1337 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001338 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001339 __u16 netfid = cfile->netfid;
1340
1341 if (posix_lck) {
Steve French08547b02006-02-28 22:39:25 +00001342 int posix_lock_type;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001343
1344 rc = cifs_posix_lock_set(file, flock);
1345 if (!rc || rc < 0)
1346 return rc;
1347
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001348 if (type & server->vals->shared_lock_type)
Steve French08547b02006-02-28 22:39:25 +00001349 posix_lock_type = CIFS_RDLCK;
1350 else
1351 posix_lock_type = CIFS_WRLCK;
Steve French50c2f752007-07-13 00:33:32 +00001352
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001353 if (unlock == 1)
Steve Frenchbeb84dc2006-03-03 23:36:34 +00001354 posix_lock_type = CIFS_UNLCK;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001355
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001356 rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid,
Jeff Laytonc5fd3632012-07-23 13:28:37 -04001357 flock->fl_start, length, NULL,
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001358 posix_lock_type, wait_flag);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001359 goto out;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001360 }
1361
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001362 if (lock) {
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001363 struct cifsLockInfo *lock;
1364
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001365 lock = cifs_lock_init(flock->fl_start, length, type);
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001366 if (!lock)
1367 return -ENOMEM;
1368
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001369 rc = cifs_lock_add_if(cfile, lock, wait_flag);
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001370 if (rc < 0)
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001371 kfree(lock);
1372 if (rc <= 0)
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001373 goto out;
1374
Pavel Shilovsky7f924472012-03-28 17:10:25 +04001375 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1376 type, 1, 0, wait_flag);
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001377 if (rc) {
1378 kfree(lock);
1379 goto out;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001380 }
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001381
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001382 cifs_lock_add(cfile, lock);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001383 } else if (unlock)
1384 rc = cifs_unlock_range(cfile, flock, xid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001385
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001386out:
1387 if (flock->fl_flags & FL_POSIX)
Steve French9ebb3892012-04-01 13:52:54 -05001388 posix_lock_file_wait(file, flock);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001389 return rc;
1390}
1391
1392int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
1393{
1394 int rc, xid;
1395 int lock = 0, unlock = 0;
1396 bool wait_flag = false;
1397 bool posix_lck = false;
1398 struct cifs_sb_info *cifs_sb;
1399 struct cifs_tcon *tcon;
1400 struct cifsInodeInfo *cinode;
1401 struct cifsFileInfo *cfile;
1402 __u16 netfid;
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001403 __u32 type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001404
1405 rc = -EACCES;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001406 xid = get_xid();
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001407
1408 cFYI(1, "Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld "
1409 "end: %lld", cmd, flock->fl_flags, flock->fl_type,
1410 flock->fl_start, flock->fl_end);
1411
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001412 cfile = (struct cifsFileInfo *)file->private_data;
1413 tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001414
1415 cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag,
1416 tcon->ses->server);
1417
1418 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001419 netfid = cfile->netfid;
1420 cinode = CIFS_I(file->f_path.dentry->d_inode);
1421
1422 if ((tcon->ses->capabilities & CAP_UNIX) &&
1423 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
1424 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
1425 posix_lck = true;
1426 /*
1427 * BB add code here to normalize offset and length to account for
1428 * negative length which we can not accept over the wire.
1429 */
1430 if (IS_GETLK(cmd)) {
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001431 rc = cifs_getlk(file, flock, type, wait_flag, posix_lck, xid);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001432 free_xid(xid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001433 return rc;
1434 }
1435
1436 if (!lock && !unlock) {
1437 /*
1438 * if no lock or unlock then nothing to do since we do not
1439 * know what it is
1440 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001441 free_xid(xid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001442 return -EOPNOTSUPP;
1443 }
1444
1445 rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock,
1446 xid);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001447 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 return rc;
1449}
1450
Jeff Layton597b0272012-03-23 14:40:56 -04001451/*
1452 * update the file size (if needed) after a write. Should be called with
1453 * the inode->i_lock held
1454 */
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001455void
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001456cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
1457 unsigned int bytes_written)
1458{
1459 loff_t end_of_write = offset + bytes_written;
1460
1461 if (end_of_write > cifsi->server_eof)
1462 cifsi->server_eof = end_of_write;
1463}
1464
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001465static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
Jeff Layton7da4b492010-10-15 15:34:00 -04001466 const char *write_data, size_t write_size,
1467 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468{
1469 int rc = 0;
1470 unsigned int bytes_written = 0;
1471 unsigned int total_written;
1472 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00001473 struct cifs_tcon *pTcon;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001474 unsigned int xid;
Jeff Layton7da4b492010-10-15 15:34:00 -04001475 struct dentry *dentry = open_file->dentry;
1476 struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001477 struct cifs_io_parms io_parms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478
Jeff Layton7da4b492010-10-15 15:34:00 -04001479 cifs_sb = CIFS_SB(dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480
Joe Perchesb6b38f72010-04-21 03:50:45 +00001481 cFYI(1, "write %zd bytes to offset %lld of %s", write_size,
Jeff Layton7da4b492010-10-15 15:34:00 -04001482 *poffset, dentry->d_name.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483
Jeff Layton13cfb732010-09-29 19:51:11 -04001484 pTcon = tlink_tcon(open_file->tlink);
Steve French50c2f752007-07-13 00:33:32 +00001485
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001486 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 for (total_written = 0; write_size > total_written;
1489 total_written += bytes_written) {
1490 rc = -EAGAIN;
1491 while (rc == -EAGAIN) {
Jeff Laytonca83ce32011-04-12 09:13:44 -04001492 struct kvec iov[2];
1493 unsigned int len;
1494
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 if (open_file->invalidHandle) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 /* we could deadlock if we called
1497 filemap_fdatawait from here so tell
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001498 reopen_file not to flush data to
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 server now */
Jeff Layton15886172010-10-15 15:33:59 -04001500 rc = cifs_reopen_file(open_file, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 if (rc != 0)
1502 break;
1503 }
Steve French3e844692005-10-03 13:37:24 -07001504
Jeff Laytonca83ce32011-04-12 09:13:44 -04001505 len = min((size_t)cifs_sb->wsize,
1506 write_size - total_written);
1507 /* iov[0] is reserved for smb header */
1508 iov[1].iov_base = (char *)write_data + total_written;
1509 iov[1].iov_len = len;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001510 io_parms.netfid = open_file->netfid;
1511 io_parms.pid = pid;
1512 io_parms.tcon = pTcon;
1513 io_parms.offset = *poffset;
1514 io_parms.length = len;
1515 rc = CIFSSMBWrite2(xid, &io_parms, &bytes_written, iov,
1516 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 }
1518 if (rc || (bytes_written == 0)) {
1519 if (total_written)
1520 break;
1521 else {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001522 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 return rc;
1524 }
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001525 } else {
Jeff Layton597b0272012-03-23 14:40:56 -04001526 spin_lock(&dentry->d_inode->i_lock);
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001527 cifs_update_eof(cifsi, *poffset, bytes_written);
Jeff Layton597b0272012-03-23 14:40:56 -04001528 spin_unlock(&dentry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 *poffset += bytes_written;
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001530 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 }
1532
Steve Frencha4544342005-08-24 13:59:35 -07001533 cifs_stats_bytes_written(pTcon, total_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534
Jeff Layton7da4b492010-10-15 15:34:00 -04001535 if (total_written > 0) {
1536 spin_lock(&dentry->d_inode->i_lock);
1537 if (*poffset > dentry->d_inode->i_size)
1538 i_size_write(dentry->d_inode, *poffset);
1539 spin_unlock(&dentry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 }
Jeff Layton7da4b492010-10-15 15:34:00 -04001541 mark_inode_dirty_sync(dentry->d_inode);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001542 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 return total_written;
1544}
1545
Jeff Layton6508d902010-09-29 19:51:11 -04001546struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1547 bool fsuid_only)
Steve French630f3f0c2007-10-25 21:17:17 +00001548{
1549 struct cifsFileInfo *open_file = NULL;
Jeff Layton6508d902010-09-29 19:51:11 -04001550 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1551
1552 /* only filter by fsuid on multiuser mounts */
1553 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1554 fsuid_only = false;
Steve French630f3f0c2007-10-25 21:17:17 +00001555
Jeff Layton44772882010-10-15 15:34:03 -04001556 spin_lock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001557 /* we could simply get the first_list_entry since write-only entries
1558 are always at the end of the list but since the first entry might
1559 have a close pending, we go through the whole list */
1560 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001561 if (fsuid_only && open_file->uid != current_fsuid())
1562 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001563 if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
Steve French630f3f0c2007-10-25 21:17:17 +00001564 if (!open_file->invalidHandle) {
1565 /* found a good file */
1566 /* lock it so it will not be closed on us */
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001567 cifsFileInfo_get(open_file);
Jeff Layton44772882010-10-15 15:34:03 -04001568 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001569 return open_file;
1570 } /* else might as well continue, and look for
1571 another, or simply have the caller reopen it
1572 again rather than trying to fix this handle */
1573 } else /* write only file */
1574 break; /* write only files are last so must be done */
1575 }
Jeff Layton44772882010-10-15 15:34:03 -04001576 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001577 return NULL;
1578}
Steve French630f3f0c2007-10-25 21:17:17 +00001579
Jeff Layton6508d902010-09-29 19:51:11 -04001580struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1581 bool fsuid_only)
Steve French6148a742005-10-05 12:23:19 -07001582{
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001583 struct cifsFileInfo *open_file, *inv_file = NULL;
Jeff Laytond3892292010-11-02 16:22:50 -04001584 struct cifs_sb_info *cifs_sb;
Jeff Layton2846d382008-09-22 21:33:33 -04001585 bool any_available = false;
Steve Frenchdd99cd82005-10-05 19:32:49 -07001586 int rc;
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001587 unsigned int refind = 0;
Steve French6148a742005-10-05 12:23:19 -07001588
Steve French60808232006-04-22 15:53:05 +00001589 /* Having a null inode here (because mapping->host was set to zero by
1590 the VFS or MM) should not happen but we had reports of on oops (due to
1591 it being zero) during stress testcases so we need to check for it */
1592
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001593 if (cifs_inode == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001594 cERROR(1, "Null inode passed to cifs_writeable_file");
Steve French60808232006-04-22 15:53:05 +00001595 dump_stack();
1596 return NULL;
1597 }
1598
Jeff Laytond3892292010-11-02 16:22:50 -04001599 cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1600
Jeff Layton6508d902010-09-29 19:51:11 -04001601 /* only filter by fsuid on multiuser mounts */
1602 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1603 fsuid_only = false;
1604
Jeff Layton44772882010-10-15 15:34:03 -04001605 spin_lock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001606refind_writable:
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001607 if (refind > MAX_REOPEN_ATT) {
1608 spin_unlock(&cifs_file_list_lock);
1609 return NULL;
1610 }
Steve French6148a742005-10-05 12:23:19 -07001611 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001612 if (!any_available && open_file->pid != current->tgid)
1613 continue;
1614 if (fsuid_only && open_file->uid != current_fsuid())
1615 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001616 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Steve French9b22b0b2007-10-02 01:11:08 +00001617 if (!open_file->invalidHandle) {
1618 /* found a good writable file */
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001619 cifsFileInfo_get(open_file);
Jeff Layton44772882010-10-15 15:34:03 -04001620 spin_unlock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001621 return open_file;
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001622 } else {
1623 if (!inv_file)
1624 inv_file = open_file;
Steve French9b22b0b2007-10-02 01:11:08 +00001625 }
Steve French6148a742005-10-05 12:23:19 -07001626 }
1627 }
Jeff Layton2846d382008-09-22 21:33:33 -04001628 /* couldn't find useable FH with same pid, try any available */
1629 if (!any_available) {
1630 any_available = true;
1631 goto refind_writable;
1632 }
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001633
1634 if (inv_file) {
1635 any_available = false;
1636 cifsFileInfo_get(inv_file);
1637 }
1638
Jeff Layton44772882010-10-15 15:34:03 -04001639 spin_unlock(&cifs_file_list_lock);
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001640
1641 if (inv_file) {
1642 rc = cifs_reopen_file(inv_file, false);
1643 if (!rc)
1644 return inv_file;
1645 else {
1646 spin_lock(&cifs_file_list_lock);
1647 list_move_tail(&inv_file->flist,
1648 &cifs_inode->openFileList);
1649 spin_unlock(&cifs_file_list_lock);
1650 cifsFileInfo_put(inv_file);
1651 spin_lock(&cifs_file_list_lock);
1652 ++refind;
1653 goto refind_writable;
1654 }
1655 }
1656
Steve French6148a742005-10-05 12:23:19 -07001657 return NULL;
1658}
1659
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1661{
1662 struct address_space *mapping = page->mapping;
1663 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1664 char *write_data;
1665 int rc = -EFAULT;
1666 int bytes_written = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 struct inode *inode;
Steve French6148a742005-10-05 12:23:19 -07001668 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669
1670 if (!mapping || !mapping->host)
1671 return -EFAULT;
1672
1673 inode = page->mapping->host;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674
1675 offset += (loff_t)from;
1676 write_data = kmap(page);
1677 write_data += from;
1678
1679 if ((to > PAGE_CACHE_SIZE) || (from > to)) {
1680 kunmap(page);
1681 return -EIO;
1682 }
1683
1684 /* racing with truncate? */
1685 if (offset > mapping->host->i_size) {
1686 kunmap(page);
1687 return 0; /* don't care */
1688 }
1689
1690 /* check to make sure that we are not extending the file */
1691 if (mapping->host->i_size - offset < (loff_t)to)
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001692 to = (unsigned)(mapping->host->i_size - offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693
Jeff Layton6508d902010-09-29 19:51:11 -04001694 open_file = find_writable_file(CIFS_I(mapping->host), false);
Steve French6148a742005-10-05 12:23:19 -07001695 if (open_file) {
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001696 bytes_written = cifs_write(open_file, open_file->pid,
1697 write_data, to - from, &offset);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001698 cifsFileInfo_put(open_file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 /* Does mm or vfs already set times? */
Steve French6148a742005-10-05 12:23:19 -07001700 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001701 if ((bytes_written > 0) && (offset))
Steve French6148a742005-10-05 12:23:19 -07001702 rc = 0;
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001703 else if (bytes_written < 0)
1704 rc = bytes_written;
Steve French6148a742005-10-05 12:23:19 -07001705 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001706 cFYI(1, "No writeable filehandles for inode");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 rc = -EIO;
1708 }
1709
1710 kunmap(page);
1711 return rc;
1712}
1713
Jeff Laytone9492872012-03-23 14:40:56 -04001714/*
1715 * Marshal up the iov array, reserving the first one for the header. Also,
1716 * set wdata->bytes.
1717 */
1718static void
1719cifs_writepages_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
1720{
1721 int i;
1722 struct inode *inode = wdata->cfile->dentry->d_inode;
1723 loff_t size = i_size_read(inode);
1724
1725 /* marshal up the pages into iov array */
1726 wdata->bytes = 0;
1727 for (i = 0; i < wdata->nr_pages; i++) {
1728 iov[i + 1].iov_len = min(size - page_offset(wdata->pages[i]),
1729 (loff_t)PAGE_CACHE_SIZE);
1730 iov[i + 1].iov_base = kmap(wdata->pages[i]);
1731 wdata->bytes += iov[i + 1].iov_len;
1732 }
1733}
1734
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735static int cifs_writepages(struct address_space *mapping,
Steve French37c0eb42005-10-05 14:50:29 -07001736 struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737{
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001738 struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb);
1739 bool done = false, scanned = false, range_whole = false;
1740 pgoff_t end, index;
1741 struct cifs_writedata *wdata;
Steve French37c0eb42005-10-05 14:50:29 -07001742 struct page *page;
Steve French37c0eb42005-10-05 14:50:29 -07001743 int rc = 0;
Steve French50c2f752007-07-13 00:33:32 +00001744
Steve French37c0eb42005-10-05 14:50:29 -07001745 /*
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001746 * If wsize is smaller than the page cache size, default to writing
Steve French37c0eb42005-10-05 14:50:29 -07001747 * one page at a time via cifs_writepage
1748 */
1749 if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1750 return generic_writepages(mapping, wbc);
1751
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001752 if (wbc->range_cyclic) {
Steve French37c0eb42005-10-05 14:50:29 -07001753 index = mapping->writeback_index; /* Start from prev offset */
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001754 end = -1;
1755 } else {
1756 index = wbc->range_start >> PAGE_CACHE_SHIFT;
1757 end = wbc->range_end >> PAGE_CACHE_SHIFT;
1758 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001759 range_whole = true;
1760 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001761 }
1762retry:
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001763 while (!done && index <= end) {
1764 unsigned int i, nr_pages, found_pages;
1765 pgoff_t next = 0, tofind;
1766 struct page **pages;
Steve French37c0eb42005-10-05 14:50:29 -07001767
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001768 tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1,
1769 end - index) + 1;
Steve French37c0eb42005-10-05 14:50:29 -07001770
Jeff Laytonc2e87642012-03-23 14:40:55 -04001771 wdata = cifs_writedata_alloc((unsigned int)tofind,
1772 cifs_writev_complete);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001773 if (!wdata) {
1774 rc = -ENOMEM;
1775 break;
1776 }
1777
1778 /*
1779 * find_get_pages_tag seems to return a max of 256 on each
1780 * iteration, so we must call it several times in order to
1781 * fill the array or the wsize is effectively limited to
1782 * 256 * PAGE_CACHE_SIZE.
1783 */
1784 found_pages = 0;
1785 pages = wdata->pages;
1786 do {
1787 nr_pages = find_get_pages_tag(mapping, &index,
1788 PAGECACHE_TAG_DIRTY,
1789 tofind, pages);
1790 found_pages += nr_pages;
1791 tofind -= nr_pages;
1792 pages += nr_pages;
1793 } while (nr_pages && tofind && index <= end);
1794
1795 if (found_pages == 0) {
1796 kref_put(&wdata->refcount, cifs_writedata_release);
1797 break;
1798 }
1799
1800 nr_pages = 0;
1801 for (i = 0; i < found_pages; i++) {
1802 page = wdata->pages[i];
Steve French37c0eb42005-10-05 14:50:29 -07001803 /*
1804 * At this point we hold neither mapping->tree_lock nor
1805 * lock on the page itself: the page may be truncated or
1806 * invalidated (changing page->mapping to NULL), or even
1807 * swizzled back from swapper_space to tmpfs file
1808 * mapping
1809 */
1810
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001811 if (nr_pages == 0)
Steve French37c0eb42005-10-05 14:50:29 -07001812 lock_page(page);
Nick Piggin529ae9a2008-08-02 12:01:03 +02001813 else if (!trylock_page(page))
Steve French37c0eb42005-10-05 14:50:29 -07001814 break;
1815
1816 if (unlikely(page->mapping != mapping)) {
1817 unlock_page(page);
1818 break;
1819 }
1820
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001821 if (!wbc->range_cyclic && page->index > end) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001822 done = true;
Steve French37c0eb42005-10-05 14:50:29 -07001823 unlock_page(page);
1824 break;
1825 }
1826
1827 if (next && (page->index != next)) {
1828 /* Not next consecutive page */
1829 unlock_page(page);
1830 break;
1831 }
1832
1833 if (wbc->sync_mode != WB_SYNC_NONE)
1834 wait_on_page_writeback(page);
1835
1836 if (PageWriteback(page) ||
Linus Torvaldscb876f42006-12-23 16:19:07 -08001837 !clear_page_dirty_for_io(page)) {
Steve French37c0eb42005-10-05 14:50:29 -07001838 unlock_page(page);
1839 break;
1840 }
Steve French84d2f072005-10-12 15:32:05 -07001841
Linus Torvaldscb876f42006-12-23 16:19:07 -08001842 /*
1843 * This actually clears the dirty bit in the radix tree.
1844 * See cifs_writepage() for more commentary.
1845 */
1846 set_page_writeback(page);
1847
Steve French84d2f072005-10-12 15:32:05 -07001848 if (page_offset(page) >= mapping->host->i_size) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001849 done = true;
Steve French84d2f072005-10-12 15:32:05 -07001850 unlock_page(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001851 end_page_writeback(page);
Steve French84d2f072005-10-12 15:32:05 -07001852 break;
1853 }
1854
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001855 wdata->pages[i] = page;
Steve French37c0eb42005-10-05 14:50:29 -07001856 next = page->index + 1;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001857 ++nr_pages;
Steve French37c0eb42005-10-05 14:50:29 -07001858 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001859
1860 /* reset index to refind any pages skipped */
1861 if (nr_pages == 0)
1862 index = wdata->pages[0]->index + 1;
1863
1864 /* put any pages we aren't going to use */
1865 for (i = nr_pages; i < found_pages; i++) {
1866 page_cache_release(wdata->pages[i]);
1867 wdata->pages[i] = NULL;
1868 }
1869
1870 /* nothing to write? */
1871 if (nr_pages == 0) {
1872 kref_put(&wdata->refcount, cifs_writedata_release);
1873 continue;
1874 }
1875
1876 wdata->sync_mode = wbc->sync_mode;
1877 wdata->nr_pages = nr_pages;
1878 wdata->offset = page_offset(wdata->pages[0]);
Jeff Laytone9492872012-03-23 14:40:56 -04001879 wdata->marshal_iov = cifs_writepages_marshal_iov;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001880
1881 do {
1882 if (wdata->cfile != NULL)
1883 cifsFileInfo_put(wdata->cfile);
1884 wdata->cfile = find_writable_file(CIFS_I(mapping->host),
1885 false);
1886 if (!wdata->cfile) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001887 cERROR(1, "No writable handles for inode");
Steve French23e7dd72005-10-20 13:44:56 -07001888 rc = -EBADF;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001889 break;
Steve French37c0eb42005-10-05 14:50:29 -07001890 }
Jeff Laytonfe5f5d22012-03-23 14:40:55 -04001891 wdata->pid = wdata->cfile->pid;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001892 rc = cifs_async_writev(wdata);
1893 } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN);
Jeff Laytonf3983c22010-09-22 16:17:40 -07001894
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001895 for (i = 0; i < nr_pages; ++i)
1896 unlock_page(wdata->pages[i]);
Jeff Layton941b8532011-01-11 07:24:01 -05001897
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001898 /* send failure -- clean up the mess */
1899 if (rc != 0) {
1900 for (i = 0; i < nr_pages; ++i) {
Jeff Layton941b8532011-01-11 07:24:01 -05001901 if (rc == -EAGAIN)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001902 redirty_page_for_writepage(wbc,
1903 wdata->pages[i]);
1904 else
1905 SetPageError(wdata->pages[i]);
1906 end_page_writeback(wdata->pages[i]);
1907 page_cache_release(wdata->pages[i]);
Steve French37c0eb42005-10-05 14:50:29 -07001908 }
Jeff Layton941b8532011-01-11 07:24:01 -05001909 if (rc != -EAGAIN)
1910 mapping_set_error(mapping, rc);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001911 }
1912 kref_put(&wdata->refcount, cifs_writedata_release);
Jeff Layton941b8532011-01-11 07:24:01 -05001913
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001914 wbc->nr_to_write -= nr_pages;
1915 if (wbc->nr_to_write <= 0)
1916 done = true;
Dave Kleikampb066a482008-11-18 03:49:05 +00001917
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001918 index = next;
Steve French37c0eb42005-10-05 14:50:29 -07001919 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001920
Steve French37c0eb42005-10-05 14:50:29 -07001921 if (!scanned && !done) {
1922 /*
1923 * We hit the last page and there is more work to be done: wrap
1924 * back to the start of the file
1925 */
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001926 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001927 index = 0;
1928 goto retry;
1929 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001930
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001931 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
Steve French37c0eb42005-10-05 14:50:29 -07001932 mapping->writeback_index = index;
1933
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 return rc;
1935}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001937static int
1938cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939{
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001940 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001941 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001943 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944/* BB add check for wbc flags */
1945 page_cache_get(page);
Steve Frenchad7a2922008-02-07 23:25:02 +00001946 if (!PageUptodate(page))
Joe Perchesb6b38f72010-04-21 03:50:45 +00001947 cFYI(1, "ppw - page not up to date");
Linus Torvaldscb876f42006-12-23 16:19:07 -08001948
1949 /*
1950 * Set the "writeback" flag, and clear "dirty" in the radix tree.
1951 *
1952 * A writepage() implementation always needs to do either this,
1953 * or re-dirty the page with "redirty_page_for_writepage()" in
1954 * the case of a failure.
1955 *
1956 * Just unlocking the page will cause the radix tree tag-bits
1957 * to fail to update with the state of the page correctly.
1958 */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001959 set_page_writeback(page);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001960retry_write:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001962 if (rc == -EAGAIN && wbc->sync_mode == WB_SYNC_ALL)
1963 goto retry_write;
1964 else if (rc == -EAGAIN)
1965 redirty_page_for_writepage(wbc, page);
1966 else if (rc != 0)
1967 SetPageError(page);
1968 else
1969 SetPageUptodate(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001970 end_page_writeback(page);
1971 page_cache_release(page);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001972 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 return rc;
1974}
1975
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001976static int cifs_writepage(struct page *page, struct writeback_control *wbc)
1977{
1978 int rc = cifs_writepage_locked(page, wbc);
1979 unlock_page(page);
1980 return rc;
1981}
1982
Nick Piggind9414772008-09-24 11:32:59 -04001983static int cifs_write_end(struct file *file, struct address_space *mapping,
1984 loff_t pos, unsigned len, unsigned copied,
1985 struct page *page, void *fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986{
Nick Piggind9414772008-09-24 11:32:59 -04001987 int rc;
1988 struct inode *inode = mapping->host;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001989 struct cifsFileInfo *cfile = file->private_data;
1990 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
1991 __u32 pid;
1992
1993 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1994 pid = cfile->pid;
1995 else
1996 pid = current->tgid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997
Joe Perchesb6b38f72010-04-21 03:50:45 +00001998 cFYI(1, "write_end for page %p from pos %lld with %d bytes",
1999 page, pos, copied);
Steve Frenchad7a2922008-02-07 23:25:02 +00002000
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002001 if (PageChecked(page)) {
2002 if (copied == len)
2003 SetPageUptodate(page);
2004 ClearPageChecked(page);
2005 } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
Nick Piggind9414772008-09-24 11:32:59 -04002006 SetPageUptodate(page);
2007
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 if (!PageUptodate(page)) {
Nick Piggind9414772008-09-24 11:32:59 -04002009 char *page_data;
2010 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002011 unsigned int xid;
Nick Piggind9414772008-09-24 11:32:59 -04002012
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002013 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 /* this is probably better than directly calling
2015 partialpage_write since in this function the file handle is
2016 known which we might as well leverage */
2017 /* BB check if anything else missing out of ppw
2018 such as updating last write time */
2019 page_data = kmap(page);
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002020 rc = cifs_write(cfile, pid, page_data + offset, copied, &pos);
Nick Piggind9414772008-09-24 11:32:59 -04002021 /* if (rc < 0) should we set writebehind rc? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 kunmap(page);
Nick Piggind9414772008-09-24 11:32:59 -04002023
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002024 free_xid(xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002025 } else {
Nick Piggind9414772008-09-24 11:32:59 -04002026 rc = copied;
2027 pos += copied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 set_page_dirty(page);
2029 }
2030
Nick Piggind9414772008-09-24 11:32:59 -04002031 if (rc > 0) {
2032 spin_lock(&inode->i_lock);
2033 if (pos > inode->i_size)
2034 i_size_write(inode, pos);
2035 spin_unlock(&inode->i_lock);
2036 }
2037
2038 unlock_page(page);
2039 page_cache_release(page);
2040
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 return rc;
2042}
2043
Josef Bacik02c24a82011-07-16 20:44:56 -04002044int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
2045 int datasync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002047 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00002049 struct cifs_tcon *tcon;
Joe Perchesc21dfb62010-07-12 13:50:14 -07002050 struct cifsFileInfo *smbfile = file->private_data;
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002051 struct inode *inode = file->f_path.dentry->d_inode;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002052 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053
Josef Bacik02c24a82011-07-16 20:44:56 -04002054 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
2055 if (rc)
2056 return rc;
2057 mutex_lock(&inode->i_mutex);
2058
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002059 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060
Joe Perchesb6b38f72010-04-21 03:50:45 +00002061 cFYI(1, "Sync file - name: %s datasync: 0x%x",
Christoph Hellwig7ea80852010-05-26 17:53:25 +02002062 file->f_path.dentry->d_name.name, datasync);
Steve French50c2f752007-07-13 00:33:32 +00002063
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002064 if (!CIFS_I(inode)->clientCanCacheRead) {
2065 rc = cifs_invalidate_mapping(inode);
2066 if (rc) {
2067 cFYI(1, "rc: %d during invalidate phase", rc);
2068 rc = 0; /* don't care about it in fsync */
2069 }
2070 }
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002071
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002072 tcon = tlink_tcon(smbfile->tlink);
2073 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
2074 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
2075
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002076 free_xid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04002077 mutex_unlock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002078 return rc;
2079}
2080
Josef Bacik02c24a82011-07-16 20:44:56 -04002081int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002082{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002083 unsigned int xid;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002084 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00002085 struct cifs_tcon *tcon;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002086 struct cifsFileInfo *smbfile = file->private_data;
2087 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Josef Bacik02c24a82011-07-16 20:44:56 -04002088 struct inode *inode = file->f_mapping->host;
2089
2090 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
2091 if (rc)
2092 return rc;
2093 mutex_lock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002094
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002095 xid = get_xid();
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002096
2097 cFYI(1, "Sync file - name: %s datasync: 0x%x",
2098 file->f_path.dentry->d_name.name, datasync);
2099
2100 tcon = tlink_tcon(smbfile->tlink);
2101 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
2102 rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
Steve Frenchb298f222009-02-21 21:17:43 +00002103
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002104 free_xid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04002105 mutex_unlock(&inode->i_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 return rc;
2107}
2108
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109/*
2110 * As file closes, flush all cached write data for this inode checking
2111 * for write behind errors.
2112 */
Miklos Szeredi75e1fcc2006-06-23 02:05:12 -07002113int cifs_flush(struct file *file, fl_owner_t id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114{
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002115 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 int rc = 0;
2117
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002118 if (file->f_mode & FMODE_WRITE)
Jeff Laytond3f13222010-10-15 15:34:07 -04002119 rc = filemap_write_and_wait(inode->i_mapping);
Steve French50c2f752007-07-13 00:33:32 +00002120
Joe Perchesb6b38f72010-04-21 03:50:45 +00002121 cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122
2123 return rc;
2124}
2125
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002126static int
2127cifs_write_allocate_pages(struct page **pages, unsigned long num_pages)
2128{
2129 int rc = 0;
2130 unsigned long i;
2131
2132 for (i = 0; i < num_pages; i++) {
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002133 pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002134 if (!pages[i]) {
2135 /*
2136 * save number of pages we have already allocated and
2137 * return with ENOMEM error
2138 */
2139 num_pages = i;
2140 rc = -ENOMEM;
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002141 break;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002142 }
2143 }
2144
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002145 if (rc) {
2146 for (i = 0; i < num_pages; i++)
2147 put_page(pages[i]);
2148 }
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002149 return rc;
2150}
2151
2152static inline
2153size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
2154{
2155 size_t num_pages;
2156 size_t clen;
2157
2158 clen = min_t(const size_t, len, wsize);
Jeff Laytona7103b92012-03-23 14:40:56 -04002159 num_pages = DIV_ROUND_UP(clen, PAGE_SIZE);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002160
2161 if (cur_len)
2162 *cur_len = clen;
2163
2164 return num_pages;
2165}
2166
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002167static void
2168cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
2169{
2170 int i;
2171 size_t bytes = wdata->bytes;
2172
2173 /* marshal up the pages into iov array */
2174 for (i = 0; i < wdata->nr_pages; i++) {
Steve Frenchc7ad42b2012-03-23 16:30:56 -05002175 iov[i + 1].iov_len = min_t(size_t, bytes, PAGE_SIZE);
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002176 iov[i + 1].iov_base = kmap(wdata->pages[i]);
2177 bytes -= iov[i + 1].iov_len;
2178 }
2179}
2180
2181static void
2182cifs_uncached_writev_complete(struct work_struct *work)
2183{
2184 int i;
2185 struct cifs_writedata *wdata = container_of(work,
2186 struct cifs_writedata, work);
2187 struct inode *inode = wdata->cfile->dentry->d_inode;
2188 struct cifsInodeInfo *cifsi = CIFS_I(inode);
2189
2190 spin_lock(&inode->i_lock);
2191 cifs_update_eof(cifsi, wdata->offset, wdata->bytes);
2192 if (cifsi->server_eof > inode->i_size)
2193 i_size_write(inode, cifsi->server_eof);
2194 spin_unlock(&inode->i_lock);
2195
2196 complete(&wdata->done);
2197
2198 if (wdata->result != -EAGAIN) {
2199 for (i = 0; i < wdata->nr_pages; i++)
2200 put_page(wdata->pages[i]);
2201 }
2202
2203 kref_put(&wdata->refcount, cifs_writedata_release);
2204}
2205
2206/* attempt to send write to server, retry on any -EAGAIN errors */
2207static int
2208cifs_uncached_retry_writev(struct cifs_writedata *wdata)
2209{
2210 int rc;
2211
2212 do {
2213 if (wdata->cfile->invalidHandle) {
2214 rc = cifs_reopen_file(wdata->cfile, false);
2215 if (rc != 0)
2216 continue;
2217 }
2218 rc = cifs_async_writev(wdata);
2219 } while (rc == -EAGAIN);
2220
2221 return rc;
2222}
2223
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002224static ssize_t
2225cifs_iovec_write(struct file *file, const struct iovec *iov,
2226 unsigned long nr_segs, loff_t *poffset)
2227{
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002228 unsigned long nr_pages, i;
Pavel Shilovsky76429c12011-01-31 16:03:08 +03002229 size_t copied, len, cur_len;
2230 ssize_t total_written = 0;
Jeff Layton3af9d8f2012-04-13 17:16:59 -04002231 loff_t offset;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002232 struct iov_iter it;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002233 struct cifsFileInfo *open_file;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002234 struct cifs_tcon *tcon;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002235 struct cifs_sb_info *cifs_sb;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002236 struct cifs_writedata *wdata, *tmp;
2237 struct list_head wdata_list;
2238 int rc;
2239 pid_t pid;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002240
2241 len = iov_length(iov, nr_segs);
2242 if (!len)
2243 return 0;
2244
2245 rc = generic_write_checks(file, poffset, &len, 0);
2246 if (rc)
2247 return rc;
2248
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002249 INIT_LIST_HEAD(&wdata_list);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002250 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002251 open_file = file->private_data;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002252 tcon = tlink_tcon(open_file->tlink);
Jeff Layton3af9d8f2012-04-13 17:16:59 -04002253 offset = *poffset;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002254
2255 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2256 pid = open_file->pid;
2257 else
2258 pid = current->tgid;
2259
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002260 iov_iter_init(&it, iov, nr_segs, len, 0);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002261 do {
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002262 size_t save_len;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002263
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002264 nr_pages = get_numpages(cifs_sb->wsize, len, &cur_len);
2265 wdata = cifs_writedata_alloc(nr_pages,
2266 cifs_uncached_writev_complete);
2267 if (!wdata) {
2268 rc = -ENOMEM;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002269 break;
2270 }
2271
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002272 rc = cifs_write_allocate_pages(wdata->pages, nr_pages);
2273 if (rc) {
2274 kfree(wdata);
2275 break;
2276 }
2277
2278 save_len = cur_len;
2279 for (i = 0; i < nr_pages; i++) {
2280 copied = min_t(const size_t, cur_len, PAGE_SIZE);
2281 copied = iov_iter_copy_from_user(wdata->pages[i], &it,
2282 0, copied);
2283 cur_len -= copied;
2284 iov_iter_advance(&it, copied);
2285 }
2286 cur_len = save_len - cur_len;
2287
2288 wdata->sync_mode = WB_SYNC_ALL;
2289 wdata->nr_pages = nr_pages;
2290 wdata->offset = (__u64)offset;
2291 wdata->cfile = cifsFileInfo_get(open_file);
2292 wdata->pid = pid;
2293 wdata->bytes = cur_len;
2294 wdata->marshal_iov = cifs_uncached_marshal_iov;
2295 rc = cifs_uncached_retry_writev(wdata);
2296 if (rc) {
2297 kref_put(&wdata->refcount, cifs_writedata_release);
2298 break;
2299 }
2300
2301 list_add_tail(&wdata->list, &wdata_list);
2302 offset += cur_len;
2303 len -= cur_len;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002304 } while (len > 0);
2305
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002306 /*
2307 * If at least one write was successfully sent, then discard any rc
2308 * value from the later writes. If the other write succeeds, then
2309 * we'll end up returning whatever was written. If it fails, then
2310 * we'll get a new rc value from that.
2311 */
2312 if (!list_empty(&wdata_list))
2313 rc = 0;
2314
2315 /*
2316 * Wait for and collect replies for any successful sends in order of
2317 * increasing offset. Once an error is hit or we get a fatal signal
2318 * while waiting, then return without waiting for any more replies.
2319 */
2320restart_loop:
2321 list_for_each_entry_safe(wdata, tmp, &wdata_list, list) {
2322 if (!rc) {
2323 /* FIXME: freezable too? */
2324 rc = wait_for_completion_killable(&wdata->done);
2325 if (rc)
2326 rc = -EINTR;
2327 else if (wdata->result)
2328 rc = wdata->result;
2329 else
2330 total_written += wdata->bytes;
2331
2332 /* resend call if it's a retryable error */
2333 if (rc == -EAGAIN) {
2334 rc = cifs_uncached_retry_writev(wdata);
2335 goto restart_loop;
2336 }
2337 }
2338 list_del_init(&wdata->list);
2339 kref_put(&wdata->refcount, cifs_writedata_release);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002340 }
2341
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002342 if (total_written > 0)
2343 *poffset += total_written;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002344
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002345 cifs_stats_bytes_written(tcon, total_written);
2346 return total_written ? total_written : (ssize_t)rc;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002347}
2348
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03002349ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002350 unsigned long nr_segs, loff_t pos)
2351{
2352 ssize_t written;
2353 struct inode *inode;
2354
2355 inode = iocb->ki_filp->f_path.dentry->d_inode;
2356
2357 /*
2358 * BB - optimize the way when signing is disabled. We can drop this
2359 * extra memory-to-memory copying and use iovec buffers for constructing
2360 * write request.
2361 */
2362
2363 written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos);
2364 if (written > 0) {
2365 CIFS_I(inode)->invalid_mapping = true;
2366 iocb->ki_pos = pos;
2367 }
2368
2369 return written;
2370}
2371
2372ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
2373 unsigned long nr_segs, loff_t pos)
2374{
2375 struct inode *inode;
2376
2377 inode = iocb->ki_filp->f_path.dentry->d_inode;
2378
2379 if (CIFS_I(inode)->clientCanCacheAll)
2380 return generic_file_aio_write(iocb, iov, nr_segs, pos);
2381
2382 /*
2383 * In strict cache mode we need to write the data to the server exactly
2384 * from the pos to pos+len-1 rather than flush all affected pages
2385 * because it may cause a error with mandatory locks on these pages but
2386 * not on the region from pos to ppos+len-1.
2387 */
2388
2389 return cifs_user_writev(iocb, iov, nr_segs, pos);
2390}
2391
Jeff Layton0471ca32012-05-16 07:13:16 -04002392static struct cifs_readdata *
2393cifs_readdata_alloc(unsigned int nr_vecs, work_func_t complete)
2394{
2395 struct cifs_readdata *rdata;
2396
2397 rdata = kzalloc(sizeof(*rdata) +
2398 sizeof(struct kvec) * nr_vecs, GFP_KERNEL);
2399 if (rdata != NULL) {
Jeff Layton6993f742012-05-16 07:13:17 -04002400 kref_init(&rdata->refcount);
Jeff Layton1c892542012-05-16 07:13:17 -04002401 INIT_LIST_HEAD(&rdata->list);
2402 init_completion(&rdata->done);
Jeff Layton0471ca32012-05-16 07:13:16 -04002403 INIT_WORK(&rdata->work, complete);
2404 INIT_LIST_HEAD(&rdata->pages);
2405 }
2406 return rdata;
2407}
2408
Jeff Layton6993f742012-05-16 07:13:17 -04002409void
2410cifs_readdata_release(struct kref *refcount)
Jeff Layton0471ca32012-05-16 07:13:16 -04002411{
Jeff Layton6993f742012-05-16 07:13:17 -04002412 struct cifs_readdata *rdata = container_of(refcount,
2413 struct cifs_readdata, refcount);
2414
2415 if (rdata->cfile)
2416 cifsFileInfo_put(rdata->cfile);
2417
Jeff Layton0471ca32012-05-16 07:13:16 -04002418 kfree(rdata);
2419}
2420
Jeff Layton2a1bb132012-05-16 07:13:17 -04002421static int
Jeff Layton1c892542012-05-16 07:13:17 -04002422cifs_read_allocate_pages(struct list_head *list, unsigned int npages)
2423{
2424 int rc = 0;
2425 struct page *page, *tpage;
2426 unsigned int i;
2427
2428 for (i = 0; i < npages; i++) {
2429 page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
2430 if (!page) {
2431 rc = -ENOMEM;
2432 break;
2433 }
2434 list_add(&page->lru, list);
2435 }
2436
2437 if (rc) {
2438 list_for_each_entry_safe(page, tpage, list, lru) {
2439 list_del(&page->lru);
2440 put_page(page);
2441 }
2442 }
2443 return rc;
2444}
2445
2446static void
2447cifs_uncached_readdata_release(struct kref *refcount)
2448{
2449 struct page *page, *tpage;
2450 struct cifs_readdata *rdata = container_of(refcount,
2451 struct cifs_readdata, refcount);
2452
2453 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2454 list_del(&page->lru);
2455 put_page(page);
2456 }
2457 cifs_readdata_release(refcount);
2458}
2459
2460static int
Jeff Layton2a1bb132012-05-16 07:13:17 -04002461cifs_retry_async_readv(struct cifs_readdata *rdata)
2462{
2463 int rc;
2464
2465 do {
2466 if (rdata->cfile->invalidHandle) {
2467 rc = cifs_reopen_file(rdata->cfile, true);
2468 if (rc != 0)
2469 continue;
2470 }
2471 rc = cifs_async_readv(rdata);
2472 } while (rc == -EAGAIN);
2473
2474 return rc;
2475}
2476
Jeff Layton1c892542012-05-16 07:13:17 -04002477/**
2478 * cifs_readdata_to_iov - copy data from pages in response to an iovec
2479 * @rdata: the readdata response with list of pages holding data
2480 * @iov: vector in which we should copy the data
2481 * @nr_segs: number of segments in vector
2482 * @offset: offset into file of the first iovec
2483 * @copied: used to return the amount of data copied to the iov
2484 *
2485 * This function copies data from a list of pages in a readdata response into
2486 * an array of iovecs. It will first calculate where the data should go
2487 * based on the info in the readdata and then copy the data into that spot.
2488 */
2489static ssize_t
2490cifs_readdata_to_iov(struct cifs_readdata *rdata, const struct iovec *iov,
2491 unsigned long nr_segs, loff_t offset, ssize_t *copied)
2492{
2493 int rc = 0;
2494 struct iov_iter ii;
2495 size_t pos = rdata->offset - offset;
2496 struct page *page, *tpage;
2497 ssize_t remaining = rdata->bytes;
2498 unsigned char *pdata;
2499
2500 /* set up iov_iter and advance to the correct offset */
2501 iov_iter_init(&ii, iov, nr_segs, iov_length(iov, nr_segs), 0);
2502 iov_iter_advance(&ii, pos);
2503
2504 *copied = 0;
2505 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2506 ssize_t copy;
2507
2508 /* copy a whole page or whatever's left */
2509 copy = min_t(ssize_t, remaining, PAGE_SIZE);
2510
2511 /* ...but limit it to whatever space is left in the iov */
2512 copy = min_t(ssize_t, copy, iov_iter_count(&ii));
2513
2514 /* go while there's data to be copied and no errors */
2515 if (copy && !rc) {
2516 pdata = kmap(page);
2517 rc = memcpy_toiovecend(ii.iov, pdata, ii.iov_offset,
2518 (int)copy);
2519 kunmap(page);
2520 if (!rc) {
2521 *copied += copy;
2522 remaining -= copy;
2523 iov_iter_advance(&ii, copy);
2524 }
2525 }
2526
2527 list_del(&page->lru);
2528 put_page(page);
2529 }
2530
2531 return rc;
2532}
2533
2534static void
2535cifs_uncached_readv_complete(struct work_struct *work)
2536{
2537 struct cifs_readdata *rdata = container_of(work,
2538 struct cifs_readdata, work);
2539
2540 /* if the result is non-zero then the pages weren't kmapped */
2541 if (rdata->result == 0) {
2542 struct page *page;
2543
2544 list_for_each_entry(page, &rdata->pages, lru)
2545 kunmap(page);
2546 }
2547
2548 complete(&rdata->done);
2549 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
2550}
2551
2552static int
2553cifs_uncached_read_marshal_iov(struct cifs_readdata *rdata,
2554 unsigned int remaining)
2555{
2556 int len = 0;
2557 struct page *page, *tpage;
2558
2559 rdata->nr_iov = 1;
2560 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2561 if (remaining >= PAGE_SIZE) {
2562 /* enough data to fill the page */
2563 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2564 rdata->iov[rdata->nr_iov].iov_len = PAGE_SIZE;
2565 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2566 rdata->nr_iov, page->index,
2567 rdata->iov[rdata->nr_iov].iov_base,
2568 rdata->iov[rdata->nr_iov].iov_len);
2569 ++rdata->nr_iov;
2570 len += PAGE_SIZE;
2571 remaining -= PAGE_SIZE;
2572 } else if (remaining > 0) {
2573 /* enough for partial page, fill and zero the rest */
2574 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2575 rdata->iov[rdata->nr_iov].iov_len = remaining;
2576 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2577 rdata->nr_iov, page->index,
2578 rdata->iov[rdata->nr_iov].iov_base,
2579 rdata->iov[rdata->nr_iov].iov_len);
2580 memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
2581 '\0', PAGE_SIZE - remaining);
2582 ++rdata->nr_iov;
2583 len += remaining;
2584 remaining = 0;
2585 } else {
2586 /* no need to hold page hostage */
2587 list_del(&page->lru);
2588 put_page(page);
2589 }
2590 }
2591
2592 return len;
2593}
2594
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002595static ssize_t
2596cifs_iovec_read(struct file *file, const struct iovec *iov,
2597 unsigned long nr_segs, loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598{
Jeff Layton1c892542012-05-16 07:13:17 -04002599 ssize_t rc;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002600 size_t len, cur_len;
Jeff Layton1c892542012-05-16 07:13:17 -04002601 ssize_t total_read = 0;
2602 loff_t offset = *poffset;
2603 unsigned int npages;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 struct cifs_sb_info *cifs_sb;
Jeff Layton1c892542012-05-16 07:13:17 -04002605 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 struct cifsFileInfo *open_file;
Jeff Layton1c892542012-05-16 07:13:17 -04002607 struct cifs_readdata *rdata, *tmp;
2608 struct list_head rdata_list;
2609 pid_t pid;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002610
2611 if (!nr_segs)
2612 return 0;
2613
2614 len = iov_length(iov, nr_segs);
2615 if (!len)
2616 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617
Jeff Layton1c892542012-05-16 07:13:17 -04002618 INIT_LIST_HEAD(&rdata_list);
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002619 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -07002620 open_file = file->private_data;
Jeff Layton1c892542012-05-16 07:13:17 -04002621 tcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002623 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2624 pid = open_file->pid;
2625 else
2626 pid = current->tgid;
2627
Steve Frenchad7a2922008-02-07 23:25:02 +00002628 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002629 cFYI(1, "attempting read on write only file instance");
Steve Frenchad7a2922008-02-07 23:25:02 +00002630
Jeff Layton1c892542012-05-16 07:13:17 -04002631 do {
2632 cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize);
2633 npages = DIV_ROUND_UP(cur_len, PAGE_SIZE);
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002634
Jeff Layton1c892542012-05-16 07:13:17 -04002635 /* allocate a readdata struct */
2636 rdata = cifs_readdata_alloc(npages,
2637 cifs_uncached_readv_complete);
2638 if (!rdata) {
2639 rc = -ENOMEM;
2640 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002642
Jeff Layton1c892542012-05-16 07:13:17 -04002643 rc = cifs_read_allocate_pages(&rdata->pages, npages);
2644 if (rc)
2645 goto error;
2646
2647 rdata->cfile = cifsFileInfo_get(open_file);
2648 rdata->offset = offset;
2649 rdata->bytes = cur_len;
2650 rdata->pid = pid;
2651 rdata->marshal_iov = cifs_uncached_read_marshal_iov;
2652
2653 rc = cifs_retry_async_readv(rdata);
2654error:
2655 if (rc) {
2656 kref_put(&rdata->refcount,
2657 cifs_uncached_readdata_release);
2658 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 }
Jeff Layton1c892542012-05-16 07:13:17 -04002660
2661 list_add_tail(&rdata->list, &rdata_list);
2662 offset += cur_len;
2663 len -= cur_len;
2664 } while (len > 0);
2665
2666 /* if at least one read request send succeeded, then reset rc */
2667 if (!list_empty(&rdata_list))
2668 rc = 0;
2669
2670 /* the loop below should proceed in the order of increasing offsets */
2671restart_loop:
2672 list_for_each_entry_safe(rdata, tmp, &rdata_list, list) {
2673 if (!rc) {
2674 ssize_t copied;
2675
2676 /* FIXME: freezable sleep too? */
2677 rc = wait_for_completion_killable(&rdata->done);
2678 if (rc)
2679 rc = -EINTR;
2680 else if (rdata->result)
2681 rc = rdata->result;
2682 else {
2683 rc = cifs_readdata_to_iov(rdata, iov,
2684 nr_segs, *poffset,
2685 &copied);
2686 total_read += copied;
2687 }
2688
2689 /* resend call if it's a retryable error */
2690 if (rc == -EAGAIN) {
2691 rc = cifs_retry_async_readv(rdata);
2692 goto restart_loop;
2693 }
2694 }
2695 list_del_init(&rdata->list);
2696 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002698
Jeff Layton1c892542012-05-16 07:13:17 -04002699 cifs_stats_bytes_read(tcon, total_read);
2700 *poffset += total_read;
2701
2702 return total_read ? total_read : rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703}
2704
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03002705ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002706 unsigned long nr_segs, loff_t pos)
2707{
2708 ssize_t read;
2709
2710 read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos);
2711 if (read > 0)
2712 iocb->ki_pos = pos;
2713
2714 return read;
2715}
2716
2717ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov,
2718 unsigned long nr_segs, loff_t pos)
2719{
2720 struct inode *inode;
2721
2722 inode = iocb->ki_filp->f_path.dentry->d_inode;
2723
2724 if (CIFS_I(inode)->clientCanCacheRead)
2725 return generic_file_aio_read(iocb, iov, nr_segs, pos);
2726
2727 /*
2728 * In strict cache mode we need to read from the server all the time
2729 * if we don't have level II oplock because the server can delay mtime
2730 * change - so we can't make a decision about inode invalidating.
2731 * And we can also fail with pagereading if there are mandatory locks
2732 * on pages affected by this read but not on the region from pos to
2733 * pos+len-1.
2734 */
2735
2736 return cifs_user_readv(iocb, iov, nr_segs, pos);
2737}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738
2739static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002740 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741{
2742 int rc = -EACCES;
2743 unsigned int bytes_read = 0;
2744 unsigned int total_read;
2745 unsigned int current_read_size;
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002746 unsigned int rsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00002748 struct cifs_tcon *pTcon;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002749 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 char *current_offset;
2751 struct cifsFileInfo *open_file;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002752 struct cifs_io_parms io_parms;
Steve Frenchec637e32005-12-12 20:53:18 -08002753 int buf_type = CIFS_NO_BUFFER;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002754 __u32 pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002756 xid = get_xid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002757 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002759 /* FIXME: set up handlers for larger reads and/or convert to async */
2760 rsize = min_t(unsigned int, cifs_sb->rsize, CIFSMaxBufSize);
2761
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302763 rc = -EBADF;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002764 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302765 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 }
Joe Perchesc21dfb62010-07-12 13:50:14 -07002767 open_file = file->private_data;
Jeff Layton13cfb732010-09-29 19:51:11 -04002768 pTcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002770 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2771 pid = open_file->pid;
2772 else
2773 pid = current->tgid;
2774
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002776 cFYI(1, "attempting read on write only file instance");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002778 for (total_read = 0, current_offset = read_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779 read_size > total_read;
2780 total_read += bytes_read, current_offset += bytes_read) {
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002781 current_read_size = min_t(uint, read_size - total_read, rsize);
2782
Steve Frenchf9f5c8172005-09-15 23:06:38 -07002783 /* For windows me and 9x we do not want to request more
2784 than it negotiated since it will refuse the read then */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002785 if ((pTcon->ses) &&
Steve Frenchf9f5c8172005-09-15 23:06:38 -07002786 !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
Dan Carpenter7748dd62011-10-18 12:41:35 +03002787 current_read_size = min_t(uint, current_read_size,
Jeff Laytonc974bef2011-10-11 06:41:32 -04002788 CIFSMaxBufSize);
Steve Frenchf9f5c8172005-09-15 23:06:38 -07002789 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 rc = -EAGAIN;
2791 while (rc == -EAGAIN) {
Steve Frenchcdff08e2010-10-21 22:46:14 +00002792 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04002793 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 if (rc != 0)
2795 break;
2796 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002797 io_parms.netfid = open_file->netfid;
2798 io_parms.pid = pid;
2799 io_parms.tcon = pTcon;
2800 io_parms.offset = *poffset;
2801 io_parms.length = current_read_size;
2802 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
2803 &current_offset, &buf_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804 }
2805 if (rc || (bytes_read == 0)) {
2806 if (total_read) {
2807 break;
2808 } else {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002809 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810 return rc;
2811 }
2812 } else {
Steve Frencha4544342005-08-24 13:59:35 -07002813 cifs_stats_bytes_read(pTcon, total_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814 *poffset += bytes_read;
2815 }
2816 }
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002817 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818 return total_read;
2819}
2820
Jeff Laytonca83ce32011-04-12 09:13:44 -04002821/*
2822 * If the page is mmap'ed into a process' page tables, then we need to make
2823 * sure that it doesn't change while being written back.
2824 */
2825static int
2826cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
2827{
2828 struct page *page = vmf->page;
2829
2830 lock_page(page);
2831 return VM_FAULT_LOCKED;
2832}
2833
2834static struct vm_operations_struct cifs_file_vm_ops = {
2835 .fault = filemap_fault,
2836 .page_mkwrite = cifs_page_mkwrite,
2837};
2838
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002839int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
2840{
2841 int rc, xid;
2842 struct inode *inode = file->f_path.dentry->d_inode;
2843
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002844 xid = get_xid();
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002845
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002846 if (!CIFS_I(inode)->clientCanCacheRead) {
2847 rc = cifs_invalidate_mapping(inode);
2848 if (rc)
2849 return rc;
2850 }
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002851
2852 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04002853 if (rc == 0)
2854 vma->vm_ops = &cifs_file_vm_ops;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002855 free_xid(xid);
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002856 return rc;
2857}
2858
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
2860{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861 int rc, xid;
2862
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002863 xid = get_xid();
Jeff Laytonabab0952010-02-12 07:44:18 -05002864 rc = cifs_revalidate_file(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002866 cFYI(1, "Validation prior to mmap failed, error=%d", rc);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002867 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868 return rc;
2869 }
2870 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04002871 if (rc == 0)
2872 vma->vm_ops = &cifs_file_vm_ops;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002873 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874 return rc;
2875}
2876
Jeff Layton0471ca32012-05-16 07:13:16 -04002877static void
2878cifs_readv_complete(struct work_struct *work)
2879{
2880 struct cifs_readdata *rdata = container_of(work,
2881 struct cifs_readdata, work);
2882 struct page *page, *tpage;
2883
2884 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2885 list_del(&page->lru);
2886 lru_cache_add_file(page);
2887
2888 if (rdata->result == 0) {
2889 kunmap(page);
2890 flush_dcache_page(page);
2891 SetPageUptodate(page);
2892 }
2893
2894 unlock_page(page);
2895
2896 if (rdata->result == 0)
2897 cifs_readpage_to_fscache(rdata->mapping->host, page);
2898
2899 page_cache_release(page);
2900 }
Jeff Layton6993f742012-05-16 07:13:17 -04002901 kref_put(&rdata->refcount, cifs_readdata_release);
Jeff Layton0471ca32012-05-16 07:13:16 -04002902}
2903
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04002904static int
2905cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining)
2906{
2907 int len = 0;
2908 struct page *page, *tpage;
2909 u64 eof;
2910 pgoff_t eof_index;
2911
2912 /* determine the eof that the server (probably) has */
2913 eof = CIFS_I(rdata->mapping->host)->server_eof;
2914 eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
2915 cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
2916
2917 rdata->nr_iov = 1;
2918 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2919 if (remaining >= PAGE_CACHE_SIZE) {
2920 /* enough data to fill the page */
2921 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2922 rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE;
2923 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2924 rdata->nr_iov, page->index,
2925 rdata->iov[rdata->nr_iov].iov_base,
2926 rdata->iov[rdata->nr_iov].iov_len);
2927 ++rdata->nr_iov;
2928 len += PAGE_CACHE_SIZE;
2929 remaining -= PAGE_CACHE_SIZE;
2930 } else if (remaining > 0) {
2931 /* enough for partial page, fill and zero the rest */
2932 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2933 rdata->iov[rdata->nr_iov].iov_len = remaining;
2934 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2935 rdata->nr_iov, page->index,
2936 rdata->iov[rdata->nr_iov].iov_base,
2937 rdata->iov[rdata->nr_iov].iov_len);
2938 memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
2939 '\0', PAGE_CACHE_SIZE - remaining);
2940 ++rdata->nr_iov;
2941 len += remaining;
2942 remaining = 0;
2943 } else if (page->index > eof_index) {
2944 /*
2945 * The VFS will not try to do readahead past the
2946 * i_size, but it's possible that we have outstanding
2947 * writes with gaps in the middle and the i_size hasn't
2948 * caught up yet. Populate those with zeroed out pages
2949 * to prevent the VFS from repeatedly attempting to
2950 * fill them until the writes are flushed.
2951 */
2952 zero_user(page, 0, PAGE_CACHE_SIZE);
2953 list_del(&page->lru);
2954 lru_cache_add_file(page);
2955 flush_dcache_page(page);
2956 SetPageUptodate(page);
2957 unlock_page(page);
2958 page_cache_release(page);
2959 } else {
2960 /* no need to hold page hostage */
2961 list_del(&page->lru);
2962 lru_cache_add_file(page);
2963 unlock_page(page);
2964 page_cache_release(page);
2965 }
2966 }
2967
2968 return len;
2969}
2970
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971static int cifs_readpages(struct file *file, struct address_space *mapping,
2972 struct list_head *page_list, unsigned num_pages)
2973{
Jeff Layton690c5e32011-10-19 15:30:16 -04002974 int rc;
2975 struct list_head tmplist;
2976 struct cifsFileInfo *open_file = file->private_data;
2977 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
2978 unsigned int rsize = cifs_sb->rsize;
2979 pid_t pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980
Jeff Layton690c5e32011-10-19 15:30:16 -04002981 /*
2982 * Give up immediately if rsize is too small to read an entire page.
2983 * The VFS will fall back to readpage. We should never reach this
2984 * point however since we set ra_pages to 0 when the rsize is smaller
2985 * than a cache page.
2986 */
2987 if (unlikely(rsize < PAGE_CACHE_SIZE))
2988 return 0;
Steve Frenchbfa0d752005-08-31 21:50:37 -07002989
Suresh Jayaraman56698232010-07-05 18:13:25 +05302990 /*
2991 * Reads as many pages as possible from fscache. Returns -ENOBUFS
2992 * immediately if the cookie is negative
2993 */
2994 rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
2995 &num_pages);
2996 if (rc == 0)
Jeff Layton690c5e32011-10-19 15:30:16 -04002997 return rc;
Suresh Jayaraman56698232010-07-05 18:13:25 +05302998
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002999 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
3000 pid = open_file->pid;
3001 else
3002 pid = current->tgid;
3003
Jeff Layton690c5e32011-10-19 15:30:16 -04003004 rc = 0;
3005 INIT_LIST_HEAD(&tmplist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006
Jeff Layton690c5e32011-10-19 15:30:16 -04003007 cFYI(1, "%s: file=%p mapping=%p num_pages=%u", __func__, file,
3008 mapping, num_pages);
3009
3010 /*
3011 * Start with the page at end of list and move it to private
3012 * list. Do the same with any following pages until we hit
3013 * the rsize limit, hit an index discontinuity, or run out of
3014 * pages. Issue the async read and then start the loop again
3015 * until the list is empty.
3016 *
3017 * Note that list order is important. The page_list is in
3018 * the order of declining indexes. When we put the pages in
3019 * the rdata->pages, then we want them in increasing order.
3020 */
3021 while (!list_empty(page_list)) {
3022 unsigned int bytes = PAGE_CACHE_SIZE;
3023 unsigned int expected_index;
3024 unsigned int nr_pages = 1;
3025 loff_t offset;
3026 struct page *page, *tpage;
3027 struct cifs_readdata *rdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028
3029 page = list_entry(page_list->prev, struct page, lru);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030
Jeff Layton690c5e32011-10-19 15:30:16 -04003031 /*
3032 * Lock the page and put it in the cache. Since no one else
3033 * should have access to this page, we're safe to simply set
3034 * PG_locked without checking it first.
3035 */
3036 __set_page_locked(page);
3037 rc = add_to_page_cache_locked(page, mapping,
3038 page->index, GFP_KERNEL);
3039
3040 /* give up if we can't stick it in the cache */
3041 if (rc) {
3042 __clear_page_locked(page);
3043 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045
Jeff Layton690c5e32011-10-19 15:30:16 -04003046 /* move first page to the tmplist */
3047 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
3048 list_move_tail(&page->lru, &tmplist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049
Jeff Layton690c5e32011-10-19 15:30:16 -04003050 /* now try and add more pages onto the request */
3051 expected_index = page->index + 1;
3052 list_for_each_entry_safe_reverse(page, tpage, page_list, lru) {
3053 /* discontinuity ? */
3054 if (page->index != expected_index)
3055 break;
3056
3057 /* would this page push the read over the rsize? */
3058 if (bytes + PAGE_CACHE_SIZE > rsize)
3059 break;
3060
3061 __set_page_locked(page);
3062 if (add_to_page_cache_locked(page, mapping,
3063 page->index, GFP_KERNEL)) {
3064 __clear_page_locked(page);
3065 break;
3066 }
3067 list_move_tail(&page->lru, &tmplist);
3068 bytes += PAGE_CACHE_SIZE;
3069 expected_index++;
3070 nr_pages++;
3071 }
3072
Jeff Layton0471ca32012-05-16 07:13:16 -04003073 rdata = cifs_readdata_alloc(nr_pages, cifs_readv_complete);
Jeff Layton690c5e32011-10-19 15:30:16 -04003074 if (!rdata) {
3075 /* best to give up if we're out of mem */
3076 list_for_each_entry_safe(page, tpage, &tmplist, lru) {
3077 list_del(&page->lru);
3078 lru_cache_add_file(page);
3079 unlock_page(page);
3080 page_cache_release(page);
3081 }
3082 rc = -ENOMEM;
3083 break;
3084 }
3085
3086 spin_lock(&cifs_file_list_lock);
Jeff Layton690c5e32011-10-19 15:30:16 -04003087 spin_unlock(&cifs_file_list_lock);
Jeff Layton6993f742012-05-16 07:13:17 -04003088 rdata->cfile = cifsFileInfo_get(open_file);
Jeff Layton690c5e32011-10-19 15:30:16 -04003089 rdata->mapping = mapping;
3090 rdata->offset = offset;
3091 rdata->bytes = bytes;
3092 rdata->pid = pid;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003093 rdata->marshal_iov = cifs_readpages_marshal_iov;
Jeff Layton690c5e32011-10-19 15:30:16 -04003094 list_splice_init(&tmplist, &rdata->pages);
3095
Jeff Layton2a1bb132012-05-16 07:13:17 -04003096 rc = cifs_retry_async_readv(rdata);
Jeff Layton690c5e32011-10-19 15:30:16 -04003097 if (rc != 0) {
3098 list_for_each_entry_safe(page, tpage, &rdata->pages,
3099 lru) {
3100 list_del(&page->lru);
3101 lru_cache_add_file(page);
3102 unlock_page(page);
3103 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104 }
Jeff Layton6993f742012-05-16 07:13:17 -04003105 kref_put(&rdata->refcount, cifs_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106 break;
3107 }
Jeff Layton6993f742012-05-16 07:13:17 -04003108
3109 kref_put(&rdata->refcount, cifs_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 }
3111
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112 return rc;
3113}
3114
3115static int cifs_readpage_worker(struct file *file, struct page *page,
3116 loff_t *poffset)
3117{
3118 char *read_data;
3119 int rc;
3120
Suresh Jayaraman56698232010-07-05 18:13:25 +05303121 /* Is the page cached? */
3122 rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page);
3123 if (rc == 0)
3124 goto read_complete;
3125
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126 page_cache_get(page);
3127 read_data = kmap(page);
3128 /* for reads over a certain size could initiate async read ahead */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003129
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003131
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 if (rc < 0)
3133 goto io_error;
3134 else
Joe Perchesb6b38f72010-04-21 03:50:45 +00003135 cFYI(1, "Bytes read %d", rc);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003136
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08003137 file->f_path.dentry->d_inode->i_atime =
3138 current_fs_time(file->f_path.dentry->d_inode->i_sb);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003139
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 if (PAGE_CACHE_SIZE > rc)
3141 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
3142
3143 flush_dcache_page(page);
3144 SetPageUptodate(page);
Suresh Jayaraman9dc06552010-07-05 18:13:11 +05303145
3146 /* send this page to the cache */
3147 cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page);
3148
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149 rc = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003150
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151io_error:
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003152 kunmap(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153 page_cache_release(page);
Suresh Jayaraman56698232010-07-05 18:13:25 +05303154
3155read_complete:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156 return rc;
3157}
3158
3159static int cifs_readpage(struct file *file, struct page *page)
3160{
3161 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
3162 int rc = -EACCES;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003163 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003165 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166
3167 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05303168 rc = -EBADF;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003169 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05303170 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171 }
3172
Jeff Laytonac3aa2f2012-07-23 13:14:28 -04003173 cFYI(1, "readpage %p at offset %d 0x%x",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003174 page, (int)offset, (int)offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175
3176 rc = cifs_readpage_worker(file, page, &offset);
3177
3178 unlock_page(page);
3179
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003180 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181 return rc;
3182}
3183
Steve Frencha403a0a2007-07-26 15:54:16 +00003184static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
3185{
3186 struct cifsFileInfo *open_file;
3187
Jeff Layton44772882010-10-15 15:34:03 -04003188 spin_lock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003189 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton2e396b82010-10-15 15:34:01 -04003190 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Jeff Layton44772882010-10-15 15:34:03 -04003191 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003192 return 1;
3193 }
3194 }
Jeff Layton44772882010-10-15 15:34:03 -04003195 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003196 return 0;
3197}
3198
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199/* We do not want to update the file size from server for inodes
3200 open for write - to avoid races with writepage extending
3201 the file - in the future we could consider allowing
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003202 refreshing the inode only on increases in the file size
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203 but this is tricky to do without racing with writebehind
3204 page caching in the current Linux kernel design */
Steve French4b18f2a2008-04-29 00:06:05 +00003205bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206{
Steve Frencha403a0a2007-07-26 15:54:16 +00003207 if (!cifsInode)
Steve French4b18f2a2008-04-29 00:06:05 +00003208 return true;
Steve French23e7dd72005-10-20 13:44:56 -07003209
Steve Frencha403a0a2007-07-26 15:54:16 +00003210 if (is_inode_writable(cifsInode)) {
3211 /* This inode is open for write at least once */
Steve Frenchc32a0b62006-01-12 14:41:28 -08003212 struct cifs_sb_info *cifs_sb;
3213
Steve Frenchc32a0b62006-01-12 14:41:28 -08003214 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
Steve Frenchad7a2922008-02-07 23:25:02 +00003215 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003216 /* since no page cache to corrupt on directio
Steve Frenchc32a0b62006-01-12 14:41:28 -08003217 we can change size safely */
Steve French4b18f2a2008-04-29 00:06:05 +00003218 return true;
Steve Frenchc32a0b62006-01-12 14:41:28 -08003219 }
3220
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003221 if (i_size_read(&cifsInode->vfs_inode) < end_of_file)
Steve French4b18f2a2008-04-29 00:06:05 +00003222 return true;
Steve French7ba52632007-02-08 18:14:13 +00003223
Steve French4b18f2a2008-04-29 00:06:05 +00003224 return false;
Steve French23e7dd72005-10-20 13:44:56 -07003225 } else
Steve French4b18f2a2008-04-29 00:06:05 +00003226 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227}
3228
Nick Piggind9414772008-09-24 11:32:59 -04003229static int cifs_write_begin(struct file *file, struct address_space *mapping,
3230 loff_t pos, unsigned len, unsigned flags,
3231 struct page **pagep, void **fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232{
Nick Piggind9414772008-09-24 11:32:59 -04003233 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
3234 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003235 loff_t page_start = pos & PAGE_MASK;
3236 loff_t i_size;
3237 struct page *page;
3238 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239
Joe Perchesb6b38f72010-04-21 03:50:45 +00003240 cFYI(1, "write_begin from %lld len %d", (long long)pos, len);
Nick Piggind9414772008-09-24 11:32:59 -04003241
Nick Piggin54566b22009-01-04 12:00:53 -08003242 page = grab_cache_page_write_begin(mapping, index, flags);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003243 if (!page) {
3244 rc = -ENOMEM;
3245 goto out;
3246 }
Nick Piggind9414772008-09-24 11:32:59 -04003247
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003248 if (PageUptodate(page))
3249 goto out;
Steve French8a236262007-03-06 00:31:00 +00003250
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003251 /*
3252 * If we write a full page it will be up to date, no need to read from
3253 * the server. If the write is short, we'll end up doing a sync write
3254 * instead.
3255 */
3256 if (len == PAGE_CACHE_SIZE)
3257 goto out;
3258
3259 /*
3260 * optimize away the read when we have an oplock, and we're not
3261 * expecting to use any of the data we'd be reading in. That
3262 * is, when the page lies beyond the EOF, or straddles the EOF
3263 * and the write will cover all of the existing data.
3264 */
3265 if (CIFS_I(mapping->host)->clientCanCacheRead) {
3266 i_size = i_size_read(mapping->host);
3267 if (page_start >= i_size ||
3268 (offset == 0 && (pos + len) >= i_size)) {
3269 zero_user_segments(page, 0, offset,
3270 offset + len,
3271 PAGE_CACHE_SIZE);
3272 /*
3273 * PageChecked means that the parts of the page
3274 * to which we're not writing are considered up
3275 * to date. Once the data is copied to the
3276 * page, it can be set uptodate.
3277 */
3278 SetPageChecked(page);
3279 goto out;
3280 }
3281 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282
Nick Piggind9414772008-09-24 11:32:59 -04003283 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003284 /*
3285 * might as well read a page, it is fast enough. If we get
3286 * an error, we don't need to return it. cifs_write_end will
3287 * do a sync write instead since PG_uptodate isn't set.
3288 */
3289 cifs_readpage_worker(file, page, &page_start);
Steve French8a236262007-03-06 00:31:00 +00003290 } else {
3291 /* we could try using another file handle if there is one -
3292 but how would we lock it to prevent close of that handle
3293 racing with this read? In any case
Nick Piggind9414772008-09-24 11:32:59 -04003294 this will be written out by write_end so is fine */
Steve French8a236262007-03-06 00:31:00 +00003295 }
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003296out:
3297 *pagep = page;
3298 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299}
3300
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303301static int cifs_release_page(struct page *page, gfp_t gfp)
3302{
3303 if (PagePrivate(page))
3304 return 0;
3305
3306 return cifs_fscache_release_page(page, gfp);
3307}
3308
3309static void cifs_invalidate_page(struct page *page, unsigned long offset)
3310{
3311 struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
3312
3313 if (offset == 0)
3314 cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
3315}
3316
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003317static int cifs_launder_page(struct page *page)
3318{
3319 int rc = 0;
3320 loff_t range_start = page_offset(page);
3321 loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
3322 struct writeback_control wbc = {
3323 .sync_mode = WB_SYNC_ALL,
3324 .nr_to_write = 0,
3325 .range_start = range_start,
3326 .range_end = range_end,
3327 };
3328
3329 cFYI(1, "Launder page: %p", page);
3330
3331 if (clear_page_dirty_for_io(page))
3332 rc = cifs_writepage_locked(page, &wbc);
3333
3334 cifs_fscache_invalidate_page(page, page->mapping->host);
3335 return rc;
3336}
3337
Tejun Heo9b646972010-07-20 22:09:02 +02003338void cifs_oplock_break(struct work_struct *work)
Jeff Layton3bc303c2009-09-21 06:47:50 -04003339{
3340 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
3341 oplock_break);
Jeff Laytona5e18bc2010-10-11 15:07:18 -04003342 struct inode *inode = cfile->dentry->d_inode;
Jeff Layton3bc303c2009-09-21 06:47:50 -04003343 struct cifsInodeInfo *cinode = CIFS_I(inode);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04003344 int rc = 0;
Jeff Layton3bc303c2009-09-21 06:47:50 -04003345
3346 if (inode && S_ISREG(inode->i_mode)) {
Steve Frenchd54ff732010-04-27 04:38:15 +00003347 if (cinode->clientCanCacheRead)
Al Viro8737c932009-12-24 06:47:55 -05003348 break_lease(inode, O_RDONLY);
Steve Frenchd54ff732010-04-27 04:38:15 +00003349 else
Al Viro8737c932009-12-24 06:47:55 -05003350 break_lease(inode, O_WRONLY);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003351 rc = filemap_fdatawrite(inode->i_mapping);
3352 if (cinode->clientCanCacheRead == 0) {
Jeff Laytoneb4b7562010-10-22 14:52:29 -04003353 rc = filemap_fdatawait(inode->i_mapping);
3354 mapping_set_error(inode->i_mapping, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003355 invalidate_remote_inode(inode);
3356 }
Joe Perchesb6b38f72010-04-21 03:50:45 +00003357 cFYI(1, "Oplock flush inode %p rc %d", inode, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003358 }
3359
Pavel Shilovsky85160e02011-10-22 15:33:29 +04003360 rc = cifs_push_locks(cfile);
3361 if (rc)
3362 cERROR(1, "Push locks rc = %d", rc);
3363
Jeff Layton3bc303c2009-09-21 06:47:50 -04003364 /*
3365 * releasing stale oplock after recent reconnect of smb session using
3366 * a now incorrect file handle is not a data integrity issue but do
3367 * not bother sending an oplock release if session to server still is
3368 * disconnected since oplock already released by the server
3369 */
Steve Frenchcdff08e2010-10-21 22:46:14 +00003370 if (!cfile->oplock_break_cancelled) {
Pavel Shilovsky03776f42010-08-17 11:26:00 +04003371 rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid,
3372 current->tgid, 0, 0, 0, 0,
3373 LOCKING_ANDX_OPLOCK_RELEASE, false,
Pavel Shilovsky12fed002011-01-17 20:15:44 +03003374 cinode->clientCanCacheRead ? 1 : 0);
Joe Perchesb6b38f72010-04-21 03:50:45 +00003375 cFYI(1, "Oplock release rc = %d", rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003376 }
Jeff Layton3bc303c2009-09-21 06:47:50 -04003377}
3378
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07003379const struct address_space_operations cifs_addr_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380 .readpage = cifs_readpage,
3381 .readpages = cifs_readpages,
3382 .writepage = cifs_writepage,
Steve French37c0eb42005-10-05 14:50:29 -07003383 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04003384 .write_begin = cifs_write_begin,
3385 .write_end = cifs_write_end,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303387 .releasepage = cifs_release_page,
3388 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003389 .launder_page = cifs_launder_page,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390};
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003391
3392/*
3393 * cifs_readpages requires the server to support a buffer large enough to
3394 * contain the header plus one complete page of data. Otherwise, we need
3395 * to leave cifs_readpages out of the address space operations.
3396 */
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07003397const struct address_space_operations cifs_addr_ops_smallbuf = {
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003398 .readpage = cifs_readpage,
3399 .writepage = cifs_writepage,
3400 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04003401 .write_begin = cifs_write_begin,
3402 .write_end = cifs_write_end,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003403 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303404 .releasepage = cifs_release_page,
3405 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003406 .launder_page = cifs_launder_page,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003407};