blob: 1246cf74e1fb4220502127d448f612a910110d89 [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,
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700172 struct cifs_tcon *tcon, unsigned int f_flags, __u32 *oplock,
173 struct cifs_fid *fid, unsigned int xid)
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300174{
175 int rc;
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700176 int desired_access;
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300177 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
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700181 if (!tcon->ses->server->ops->open)
182 return -ENOSYS;
183
184 desired_access = cifs_convert_flags(f_flags);
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300185
186/*********************************************************************
187 * open flag mapping table:
188 *
189 * POSIX Flag CIFS Disposition
190 * ---------- ----------------
191 * O_CREAT FILE_OPEN_IF
192 * O_CREAT | O_EXCL FILE_CREATE
193 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
194 * O_TRUNC FILE_OVERWRITE
195 * none of the above FILE_OPEN
196 *
197 * Note that there is not a direct match between disposition
198 * FILE_SUPERSEDE (ie create whether or not file exists although
199 * O_CREAT | O_TRUNC is similar but truncates the existing
200 * file rather than creating a new file as FILE_SUPERSEDE does
201 * (which uses the attributes / metadata passed in on open call)
202 *?
203 *? O_SYNC is a reasonable match to CIFS writethrough flag
204 *? and the read write flags match reasonably. O_LARGEFILE
205 *? is irrelevant because largefile support is always used
206 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
207 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
208 *********************************************************************/
209
210 disposition = cifs_get_disposition(f_flags);
211
212 /* BB pass O_SYNC flag through on file attributes .. BB */
213
214 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
215 if (!buf)
216 return -ENOMEM;
217
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500218 if (backup_cred(cifs_sb))
219 create_options |= CREATE_OPEN_BACKUP_INTENT;
220
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700221 rc = tcon->ses->server->ops->open(xid, tcon, full_path, disposition,
222 desired_access, create_options, fid,
223 oplock, buf, cifs_sb);
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300224
225 if (rc)
226 goto out;
227
228 if (tcon->unix_ext)
229 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
230 xid);
231 else
232 rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700233 xid, &fid->netfid);
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300234
235out:
236 kfree(buf);
237 return rc;
238}
239
Jeff Layton15ecb432010-10-15 15:34:02 -0400240struct cifsFileInfo *
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700241cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
Jeff Layton15ecb432010-10-15 15:34:02 -0400242 struct tcon_link *tlink, __u32 oplock)
243{
244 struct dentry *dentry = file->f_path.dentry;
245 struct inode *inode = dentry->d_inode;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700246 struct cifsInodeInfo *cinode = CIFS_I(inode);
247 struct cifsFileInfo *cfile;
Jeff Layton15ecb432010-10-15 15:34:02 -0400248
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700249 cfile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
250 if (cfile == NULL)
251 return cfile;
Jeff Layton15ecb432010-10-15 15:34:02 -0400252
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700253 cfile->count = 1;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700254 cfile->pid = current->tgid;
255 cfile->uid = current_fsuid();
256 cfile->dentry = dget(dentry);
257 cfile->f_flags = file->f_flags;
258 cfile->invalidHandle = false;
259 cfile->tlink = cifs_get_tlink(tlink);
260 mutex_init(&cfile->fh_mutex);
261 INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
262 INIT_LIST_HEAD(&cfile->llist);
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700263 tlink_tcon(tlink)->ses->server->ops->set_fid(cfile, fid, oplock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400264
Jeff Layton44772882010-10-15 15:34:03 -0400265 spin_lock(&cifs_file_list_lock);
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700266 list_add(&cfile->tlist, &(tlink_tcon(tlink)->openFileList));
Jeff Layton15ecb432010-10-15 15:34:02 -0400267 /* if readable file instance put first in list*/
268 if (file->f_mode & FMODE_READ)
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700269 list_add(&cfile->flist, &cinode->openFileList);
Jeff Layton15ecb432010-10-15 15:34:02 -0400270 else
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700271 list_add_tail(&cfile->flist, &cinode->openFileList);
Jeff Layton44772882010-10-15 15:34:03 -0400272 spin_unlock(&cifs_file_list_lock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400273
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700274 file->private_data = cfile;
275 return cfile;
Jeff Layton15ecb432010-10-15 15:34:02 -0400276}
277
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400278static void cifs_del_lock_waiters(struct cifsLockInfo *lock);
279
Jeff Layton764a1b12012-07-25 14:59:54 -0400280struct cifsFileInfo *
281cifsFileInfo_get(struct cifsFileInfo *cifs_file)
282{
283 spin_lock(&cifs_file_list_lock);
284 cifsFileInfo_get_locked(cifs_file);
285 spin_unlock(&cifs_file_list_lock);
286 return cifs_file;
287}
288
Steve Frenchcdff08e2010-10-21 22:46:14 +0000289/*
290 * Release a reference on the file private data. This may involve closing
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400291 * the filehandle out on the server. Must be called without holding
292 * cifs_file_list_lock.
Steve Frenchcdff08e2010-10-21 22:46:14 +0000293 */
Jeff Laytonb33879a2010-10-15 15:34:04 -0400294void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
295{
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300296 struct inode *inode = cifs_file->dentry->d_inode;
Steve French96daf2b2011-05-27 04:34:02 +0000297 struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300298 struct cifsInodeInfo *cifsi = CIFS_I(inode);
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300299 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000300 struct cifsLockInfo *li, *tmp;
301
302 spin_lock(&cifs_file_list_lock);
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400303 if (--cifs_file->count > 0) {
Steve Frenchcdff08e2010-10-21 22:46:14 +0000304 spin_unlock(&cifs_file_list_lock);
305 return;
Jeff Laytonb33879a2010-10-15 15:34:04 -0400306 }
Steve Frenchcdff08e2010-10-21 22:46:14 +0000307
308 /* remove it from the lists */
309 list_del(&cifs_file->flist);
310 list_del(&cifs_file->tlist);
311
312 if (list_empty(&cifsi->openFileList)) {
313 cFYI(1, "closing last open instance for inode %p",
314 cifs_file->dentry->d_inode);
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300315
316 /* in strict cache mode we need invalidate mapping on the last
317 close because it may cause a error when we open this file
318 again and get at least level II oplock */
319 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
320 CIFS_I(inode)->invalid_mapping = true;
321
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300322 cifs_set_oplock_level(cifsi, 0);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000323 }
324 spin_unlock(&cifs_file_list_lock);
325
Jeff Laytonad635942011-07-26 12:20:17 -0400326 cancel_work_sync(&cifs_file->oplock_break);
327
Steve Frenchcdff08e2010-10-21 22:46:14 +0000328 if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400329 unsigned int xid;
330 int rc;
331 xid = get_xid();
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700332 rc = CIFSSMBClose(xid, tcon, cifs_file->fid.netfid);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400333 free_xid(xid);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000334 }
335
336 /* Delete any outstanding lock records. We'll lose them when the file
337 * is closed anyway.
338 */
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400339 mutex_lock(&cifsi->lock_mutex);
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300340 list_for_each_entry_safe(li, tmp, &cifs_file->llist, llist) {
Steve Frenchcdff08e2010-10-21 22:46:14 +0000341 list_del(&li->llist);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400342 cifs_del_lock_waiters(li);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000343 kfree(li);
344 }
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400345 mutex_unlock(&cifsi->lock_mutex);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000346
347 cifs_put_tlink(cifs_file->tlink);
348 dput(cifs_file->dentry);
349 kfree(cifs_file);
Jeff Laytonb33879a2010-10-15 15:34:04 -0400350}
351
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352int cifs_open(struct inode *inode, struct file *file)
353{
354 int rc = -EACCES;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400355 unsigned int xid;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400356 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000358 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400359 struct tcon_link *tlink;
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700360 struct cifsFileInfo *cfile = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 char *full_path = NULL;
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300362 bool posix_open_ok = false;
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700363 struct cifs_fid fid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400365 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
367 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400368 tlink = cifs_sb_tlink(cifs_sb);
369 if (IS_ERR(tlink)) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400370 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400371 return PTR_ERR(tlink);
372 }
373 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -0800375 full_path = build_path_from_dentry(file->f_path.dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530377 rc = -ENOMEM;
Jeff Layton232341b2010-08-05 13:58:38 -0400378 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 }
380
Joe Perchesb6b38f72010-04-21 03:50:45 +0000381 cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
382 inode, file->f_flags, full_path);
Steve French276a74a2009-03-03 18:00:34 +0000383
Pavel Shilovsky10b9b982012-03-20 12:55:09 +0300384 if (tcon->ses->server->oplocks)
Steve French276a74a2009-03-03 18:00:34 +0000385 oplock = REQ_OPLOCK;
386 else
387 oplock = 0;
388
Steve French64cc2c62009-03-04 19:54:08 +0000389 if (!tcon->broken_posix_open && tcon->unix_ext &&
Pavel Shilovsky29e20f92012-07-13 13:58:14 +0400390 cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
391 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Steve French276a74a2009-03-03 18:00:34 +0000392 /* can not refresh inode info since size could be stale */
Jeff Layton2422f672010-06-16 13:40:16 -0400393 rc = cifs_posix_open(full_path, &inode, inode->i_sb,
Steve Frenchfa588e02010-04-22 19:21:55 +0000394 cifs_sb->mnt_file_mode /* ignored */,
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700395 file->f_flags, &oplock, &fid.netfid, xid);
Steve French276a74a2009-03-03 18:00:34 +0000396 if (rc == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000397 cFYI(1, "posix open succeeded");
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300398 posix_open_ok = true;
Steve French64cc2c62009-03-04 19:54:08 +0000399 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
400 if (tcon->ses->serverNOS)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000401 cERROR(1, "server %s of type %s returned"
Steve French64cc2c62009-03-04 19:54:08 +0000402 " unexpected error on SMB posix open"
403 ", disabling posix open support."
404 " Check if server update available.",
405 tcon->ses->serverName,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000406 tcon->ses->serverNOS);
Steve French64cc2c62009-03-04 19:54:08 +0000407 tcon->broken_posix_open = true;
Steve French276a74a2009-03-03 18:00:34 +0000408 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
409 (rc != -EOPNOTSUPP)) /* path not found or net err */
410 goto out;
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700411 /*
412 * Else fallthrough to retry open the old way on network i/o
413 * or DFS errors.
414 */
Steve French276a74a2009-03-03 18:00:34 +0000415 }
416
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300417 if (!posix_open_ok) {
418 rc = cifs_nt_open(full_path, inode, cifs_sb, tcon,
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700419 file->f_flags, &oplock, &fid, xid);
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300420 if (rc)
421 goto out;
422 }
Jeff Layton47c78b72010-06-16 13:40:17 -0400423
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700424 cfile = cifs_new_fileinfo(&fid, file, tlink, oplock);
425 if (cfile == NULL) {
426 CIFSSMBClose(xid, tcon, fid.netfid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 rc = -ENOMEM;
428 goto out;
429 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530431 cifs_fscache_set_inode_cookie(inode, file);
432
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300433 if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) {
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700434 /*
435 * Time to set mode which we can not set earlier due to
436 * problems creating new read-only files.
437 */
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300438 struct cifs_unix_set_info_args args = {
439 .mode = inode->i_mode,
440 .uid = NO_CHANGE_64,
441 .gid = NO_CHANGE_64,
442 .ctime = NO_CHANGE_64,
443 .atime = NO_CHANGE_64,
444 .mtime = NO_CHANGE_64,
445 .device = 0,
446 };
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700447 CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid.netfid,
448 cfile->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 }
450
451out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400453 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400454 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 return rc;
456}
457
Adrian Bunk04187262006-06-30 18:23:04 +0200458/* Try to reacquire byte range locks that were released when session */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459/* to server was lost */
460static int cifs_relock_file(struct cifsFileInfo *cifsFile)
461{
462 int rc = 0;
463
464/* BB list all locks open on this file and relock */
465
466 return rc;
467}
468
Jeff Layton15886172010-10-15 15:33:59 -0400469static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470{
471 int rc = -EACCES;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400472 unsigned int xid;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400473 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000475 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 struct cifsInodeInfo *pCifsInode;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000477 struct inode *inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 char *full_path = NULL;
479 int desiredAccess;
480 int disposition = FILE_OPEN;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500481 int create_options = CREATE_NOT_DIR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 __u16 netfid;
483
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400484 xid = get_xid();
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400485 mutex_lock(&pCifsFile->fh_mutex);
Steve French4b18f2a2008-04-29 00:06:05 +0000486 if (!pCifsFile->invalidHandle) {
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400487 mutex_unlock(&pCifsFile->fh_mutex);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530488 rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400489 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530490 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 }
492
Jeff Layton15886172010-10-15 15:33:59 -0400493 inode = pCifsFile->dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton13cfb732010-09-29 19:51:11 -0400495 tcon = tlink_tcon(pCifsFile->tlink);
Steve French3a9f4622007-04-04 17:10:24 +0000496
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497/* can not grab rename sem here because various ops, including
498 those that already have the rename sem can end up causing writepage
499 to get called and if the server was down that means we end up here,
500 and we can never tell if the caller already has the rename_sem */
Jeff Layton15886172010-10-15 15:33:59 -0400501 full_path = build_path_from_dentry(pCifsFile->dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 if (full_path == NULL) {
Steve French3a9f4622007-04-04 17:10:24 +0000503 rc = -ENOMEM;
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400504 mutex_unlock(&pCifsFile->fh_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400505 free_xid(xid);
Steve French3a9f4622007-04-04 17:10:24 +0000506 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 }
508
Joe Perchesb6b38f72010-04-21 03:50:45 +0000509 cFYI(1, "inode = 0x%p file flags 0x%x for %s",
Jeff Layton15886172010-10-15 15:33:59 -0400510 inode, pCifsFile->f_flags, full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511
Pavel Shilovsky10b9b982012-03-20 12:55:09 +0300512 if (tcon->ses->server->oplocks)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 oplock = REQ_OPLOCK;
514 else
Steve French4b18f2a2008-04-29 00:06:05 +0000515 oplock = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
Pavel Shilovsky29e20f92012-07-13 13:58:14 +0400517 if (tcon->unix_ext && cap_unix(tcon->ses) &&
Steve French7fc8f4e2009-02-23 20:43:11 +0000518 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
Pavel Shilovsky29e20f92012-07-13 13:58:14 +0400519 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton608712f2010-10-15 15:33:56 -0400520 /*
521 * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
522 * original open. Must mask them off for a reopen.
523 */
Jeff Layton15886172010-10-15 15:33:59 -0400524 unsigned int oflags = pCifsFile->f_flags &
525 ~(O_CREAT | O_EXCL | O_TRUNC);
Jeff Layton608712f2010-10-15 15:33:56 -0400526
Jeff Layton2422f672010-06-16 13:40:16 -0400527 rc = cifs_posix_open(full_path, NULL, inode->i_sb,
Steve Frenchfa588e02010-04-22 19:21:55 +0000528 cifs_sb->mnt_file_mode /* ignored */,
529 oflags, &oplock, &netfid, xid);
Steve French7fc8f4e2009-02-23 20:43:11 +0000530 if (rc == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000531 cFYI(1, "posix reopen succeeded");
Steve French7fc8f4e2009-02-23 20:43:11 +0000532 goto reopen_success;
533 }
534 /* fallthrough to retry open the old way on errors, especially
535 in the reconnect path it is important to retry hard */
536 }
537
Jeff Layton15886172010-10-15 15:33:59 -0400538 desiredAccess = cifs_convert_flags(pCifsFile->f_flags);
Steve French7fc8f4e2009-02-23 20:43:11 +0000539
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500540 if (backup_cred(cifs_sb))
541 create_options |= CREATE_OPEN_BACKUP_INTENT;
542
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 /* Can not refresh inode by passing in file_info buf to be returned
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000544 by SMBOpen and then calling get_inode_info with returned buf
545 since file might have write behind data that needs to be flushed
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 and server version of file size can be stale. If we knew for sure
547 that inode was not dirty locally we could do this */
548
Steve French7fc8f4e2009-02-23 20:43:11 +0000549 rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess,
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500550 create_options, &netfid, &oplock, NULL,
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000551 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
Steve French737b7582005-04-28 22:41:06 -0700552 CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 if (rc) {
Jeff Laytonf0a71eb2009-06-27 07:04:55 -0400554 mutex_unlock(&pCifsFile->fh_mutex);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000555 cFYI(1, "cifs_open returned 0x%x", rc);
556 cFYI(1, "oplock: %d", oplock);
Jeff Layton15886172010-10-15 15:33:59 -0400557 goto reopen_error_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 }
Jeff Layton15886172010-10-15 15:33:59 -0400559
560reopen_success:
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700561 pCifsFile->fid.netfid = netfid;
Jeff Layton15886172010-10-15 15:33:59 -0400562 pCifsFile->invalidHandle = false;
563 mutex_unlock(&pCifsFile->fh_mutex);
564 pCifsInode = CIFS_I(inode);
565
566 if (can_flush) {
567 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -0400568 mapping_set_error(inode->i_mapping, rc);
Jeff Layton15886172010-10-15 15:33:59 -0400569
Jeff Layton15886172010-10-15 15:33:59 -0400570 if (tcon->unix_ext)
571 rc = cifs_get_inode_info_unix(&inode,
572 full_path, inode->i_sb, xid);
573 else
574 rc = cifs_get_inode_info(&inode,
575 full_path, NULL, inode->i_sb,
576 xid, NULL);
577 } /* else we are writing out data to server already
578 and could deadlock if we tried to flush data, and
579 since we do not know if we have data that would
580 invalidate the current end of file on the server
581 we can not go to the server to get the new inod
582 info */
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300583
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300584 cifs_set_oplock_level(pCifsInode, oplock);
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300585
Jeff Layton15886172010-10-15 15:33:59 -0400586 cifs_relock_file(pCifsFile);
587
588reopen_error_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400590 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 return rc;
592}
593
594int cifs_close(struct inode *inode, struct file *file)
595{
Jeff Layton77970692011-04-05 16:23:47 -0700596 if (file->private_data != NULL) {
597 cifsFileInfo_put(file->private_data);
598 file->private_data = NULL;
599 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Steve Frenchcdff08e2010-10-21 22:46:14 +0000601 /* return code from the ->release op is always ignored */
602 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603}
604
605int cifs_closedir(struct inode *inode, struct file *file)
606{
607 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400608 unsigned int xid;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700609 struct cifsFileInfo *cfile = file->private_data;
610 char *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
Joe Perchesb6b38f72010-04-21 03:50:45 +0000612 cFYI(1, "Closedir inode = 0x%p", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400614 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700616 if (cfile) {
617 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618
Joe Perchesb6b38f72010-04-21 03:50:45 +0000619 cFYI(1, "Freeing private data in close dir");
Jeff Layton44772882010-10-15 15:34:03 -0400620 spin_lock(&cifs_file_list_lock);
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700621 if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
622 cfile->invalidHandle = true;
Jeff Layton44772882010-10-15 15:34:03 -0400623 spin_unlock(&cifs_file_list_lock);
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700624 rc = CIFSFindClose(xid, tcon, cfile->fid.netfid);
625 cFYI(1, "Closing uncompleted readdir with rc %d", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 /* not much we can do if it fails anyway, ignore rc */
627 rc = 0;
Steve Frenchddb4cbf2008-11-20 20:00:44 +0000628 } else
Jeff Layton44772882010-10-15 15:34:03 -0400629 spin_unlock(&cifs_file_list_lock);
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700630 tmp = cfile->srch_inf.ntwrk_buf_start;
631 if (tmp) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000632 cFYI(1, "closedir free smb buf in srch struct");
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700633 cfile->srch_inf.ntwrk_buf_start = NULL;
634 if (cfile->srch_inf.smallBuf)
635 cifs_small_buf_release(tmp);
Steve Frenchd47d7c12006-02-28 03:45:48 +0000636 else
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700637 cifs_buf_release(tmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 }
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700639 cifs_put_tlink(cfile->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 kfree(file->private_data);
641 file->private_data = NULL;
642 }
643 /* BB can we lock the filestruct while this is going on? */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400644 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 return rc;
646}
647
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400648static struct cifsLockInfo *
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300649cifs_lock_init(__u64 offset, __u64 length, __u8 type)
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000650{
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400651 struct cifsLockInfo *lock =
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000652 kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400653 if (!lock)
654 return lock;
655 lock->offset = offset;
656 lock->length = length;
657 lock->type = type;
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400658 lock->pid = current->tgid;
659 INIT_LIST_HEAD(&lock->blist);
660 init_waitqueue_head(&lock->block_q);
661 return lock;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400662}
663
664static void
665cifs_del_lock_waiters(struct cifsLockInfo *lock)
666{
667 struct cifsLockInfo *li, *tmp;
668 list_for_each_entry_safe(li, tmp, &lock->blist, blist) {
669 list_del_init(&li->blist);
670 wake_up(&li->block_q);
671 }
672}
673
674static bool
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300675cifs_find_fid_lock_conflict(struct cifsFileInfo *cfile, __u64 offset,
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300676 __u64 length, __u8 type, struct cifsFileInfo *cur,
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300677 struct cifsLockInfo **conf_lock)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400678{
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300679 struct cifsLockInfo *li;
Pavel Shilovsky106dc532012-02-28 14:23:34 +0300680 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400681
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300682 list_for_each_entry(li, &cfile->llist, llist) {
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400683 if (offset + length <= li->offset ||
684 offset >= li->offset + li->length)
685 continue;
Pavel Shilovsky106dc532012-02-28 14:23:34 +0300686 else if ((type & server->vals->shared_lock_type) &&
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300687 ((server->ops->compare_fids(cur, cfile) &&
688 current->tgid == li->pid) || type == li->type))
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400689 continue;
690 else {
691 *conf_lock = li;
692 return true;
693 }
694 }
695 return false;
696}
697
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400698static bool
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300699cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
700 __u8 type, struct cifsLockInfo **conf_lock)
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400701{
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300702 bool rc = false;
703 struct cifsFileInfo *fid, *tmp;
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300704 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300705
706 spin_lock(&cifs_file_list_lock);
707 list_for_each_entry_safe(fid, tmp, &cinode->openFileList, flist) {
708 rc = cifs_find_fid_lock_conflict(fid, offset, length, type,
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300709 cfile, conf_lock);
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300710 if (rc)
711 break;
712 }
713 spin_unlock(&cifs_file_list_lock);
714
715 return rc;
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400716}
717
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300718/*
719 * Check if there is another lock that prevents us to set the lock (mandatory
720 * style). If such a lock exists, update the flock structure with its
721 * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks
722 * or leave it the same if we can't. Returns 0 if we don't need to request to
723 * the server or 1 otherwise.
724 */
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400725static int
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300726cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
727 __u8 type, struct file_lock *flock)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400728{
729 int rc = 0;
730 struct cifsLockInfo *conf_lock;
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300731 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovsky106dc532012-02-28 14:23:34 +0300732 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400733 bool exist;
734
735 mutex_lock(&cinode->lock_mutex);
736
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300737 exist = cifs_find_lock_conflict(cfile, offset, length, type,
738 &conf_lock);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400739 if (exist) {
740 flock->fl_start = conf_lock->offset;
741 flock->fl_end = conf_lock->offset + conf_lock->length - 1;
742 flock->fl_pid = conf_lock->pid;
Pavel Shilovsky106dc532012-02-28 14:23:34 +0300743 if (conf_lock->type & server->vals->shared_lock_type)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400744 flock->fl_type = F_RDLCK;
745 else
746 flock->fl_type = F_WRLCK;
747 } else if (!cinode->can_cache_brlcks)
748 rc = 1;
749 else
750 flock->fl_type = F_UNLCK;
751
752 mutex_unlock(&cinode->lock_mutex);
753 return rc;
754}
755
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400756static void
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300757cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400758{
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300759 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400760 mutex_lock(&cinode->lock_mutex);
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300761 list_add_tail(&lock->llist, &cfile->llist);
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400762 mutex_unlock(&cinode->lock_mutex);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000763}
764
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300765/*
766 * Set the byte-range lock (mandatory style). Returns:
767 * 1) 0, if we set the lock and don't need to request to the server;
768 * 2) 1, if no locks prevent us but we need to request to the server;
769 * 3) -EACCESS, if there is a lock that prevents us and wait is false.
770 */
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400771static int
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300772cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock,
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400773 bool wait)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400774{
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400775 struct cifsLockInfo *conf_lock;
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300776 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400777 bool exist;
778 int rc = 0;
779
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400780try_again:
781 exist = false;
782 mutex_lock(&cinode->lock_mutex);
783
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300784 exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length,
785 lock->type, &conf_lock);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400786 if (!exist && cinode->can_cache_brlcks) {
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300787 list_add_tail(&lock->llist, &cfile->llist);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400788 mutex_unlock(&cinode->lock_mutex);
789 return rc;
790 }
791
792 if (!exist)
793 rc = 1;
794 else if (!wait)
795 rc = -EACCES;
796 else {
797 list_add_tail(&lock->blist, &conf_lock->blist);
798 mutex_unlock(&cinode->lock_mutex);
799 rc = wait_event_interruptible(lock->block_q,
800 (lock->blist.prev == &lock->blist) &&
801 (lock->blist.next == &lock->blist));
802 if (!rc)
803 goto try_again;
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400804 mutex_lock(&cinode->lock_mutex);
805 list_del_init(&lock->blist);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400806 }
807
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400808 mutex_unlock(&cinode->lock_mutex);
809 return rc;
810}
811
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300812/*
813 * Check if there is another lock that prevents us to set the lock (posix
814 * style). If such a lock exists, update the flock structure with its
815 * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks
816 * or leave it the same if we can't. Returns 0 if we don't need to request to
817 * the server or 1 otherwise.
818 */
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400819static int
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400820cifs_posix_lock_test(struct file *file, struct file_lock *flock)
821{
822 int rc = 0;
823 struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode);
824 unsigned char saved_type = flock->fl_type;
825
Pavel Shilovsky50792762011-10-29 17:17:57 +0400826 if ((flock->fl_flags & FL_POSIX) == 0)
827 return 1;
828
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400829 mutex_lock(&cinode->lock_mutex);
830 posix_test_lock(file, flock);
831
832 if (flock->fl_type == F_UNLCK && !cinode->can_cache_brlcks) {
833 flock->fl_type = saved_type;
834 rc = 1;
835 }
836
837 mutex_unlock(&cinode->lock_mutex);
838 return rc;
839}
840
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300841/*
842 * Set the byte-range lock (posix style). Returns:
843 * 1) 0, if we set the lock and don't need to request to the server;
844 * 2) 1, if we need to request to the server;
845 * 3) <0, if the error occurs while setting the lock.
846 */
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400847static int
848cifs_posix_lock_set(struct file *file, struct file_lock *flock)
849{
850 struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode);
Pavel Shilovsky50792762011-10-29 17:17:57 +0400851 int rc = 1;
852
853 if ((flock->fl_flags & FL_POSIX) == 0)
854 return rc;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400855
Pavel Shilovsky66189be2012-03-28 21:56:19 +0400856try_again:
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400857 mutex_lock(&cinode->lock_mutex);
858 if (!cinode->can_cache_brlcks) {
859 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky50792762011-10-29 17:17:57 +0400860 return rc;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400861 }
Pavel Shilovsky66189be2012-03-28 21:56:19 +0400862
863 rc = posix_lock_file(file, flock, NULL);
Steve French9ebb3892012-04-01 13:52:54 -0500864 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky66189be2012-03-28 21:56:19 +0400865 if (rc == FILE_LOCK_DEFERRED) {
866 rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next);
867 if (!rc)
868 goto try_again;
869 locks_delete_block(flock);
870 }
Steve French9ebb3892012-04-01 13:52:54 -0500871 return rc;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400872}
873
874static int
875cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400876{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400877 unsigned int xid;
878 int rc = 0, stored_rc;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400879 struct cifsLockInfo *li, *tmp;
880 struct cifs_tcon *tcon;
881 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovsky0013fb42012-05-31 13:03:26 +0400882 unsigned int num, max_num, max_buf;
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400883 LOCKING_ANDX_RANGE *buf, *cur;
884 int types[] = {LOCKING_ANDX_LARGE_FILES,
885 LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
886 int i;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400887
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400888 xid = get_xid();
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400889 tcon = tlink_tcon(cfile->tlink);
890
891 mutex_lock(&cinode->lock_mutex);
892 if (!cinode->can_cache_brlcks) {
893 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400894 free_xid(xid);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400895 return rc;
896 }
897
Pavel Shilovsky0013fb42012-05-31 13:03:26 +0400898 /*
899 * Accessing maxBuf is racy with cifs_reconnect - need to store value
900 * and check it for zero before using.
901 */
902 max_buf = tcon->ses->server->maxBuf;
903 if (!max_buf) {
904 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400905 free_xid(xid);
Pavel Shilovsky0013fb42012-05-31 13:03:26 +0400906 return -EINVAL;
907 }
908
909 max_num = (max_buf - sizeof(struct smb_hdr)) /
910 sizeof(LOCKING_ANDX_RANGE);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400911 buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
912 if (!buf) {
913 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400914 free_xid(xid);
Pavel Shilovskye2f28862012-08-29 21:13:38 +0400915 return -ENOMEM;
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400916 }
917
918 for (i = 0; i < 2; i++) {
919 cur = buf;
920 num = 0;
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300921 list_for_each_entry_safe(li, tmp, &cfile->llist, llist) {
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400922 if (li->type != types[i])
923 continue;
924 cur->Pid = cpu_to_le16(li->pid);
925 cur->LengthLow = cpu_to_le32((u32)li->length);
926 cur->LengthHigh = cpu_to_le32((u32)(li->length>>32));
927 cur->OffsetLow = cpu_to_le32((u32)li->offset);
928 cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
929 if (++num == max_num) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700930 stored_rc = cifs_lockv(xid, tcon,
931 cfile->fid.netfid,
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +0300932 (__u8)li->type, 0, num,
933 buf);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400934 if (stored_rc)
935 rc = stored_rc;
936 cur = buf;
937 num = 0;
938 } else
939 cur++;
940 }
941
942 if (num) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700943 stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid,
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +0300944 (__u8)types[i], 0, num, buf);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400945 if (stored_rc)
946 rc = stored_rc;
947 }
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400948 }
949
950 cinode->can_cache_brlcks = false;
951 mutex_unlock(&cinode->lock_mutex);
952
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400953 kfree(buf);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400954 free_xid(xid);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400955 return rc;
956}
957
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400958/* copied from fs/locks.c with a name change */
959#define cifs_for_each_lock(inode, lockp) \
960 for (lockp = &inode->i_flock; *lockp != NULL; \
961 lockp = &(*lockp)->fl_next)
962
Pavel Shilovskyd5751462012-03-05 09:39:20 +0300963struct lock_to_push {
964 struct list_head llist;
965 __u64 offset;
966 __u64 length;
967 __u32 pid;
968 __u16 netfid;
969 __u8 type;
970};
971
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400972static int
973cifs_push_posix_locks(struct cifsFileInfo *cfile)
974{
975 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
976 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
977 struct file_lock *flock, **before;
Pavel Shilovskyd5751462012-03-05 09:39:20 +0300978 unsigned int count = 0, i = 0;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400979 int rc = 0, xid, type;
Pavel Shilovskyd5751462012-03-05 09:39:20 +0300980 struct list_head locks_to_send, *el;
981 struct lock_to_push *lck, *tmp;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400982 __u64 length;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400983
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400984 xid = get_xid();
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400985
986 mutex_lock(&cinode->lock_mutex);
987 if (!cinode->can_cache_brlcks) {
988 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400989 free_xid(xid);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400990 return rc;
991 }
992
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400993 lock_flocks();
994 cifs_for_each_lock(cfile->dentry->d_inode, before) {
Pavel Shilovskyd5751462012-03-05 09:39:20 +0300995 if ((*before)->fl_flags & FL_POSIX)
996 count++;
997 }
998 unlock_flocks();
999
1000 INIT_LIST_HEAD(&locks_to_send);
1001
1002 /*
Pavel Shilovskyce858522012-03-17 09:46:55 +03001003 * Allocating count locks is enough because no FL_POSIX locks can be
1004 * added to the list while we are holding cinode->lock_mutex that
1005 * protects locking operations of this inode.
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001006 */
1007 for (; i < count; i++) {
1008 lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL);
1009 if (!lck) {
1010 rc = -ENOMEM;
1011 goto err_out;
1012 }
1013 list_add_tail(&lck->llist, &locks_to_send);
1014 }
1015
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001016 el = locks_to_send.next;
1017 lock_flocks();
1018 cifs_for_each_lock(cfile->dentry->d_inode, before) {
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001019 flock = *before;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001020 if ((flock->fl_flags & FL_POSIX) == 0)
1021 continue;
Pavel Shilovskyce858522012-03-17 09:46:55 +03001022 if (el == &locks_to_send) {
1023 /*
1024 * The list ended. We don't have enough allocated
1025 * structures - something is really wrong.
1026 */
1027 cERROR(1, "Can't push all brlocks!");
1028 break;
1029 }
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001030 length = 1 + flock->fl_end - flock->fl_start;
1031 if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK)
1032 type = CIFS_RDLCK;
1033 else
1034 type = CIFS_WRLCK;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001035 lck = list_entry(el, struct lock_to_push, llist);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001036 lck->pid = flock->fl_pid;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001037 lck->netfid = cfile->fid.netfid;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001038 lck->length = length;
1039 lck->type = type;
1040 lck->offset = flock->fl_start;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001041 el = el->next;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001042 }
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001043 unlock_flocks();
1044
1045 list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001046 int stored_rc;
1047
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001048 stored_rc = CIFSSMBPosixLock(xid, tcon, lck->netfid, lck->pid,
Jeff Laytonc5fd3632012-07-23 13:28:37 -04001049 lck->offset, lck->length, NULL,
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001050 lck->type, 0);
1051 if (stored_rc)
1052 rc = stored_rc;
1053 list_del(&lck->llist);
1054 kfree(lck);
1055 }
1056
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001057out:
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001058 cinode->can_cache_brlcks = false;
1059 mutex_unlock(&cinode->lock_mutex);
1060
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001061 free_xid(xid);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001062 return rc;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001063err_out:
1064 list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
1065 list_del(&lck->llist);
1066 kfree(lck);
1067 }
1068 goto out;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001069}
1070
1071static int
1072cifs_push_locks(struct cifsFileInfo *cfile)
1073{
1074 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
1075 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1076
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001077 if (cap_unix(tcon->ses) &&
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001078 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
1079 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
1080 return cifs_push_posix_locks(cfile);
1081
1082 return cifs_push_mandatory_locks(cfile);
1083}
1084
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001085static void
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001086cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock,
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001087 bool *wait_flag, struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088{
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001089 if (flock->fl_flags & FL_POSIX)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001090 cFYI(1, "Posix");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001091 if (flock->fl_flags & FL_FLOCK)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001092 cFYI(1, "Flock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001093 if (flock->fl_flags & FL_SLEEP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001094 cFYI(1, "Blocking lock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001095 *wait_flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 }
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001097 if (flock->fl_flags & FL_ACCESS)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001098 cFYI(1, "Process suspended by mandatory locking - "
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001099 "not implemented yet");
1100 if (flock->fl_flags & FL_LEASE)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001101 cFYI(1, "Lease on file - not implemented yet");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001102 if (flock->fl_flags &
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001104 cFYI(1, "Unknown lock flags 0x%x", flock->fl_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001106 *type = server->vals->large_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001107 if (flock->fl_type == F_WRLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001108 cFYI(1, "F_WRLCK ");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001109 *type |= server->vals->exclusive_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001110 *lock = 1;
1111 } else if (flock->fl_type == F_UNLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001112 cFYI(1, "F_UNLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001113 *type |= server->vals->unlock_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001114 *unlock = 1;
1115 /* Check if unlock includes more than one lock range */
1116 } else if (flock->fl_type == F_RDLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001117 cFYI(1, "F_RDLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001118 *type |= server->vals->shared_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001119 *lock = 1;
1120 } else if (flock->fl_type == F_EXLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001121 cFYI(1, "F_EXLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001122 *type |= server->vals->exclusive_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001123 *lock = 1;
1124 } else if (flock->fl_type == F_SHLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001125 cFYI(1, "F_SHLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001126 *type |= server->vals->shared_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001127 *lock = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +00001129 cFYI(1, "Unknown type of lock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001130}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001132static int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001133cifs_mandatory_lock(unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001134 __u64 length, __u32 type, int lock, int unlock, bool wait)
1135{
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001136 return CIFSSMBLock(xid, tlink_tcon(cfile->tlink), cfile->fid.netfid,
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001137 current->tgid, length, offset, unlock, lock,
1138 (__u8)type, wait, 0);
1139}
1140
1141static int
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001142cifs_getlk(struct file *file, struct file_lock *flock, __u32 type,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001143 bool wait_flag, bool posix_lck, unsigned int xid)
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001144{
1145 int rc = 0;
1146 __u64 length = 1 + flock->fl_end - flock->fl_start;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001147 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
1148 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001149 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001150 __u16 netfid = cfile->fid.netfid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001152 if (posix_lck) {
1153 int posix_lock_type;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001154
1155 rc = cifs_posix_lock_test(file, flock);
1156 if (!rc)
1157 return rc;
1158
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001159 if (type & server->vals->shared_lock_type)
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001160 posix_lock_type = CIFS_RDLCK;
1161 else
1162 posix_lock_type = CIFS_WRLCK;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001163 rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid,
Jeff Laytonc5fd3632012-07-23 13:28:37 -04001164 flock->fl_start, length, flock,
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001165 posix_lock_type, wait_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 return rc;
1167 }
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001168
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001169 rc = cifs_lock_test(cfile, flock->fl_start, length, type, flock);
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001170 if (!rc)
1171 return rc;
1172
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001173 /* BB we could chain these into one lock request BB */
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001174 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length, type,
1175 1, 0, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001176 if (rc == 0) {
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001177 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1178 type, 0, 1, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001179 flock->fl_type = F_UNLCK;
1180 if (rc != 0)
1181 cERROR(1, "Error unlocking previously locked "
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001182 "range %d during test of lock", rc);
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001183 return 0;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001184 }
1185
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001186 if (type & server->vals->shared_lock_type) {
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001187 flock->fl_type = F_WRLCK;
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001188 return 0;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001189 }
1190
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001191 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1192 type | server->vals->shared_lock_type, 1, 0,
1193 false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001194 if (rc == 0) {
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001195 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1196 type | server->vals->shared_lock_type,
1197 0, 1, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001198 flock->fl_type = F_RDLCK;
1199 if (rc != 0)
1200 cERROR(1, "Error unlocking previously locked "
1201 "range %d during test of lock", rc);
1202 } else
1203 flock->fl_type = F_WRLCK;
1204
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001205 return 0;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001206}
1207
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001208static void
1209cifs_move_llist(struct list_head *source, struct list_head *dest)
1210{
1211 struct list_head *li, *tmp;
1212 list_for_each_safe(li, tmp, source)
1213 list_move(li, dest);
1214}
1215
1216static void
1217cifs_free_llist(struct list_head *llist)
1218{
1219 struct cifsLockInfo *li, *tmp;
1220 list_for_each_entry_safe(li, tmp, llist, llist) {
1221 cifs_del_lock_waiters(li);
1222 list_del(&li->llist);
1223 kfree(li);
1224 }
1225}
1226
1227static int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001228cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
1229 unsigned int xid)
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001230{
1231 int rc = 0, stored_rc;
1232 int types[] = {LOCKING_ANDX_LARGE_FILES,
1233 LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
1234 unsigned int i;
Pavel Shilovsky0013fb42012-05-31 13:03:26 +04001235 unsigned int max_num, num, max_buf;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001236 LOCKING_ANDX_RANGE *buf, *cur;
1237 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1238 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
1239 struct cifsLockInfo *li, *tmp;
1240 __u64 length = 1 + flock->fl_end - flock->fl_start;
1241 struct list_head tmp_llist;
1242
1243 INIT_LIST_HEAD(&tmp_llist);
1244
Pavel Shilovsky0013fb42012-05-31 13:03:26 +04001245 /*
1246 * Accessing maxBuf is racy with cifs_reconnect - need to store value
1247 * and check it for zero before using.
1248 */
1249 max_buf = tcon->ses->server->maxBuf;
1250 if (!max_buf)
1251 return -EINVAL;
1252
1253 max_num = (max_buf - sizeof(struct smb_hdr)) /
1254 sizeof(LOCKING_ANDX_RANGE);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001255 buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
1256 if (!buf)
1257 return -ENOMEM;
1258
1259 mutex_lock(&cinode->lock_mutex);
1260 for (i = 0; i < 2; i++) {
1261 cur = buf;
1262 num = 0;
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001263 list_for_each_entry_safe(li, tmp, &cfile->llist, llist) {
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001264 if (flock->fl_start > li->offset ||
1265 (flock->fl_start + length) <
1266 (li->offset + li->length))
1267 continue;
1268 if (current->tgid != li->pid)
1269 continue;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001270 if (types[i] != li->type)
1271 continue;
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001272 if (cinode->can_cache_brlcks) {
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001273 /*
1274 * We can cache brlock requests - simply remove
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001275 * a lock from the file's list.
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001276 */
1277 list_del(&li->llist);
1278 cifs_del_lock_waiters(li);
1279 kfree(li);
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001280 continue;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001281 }
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001282 cur->Pid = cpu_to_le16(li->pid);
1283 cur->LengthLow = cpu_to_le32((u32)li->length);
1284 cur->LengthHigh = cpu_to_le32((u32)(li->length>>32));
1285 cur->OffsetLow = cpu_to_le32((u32)li->offset);
1286 cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
1287 /*
1288 * We need to save a lock here to let us add it again to
1289 * the file's list if the unlock range request fails on
1290 * the server.
1291 */
1292 list_move(&li->llist, &tmp_llist);
1293 if (++num == max_num) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001294 stored_rc = cifs_lockv(xid, tcon,
1295 cfile->fid.netfid,
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001296 li->type, num, 0, buf);
1297 if (stored_rc) {
1298 /*
1299 * We failed on the unlock range
1300 * request - add all locks from the tmp
1301 * list to the head of the file's list.
1302 */
1303 cifs_move_llist(&tmp_llist,
1304 &cfile->llist);
1305 rc = stored_rc;
1306 } else
1307 /*
1308 * The unlock range request succeed -
1309 * free the tmp list.
1310 */
1311 cifs_free_llist(&tmp_llist);
1312 cur = buf;
1313 num = 0;
1314 } else
1315 cur++;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001316 }
1317 if (num) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001318 stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid,
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001319 types[i], num, 0, buf);
1320 if (stored_rc) {
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001321 cifs_move_llist(&tmp_llist, &cfile->llist);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001322 rc = stored_rc;
1323 } else
1324 cifs_free_llist(&tmp_llist);
1325 }
1326 }
1327
1328 mutex_unlock(&cinode->lock_mutex);
1329 kfree(buf);
1330 return rc;
1331}
1332
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001333static int
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001334cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001335 bool wait_flag, bool posix_lck, int lock, int unlock,
1336 unsigned int xid)
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001337{
1338 int rc = 0;
1339 __u64 length = 1 + flock->fl_end - flock->fl_start;
1340 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
1341 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001342 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001343 __u16 netfid = cfile->fid.netfid;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001344
1345 if (posix_lck) {
Steve French08547b02006-02-28 22:39:25 +00001346 int posix_lock_type;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001347
1348 rc = cifs_posix_lock_set(file, flock);
1349 if (!rc || rc < 0)
1350 return rc;
1351
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001352 if (type & server->vals->shared_lock_type)
Steve French08547b02006-02-28 22:39:25 +00001353 posix_lock_type = CIFS_RDLCK;
1354 else
1355 posix_lock_type = CIFS_WRLCK;
Steve French50c2f752007-07-13 00:33:32 +00001356
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001357 if (unlock == 1)
Steve Frenchbeb84dc2006-03-03 23:36:34 +00001358 posix_lock_type = CIFS_UNLCK;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001359
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001360 rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid,
Jeff Laytonc5fd3632012-07-23 13:28:37 -04001361 flock->fl_start, length, NULL,
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001362 posix_lock_type, wait_flag);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001363 goto out;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001364 }
1365
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001366 if (lock) {
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001367 struct cifsLockInfo *lock;
1368
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001369 lock = cifs_lock_init(flock->fl_start, length, type);
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001370 if (!lock)
1371 return -ENOMEM;
1372
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001373 rc = cifs_lock_add_if(cfile, lock, wait_flag);
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001374 if (rc < 0)
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001375 kfree(lock);
1376 if (rc <= 0)
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001377 goto out;
1378
Pavel Shilovsky7f924472012-03-28 17:10:25 +04001379 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1380 type, 1, 0, wait_flag);
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001381 if (rc) {
1382 kfree(lock);
1383 goto out;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001384 }
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001385
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001386 cifs_lock_add(cfile, lock);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001387 } else if (unlock)
1388 rc = cifs_unlock_range(cfile, flock, xid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001389
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001390out:
1391 if (flock->fl_flags & FL_POSIX)
Steve French9ebb3892012-04-01 13:52:54 -05001392 posix_lock_file_wait(file, flock);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001393 return rc;
1394}
1395
1396int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
1397{
1398 int rc, xid;
1399 int lock = 0, unlock = 0;
1400 bool wait_flag = false;
1401 bool posix_lck = false;
1402 struct cifs_sb_info *cifs_sb;
1403 struct cifs_tcon *tcon;
1404 struct cifsInodeInfo *cinode;
1405 struct cifsFileInfo *cfile;
1406 __u16 netfid;
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001407 __u32 type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001408
1409 rc = -EACCES;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001410 xid = get_xid();
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001411
1412 cFYI(1, "Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld "
1413 "end: %lld", cmd, flock->fl_flags, flock->fl_type,
1414 flock->fl_start, flock->fl_end);
1415
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001416 cfile = (struct cifsFileInfo *)file->private_data;
1417 tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001418
1419 cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag,
1420 tcon->ses->server);
1421
1422 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001423 netfid = cfile->fid.netfid;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001424 cinode = CIFS_I(file->f_path.dentry->d_inode);
1425
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001426 if (cap_unix(tcon->ses) &&
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001427 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
1428 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
1429 posix_lck = true;
1430 /*
1431 * BB add code here to normalize offset and length to account for
1432 * negative length which we can not accept over the wire.
1433 */
1434 if (IS_GETLK(cmd)) {
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001435 rc = cifs_getlk(file, flock, type, wait_flag, posix_lck, xid);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001436 free_xid(xid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001437 return rc;
1438 }
1439
1440 if (!lock && !unlock) {
1441 /*
1442 * if no lock or unlock then nothing to do since we do not
1443 * know what it is
1444 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001445 free_xid(xid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001446 return -EOPNOTSUPP;
1447 }
1448
1449 rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock,
1450 xid);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001451 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 return rc;
1453}
1454
Jeff Layton597b0272012-03-23 14:40:56 -04001455/*
1456 * update the file size (if needed) after a write. Should be called with
1457 * the inode->i_lock held
1458 */
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001459void
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001460cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
1461 unsigned int bytes_written)
1462{
1463 loff_t end_of_write = offset + bytes_written;
1464
1465 if (end_of_write > cifsi->server_eof)
1466 cifsi->server_eof = end_of_write;
1467}
1468
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001469static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
Jeff Layton7da4b492010-10-15 15:34:00 -04001470 const char *write_data, size_t write_size,
1471 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472{
1473 int rc = 0;
1474 unsigned int bytes_written = 0;
1475 unsigned int total_written;
1476 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +00001477 struct cifs_tcon *pTcon;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001478 unsigned int xid;
Jeff Layton7da4b492010-10-15 15:34:00 -04001479 struct dentry *dentry = open_file->dentry;
1480 struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001481 struct cifs_io_parms io_parms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
Jeff Layton7da4b492010-10-15 15:34:00 -04001483 cifs_sb = CIFS_SB(dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
Joe Perchesb6b38f72010-04-21 03:50:45 +00001485 cFYI(1, "write %zd bytes to offset %lld of %s", write_size,
Jeff Layton7da4b492010-10-15 15:34:00 -04001486 *poffset, dentry->d_name.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487
Jeff Layton13cfb732010-09-29 19:51:11 -04001488 pTcon = tlink_tcon(open_file->tlink);
Steve French50c2f752007-07-13 00:33:32 +00001489
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001490 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 for (total_written = 0; write_size > total_written;
1493 total_written += bytes_written) {
1494 rc = -EAGAIN;
1495 while (rc == -EAGAIN) {
Jeff Laytonca83ce32011-04-12 09:13:44 -04001496 struct kvec iov[2];
1497 unsigned int len;
1498
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 if (open_file->invalidHandle) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 /* we could deadlock if we called
1501 filemap_fdatawait from here so tell
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001502 reopen_file not to flush data to
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 server now */
Jeff Layton15886172010-10-15 15:33:59 -04001504 rc = cifs_reopen_file(open_file, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 if (rc != 0)
1506 break;
1507 }
Steve French3e844692005-10-03 13:37:24 -07001508
Jeff Laytonca83ce32011-04-12 09:13:44 -04001509 len = min((size_t)cifs_sb->wsize,
1510 write_size - total_written);
1511 /* iov[0] is reserved for smb header */
1512 iov[1].iov_base = (char *)write_data + total_written;
1513 iov[1].iov_len = len;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001514 io_parms.netfid = open_file->fid.netfid;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001515 io_parms.pid = pid;
1516 io_parms.tcon = pTcon;
1517 io_parms.offset = *poffset;
1518 io_parms.length = len;
1519 rc = CIFSSMBWrite2(xid, &io_parms, &bytes_written, iov,
1520 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 }
1522 if (rc || (bytes_written == 0)) {
1523 if (total_written)
1524 break;
1525 else {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001526 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 return rc;
1528 }
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001529 } else {
Jeff Layton597b0272012-03-23 14:40:56 -04001530 spin_lock(&dentry->d_inode->i_lock);
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001531 cifs_update_eof(cifsi, *poffset, bytes_written);
Jeff Layton597b0272012-03-23 14:40:56 -04001532 spin_unlock(&dentry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 *poffset += bytes_written;
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001534 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 }
1536
Steve Frencha4544342005-08-24 13:59:35 -07001537 cifs_stats_bytes_written(pTcon, total_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538
Jeff Layton7da4b492010-10-15 15:34:00 -04001539 if (total_written > 0) {
1540 spin_lock(&dentry->d_inode->i_lock);
1541 if (*poffset > dentry->d_inode->i_size)
1542 i_size_write(dentry->d_inode, *poffset);
1543 spin_unlock(&dentry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 }
Jeff Layton7da4b492010-10-15 15:34:00 -04001545 mark_inode_dirty_sync(dentry->d_inode);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001546 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 return total_written;
1548}
1549
Jeff Layton6508d902010-09-29 19:51:11 -04001550struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1551 bool fsuid_only)
Steve French630f3f0c2007-10-25 21:17:17 +00001552{
1553 struct cifsFileInfo *open_file = NULL;
Jeff Layton6508d902010-09-29 19:51:11 -04001554 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1555
1556 /* only filter by fsuid on multiuser mounts */
1557 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1558 fsuid_only = false;
Steve French630f3f0c2007-10-25 21:17:17 +00001559
Jeff Layton44772882010-10-15 15:34:03 -04001560 spin_lock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001561 /* we could simply get the first_list_entry since write-only entries
1562 are always at the end of the list but since the first entry might
1563 have a close pending, we go through the whole list */
1564 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001565 if (fsuid_only && open_file->uid != current_fsuid())
1566 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001567 if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
Steve French630f3f0c2007-10-25 21:17:17 +00001568 if (!open_file->invalidHandle) {
1569 /* found a good file */
1570 /* lock it so it will not be closed on us */
Jeff Layton764a1b12012-07-25 14:59:54 -04001571 cifsFileInfo_get_locked(open_file);
Jeff Layton44772882010-10-15 15:34:03 -04001572 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001573 return open_file;
1574 } /* else might as well continue, and look for
1575 another, or simply have the caller reopen it
1576 again rather than trying to fix this handle */
1577 } else /* write only file */
1578 break; /* write only files are last so must be done */
1579 }
Jeff Layton44772882010-10-15 15:34:03 -04001580 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001581 return NULL;
1582}
Steve French630f3f0c2007-10-25 21:17:17 +00001583
Jeff Layton6508d902010-09-29 19:51:11 -04001584struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1585 bool fsuid_only)
Steve French6148a742005-10-05 12:23:19 -07001586{
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001587 struct cifsFileInfo *open_file, *inv_file = NULL;
Jeff Laytond3892292010-11-02 16:22:50 -04001588 struct cifs_sb_info *cifs_sb;
Jeff Layton2846d382008-09-22 21:33:33 -04001589 bool any_available = false;
Steve Frenchdd99cd82005-10-05 19:32:49 -07001590 int rc;
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001591 unsigned int refind = 0;
Steve French6148a742005-10-05 12:23:19 -07001592
Steve French60808232006-04-22 15:53:05 +00001593 /* Having a null inode here (because mapping->host was set to zero by
1594 the VFS or MM) should not happen but we had reports of on oops (due to
1595 it being zero) during stress testcases so we need to check for it */
1596
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001597 if (cifs_inode == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001598 cERROR(1, "Null inode passed to cifs_writeable_file");
Steve French60808232006-04-22 15:53:05 +00001599 dump_stack();
1600 return NULL;
1601 }
1602
Jeff Laytond3892292010-11-02 16:22:50 -04001603 cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1604
Jeff Layton6508d902010-09-29 19:51:11 -04001605 /* only filter by fsuid on multiuser mounts */
1606 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1607 fsuid_only = false;
1608
Jeff Layton44772882010-10-15 15:34:03 -04001609 spin_lock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001610refind_writable:
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001611 if (refind > MAX_REOPEN_ATT) {
1612 spin_unlock(&cifs_file_list_lock);
1613 return NULL;
1614 }
Steve French6148a742005-10-05 12:23:19 -07001615 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001616 if (!any_available && open_file->pid != current->tgid)
1617 continue;
1618 if (fsuid_only && open_file->uid != current_fsuid())
1619 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001620 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Steve French9b22b0b2007-10-02 01:11:08 +00001621 if (!open_file->invalidHandle) {
1622 /* found a good writable file */
Jeff Layton764a1b12012-07-25 14:59:54 -04001623 cifsFileInfo_get_locked(open_file);
Jeff Layton44772882010-10-15 15:34:03 -04001624 spin_unlock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001625 return open_file;
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001626 } else {
1627 if (!inv_file)
1628 inv_file = open_file;
Steve French9b22b0b2007-10-02 01:11:08 +00001629 }
Steve French6148a742005-10-05 12:23:19 -07001630 }
1631 }
Jeff Layton2846d382008-09-22 21:33:33 -04001632 /* couldn't find useable FH with same pid, try any available */
1633 if (!any_available) {
1634 any_available = true;
1635 goto refind_writable;
1636 }
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001637
1638 if (inv_file) {
1639 any_available = false;
Jeff Layton764a1b12012-07-25 14:59:54 -04001640 cifsFileInfo_get_locked(inv_file);
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001641 }
1642
Jeff Layton44772882010-10-15 15:34:03 -04001643 spin_unlock(&cifs_file_list_lock);
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001644
1645 if (inv_file) {
1646 rc = cifs_reopen_file(inv_file, false);
1647 if (!rc)
1648 return inv_file;
1649 else {
1650 spin_lock(&cifs_file_list_lock);
1651 list_move_tail(&inv_file->flist,
1652 &cifs_inode->openFileList);
1653 spin_unlock(&cifs_file_list_lock);
1654 cifsFileInfo_put(inv_file);
1655 spin_lock(&cifs_file_list_lock);
1656 ++refind;
1657 goto refind_writable;
1658 }
1659 }
1660
Steve French6148a742005-10-05 12:23:19 -07001661 return NULL;
1662}
1663
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1665{
1666 struct address_space *mapping = page->mapping;
1667 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1668 char *write_data;
1669 int rc = -EFAULT;
1670 int bytes_written = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 struct inode *inode;
Steve French6148a742005-10-05 12:23:19 -07001672 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
1674 if (!mapping || !mapping->host)
1675 return -EFAULT;
1676
1677 inode = page->mapping->host;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678
1679 offset += (loff_t)from;
1680 write_data = kmap(page);
1681 write_data += from;
1682
1683 if ((to > PAGE_CACHE_SIZE) || (from > to)) {
1684 kunmap(page);
1685 return -EIO;
1686 }
1687
1688 /* racing with truncate? */
1689 if (offset > mapping->host->i_size) {
1690 kunmap(page);
1691 return 0; /* don't care */
1692 }
1693
1694 /* check to make sure that we are not extending the file */
1695 if (mapping->host->i_size - offset < (loff_t)to)
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001696 to = (unsigned)(mapping->host->i_size - offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697
Jeff Layton6508d902010-09-29 19:51:11 -04001698 open_file = find_writable_file(CIFS_I(mapping->host), false);
Steve French6148a742005-10-05 12:23:19 -07001699 if (open_file) {
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001700 bytes_written = cifs_write(open_file, open_file->pid,
1701 write_data, to - from, &offset);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001702 cifsFileInfo_put(open_file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 /* Does mm or vfs already set times? */
Steve French6148a742005-10-05 12:23:19 -07001704 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001705 if ((bytes_written > 0) && (offset))
Steve French6148a742005-10-05 12:23:19 -07001706 rc = 0;
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001707 else if (bytes_written < 0)
1708 rc = bytes_written;
Steve French6148a742005-10-05 12:23:19 -07001709 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001710 cFYI(1, "No writeable filehandles for inode");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 rc = -EIO;
1712 }
1713
1714 kunmap(page);
1715 return rc;
1716}
1717
Jeff Laytone9492872012-03-23 14:40:56 -04001718/*
1719 * Marshal up the iov array, reserving the first one for the header. Also,
1720 * set wdata->bytes.
1721 */
1722static void
1723cifs_writepages_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
1724{
1725 int i;
1726 struct inode *inode = wdata->cfile->dentry->d_inode;
1727 loff_t size = i_size_read(inode);
1728
1729 /* marshal up the pages into iov array */
1730 wdata->bytes = 0;
1731 for (i = 0; i < wdata->nr_pages; i++) {
1732 iov[i + 1].iov_len = min(size - page_offset(wdata->pages[i]),
1733 (loff_t)PAGE_CACHE_SIZE);
1734 iov[i + 1].iov_base = kmap(wdata->pages[i]);
1735 wdata->bytes += iov[i + 1].iov_len;
1736 }
1737}
1738
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739static int cifs_writepages(struct address_space *mapping,
Steve French37c0eb42005-10-05 14:50:29 -07001740 struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741{
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001742 struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb);
1743 bool done = false, scanned = false, range_whole = false;
1744 pgoff_t end, index;
1745 struct cifs_writedata *wdata;
Steve French37c0eb42005-10-05 14:50:29 -07001746 struct page *page;
Steve French37c0eb42005-10-05 14:50:29 -07001747 int rc = 0;
Steve French50c2f752007-07-13 00:33:32 +00001748
Steve French37c0eb42005-10-05 14:50:29 -07001749 /*
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001750 * If wsize is smaller than the page cache size, default to writing
Steve French37c0eb42005-10-05 14:50:29 -07001751 * one page at a time via cifs_writepage
1752 */
1753 if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1754 return generic_writepages(mapping, wbc);
1755
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001756 if (wbc->range_cyclic) {
Steve French37c0eb42005-10-05 14:50:29 -07001757 index = mapping->writeback_index; /* Start from prev offset */
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001758 end = -1;
1759 } else {
1760 index = wbc->range_start >> PAGE_CACHE_SHIFT;
1761 end = wbc->range_end >> PAGE_CACHE_SHIFT;
1762 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001763 range_whole = true;
1764 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001765 }
1766retry:
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001767 while (!done && index <= end) {
1768 unsigned int i, nr_pages, found_pages;
1769 pgoff_t next = 0, tofind;
1770 struct page **pages;
Steve French37c0eb42005-10-05 14:50:29 -07001771
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001772 tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1,
1773 end - index) + 1;
Steve French37c0eb42005-10-05 14:50:29 -07001774
Jeff Laytonc2e87642012-03-23 14:40:55 -04001775 wdata = cifs_writedata_alloc((unsigned int)tofind,
1776 cifs_writev_complete);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001777 if (!wdata) {
1778 rc = -ENOMEM;
1779 break;
1780 }
1781
1782 /*
1783 * find_get_pages_tag seems to return a max of 256 on each
1784 * iteration, so we must call it several times in order to
1785 * fill the array or the wsize is effectively limited to
1786 * 256 * PAGE_CACHE_SIZE.
1787 */
1788 found_pages = 0;
1789 pages = wdata->pages;
1790 do {
1791 nr_pages = find_get_pages_tag(mapping, &index,
1792 PAGECACHE_TAG_DIRTY,
1793 tofind, pages);
1794 found_pages += nr_pages;
1795 tofind -= nr_pages;
1796 pages += nr_pages;
1797 } while (nr_pages && tofind && index <= end);
1798
1799 if (found_pages == 0) {
1800 kref_put(&wdata->refcount, cifs_writedata_release);
1801 break;
1802 }
1803
1804 nr_pages = 0;
1805 for (i = 0; i < found_pages; i++) {
1806 page = wdata->pages[i];
Steve French37c0eb42005-10-05 14:50:29 -07001807 /*
1808 * At this point we hold neither mapping->tree_lock nor
1809 * lock on the page itself: the page may be truncated or
1810 * invalidated (changing page->mapping to NULL), or even
1811 * swizzled back from swapper_space to tmpfs file
1812 * mapping
1813 */
1814
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001815 if (nr_pages == 0)
Steve French37c0eb42005-10-05 14:50:29 -07001816 lock_page(page);
Nick Piggin529ae9a2008-08-02 12:01:03 +02001817 else if (!trylock_page(page))
Steve French37c0eb42005-10-05 14:50:29 -07001818 break;
1819
1820 if (unlikely(page->mapping != mapping)) {
1821 unlock_page(page);
1822 break;
1823 }
1824
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001825 if (!wbc->range_cyclic && page->index > end) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001826 done = true;
Steve French37c0eb42005-10-05 14:50:29 -07001827 unlock_page(page);
1828 break;
1829 }
1830
1831 if (next && (page->index != next)) {
1832 /* Not next consecutive page */
1833 unlock_page(page);
1834 break;
1835 }
1836
1837 if (wbc->sync_mode != WB_SYNC_NONE)
1838 wait_on_page_writeback(page);
1839
1840 if (PageWriteback(page) ||
Linus Torvaldscb876f42006-12-23 16:19:07 -08001841 !clear_page_dirty_for_io(page)) {
Steve French37c0eb42005-10-05 14:50:29 -07001842 unlock_page(page);
1843 break;
1844 }
Steve French84d2f072005-10-12 15:32:05 -07001845
Linus Torvaldscb876f42006-12-23 16:19:07 -08001846 /*
1847 * This actually clears the dirty bit in the radix tree.
1848 * See cifs_writepage() for more commentary.
1849 */
1850 set_page_writeback(page);
1851
Steve French84d2f072005-10-12 15:32:05 -07001852 if (page_offset(page) >= mapping->host->i_size) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001853 done = true;
Steve French84d2f072005-10-12 15:32:05 -07001854 unlock_page(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001855 end_page_writeback(page);
Steve French84d2f072005-10-12 15:32:05 -07001856 break;
1857 }
1858
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001859 wdata->pages[i] = page;
Steve French37c0eb42005-10-05 14:50:29 -07001860 next = page->index + 1;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001861 ++nr_pages;
Steve French37c0eb42005-10-05 14:50:29 -07001862 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001863
1864 /* reset index to refind any pages skipped */
1865 if (nr_pages == 0)
1866 index = wdata->pages[0]->index + 1;
1867
1868 /* put any pages we aren't going to use */
1869 for (i = nr_pages; i < found_pages; i++) {
1870 page_cache_release(wdata->pages[i]);
1871 wdata->pages[i] = NULL;
1872 }
1873
1874 /* nothing to write? */
1875 if (nr_pages == 0) {
1876 kref_put(&wdata->refcount, cifs_writedata_release);
1877 continue;
1878 }
1879
1880 wdata->sync_mode = wbc->sync_mode;
1881 wdata->nr_pages = nr_pages;
1882 wdata->offset = page_offset(wdata->pages[0]);
Jeff Laytone9492872012-03-23 14:40:56 -04001883 wdata->marshal_iov = cifs_writepages_marshal_iov;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001884
1885 do {
1886 if (wdata->cfile != NULL)
1887 cifsFileInfo_put(wdata->cfile);
1888 wdata->cfile = find_writable_file(CIFS_I(mapping->host),
1889 false);
1890 if (!wdata->cfile) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001891 cERROR(1, "No writable handles for inode");
Steve French23e7dd72005-10-20 13:44:56 -07001892 rc = -EBADF;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001893 break;
Steve French37c0eb42005-10-05 14:50:29 -07001894 }
Jeff Laytonfe5f5d22012-03-23 14:40:55 -04001895 wdata->pid = wdata->cfile->pid;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001896 rc = cifs_async_writev(wdata);
1897 } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN);
Jeff Laytonf3983c22010-09-22 16:17:40 -07001898
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001899 for (i = 0; i < nr_pages; ++i)
1900 unlock_page(wdata->pages[i]);
Jeff Layton941b8532011-01-11 07:24:01 -05001901
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001902 /* send failure -- clean up the mess */
1903 if (rc != 0) {
1904 for (i = 0; i < nr_pages; ++i) {
Jeff Layton941b8532011-01-11 07:24:01 -05001905 if (rc == -EAGAIN)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001906 redirty_page_for_writepage(wbc,
1907 wdata->pages[i]);
1908 else
1909 SetPageError(wdata->pages[i]);
1910 end_page_writeback(wdata->pages[i]);
1911 page_cache_release(wdata->pages[i]);
Steve French37c0eb42005-10-05 14:50:29 -07001912 }
Jeff Layton941b8532011-01-11 07:24:01 -05001913 if (rc != -EAGAIN)
1914 mapping_set_error(mapping, rc);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001915 }
1916 kref_put(&wdata->refcount, cifs_writedata_release);
Jeff Layton941b8532011-01-11 07:24:01 -05001917
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001918 wbc->nr_to_write -= nr_pages;
1919 if (wbc->nr_to_write <= 0)
1920 done = true;
Dave Kleikampb066a482008-11-18 03:49:05 +00001921
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001922 index = next;
Steve French37c0eb42005-10-05 14:50:29 -07001923 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001924
Steve French37c0eb42005-10-05 14:50:29 -07001925 if (!scanned && !done) {
1926 /*
1927 * We hit the last page and there is more work to be done: wrap
1928 * back to the start of the file
1929 */
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001930 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001931 index = 0;
1932 goto retry;
1933 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001934
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001935 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
Steve French37c0eb42005-10-05 14:50:29 -07001936 mapping->writeback_index = index;
1937
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 return rc;
1939}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001941static int
1942cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943{
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001944 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001945 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001947 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948/* BB add check for wbc flags */
1949 page_cache_get(page);
Steve Frenchad7a2922008-02-07 23:25:02 +00001950 if (!PageUptodate(page))
Joe Perchesb6b38f72010-04-21 03:50:45 +00001951 cFYI(1, "ppw - page not up to date");
Linus Torvaldscb876f42006-12-23 16:19:07 -08001952
1953 /*
1954 * Set the "writeback" flag, and clear "dirty" in the radix tree.
1955 *
1956 * A writepage() implementation always needs to do either this,
1957 * or re-dirty the page with "redirty_page_for_writepage()" in
1958 * the case of a failure.
1959 *
1960 * Just unlocking the page will cause the radix tree tag-bits
1961 * to fail to update with the state of the page correctly.
1962 */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001963 set_page_writeback(page);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001964retry_write:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001966 if (rc == -EAGAIN && wbc->sync_mode == WB_SYNC_ALL)
1967 goto retry_write;
1968 else if (rc == -EAGAIN)
1969 redirty_page_for_writepage(wbc, page);
1970 else if (rc != 0)
1971 SetPageError(page);
1972 else
1973 SetPageUptodate(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001974 end_page_writeback(page);
1975 page_cache_release(page);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001976 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 return rc;
1978}
1979
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001980static int cifs_writepage(struct page *page, struct writeback_control *wbc)
1981{
1982 int rc = cifs_writepage_locked(page, wbc);
1983 unlock_page(page);
1984 return rc;
1985}
1986
Nick Piggind9414772008-09-24 11:32:59 -04001987static int cifs_write_end(struct file *file, struct address_space *mapping,
1988 loff_t pos, unsigned len, unsigned copied,
1989 struct page *page, void *fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990{
Nick Piggind9414772008-09-24 11:32:59 -04001991 int rc;
1992 struct inode *inode = mapping->host;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001993 struct cifsFileInfo *cfile = file->private_data;
1994 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
1995 __u32 pid;
1996
1997 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
1998 pid = cfile->pid;
1999 else
2000 pid = current->tgid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001
Joe Perchesb6b38f72010-04-21 03:50:45 +00002002 cFYI(1, "write_end for page %p from pos %lld with %d bytes",
2003 page, pos, copied);
Steve Frenchad7a2922008-02-07 23:25:02 +00002004
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002005 if (PageChecked(page)) {
2006 if (copied == len)
2007 SetPageUptodate(page);
2008 ClearPageChecked(page);
2009 } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
Nick Piggind9414772008-09-24 11:32:59 -04002010 SetPageUptodate(page);
2011
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 if (!PageUptodate(page)) {
Nick Piggind9414772008-09-24 11:32:59 -04002013 char *page_data;
2014 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002015 unsigned int xid;
Nick Piggind9414772008-09-24 11:32:59 -04002016
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002017 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 /* this is probably better than directly calling
2019 partialpage_write since in this function the file handle is
2020 known which we might as well leverage */
2021 /* BB check if anything else missing out of ppw
2022 such as updating last write time */
2023 page_data = kmap(page);
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002024 rc = cifs_write(cfile, pid, page_data + offset, copied, &pos);
Nick Piggind9414772008-09-24 11:32:59 -04002025 /* if (rc < 0) should we set writebehind rc? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 kunmap(page);
Nick Piggind9414772008-09-24 11:32:59 -04002027
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002028 free_xid(xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002029 } else {
Nick Piggind9414772008-09-24 11:32:59 -04002030 rc = copied;
2031 pos += copied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 set_page_dirty(page);
2033 }
2034
Nick Piggind9414772008-09-24 11:32:59 -04002035 if (rc > 0) {
2036 spin_lock(&inode->i_lock);
2037 if (pos > inode->i_size)
2038 i_size_write(inode, pos);
2039 spin_unlock(&inode->i_lock);
2040 }
2041
2042 unlock_page(page);
2043 page_cache_release(page);
2044
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 return rc;
2046}
2047
Josef Bacik02c24a82011-07-16 20:44:56 -04002048int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
2049 int datasync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002051 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00002053 struct cifs_tcon *tcon;
Joe Perchesc21dfb62010-07-12 13:50:14 -07002054 struct cifsFileInfo *smbfile = file->private_data;
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002055 struct inode *inode = file->f_path.dentry->d_inode;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002056 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057
Josef Bacik02c24a82011-07-16 20:44:56 -04002058 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
2059 if (rc)
2060 return rc;
2061 mutex_lock(&inode->i_mutex);
2062
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002063 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064
Joe Perchesb6b38f72010-04-21 03:50:45 +00002065 cFYI(1, "Sync file - name: %s datasync: 0x%x",
Christoph Hellwig7ea80852010-05-26 17:53:25 +02002066 file->f_path.dentry->d_name.name, datasync);
Steve French50c2f752007-07-13 00:33:32 +00002067
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002068 if (!CIFS_I(inode)->clientCanCacheRead) {
2069 rc = cifs_invalidate_mapping(inode);
2070 if (rc) {
2071 cFYI(1, "rc: %d during invalidate phase", rc);
2072 rc = 0; /* don't care about it in fsync */
2073 }
2074 }
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002075
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002076 tcon = tlink_tcon(smbfile->tlink);
2077 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002078 rc = CIFSSMBFlush(xid, tcon, smbfile->fid.netfid);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002079
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002080 free_xid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04002081 mutex_unlock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002082 return rc;
2083}
2084
Josef Bacik02c24a82011-07-16 20:44:56 -04002085int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002086{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002087 unsigned int xid;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002088 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00002089 struct cifs_tcon *tcon;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002090 struct cifsFileInfo *smbfile = file->private_data;
2091 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Josef Bacik02c24a82011-07-16 20:44:56 -04002092 struct inode *inode = file->f_mapping->host;
2093
2094 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
2095 if (rc)
2096 return rc;
2097 mutex_lock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002098
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002099 xid = get_xid();
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002100
2101 cFYI(1, "Sync file - name: %s datasync: 0x%x",
2102 file->f_path.dentry->d_name.name, datasync);
2103
2104 tcon = tlink_tcon(smbfile->tlink);
2105 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002106 rc = CIFSSMBFlush(xid, tcon, smbfile->fid.netfid);
Steve Frenchb298f222009-02-21 21:17:43 +00002107
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002108 free_xid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04002109 mutex_unlock(&inode->i_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 return rc;
2111}
2112
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113/*
2114 * As file closes, flush all cached write data for this inode checking
2115 * for write behind errors.
2116 */
Miklos Szeredi75e1fcc2006-06-23 02:05:12 -07002117int cifs_flush(struct file *file, fl_owner_t id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118{
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002119 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 int rc = 0;
2121
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002122 if (file->f_mode & FMODE_WRITE)
Jeff Laytond3f13222010-10-15 15:34:07 -04002123 rc = filemap_write_and_wait(inode->i_mapping);
Steve French50c2f752007-07-13 00:33:32 +00002124
Joe Perchesb6b38f72010-04-21 03:50:45 +00002125 cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126
2127 return rc;
2128}
2129
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002130static int
2131cifs_write_allocate_pages(struct page **pages, unsigned long num_pages)
2132{
2133 int rc = 0;
2134 unsigned long i;
2135
2136 for (i = 0; i < num_pages; i++) {
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002137 pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002138 if (!pages[i]) {
2139 /*
2140 * save number of pages we have already allocated and
2141 * return with ENOMEM error
2142 */
2143 num_pages = i;
2144 rc = -ENOMEM;
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002145 break;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002146 }
2147 }
2148
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002149 if (rc) {
2150 for (i = 0; i < num_pages; i++)
2151 put_page(pages[i]);
2152 }
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002153 return rc;
2154}
2155
2156static inline
2157size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
2158{
2159 size_t num_pages;
2160 size_t clen;
2161
2162 clen = min_t(const size_t, len, wsize);
Jeff Laytona7103b92012-03-23 14:40:56 -04002163 num_pages = DIV_ROUND_UP(clen, PAGE_SIZE);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002164
2165 if (cur_len)
2166 *cur_len = clen;
2167
2168 return num_pages;
2169}
2170
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002171static void
2172cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
2173{
2174 int i;
2175 size_t bytes = wdata->bytes;
2176
2177 /* marshal up the pages into iov array */
2178 for (i = 0; i < wdata->nr_pages; i++) {
Steve Frenchc7ad42b2012-03-23 16:30:56 -05002179 iov[i + 1].iov_len = min_t(size_t, bytes, PAGE_SIZE);
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002180 iov[i + 1].iov_base = kmap(wdata->pages[i]);
2181 bytes -= iov[i + 1].iov_len;
2182 }
2183}
2184
2185static void
2186cifs_uncached_writev_complete(struct work_struct *work)
2187{
2188 int i;
2189 struct cifs_writedata *wdata = container_of(work,
2190 struct cifs_writedata, work);
2191 struct inode *inode = wdata->cfile->dentry->d_inode;
2192 struct cifsInodeInfo *cifsi = CIFS_I(inode);
2193
2194 spin_lock(&inode->i_lock);
2195 cifs_update_eof(cifsi, wdata->offset, wdata->bytes);
2196 if (cifsi->server_eof > inode->i_size)
2197 i_size_write(inode, cifsi->server_eof);
2198 spin_unlock(&inode->i_lock);
2199
2200 complete(&wdata->done);
2201
2202 if (wdata->result != -EAGAIN) {
2203 for (i = 0; i < wdata->nr_pages; i++)
2204 put_page(wdata->pages[i]);
2205 }
2206
2207 kref_put(&wdata->refcount, cifs_writedata_release);
2208}
2209
2210/* attempt to send write to server, retry on any -EAGAIN errors */
2211static int
2212cifs_uncached_retry_writev(struct cifs_writedata *wdata)
2213{
2214 int rc;
2215
2216 do {
2217 if (wdata->cfile->invalidHandle) {
2218 rc = cifs_reopen_file(wdata->cfile, false);
2219 if (rc != 0)
2220 continue;
2221 }
2222 rc = cifs_async_writev(wdata);
2223 } while (rc == -EAGAIN);
2224
2225 return rc;
2226}
2227
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002228static ssize_t
2229cifs_iovec_write(struct file *file, const struct iovec *iov,
2230 unsigned long nr_segs, loff_t *poffset)
2231{
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002232 unsigned long nr_pages, i;
Pavel Shilovsky76429c12011-01-31 16:03:08 +03002233 size_t copied, len, cur_len;
2234 ssize_t total_written = 0;
Jeff Layton3af9d8f2012-04-13 17:16:59 -04002235 loff_t offset;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002236 struct iov_iter it;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002237 struct cifsFileInfo *open_file;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002238 struct cifs_tcon *tcon;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002239 struct cifs_sb_info *cifs_sb;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002240 struct cifs_writedata *wdata, *tmp;
2241 struct list_head wdata_list;
2242 int rc;
2243 pid_t pid;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002244
2245 len = iov_length(iov, nr_segs);
2246 if (!len)
2247 return 0;
2248
2249 rc = generic_write_checks(file, poffset, &len, 0);
2250 if (rc)
2251 return rc;
2252
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002253 INIT_LIST_HEAD(&wdata_list);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002254 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002255 open_file = file->private_data;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002256 tcon = tlink_tcon(open_file->tlink);
Jeff Layton3af9d8f2012-04-13 17:16:59 -04002257 offset = *poffset;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002258
2259 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2260 pid = open_file->pid;
2261 else
2262 pid = current->tgid;
2263
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002264 iov_iter_init(&it, iov, nr_segs, len, 0);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002265 do {
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002266 size_t save_len;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002267
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002268 nr_pages = get_numpages(cifs_sb->wsize, len, &cur_len);
2269 wdata = cifs_writedata_alloc(nr_pages,
2270 cifs_uncached_writev_complete);
2271 if (!wdata) {
2272 rc = -ENOMEM;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002273 break;
2274 }
2275
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002276 rc = cifs_write_allocate_pages(wdata->pages, nr_pages);
2277 if (rc) {
2278 kfree(wdata);
2279 break;
2280 }
2281
2282 save_len = cur_len;
2283 for (i = 0; i < nr_pages; i++) {
2284 copied = min_t(const size_t, cur_len, PAGE_SIZE);
2285 copied = iov_iter_copy_from_user(wdata->pages[i], &it,
2286 0, copied);
2287 cur_len -= copied;
2288 iov_iter_advance(&it, copied);
2289 }
2290 cur_len = save_len - cur_len;
2291
2292 wdata->sync_mode = WB_SYNC_ALL;
2293 wdata->nr_pages = nr_pages;
2294 wdata->offset = (__u64)offset;
2295 wdata->cfile = cifsFileInfo_get(open_file);
2296 wdata->pid = pid;
2297 wdata->bytes = cur_len;
2298 wdata->marshal_iov = cifs_uncached_marshal_iov;
2299 rc = cifs_uncached_retry_writev(wdata);
2300 if (rc) {
2301 kref_put(&wdata->refcount, cifs_writedata_release);
2302 break;
2303 }
2304
2305 list_add_tail(&wdata->list, &wdata_list);
2306 offset += cur_len;
2307 len -= cur_len;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002308 } while (len > 0);
2309
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002310 /*
2311 * If at least one write was successfully sent, then discard any rc
2312 * value from the later writes. If the other write succeeds, then
2313 * we'll end up returning whatever was written. If it fails, then
2314 * we'll get a new rc value from that.
2315 */
2316 if (!list_empty(&wdata_list))
2317 rc = 0;
2318
2319 /*
2320 * Wait for and collect replies for any successful sends in order of
2321 * increasing offset. Once an error is hit or we get a fatal signal
2322 * while waiting, then return without waiting for any more replies.
2323 */
2324restart_loop:
2325 list_for_each_entry_safe(wdata, tmp, &wdata_list, list) {
2326 if (!rc) {
2327 /* FIXME: freezable too? */
2328 rc = wait_for_completion_killable(&wdata->done);
2329 if (rc)
2330 rc = -EINTR;
2331 else if (wdata->result)
2332 rc = wdata->result;
2333 else
2334 total_written += wdata->bytes;
2335
2336 /* resend call if it's a retryable error */
2337 if (rc == -EAGAIN) {
2338 rc = cifs_uncached_retry_writev(wdata);
2339 goto restart_loop;
2340 }
2341 }
2342 list_del_init(&wdata->list);
2343 kref_put(&wdata->refcount, cifs_writedata_release);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002344 }
2345
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002346 if (total_written > 0)
2347 *poffset += total_written;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002348
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002349 cifs_stats_bytes_written(tcon, total_written);
2350 return total_written ? total_written : (ssize_t)rc;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002351}
2352
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03002353ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002354 unsigned long nr_segs, loff_t pos)
2355{
2356 ssize_t written;
2357 struct inode *inode;
2358
2359 inode = iocb->ki_filp->f_path.dentry->d_inode;
2360
2361 /*
2362 * BB - optimize the way when signing is disabled. We can drop this
2363 * extra memory-to-memory copying and use iovec buffers for constructing
2364 * write request.
2365 */
2366
2367 written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos);
2368 if (written > 0) {
2369 CIFS_I(inode)->invalid_mapping = true;
2370 iocb->ki_pos = pos;
2371 }
2372
2373 return written;
2374}
2375
2376ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
2377 unsigned long nr_segs, loff_t pos)
2378{
2379 struct inode *inode;
2380
2381 inode = iocb->ki_filp->f_path.dentry->d_inode;
2382
2383 if (CIFS_I(inode)->clientCanCacheAll)
2384 return generic_file_aio_write(iocb, iov, nr_segs, pos);
2385
2386 /*
2387 * In strict cache mode we need to write the data to the server exactly
2388 * from the pos to pos+len-1 rather than flush all affected pages
2389 * because it may cause a error with mandatory locks on these pages but
2390 * not on the region from pos to ppos+len-1.
2391 */
2392
2393 return cifs_user_writev(iocb, iov, nr_segs, pos);
2394}
2395
Jeff Layton0471ca32012-05-16 07:13:16 -04002396static struct cifs_readdata *
2397cifs_readdata_alloc(unsigned int nr_vecs, work_func_t complete)
2398{
2399 struct cifs_readdata *rdata;
2400
2401 rdata = kzalloc(sizeof(*rdata) +
2402 sizeof(struct kvec) * nr_vecs, GFP_KERNEL);
2403 if (rdata != NULL) {
Jeff Layton6993f742012-05-16 07:13:17 -04002404 kref_init(&rdata->refcount);
Jeff Layton1c892542012-05-16 07:13:17 -04002405 INIT_LIST_HEAD(&rdata->list);
2406 init_completion(&rdata->done);
Jeff Layton0471ca32012-05-16 07:13:16 -04002407 INIT_WORK(&rdata->work, complete);
2408 INIT_LIST_HEAD(&rdata->pages);
2409 }
2410 return rdata;
2411}
2412
Jeff Layton6993f742012-05-16 07:13:17 -04002413void
2414cifs_readdata_release(struct kref *refcount)
Jeff Layton0471ca32012-05-16 07:13:16 -04002415{
Jeff Layton6993f742012-05-16 07:13:17 -04002416 struct cifs_readdata *rdata = container_of(refcount,
2417 struct cifs_readdata, refcount);
2418
2419 if (rdata->cfile)
2420 cifsFileInfo_put(rdata->cfile);
2421
Jeff Layton0471ca32012-05-16 07:13:16 -04002422 kfree(rdata);
2423}
2424
Jeff Layton2a1bb132012-05-16 07:13:17 -04002425static int
Jeff Layton1c892542012-05-16 07:13:17 -04002426cifs_read_allocate_pages(struct list_head *list, unsigned int npages)
2427{
2428 int rc = 0;
2429 struct page *page, *tpage;
2430 unsigned int i;
2431
2432 for (i = 0; i < npages; i++) {
2433 page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
2434 if (!page) {
2435 rc = -ENOMEM;
2436 break;
2437 }
2438 list_add(&page->lru, list);
2439 }
2440
2441 if (rc) {
2442 list_for_each_entry_safe(page, tpage, list, lru) {
2443 list_del(&page->lru);
2444 put_page(page);
2445 }
2446 }
2447 return rc;
2448}
2449
2450static void
2451cifs_uncached_readdata_release(struct kref *refcount)
2452{
2453 struct page *page, *tpage;
2454 struct cifs_readdata *rdata = container_of(refcount,
2455 struct cifs_readdata, refcount);
2456
2457 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2458 list_del(&page->lru);
2459 put_page(page);
2460 }
2461 cifs_readdata_release(refcount);
2462}
2463
2464static int
Jeff Layton2a1bb132012-05-16 07:13:17 -04002465cifs_retry_async_readv(struct cifs_readdata *rdata)
2466{
2467 int rc;
2468
2469 do {
2470 if (rdata->cfile->invalidHandle) {
2471 rc = cifs_reopen_file(rdata->cfile, true);
2472 if (rc != 0)
2473 continue;
2474 }
2475 rc = cifs_async_readv(rdata);
2476 } while (rc == -EAGAIN);
2477
2478 return rc;
2479}
2480
Jeff Layton1c892542012-05-16 07:13:17 -04002481/**
2482 * cifs_readdata_to_iov - copy data from pages in response to an iovec
2483 * @rdata: the readdata response with list of pages holding data
2484 * @iov: vector in which we should copy the data
2485 * @nr_segs: number of segments in vector
2486 * @offset: offset into file of the first iovec
2487 * @copied: used to return the amount of data copied to the iov
2488 *
2489 * This function copies data from a list of pages in a readdata response into
2490 * an array of iovecs. It will first calculate where the data should go
2491 * based on the info in the readdata and then copy the data into that spot.
2492 */
2493static ssize_t
2494cifs_readdata_to_iov(struct cifs_readdata *rdata, const struct iovec *iov,
2495 unsigned long nr_segs, loff_t offset, ssize_t *copied)
2496{
2497 int rc = 0;
2498 struct iov_iter ii;
2499 size_t pos = rdata->offset - offset;
2500 struct page *page, *tpage;
2501 ssize_t remaining = rdata->bytes;
2502 unsigned char *pdata;
2503
2504 /* set up iov_iter and advance to the correct offset */
2505 iov_iter_init(&ii, iov, nr_segs, iov_length(iov, nr_segs), 0);
2506 iov_iter_advance(&ii, pos);
2507
2508 *copied = 0;
2509 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2510 ssize_t copy;
2511
2512 /* copy a whole page or whatever's left */
2513 copy = min_t(ssize_t, remaining, PAGE_SIZE);
2514
2515 /* ...but limit it to whatever space is left in the iov */
2516 copy = min_t(ssize_t, copy, iov_iter_count(&ii));
2517
2518 /* go while there's data to be copied and no errors */
2519 if (copy && !rc) {
2520 pdata = kmap(page);
2521 rc = memcpy_toiovecend(ii.iov, pdata, ii.iov_offset,
2522 (int)copy);
2523 kunmap(page);
2524 if (!rc) {
2525 *copied += copy;
2526 remaining -= copy;
2527 iov_iter_advance(&ii, copy);
2528 }
2529 }
2530
2531 list_del(&page->lru);
2532 put_page(page);
2533 }
2534
2535 return rc;
2536}
2537
2538static void
2539cifs_uncached_readv_complete(struct work_struct *work)
2540{
2541 struct cifs_readdata *rdata = container_of(work,
2542 struct cifs_readdata, work);
2543
2544 /* if the result is non-zero then the pages weren't kmapped */
2545 if (rdata->result == 0) {
2546 struct page *page;
2547
2548 list_for_each_entry(page, &rdata->pages, lru)
2549 kunmap(page);
2550 }
2551
2552 complete(&rdata->done);
2553 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
2554}
2555
2556static int
2557cifs_uncached_read_marshal_iov(struct cifs_readdata *rdata,
2558 unsigned int remaining)
2559{
2560 int len = 0;
2561 struct page *page, *tpage;
2562
2563 rdata->nr_iov = 1;
2564 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2565 if (remaining >= PAGE_SIZE) {
2566 /* enough data to fill the page */
2567 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2568 rdata->iov[rdata->nr_iov].iov_len = PAGE_SIZE;
2569 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2570 rdata->nr_iov, page->index,
2571 rdata->iov[rdata->nr_iov].iov_base,
2572 rdata->iov[rdata->nr_iov].iov_len);
2573 ++rdata->nr_iov;
2574 len += PAGE_SIZE;
2575 remaining -= PAGE_SIZE;
2576 } else if (remaining > 0) {
2577 /* enough for partial page, fill and zero the rest */
2578 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2579 rdata->iov[rdata->nr_iov].iov_len = remaining;
2580 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2581 rdata->nr_iov, page->index,
2582 rdata->iov[rdata->nr_iov].iov_base,
2583 rdata->iov[rdata->nr_iov].iov_len);
2584 memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
2585 '\0', PAGE_SIZE - remaining);
2586 ++rdata->nr_iov;
2587 len += remaining;
2588 remaining = 0;
2589 } else {
2590 /* no need to hold page hostage */
2591 list_del(&page->lru);
2592 put_page(page);
2593 }
2594 }
2595
2596 return len;
2597}
2598
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002599static ssize_t
2600cifs_iovec_read(struct file *file, const struct iovec *iov,
2601 unsigned long nr_segs, loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602{
Jeff Layton1c892542012-05-16 07:13:17 -04002603 ssize_t rc;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002604 size_t len, cur_len;
Jeff Layton1c892542012-05-16 07:13:17 -04002605 ssize_t total_read = 0;
2606 loff_t offset = *poffset;
2607 unsigned int npages;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608 struct cifs_sb_info *cifs_sb;
Jeff Layton1c892542012-05-16 07:13:17 -04002609 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 struct cifsFileInfo *open_file;
Jeff Layton1c892542012-05-16 07:13:17 -04002611 struct cifs_readdata *rdata, *tmp;
2612 struct list_head rdata_list;
2613 pid_t pid;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002614
2615 if (!nr_segs)
2616 return 0;
2617
2618 len = iov_length(iov, nr_segs);
2619 if (!len)
2620 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621
Jeff Layton1c892542012-05-16 07:13:17 -04002622 INIT_LIST_HEAD(&rdata_list);
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002623 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -07002624 open_file = file->private_data;
Jeff Layton1c892542012-05-16 07:13:17 -04002625 tcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002627 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2628 pid = open_file->pid;
2629 else
2630 pid = current->tgid;
2631
Steve Frenchad7a2922008-02-07 23:25:02 +00002632 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002633 cFYI(1, "attempting read on write only file instance");
Steve Frenchad7a2922008-02-07 23:25:02 +00002634
Jeff Layton1c892542012-05-16 07:13:17 -04002635 do {
2636 cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize);
2637 npages = DIV_ROUND_UP(cur_len, PAGE_SIZE);
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002638
Jeff Layton1c892542012-05-16 07:13:17 -04002639 /* allocate a readdata struct */
2640 rdata = cifs_readdata_alloc(npages,
2641 cifs_uncached_readv_complete);
2642 if (!rdata) {
2643 rc = -ENOMEM;
2644 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002646
Jeff Layton1c892542012-05-16 07:13:17 -04002647 rc = cifs_read_allocate_pages(&rdata->pages, npages);
2648 if (rc)
2649 goto error;
2650
2651 rdata->cfile = cifsFileInfo_get(open_file);
2652 rdata->offset = offset;
2653 rdata->bytes = cur_len;
2654 rdata->pid = pid;
2655 rdata->marshal_iov = cifs_uncached_read_marshal_iov;
2656
2657 rc = cifs_retry_async_readv(rdata);
2658error:
2659 if (rc) {
2660 kref_put(&rdata->refcount,
2661 cifs_uncached_readdata_release);
2662 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 }
Jeff Layton1c892542012-05-16 07:13:17 -04002664
2665 list_add_tail(&rdata->list, &rdata_list);
2666 offset += cur_len;
2667 len -= cur_len;
2668 } while (len > 0);
2669
2670 /* if at least one read request send succeeded, then reset rc */
2671 if (!list_empty(&rdata_list))
2672 rc = 0;
2673
2674 /* the loop below should proceed in the order of increasing offsets */
2675restart_loop:
2676 list_for_each_entry_safe(rdata, tmp, &rdata_list, list) {
2677 if (!rc) {
2678 ssize_t copied;
2679
2680 /* FIXME: freezable sleep too? */
2681 rc = wait_for_completion_killable(&rdata->done);
2682 if (rc)
2683 rc = -EINTR;
2684 else if (rdata->result)
2685 rc = rdata->result;
2686 else {
2687 rc = cifs_readdata_to_iov(rdata, iov,
2688 nr_segs, *poffset,
2689 &copied);
2690 total_read += copied;
2691 }
2692
2693 /* resend call if it's a retryable error */
2694 if (rc == -EAGAIN) {
2695 rc = cifs_retry_async_readv(rdata);
2696 goto restart_loop;
2697 }
2698 }
2699 list_del_init(&rdata->list);
2700 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002702
Jeff Layton1c892542012-05-16 07:13:17 -04002703 cifs_stats_bytes_read(tcon, total_read);
2704 *poffset += total_read;
2705
2706 return total_read ? total_read : rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707}
2708
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03002709ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002710 unsigned long nr_segs, loff_t pos)
2711{
2712 ssize_t read;
2713
2714 read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos);
2715 if (read > 0)
2716 iocb->ki_pos = pos;
2717
2718 return read;
2719}
2720
2721ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov,
2722 unsigned long nr_segs, loff_t pos)
2723{
2724 struct inode *inode;
2725
2726 inode = iocb->ki_filp->f_path.dentry->d_inode;
2727
2728 if (CIFS_I(inode)->clientCanCacheRead)
2729 return generic_file_aio_read(iocb, iov, nr_segs, pos);
2730
2731 /*
2732 * In strict cache mode we need to read from the server all the time
2733 * if we don't have level II oplock because the server can delay mtime
2734 * change - so we can't make a decision about inode invalidating.
2735 * And we can also fail with pagereading if there are mandatory locks
2736 * on pages affected by this read but not on the region from pos to
2737 * pos+len-1.
2738 */
2739
2740 return cifs_user_readv(iocb, iov, nr_segs, pos);
2741}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742
2743static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002744 loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745{
2746 int rc = -EACCES;
2747 unsigned int bytes_read = 0;
2748 unsigned int total_read;
2749 unsigned int current_read_size;
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002750 unsigned int rsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 struct cifs_sb_info *cifs_sb;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04002752 struct cifs_tcon *tcon;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002753 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754 char *current_offset;
2755 struct cifsFileInfo *open_file;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002756 struct cifs_io_parms io_parms;
Steve Frenchec637e32005-12-12 20:53:18 -08002757 int buf_type = CIFS_NO_BUFFER;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002758 __u32 pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002760 xid = get_xid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002761 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002763 /* FIXME: set up handlers for larger reads and/or convert to async */
2764 rsize = min_t(unsigned int, cifs_sb->rsize, CIFSMaxBufSize);
2765
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302767 rc = -EBADF;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002768 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302769 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 }
Joe Perchesc21dfb62010-07-12 13:50:14 -07002771 open_file = file->private_data;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04002772 tcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002774 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2775 pid = open_file->pid;
2776 else
2777 pid = current->tgid;
2778
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002780 cFYI(1, "attempting read on write only file instance");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002782 for (total_read = 0, current_offset = read_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 read_size > total_read;
2784 total_read += bytes_read, current_offset += bytes_read) {
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002785 current_read_size = min_t(uint, read_size - total_read, rsize);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04002786 /*
2787 * For windows me and 9x we do not want to request more than it
2788 * negotiated since it will refuse the read then.
2789 */
2790 if ((tcon->ses) && !(tcon->ses->capabilities &
2791 tcon->ses->server->vals->cap_large_files)) {
Dan Carpenter7748dd62011-10-18 12:41:35 +03002792 current_read_size = min_t(uint, current_read_size,
Jeff Laytonc974bef2011-10-11 06:41:32 -04002793 CIFSMaxBufSize);
Steve Frenchf9f5c8172005-09-15 23:06:38 -07002794 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 rc = -EAGAIN;
2796 while (rc == -EAGAIN) {
Steve Frenchcdff08e2010-10-21 22:46:14 +00002797 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04002798 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 if (rc != 0)
2800 break;
2801 }
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002802 io_parms.netfid = open_file->fid.netfid;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002803 io_parms.pid = pid;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04002804 io_parms.tcon = tcon;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002805 io_parms.offset = *poffset;
2806 io_parms.length = current_read_size;
2807 rc = CIFSSMBRead(xid, &io_parms, &bytes_read,
2808 &current_offset, &buf_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809 }
2810 if (rc || (bytes_read == 0)) {
2811 if (total_read) {
2812 break;
2813 } else {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002814 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815 return rc;
2816 }
2817 } else {
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04002818 cifs_stats_bytes_read(tcon, total_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 *poffset += bytes_read;
2820 }
2821 }
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002822 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 return total_read;
2824}
2825
Jeff Laytonca83ce32011-04-12 09:13:44 -04002826/*
2827 * If the page is mmap'ed into a process' page tables, then we need to make
2828 * sure that it doesn't change while being written back.
2829 */
2830static int
2831cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
2832{
2833 struct page *page = vmf->page;
2834
2835 lock_page(page);
2836 return VM_FAULT_LOCKED;
2837}
2838
2839static struct vm_operations_struct cifs_file_vm_ops = {
2840 .fault = filemap_fault,
2841 .page_mkwrite = cifs_page_mkwrite,
2842};
2843
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002844int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
2845{
2846 int rc, xid;
2847 struct inode *inode = file->f_path.dentry->d_inode;
2848
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002849 xid = get_xid();
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002850
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002851 if (!CIFS_I(inode)->clientCanCacheRead) {
2852 rc = cifs_invalidate_mapping(inode);
2853 if (rc)
2854 return rc;
2855 }
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002856
2857 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04002858 if (rc == 0)
2859 vma->vm_ops = &cifs_file_vm_ops;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002860 free_xid(xid);
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002861 return rc;
2862}
2863
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
2865{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866 int rc, xid;
2867
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002868 xid = get_xid();
Jeff Laytonabab0952010-02-12 07:44:18 -05002869 rc = cifs_revalidate_file(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002871 cFYI(1, "Validation prior to mmap failed, error=%d", rc);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002872 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873 return rc;
2874 }
2875 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04002876 if (rc == 0)
2877 vma->vm_ops = &cifs_file_vm_ops;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002878 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 return rc;
2880}
2881
Jeff Layton0471ca32012-05-16 07:13:16 -04002882static void
2883cifs_readv_complete(struct work_struct *work)
2884{
2885 struct cifs_readdata *rdata = container_of(work,
2886 struct cifs_readdata, work);
2887 struct page *page, *tpage;
2888
2889 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2890 list_del(&page->lru);
2891 lru_cache_add_file(page);
2892
2893 if (rdata->result == 0) {
2894 kunmap(page);
2895 flush_dcache_page(page);
2896 SetPageUptodate(page);
2897 }
2898
2899 unlock_page(page);
2900
2901 if (rdata->result == 0)
2902 cifs_readpage_to_fscache(rdata->mapping->host, page);
2903
2904 page_cache_release(page);
2905 }
Jeff Layton6993f742012-05-16 07:13:17 -04002906 kref_put(&rdata->refcount, cifs_readdata_release);
Jeff Layton0471ca32012-05-16 07:13:16 -04002907}
2908
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04002909static int
2910cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining)
2911{
2912 int len = 0;
2913 struct page *page, *tpage;
2914 u64 eof;
2915 pgoff_t eof_index;
2916
2917 /* determine the eof that the server (probably) has */
2918 eof = CIFS_I(rdata->mapping->host)->server_eof;
2919 eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
2920 cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
2921
2922 rdata->nr_iov = 1;
2923 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2924 if (remaining >= PAGE_CACHE_SIZE) {
2925 /* enough data to fill the page */
2926 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2927 rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE;
2928 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2929 rdata->nr_iov, page->index,
2930 rdata->iov[rdata->nr_iov].iov_base,
2931 rdata->iov[rdata->nr_iov].iov_len);
2932 ++rdata->nr_iov;
2933 len += PAGE_CACHE_SIZE;
2934 remaining -= PAGE_CACHE_SIZE;
2935 } else if (remaining > 0) {
2936 /* enough for partial page, fill and zero the rest */
2937 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2938 rdata->iov[rdata->nr_iov].iov_len = remaining;
2939 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2940 rdata->nr_iov, page->index,
2941 rdata->iov[rdata->nr_iov].iov_base,
2942 rdata->iov[rdata->nr_iov].iov_len);
2943 memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
2944 '\0', PAGE_CACHE_SIZE - remaining);
2945 ++rdata->nr_iov;
2946 len += remaining;
2947 remaining = 0;
2948 } else if (page->index > eof_index) {
2949 /*
2950 * The VFS will not try to do readahead past the
2951 * i_size, but it's possible that we have outstanding
2952 * writes with gaps in the middle and the i_size hasn't
2953 * caught up yet. Populate those with zeroed out pages
2954 * to prevent the VFS from repeatedly attempting to
2955 * fill them until the writes are flushed.
2956 */
2957 zero_user(page, 0, PAGE_CACHE_SIZE);
2958 list_del(&page->lru);
2959 lru_cache_add_file(page);
2960 flush_dcache_page(page);
2961 SetPageUptodate(page);
2962 unlock_page(page);
2963 page_cache_release(page);
2964 } else {
2965 /* no need to hold page hostage */
2966 list_del(&page->lru);
2967 lru_cache_add_file(page);
2968 unlock_page(page);
2969 page_cache_release(page);
2970 }
2971 }
2972
2973 return len;
2974}
2975
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976static int cifs_readpages(struct file *file, struct address_space *mapping,
2977 struct list_head *page_list, unsigned num_pages)
2978{
Jeff Layton690c5e32011-10-19 15:30:16 -04002979 int rc;
2980 struct list_head tmplist;
2981 struct cifsFileInfo *open_file = file->private_data;
2982 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
2983 unsigned int rsize = cifs_sb->rsize;
2984 pid_t pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985
Jeff Layton690c5e32011-10-19 15:30:16 -04002986 /*
2987 * Give up immediately if rsize is too small to read an entire page.
2988 * The VFS will fall back to readpage. We should never reach this
2989 * point however since we set ra_pages to 0 when the rsize is smaller
2990 * than a cache page.
2991 */
2992 if (unlikely(rsize < PAGE_CACHE_SIZE))
2993 return 0;
Steve Frenchbfa0d752005-08-31 21:50:37 -07002994
Suresh Jayaraman56698232010-07-05 18:13:25 +05302995 /*
2996 * Reads as many pages as possible from fscache. Returns -ENOBUFS
2997 * immediately if the cookie is negative
2998 */
2999 rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
3000 &num_pages);
3001 if (rc == 0)
Jeff Layton690c5e32011-10-19 15:30:16 -04003002 return rc;
Suresh Jayaraman56698232010-07-05 18:13:25 +05303003
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003004 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
3005 pid = open_file->pid;
3006 else
3007 pid = current->tgid;
3008
Jeff Layton690c5e32011-10-19 15:30:16 -04003009 rc = 0;
3010 INIT_LIST_HEAD(&tmplist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011
Jeff Layton690c5e32011-10-19 15:30:16 -04003012 cFYI(1, "%s: file=%p mapping=%p num_pages=%u", __func__, file,
3013 mapping, num_pages);
3014
3015 /*
3016 * Start with the page at end of list and move it to private
3017 * list. Do the same with any following pages until we hit
3018 * the rsize limit, hit an index discontinuity, or run out of
3019 * pages. Issue the async read and then start the loop again
3020 * until the list is empty.
3021 *
3022 * Note that list order is important. The page_list is in
3023 * the order of declining indexes. When we put the pages in
3024 * the rdata->pages, then we want them in increasing order.
3025 */
3026 while (!list_empty(page_list)) {
3027 unsigned int bytes = PAGE_CACHE_SIZE;
3028 unsigned int expected_index;
3029 unsigned int nr_pages = 1;
3030 loff_t offset;
3031 struct page *page, *tpage;
3032 struct cifs_readdata *rdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033
3034 page = list_entry(page_list->prev, struct page, lru);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035
Jeff Layton690c5e32011-10-19 15:30:16 -04003036 /*
3037 * Lock the page and put it in the cache. Since no one else
3038 * should have access to this page, we're safe to simply set
3039 * PG_locked without checking it first.
3040 */
3041 __set_page_locked(page);
3042 rc = add_to_page_cache_locked(page, mapping,
3043 page->index, GFP_KERNEL);
3044
3045 /* give up if we can't stick it in the cache */
3046 if (rc) {
3047 __clear_page_locked(page);
3048 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050
Jeff Layton690c5e32011-10-19 15:30:16 -04003051 /* move first page to the tmplist */
3052 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
3053 list_move_tail(&page->lru, &tmplist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054
Jeff Layton690c5e32011-10-19 15:30:16 -04003055 /* now try and add more pages onto the request */
3056 expected_index = page->index + 1;
3057 list_for_each_entry_safe_reverse(page, tpage, page_list, lru) {
3058 /* discontinuity ? */
3059 if (page->index != expected_index)
3060 break;
3061
3062 /* would this page push the read over the rsize? */
3063 if (bytes + PAGE_CACHE_SIZE > rsize)
3064 break;
3065
3066 __set_page_locked(page);
3067 if (add_to_page_cache_locked(page, mapping,
3068 page->index, GFP_KERNEL)) {
3069 __clear_page_locked(page);
3070 break;
3071 }
3072 list_move_tail(&page->lru, &tmplist);
3073 bytes += PAGE_CACHE_SIZE;
3074 expected_index++;
3075 nr_pages++;
3076 }
3077
Jeff Layton0471ca32012-05-16 07:13:16 -04003078 rdata = cifs_readdata_alloc(nr_pages, cifs_readv_complete);
Jeff Layton690c5e32011-10-19 15:30:16 -04003079 if (!rdata) {
3080 /* best to give up if we're out of mem */
3081 list_for_each_entry_safe(page, tpage, &tmplist, lru) {
3082 list_del(&page->lru);
3083 lru_cache_add_file(page);
3084 unlock_page(page);
3085 page_cache_release(page);
3086 }
3087 rc = -ENOMEM;
3088 break;
3089 }
3090
Jeff Layton6993f742012-05-16 07:13:17 -04003091 rdata->cfile = cifsFileInfo_get(open_file);
Jeff Layton690c5e32011-10-19 15:30:16 -04003092 rdata->mapping = mapping;
3093 rdata->offset = offset;
3094 rdata->bytes = bytes;
3095 rdata->pid = pid;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003096 rdata->marshal_iov = cifs_readpages_marshal_iov;
Jeff Layton690c5e32011-10-19 15:30:16 -04003097 list_splice_init(&tmplist, &rdata->pages);
3098
Jeff Layton2a1bb132012-05-16 07:13:17 -04003099 rc = cifs_retry_async_readv(rdata);
Jeff Layton690c5e32011-10-19 15:30:16 -04003100 if (rc != 0) {
3101 list_for_each_entry_safe(page, tpage, &rdata->pages,
3102 lru) {
3103 list_del(&page->lru);
3104 lru_cache_add_file(page);
3105 unlock_page(page);
3106 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107 }
Jeff Layton6993f742012-05-16 07:13:17 -04003108 kref_put(&rdata->refcount, cifs_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 break;
3110 }
Jeff Layton6993f742012-05-16 07:13:17 -04003111
3112 kref_put(&rdata->refcount, cifs_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113 }
3114
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115 return rc;
3116}
3117
3118static int cifs_readpage_worker(struct file *file, struct page *page,
3119 loff_t *poffset)
3120{
3121 char *read_data;
3122 int rc;
3123
Suresh Jayaraman56698232010-07-05 18:13:25 +05303124 /* Is the page cached? */
3125 rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page);
3126 if (rc == 0)
3127 goto read_complete;
3128
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129 page_cache_get(page);
3130 read_data = kmap(page);
3131 /* for reads over a certain size could initiate async read ahead */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003132
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003134
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 if (rc < 0)
3136 goto io_error;
3137 else
Joe Perchesb6b38f72010-04-21 03:50:45 +00003138 cFYI(1, "Bytes read %d", rc);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003139
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08003140 file->f_path.dentry->d_inode->i_atime =
3141 current_fs_time(file->f_path.dentry->d_inode->i_sb);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003142
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 if (PAGE_CACHE_SIZE > rc)
3144 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
3145
3146 flush_dcache_page(page);
3147 SetPageUptodate(page);
Suresh Jayaraman9dc06552010-07-05 18:13:11 +05303148
3149 /* send this page to the cache */
3150 cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page);
3151
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152 rc = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003153
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154io_error:
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003155 kunmap(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156 page_cache_release(page);
Suresh Jayaraman56698232010-07-05 18:13:25 +05303157
3158read_complete:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159 return rc;
3160}
3161
3162static int cifs_readpage(struct file *file, struct page *page)
3163{
3164 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
3165 int rc = -EACCES;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003166 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003168 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169
3170 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05303171 rc = -EBADF;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003172 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05303173 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174 }
3175
Jeff Laytonac3aa2f2012-07-23 13:14:28 -04003176 cFYI(1, "readpage %p at offset %d 0x%x",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003177 page, (int)offset, (int)offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178
3179 rc = cifs_readpage_worker(file, page, &offset);
3180
3181 unlock_page(page);
3182
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003183 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184 return rc;
3185}
3186
Steve Frencha403a0a2007-07-26 15:54:16 +00003187static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
3188{
3189 struct cifsFileInfo *open_file;
3190
Jeff Layton44772882010-10-15 15:34:03 -04003191 spin_lock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003192 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton2e396b82010-10-15 15:34:01 -04003193 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Jeff Layton44772882010-10-15 15:34:03 -04003194 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003195 return 1;
3196 }
3197 }
Jeff Layton44772882010-10-15 15:34:03 -04003198 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003199 return 0;
3200}
3201
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202/* We do not want to update the file size from server for inodes
3203 open for write - to avoid races with writepage extending
3204 the file - in the future we could consider allowing
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003205 refreshing the inode only on increases in the file size
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206 but this is tricky to do without racing with writebehind
3207 page caching in the current Linux kernel design */
Steve French4b18f2a2008-04-29 00:06:05 +00003208bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209{
Steve Frencha403a0a2007-07-26 15:54:16 +00003210 if (!cifsInode)
Steve French4b18f2a2008-04-29 00:06:05 +00003211 return true;
Steve French23e7dd72005-10-20 13:44:56 -07003212
Steve Frencha403a0a2007-07-26 15:54:16 +00003213 if (is_inode_writable(cifsInode)) {
3214 /* This inode is open for write at least once */
Steve Frenchc32a0b62006-01-12 14:41:28 -08003215 struct cifs_sb_info *cifs_sb;
3216
Steve Frenchc32a0b62006-01-12 14:41:28 -08003217 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
Steve Frenchad7a2922008-02-07 23:25:02 +00003218 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003219 /* since no page cache to corrupt on directio
Steve Frenchc32a0b62006-01-12 14:41:28 -08003220 we can change size safely */
Steve French4b18f2a2008-04-29 00:06:05 +00003221 return true;
Steve Frenchc32a0b62006-01-12 14:41:28 -08003222 }
3223
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003224 if (i_size_read(&cifsInode->vfs_inode) < end_of_file)
Steve French4b18f2a2008-04-29 00:06:05 +00003225 return true;
Steve French7ba52632007-02-08 18:14:13 +00003226
Steve French4b18f2a2008-04-29 00:06:05 +00003227 return false;
Steve French23e7dd72005-10-20 13:44:56 -07003228 } else
Steve French4b18f2a2008-04-29 00:06:05 +00003229 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230}
3231
Nick Piggind9414772008-09-24 11:32:59 -04003232static int cifs_write_begin(struct file *file, struct address_space *mapping,
3233 loff_t pos, unsigned len, unsigned flags,
3234 struct page **pagep, void **fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235{
Nick Piggind9414772008-09-24 11:32:59 -04003236 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
3237 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003238 loff_t page_start = pos & PAGE_MASK;
3239 loff_t i_size;
3240 struct page *page;
3241 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242
Joe Perchesb6b38f72010-04-21 03:50:45 +00003243 cFYI(1, "write_begin from %lld len %d", (long long)pos, len);
Nick Piggind9414772008-09-24 11:32:59 -04003244
Nick Piggin54566b22009-01-04 12:00:53 -08003245 page = grab_cache_page_write_begin(mapping, index, flags);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003246 if (!page) {
3247 rc = -ENOMEM;
3248 goto out;
3249 }
Nick Piggind9414772008-09-24 11:32:59 -04003250
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003251 if (PageUptodate(page))
3252 goto out;
Steve French8a236262007-03-06 00:31:00 +00003253
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003254 /*
3255 * If we write a full page it will be up to date, no need to read from
3256 * the server. If the write is short, we'll end up doing a sync write
3257 * instead.
3258 */
3259 if (len == PAGE_CACHE_SIZE)
3260 goto out;
3261
3262 /*
3263 * optimize away the read when we have an oplock, and we're not
3264 * expecting to use any of the data we'd be reading in. That
3265 * is, when the page lies beyond the EOF, or straddles the EOF
3266 * and the write will cover all of the existing data.
3267 */
3268 if (CIFS_I(mapping->host)->clientCanCacheRead) {
3269 i_size = i_size_read(mapping->host);
3270 if (page_start >= i_size ||
3271 (offset == 0 && (pos + len) >= i_size)) {
3272 zero_user_segments(page, 0, offset,
3273 offset + len,
3274 PAGE_CACHE_SIZE);
3275 /*
3276 * PageChecked means that the parts of the page
3277 * to which we're not writing are considered up
3278 * to date. Once the data is copied to the
3279 * page, it can be set uptodate.
3280 */
3281 SetPageChecked(page);
3282 goto out;
3283 }
3284 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285
Nick Piggind9414772008-09-24 11:32:59 -04003286 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003287 /*
3288 * might as well read a page, it is fast enough. If we get
3289 * an error, we don't need to return it. cifs_write_end will
3290 * do a sync write instead since PG_uptodate isn't set.
3291 */
3292 cifs_readpage_worker(file, page, &page_start);
Steve French8a236262007-03-06 00:31:00 +00003293 } else {
3294 /* we could try using another file handle if there is one -
3295 but how would we lock it to prevent close of that handle
3296 racing with this read? In any case
Nick Piggind9414772008-09-24 11:32:59 -04003297 this will be written out by write_end so is fine */
Steve French8a236262007-03-06 00:31:00 +00003298 }
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003299out:
3300 *pagep = page;
3301 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302}
3303
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303304static int cifs_release_page(struct page *page, gfp_t gfp)
3305{
3306 if (PagePrivate(page))
3307 return 0;
3308
3309 return cifs_fscache_release_page(page, gfp);
3310}
3311
3312static void cifs_invalidate_page(struct page *page, unsigned long offset)
3313{
3314 struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
3315
3316 if (offset == 0)
3317 cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
3318}
3319
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003320static int cifs_launder_page(struct page *page)
3321{
3322 int rc = 0;
3323 loff_t range_start = page_offset(page);
3324 loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
3325 struct writeback_control wbc = {
3326 .sync_mode = WB_SYNC_ALL,
3327 .nr_to_write = 0,
3328 .range_start = range_start,
3329 .range_end = range_end,
3330 };
3331
3332 cFYI(1, "Launder page: %p", page);
3333
3334 if (clear_page_dirty_for_io(page))
3335 rc = cifs_writepage_locked(page, &wbc);
3336
3337 cifs_fscache_invalidate_page(page, page->mapping->host);
3338 return rc;
3339}
3340
Tejun Heo9b646972010-07-20 22:09:02 +02003341void cifs_oplock_break(struct work_struct *work)
Jeff Layton3bc303c2009-09-21 06:47:50 -04003342{
3343 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
3344 oplock_break);
Jeff Laytona5e18bc2010-10-11 15:07:18 -04003345 struct inode *inode = cfile->dentry->d_inode;
Jeff Layton3bc303c2009-09-21 06:47:50 -04003346 struct cifsInodeInfo *cinode = CIFS_I(inode);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04003347 int rc = 0;
Jeff Layton3bc303c2009-09-21 06:47:50 -04003348
3349 if (inode && S_ISREG(inode->i_mode)) {
Steve Frenchd54ff732010-04-27 04:38:15 +00003350 if (cinode->clientCanCacheRead)
Al Viro8737c932009-12-24 06:47:55 -05003351 break_lease(inode, O_RDONLY);
Steve Frenchd54ff732010-04-27 04:38:15 +00003352 else
Al Viro8737c932009-12-24 06:47:55 -05003353 break_lease(inode, O_WRONLY);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003354 rc = filemap_fdatawrite(inode->i_mapping);
3355 if (cinode->clientCanCacheRead == 0) {
Jeff Laytoneb4b7562010-10-22 14:52:29 -04003356 rc = filemap_fdatawait(inode->i_mapping);
3357 mapping_set_error(inode->i_mapping, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003358 invalidate_remote_inode(inode);
3359 }
Joe Perchesb6b38f72010-04-21 03:50:45 +00003360 cFYI(1, "Oplock flush inode %p rc %d", inode, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003361 }
3362
Pavel Shilovsky85160e02011-10-22 15:33:29 +04003363 rc = cifs_push_locks(cfile);
3364 if (rc)
3365 cERROR(1, "Push locks rc = %d", rc);
3366
Jeff Layton3bc303c2009-09-21 06:47:50 -04003367 /*
3368 * releasing stale oplock after recent reconnect of smb session using
3369 * a now incorrect file handle is not a data integrity issue but do
3370 * not bother sending an oplock release if session to server still is
3371 * disconnected since oplock already released by the server
3372 */
Steve Frenchcdff08e2010-10-21 22:46:14 +00003373 if (!cfile->oplock_break_cancelled) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07003374 rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->fid.netfid,
Pavel Shilovsky03776f42010-08-17 11:26:00 +04003375 current->tgid, 0, 0, 0, 0,
3376 LOCKING_ANDX_OPLOCK_RELEASE, false,
Pavel Shilovsky12fed002011-01-17 20:15:44 +03003377 cinode->clientCanCacheRead ? 1 : 0);
Joe Perchesb6b38f72010-04-21 03:50:45 +00003378 cFYI(1, "Oplock release rc = %d", rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003379 }
Jeff Layton3bc303c2009-09-21 06:47:50 -04003380}
3381
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07003382const struct address_space_operations cifs_addr_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383 .readpage = cifs_readpage,
3384 .readpages = cifs_readpages,
3385 .writepage = cifs_writepage,
Steve French37c0eb42005-10-05 14:50:29 -07003386 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04003387 .write_begin = cifs_write_begin,
3388 .write_end = cifs_write_end,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303390 .releasepage = cifs_release_page,
3391 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003392 .launder_page = cifs_launder_page,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393};
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003394
3395/*
3396 * cifs_readpages requires the server to support a buffer large enough to
3397 * contain the header plus one complete page of data. Otherwise, we need
3398 * to leave cifs_readpages out of the address space operations.
3399 */
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07003400const struct address_space_operations cifs_addr_ops_smallbuf = {
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003401 .readpage = cifs_readpage,
3402 .writepage = cifs_writepage,
3403 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04003404 .write_begin = cifs_write_begin,
3405 .write_end = cifs_write_end,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003406 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303407 .releasepage = cifs_release_page,
3408 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003409 .launder_page = cifs_launder_page,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003410};