blob: 63963730cb285548ce0fdf1aadb758acf7bcac87 [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;
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700248 struct cifs_fid_locks *fdlocks;
Jeff Layton15ecb432010-10-15 15:34:02 -0400249
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700250 cfile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
251 if (cfile == NULL)
252 return cfile;
Jeff Layton15ecb432010-10-15 15:34:02 -0400253
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700254 fdlocks = kzalloc(sizeof(struct cifs_fid_locks), GFP_KERNEL);
255 if (!fdlocks) {
256 kfree(cfile);
257 return NULL;
258 }
259
260 INIT_LIST_HEAD(&fdlocks->locks);
261 fdlocks->cfile = cfile;
262 cfile->llist = fdlocks;
263 mutex_lock(&cinode->lock_mutex);
264 list_add(&fdlocks->llist, &cinode->llist);
265 mutex_unlock(&cinode->lock_mutex);
266
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700267 cfile->count = 1;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700268 cfile->pid = current->tgid;
269 cfile->uid = current_fsuid();
270 cfile->dentry = dget(dentry);
271 cfile->f_flags = file->f_flags;
272 cfile->invalidHandle = false;
273 cfile->tlink = cifs_get_tlink(tlink);
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700274 INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700275 mutex_init(&cfile->fh_mutex);
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700276 tlink_tcon(tlink)->ses->server->ops->set_fid(cfile, fid, oplock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400277
Jeff Layton44772882010-10-15 15:34:03 -0400278 spin_lock(&cifs_file_list_lock);
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700279 list_add(&cfile->tlist, &(tlink_tcon(tlink)->openFileList));
Jeff Layton15ecb432010-10-15 15:34:02 -0400280 /* if readable file instance put first in list*/
281 if (file->f_mode & FMODE_READ)
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700282 list_add(&cfile->flist, &cinode->openFileList);
Jeff Layton15ecb432010-10-15 15:34:02 -0400283 else
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700284 list_add_tail(&cfile->flist, &cinode->openFileList);
Jeff Layton44772882010-10-15 15:34:03 -0400285 spin_unlock(&cifs_file_list_lock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400286
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700287 file->private_data = cfile;
288 return cfile;
Jeff Layton15ecb432010-10-15 15:34:02 -0400289}
290
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400291static void cifs_del_lock_waiters(struct cifsLockInfo *lock);
292
Jeff Layton764a1b12012-07-25 14:59:54 -0400293struct cifsFileInfo *
294cifsFileInfo_get(struct cifsFileInfo *cifs_file)
295{
296 spin_lock(&cifs_file_list_lock);
297 cifsFileInfo_get_locked(cifs_file);
298 spin_unlock(&cifs_file_list_lock);
299 return cifs_file;
300}
301
Steve Frenchcdff08e2010-10-21 22:46:14 +0000302/*
303 * Release a reference on the file private data. This may involve closing
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400304 * the filehandle out on the server. Must be called without holding
305 * cifs_file_list_lock.
Steve Frenchcdff08e2010-10-21 22:46:14 +0000306 */
Jeff Laytonb33879a2010-10-15 15:34:04 -0400307void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
308{
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300309 struct inode *inode = cifs_file->dentry->d_inode;
Steve French96daf2b2011-05-27 04:34:02 +0000310 struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300311 struct cifsInodeInfo *cifsi = CIFS_I(inode);
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300312 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000313 struct cifsLockInfo *li, *tmp;
314
315 spin_lock(&cifs_file_list_lock);
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400316 if (--cifs_file->count > 0) {
Steve Frenchcdff08e2010-10-21 22:46:14 +0000317 spin_unlock(&cifs_file_list_lock);
318 return;
Jeff Laytonb33879a2010-10-15 15:34:04 -0400319 }
Steve Frenchcdff08e2010-10-21 22:46:14 +0000320
321 /* remove it from the lists */
322 list_del(&cifs_file->flist);
323 list_del(&cifs_file->tlist);
324
325 if (list_empty(&cifsi->openFileList)) {
326 cFYI(1, "closing last open instance for inode %p",
327 cifs_file->dentry->d_inode);
Pavel Shilovsky25364132012-09-18 16:20:27 -0700328 /*
329 * In strict cache mode we need invalidate mapping on the last
330 * close because it may cause a error when we open this file
331 * again and get at least level II oplock.
332 */
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300333 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
334 CIFS_I(inode)->invalid_mapping = true;
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300335 cifs_set_oplock_level(cifsi, 0);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000336 }
337 spin_unlock(&cifs_file_list_lock);
338
Jeff Laytonad635942011-07-26 12:20:17 -0400339 cancel_work_sync(&cifs_file->oplock_break);
340
Steve Frenchcdff08e2010-10-21 22:46:14 +0000341 if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
Pavel Shilovsky0ff78a22012-09-18 16:20:26 -0700342 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400343 unsigned int xid;
Pavel Shilovsky0ff78a22012-09-18 16:20:26 -0700344 int rc = -ENOSYS;
345
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400346 xid = get_xid();
Pavel Shilovsky0ff78a22012-09-18 16:20:26 -0700347 if (server->ops->close)
348 rc = server->ops->close(xid, tcon, &cifs_file->fid);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400349 free_xid(xid);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000350 }
351
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700352 /*
353 * Delete any outstanding lock records. We'll lose them when the file
Steve Frenchcdff08e2010-10-21 22:46:14 +0000354 * is closed anyway.
355 */
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400356 mutex_lock(&cifsi->lock_mutex);
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700357 list_for_each_entry_safe(li, tmp, &cifs_file->llist->locks, llist) {
Steve Frenchcdff08e2010-10-21 22:46:14 +0000358 list_del(&li->llist);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400359 cifs_del_lock_waiters(li);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000360 kfree(li);
361 }
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700362 list_del(&cifs_file->llist->llist);
363 kfree(cifs_file->llist);
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400364 mutex_unlock(&cifsi->lock_mutex);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000365
366 cifs_put_tlink(cifs_file->tlink);
367 dput(cifs_file->dentry);
368 kfree(cifs_file);
Jeff Laytonb33879a2010-10-15 15:34:04 -0400369}
370
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371int cifs_open(struct inode *inode, struct file *file)
372{
373 int rc = -EACCES;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400374 unsigned int xid;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400375 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000377 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400378 struct tcon_link *tlink;
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700379 struct cifsFileInfo *cfile = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 char *full_path = NULL;
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300381 bool posix_open_ok = false;
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700382 struct cifs_fid fid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400384 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385
386 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400387 tlink = cifs_sb_tlink(cifs_sb);
388 if (IS_ERR(tlink)) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400389 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400390 return PTR_ERR(tlink);
391 }
392 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -0800394 full_path = build_path_from_dentry(file->f_path.dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530396 rc = -ENOMEM;
Jeff Layton232341b2010-08-05 13:58:38 -0400397 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 }
399
Joe Perchesb6b38f72010-04-21 03:50:45 +0000400 cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
401 inode, file->f_flags, full_path);
Steve French276a74a2009-03-03 18:00:34 +0000402
Pavel Shilovsky10b9b982012-03-20 12:55:09 +0300403 if (tcon->ses->server->oplocks)
Steve French276a74a2009-03-03 18:00:34 +0000404 oplock = REQ_OPLOCK;
405 else
406 oplock = 0;
407
Steve French64cc2c62009-03-04 19:54:08 +0000408 if (!tcon->broken_posix_open && tcon->unix_ext &&
Pavel Shilovsky29e20f92012-07-13 13:58:14 +0400409 cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
410 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Steve French276a74a2009-03-03 18:00:34 +0000411 /* can not refresh inode info since size could be stale */
Jeff Layton2422f672010-06-16 13:40:16 -0400412 rc = cifs_posix_open(full_path, &inode, inode->i_sb,
Steve Frenchfa588e02010-04-22 19:21:55 +0000413 cifs_sb->mnt_file_mode /* ignored */,
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700414 file->f_flags, &oplock, &fid.netfid, xid);
Steve French276a74a2009-03-03 18:00:34 +0000415 if (rc == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000416 cFYI(1, "posix open succeeded");
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300417 posix_open_ok = true;
Steve French64cc2c62009-03-04 19:54:08 +0000418 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
419 if (tcon->ses->serverNOS)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000420 cERROR(1, "server %s of type %s returned"
Steve French64cc2c62009-03-04 19:54:08 +0000421 " unexpected error on SMB posix open"
422 ", disabling posix open support."
423 " Check if server update available.",
424 tcon->ses->serverName,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000425 tcon->ses->serverNOS);
Steve French64cc2c62009-03-04 19:54:08 +0000426 tcon->broken_posix_open = true;
Steve French276a74a2009-03-03 18:00:34 +0000427 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
428 (rc != -EOPNOTSUPP)) /* path not found or net err */
429 goto out;
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700430 /*
431 * Else fallthrough to retry open the old way on network i/o
432 * or DFS errors.
433 */
Steve French276a74a2009-03-03 18:00:34 +0000434 }
435
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300436 if (!posix_open_ok) {
437 rc = cifs_nt_open(full_path, inode, cifs_sb, tcon,
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700438 file->f_flags, &oplock, &fid, xid);
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300439 if (rc)
440 goto out;
441 }
Jeff Layton47c78b72010-06-16 13:40:17 -0400442
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700443 cfile = cifs_new_fileinfo(&fid, file, tlink, oplock);
444 if (cfile == NULL) {
Pavel Shilovsky0ff78a22012-09-18 16:20:26 -0700445 if (tcon->ses->server->ops->close)
446 tcon->ses->server->ops->close(xid, tcon, &fid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 rc = -ENOMEM;
448 goto out;
449 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530451 cifs_fscache_set_inode_cookie(inode, file);
452
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300453 if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) {
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700454 /*
455 * Time to set mode which we can not set earlier due to
456 * problems creating new read-only files.
457 */
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300458 struct cifs_unix_set_info_args args = {
459 .mode = inode->i_mode,
460 .uid = NO_CHANGE_64,
461 .gid = NO_CHANGE_64,
462 .ctime = NO_CHANGE_64,
463 .atime = NO_CHANGE_64,
464 .mtime = NO_CHANGE_64,
465 .device = 0,
466 };
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700467 CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid.netfid,
468 cfile->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 }
470
471out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400473 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400474 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 return rc;
476}
477
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700478/*
479 * Try to reacquire byte range locks that were released when session
480 * to server was lost
481 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482static int cifs_relock_file(struct cifsFileInfo *cifsFile)
483{
484 int rc = 0;
485
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700486 /* BB list all locks open on this file and relock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
488 return rc;
489}
490
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700491static int
492cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493{
494 int rc = -EACCES;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400495 unsigned int xid;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400496 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000498 struct cifs_tcon *tcon;
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700499 struct TCP_Server_Info *server;
500 struct cifsInodeInfo *cinode;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000501 struct inode *inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 char *full_path = NULL;
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700503 int desired_access;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 int disposition = FILE_OPEN;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500505 int create_options = CREATE_NOT_DIR;
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700506 struct cifs_fid fid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400508 xid = get_xid();
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700509 mutex_lock(&cfile->fh_mutex);
510 if (!cfile->invalidHandle) {
511 mutex_unlock(&cfile->fh_mutex);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530512 rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400513 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530514 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 }
516
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700517 inode = cfile->dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700519 tcon = tlink_tcon(cfile->tlink);
520 server = tcon->ses->server;
Steve French3a9f4622007-04-04 17:10:24 +0000521
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700522 /*
523 * Can not grab rename sem here because various ops, including those
524 * that already have the rename sem can end up causing writepage to get
525 * called and if the server was down that means we end up here, and we
526 * can never tell if the caller already has the rename_sem.
527 */
528 full_path = build_path_from_dentry(cfile->dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 if (full_path == NULL) {
Steve French3a9f4622007-04-04 17:10:24 +0000530 rc = -ENOMEM;
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700531 mutex_unlock(&cfile->fh_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400532 free_xid(xid);
Steve French3a9f4622007-04-04 17:10:24 +0000533 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 }
535
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700536 cFYI(1, "inode = 0x%p file flags 0x%x for %s", inode, cfile->f_flags,
537 full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
Pavel Shilovsky10b9b982012-03-20 12:55:09 +0300539 if (tcon->ses->server->oplocks)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 oplock = REQ_OPLOCK;
541 else
Steve French4b18f2a2008-04-29 00:06:05 +0000542 oplock = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
Pavel Shilovsky29e20f92012-07-13 13:58:14 +0400544 if (tcon->unix_ext && cap_unix(tcon->ses) &&
Steve French7fc8f4e2009-02-23 20:43:11 +0000545 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
Pavel Shilovsky29e20f92012-07-13 13:58:14 +0400546 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton608712f2010-10-15 15:33:56 -0400547 /*
548 * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
549 * original open. Must mask them off for a reopen.
550 */
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700551 unsigned int oflags = cfile->f_flags &
Jeff Layton15886172010-10-15 15:33:59 -0400552 ~(O_CREAT | O_EXCL | O_TRUNC);
Jeff Layton608712f2010-10-15 15:33:56 -0400553
Jeff Layton2422f672010-06-16 13:40:16 -0400554 rc = cifs_posix_open(full_path, NULL, inode->i_sb,
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700555 cifs_sb->mnt_file_mode /* ignored */,
556 oflags, &oplock, &fid.netfid, xid);
Steve French7fc8f4e2009-02-23 20:43:11 +0000557 if (rc == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000558 cFYI(1, "posix reopen succeeded");
Steve French7fc8f4e2009-02-23 20:43:11 +0000559 goto reopen_success;
560 }
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700561 /*
562 * fallthrough to retry open the old way on errors, especially
563 * in the reconnect path it is important to retry hard
564 */
Steve French7fc8f4e2009-02-23 20:43:11 +0000565 }
566
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700567 desired_access = cifs_convert_flags(cfile->f_flags);
Steve French7fc8f4e2009-02-23 20:43:11 +0000568
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500569 if (backup_cred(cifs_sb))
570 create_options |= CREATE_OPEN_BACKUP_INTENT;
571
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700572 /*
573 * Can not refresh inode by passing in file_info buf to be returned by
574 * CIFSSMBOpen and then calling get_inode_info with returned buf since
575 * file might have write behind data that needs to be flushed and server
576 * version of file size can be stale. If we knew for sure that inode was
577 * not dirty locally we could do this.
578 */
579 rc = server->ops->open(xid, tcon, full_path, disposition,
580 desired_access, create_options, &fid, &oplock,
581 NULL, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 if (rc) {
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700583 mutex_unlock(&cfile->fh_mutex);
584 cFYI(1, "cifs_reopen returned 0x%x", rc);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000585 cFYI(1, "oplock: %d", oplock);
Jeff Layton15886172010-10-15 15:33:59 -0400586 goto reopen_error_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 }
Jeff Layton15886172010-10-15 15:33:59 -0400588
589reopen_success:
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700590 cfile->invalidHandle = false;
591 mutex_unlock(&cfile->fh_mutex);
592 cinode = CIFS_I(inode);
Jeff Layton15886172010-10-15 15:33:59 -0400593
594 if (can_flush) {
595 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -0400596 mapping_set_error(inode->i_mapping, rc);
Jeff Layton15886172010-10-15 15:33:59 -0400597
Jeff Layton15886172010-10-15 15:33:59 -0400598 if (tcon->unix_ext)
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700599 rc = cifs_get_inode_info_unix(&inode, full_path,
600 inode->i_sb, xid);
Jeff Layton15886172010-10-15 15:33:59 -0400601 else
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700602 rc = cifs_get_inode_info(&inode, full_path, NULL,
603 inode->i_sb, xid, NULL);
604 }
605 /*
606 * Else we are writing out data to server already and could deadlock if
607 * we tried to flush data, and since we do not know if we have data that
608 * would invalidate the current end of file on the server we can not go
609 * to the server to get the new inode info.
610 */
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300611
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700612 server->ops->set_fid(cfile, &fid, oplock);
613 cifs_relock_file(cfile);
Jeff Layton15886172010-10-15 15:33:59 -0400614
615reopen_error_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400617 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 return rc;
619}
620
621int cifs_close(struct inode *inode, struct file *file)
622{
Jeff Layton77970692011-04-05 16:23:47 -0700623 if (file->private_data != NULL) {
624 cifsFileInfo_put(file->private_data);
625 file->private_data = NULL;
626 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
Steve Frenchcdff08e2010-10-21 22:46:14 +0000628 /* return code from the ->release op is always ignored */
629 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630}
631
632int cifs_closedir(struct inode *inode, struct file *file)
633{
634 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400635 unsigned int xid;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700636 struct cifsFileInfo *cfile = file->private_data;
Pavel Shilovsky92fc65a2012-09-18 16:20:32 -0700637 struct cifs_tcon *tcon;
638 struct TCP_Server_Info *server;
639 char *buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
Joe Perchesb6b38f72010-04-21 03:50:45 +0000641 cFYI(1, "Closedir inode = 0x%p", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642
Pavel Shilovsky92fc65a2012-09-18 16:20:32 -0700643 if (cfile == NULL)
644 return rc;
645
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400646 xid = get_xid();
Pavel Shilovsky92fc65a2012-09-18 16:20:32 -0700647 tcon = tlink_tcon(cfile->tlink);
648 server = tcon->ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649
Pavel Shilovsky92fc65a2012-09-18 16:20:32 -0700650 cFYI(1, "Freeing private data in close dir");
651 spin_lock(&cifs_file_list_lock);
652 if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
653 cfile->invalidHandle = true;
654 spin_unlock(&cifs_file_list_lock);
655 if (server->ops->close_dir)
656 rc = server->ops->close_dir(xid, tcon, &cfile->fid);
657 else
658 rc = -ENOSYS;
659 cFYI(1, "Closing uncompleted readdir with rc %d", rc);
660 /* not much we can do if it fails anyway, ignore rc */
661 rc = 0;
662 } else
663 spin_unlock(&cifs_file_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664
Pavel Shilovsky92fc65a2012-09-18 16:20:32 -0700665 buf = cfile->srch_inf.ntwrk_buf_start;
666 if (buf) {
667 cFYI(1, "closedir free smb buf in srch struct");
668 cfile->srch_inf.ntwrk_buf_start = NULL;
669 if (cfile->srch_inf.smallBuf)
670 cifs_small_buf_release(buf);
671 else
672 cifs_buf_release(buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 }
Pavel Shilovsky92fc65a2012-09-18 16:20:32 -0700674
675 cifs_put_tlink(cfile->tlink);
676 kfree(file->private_data);
677 file->private_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 /* BB can we lock the filestruct while this is going on? */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400679 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 return rc;
681}
682
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400683static struct cifsLockInfo *
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300684cifs_lock_init(__u64 offset, __u64 length, __u8 type)
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000685{
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400686 struct cifsLockInfo *lock =
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000687 kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400688 if (!lock)
689 return lock;
690 lock->offset = offset;
691 lock->length = length;
692 lock->type = type;
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400693 lock->pid = current->tgid;
694 INIT_LIST_HEAD(&lock->blist);
695 init_waitqueue_head(&lock->block_q);
696 return lock;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400697}
698
699static void
700cifs_del_lock_waiters(struct cifsLockInfo *lock)
701{
702 struct cifsLockInfo *li, *tmp;
703 list_for_each_entry_safe(li, tmp, &lock->blist, blist) {
704 list_del_init(&li->blist);
705 wake_up(&li->block_q);
706 }
707}
708
709static bool
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700710cifs_find_fid_lock_conflict(struct cifs_fid_locks *fdlocks, __u64 offset,
711 __u64 length, __u8 type, struct cifsFileInfo *cfile,
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300712 struct cifsLockInfo **conf_lock)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400713{
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300714 struct cifsLockInfo *li;
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700715 struct cifsFileInfo *cur_cfile = fdlocks->cfile;
Pavel Shilovsky106dc532012-02-28 14:23:34 +0300716 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400717
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700718 list_for_each_entry(li, &fdlocks->locks, llist) {
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400719 if (offset + length <= li->offset ||
720 offset >= li->offset + li->length)
721 continue;
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700722 if ((type & server->vals->shared_lock_type) &&
723 ((server->ops->compare_fids(cfile, cur_cfile) &&
724 current->tgid == li->pid) || type == li->type))
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400725 continue;
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700726 *conf_lock = li;
727 return true;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400728 }
729 return false;
730}
731
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400732static bool
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300733cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
734 __u8 type, struct cifsLockInfo **conf_lock)
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400735{
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300736 bool rc = false;
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700737 struct cifs_fid_locks *cur;
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300738 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300739
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700740 list_for_each_entry(cur, &cinode->llist, llist) {
741 rc = cifs_find_fid_lock_conflict(cur, offset, length, type,
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300742 cfile, conf_lock);
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300743 if (rc)
744 break;
745 }
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300746
747 return rc;
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400748}
749
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300750/*
751 * Check if there is another lock that prevents us to set the lock (mandatory
752 * style). If such a lock exists, update the flock structure with its
753 * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks
754 * or leave it the same if we can't. Returns 0 if we don't need to request to
755 * the server or 1 otherwise.
756 */
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400757static int
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300758cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
759 __u8 type, struct file_lock *flock)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400760{
761 int rc = 0;
762 struct cifsLockInfo *conf_lock;
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300763 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovsky106dc532012-02-28 14:23:34 +0300764 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400765 bool exist;
766
767 mutex_lock(&cinode->lock_mutex);
768
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300769 exist = cifs_find_lock_conflict(cfile, offset, length, type,
770 &conf_lock);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400771 if (exist) {
772 flock->fl_start = conf_lock->offset;
773 flock->fl_end = conf_lock->offset + conf_lock->length - 1;
774 flock->fl_pid = conf_lock->pid;
Pavel Shilovsky106dc532012-02-28 14:23:34 +0300775 if (conf_lock->type & server->vals->shared_lock_type)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400776 flock->fl_type = F_RDLCK;
777 else
778 flock->fl_type = F_WRLCK;
779 } else if (!cinode->can_cache_brlcks)
780 rc = 1;
781 else
782 flock->fl_type = F_UNLCK;
783
784 mutex_unlock(&cinode->lock_mutex);
785 return rc;
786}
787
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400788static void
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300789cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400790{
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300791 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400792 mutex_lock(&cinode->lock_mutex);
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700793 list_add_tail(&lock->llist, &cfile->llist->locks);
Pavel Shilovskyd59dad22011-09-22 09:53:59 +0400794 mutex_unlock(&cinode->lock_mutex);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000795}
796
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300797/*
798 * Set the byte-range lock (mandatory style). Returns:
799 * 1) 0, if we set the lock and don't need to request to the server;
800 * 2) 1, if no locks prevent us but we need to request to the server;
801 * 3) -EACCESS, if there is a lock that prevents us and wait is false.
802 */
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400803static int
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300804cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock,
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400805 bool wait)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400806{
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400807 struct cifsLockInfo *conf_lock;
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300808 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400809 bool exist;
810 int rc = 0;
811
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400812try_again:
813 exist = false;
814 mutex_lock(&cinode->lock_mutex);
815
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300816 exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length,
817 lock->type, &conf_lock);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400818 if (!exist && cinode->can_cache_brlcks) {
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700819 list_add_tail(&lock->llist, &cfile->llist->locks);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400820 mutex_unlock(&cinode->lock_mutex);
821 return rc;
822 }
823
824 if (!exist)
825 rc = 1;
826 else if (!wait)
827 rc = -EACCES;
828 else {
829 list_add_tail(&lock->blist, &conf_lock->blist);
830 mutex_unlock(&cinode->lock_mutex);
831 rc = wait_event_interruptible(lock->block_q,
832 (lock->blist.prev == &lock->blist) &&
833 (lock->blist.next == &lock->blist));
834 if (!rc)
835 goto try_again;
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400836 mutex_lock(&cinode->lock_mutex);
837 list_del_init(&lock->blist);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400838 }
839
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400840 mutex_unlock(&cinode->lock_mutex);
841 return rc;
842}
843
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300844/*
845 * Check if there is another lock that prevents us to set the lock (posix
846 * style). If such a lock exists, update the flock structure with its
847 * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks
848 * or leave it the same if we can't. Returns 0 if we don't need to request to
849 * the server or 1 otherwise.
850 */
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400851static int
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400852cifs_posix_lock_test(struct file *file, struct file_lock *flock)
853{
854 int rc = 0;
855 struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode);
856 unsigned char saved_type = flock->fl_type;
857
Pavel Shilovsky50792762011-10-29 17:17:57 +0400858 if ((flock->fl_flags & FL_POSIX) == 0)
859 return 1;
860
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400861 mutex_lock(&cinode->lock_mutex);
862 posix_test_lock(file, flock);
863
864 if (flock->fl_type == F_UNLCK && !cinode->can_cache_brlcks) {
865 flock->fl_type = saved_type;
866 rc = 1;
867 }
868
869 mutex_unlock(&cinode->lock_mutex);
870 return rc;
871}
872
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300873/*
874 * Set the byte-range lock (posix style). Returns:
875 * 1) 0, if we set the lock and don't need to request to the server;
876 * 2) 1, if we need to request to the server;
877 * 3) <0, if the error occurs while setting the lock.
878 */
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400879static int
880cifs_posix_lock_set(struct file *file, struct file_lock *flock)
881{
882 struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode);
Pavel Shilovsky50792762011-10-29 17:17:57 +0400883 int rc = 1;
884
885 if ((flock->fl_flags & FL_POSIX) == 0)
886 return rc;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400887
Pavel Shilovsky66189be2012-03-28 21:56:19 +0400888try_again:
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400889 mutex_lock(&cinode->lock_mutex);
890 if (!cinode->can_cache_brlcks) {
891 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky50792762011-10-29 17:17:57 +0400892 return rc;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400893 }
Pavel Shilovsky66189be2012-03-28 21:56:19 +0400894
895 rc = posix_lock_file(file, flock, NULL);
Steve French9ebb3892012-04-01 13:52:54 -0500896 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky66189be2012-03-28 21:56:19 +0400897 if (rc == FILE_LOCK_DEFERRED) {
898 rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next);
899 if (!rc)
900 goto try_again;
901 locks_delete_block(flock);
902 }
Steve French9ebb3892012-04-01 13:52:54 -0500903 return rc;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400904}
905
906static int
907cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400908{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400909 unsigned int xid;
910 int rc = 0, stored_rc;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400911 struct cifsLockInfo *li, *tmp;
912 struct cifs_tcon *tcon;
913 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovsky0013fb42012-05-31 13:03:26 +0400914 unsigned int num, max_num, max_buf;
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400915 LOCKING_ANDX_RANGE *buf, *cur;
916 int types[] = {LOCKING_ANDX_LARGE_FILES,
917 LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
918 int i;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400919
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400920 xid = get_xid();
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400921 tcon = tlink_tcon(cfile->tlink);
922
923 mutex_lock(&cinode->lock_mutex);
924 if (!cinode->can_cache_brlcks) {
925 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400926 free_xid(xid);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400927 return rc;
928 }
929
Pavel Shilovsky0013fb42012-05-31 13:03:26 +0400930 /*
931 * Accessing maxBuf is racy with cifs_reconnect - need to store value
932 * and check it for zero before using.
933 */
934 max_buf = tcon->ses->server->maxBuf;
935 if (!max_buf) {
936 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400937 free_xid(xid);
Pavel Shilovsky0013fb42012-05-31 13:03:26 +0400938 return -EINVAL;
939 }
940
941 max_num = (max_buf - sizeof(struct smb_hdr)) /
942 sizeof(LOCKING_ANDX_RANGE);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400943 buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
944 if (!buf) {
945 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400946 free_xid(xid);
Pavel Shilovskye2f28862012-08-29 21:13:38 +0400947 return -ENOMEM;
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400948 }
949
950 for (i = 0; i < 2; i++) {
951 cur = buf;
952 num = 0;
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700953 list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400954 if (li->type != types[i])
955 continue;
956 cur->Pid = cpu_to_le16(li->pid);
957 cur->LengthLow = cpu_to_le32((u32)li->length);
958 cur->LengthHigh = cpu_to_le32((u32)(li->length>>32));
959 cur->OffsetLow = cpu_to_le32((u32)li->offset);
960 cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
961 if (++num == max_num) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700962 stored_rc = cifs_lockv(xid, tcon,
963 cfile->fid.netfid,
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +0300964 (__u8)li->type, 0, num,
965 buf);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400966 if (stored_rc)
967 rc = stored_rc;
968 cur = buf;
969 num = 0;
970 } else
971 cur++;
972 }
973
974 if (num) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700975 stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid,
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +0300976 (__u8)types[i], 0, num, buf);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400977 if (stored_rc)
978 rc = stored_rc;
979 }
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400980 }
981
982 cinode->can_cache_brlcks = false;
983 mutex_unlock(&cinode->lock_mutex);
984
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +0400985 kfree(buf);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400986 free_xid(xid);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400987 return rc;
988}
989
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400990/* copied from fs/locks.c with a name change */
991#define cifs_for_each_lock(inode, lockp) \
992 for (lockp = &inode->i_flock; *lockp != NULL; \
993 lockp = &(*lockp)->fl_next)
994
Pavel Shilovskyd5751462012-03-05 09:39:20 +0300995struct lock_to_push {
996 struct list_head llist;
997 __u64 offset;
998 __u64 length;
999 __u32 pid;
1000 __u16 netfid;
1001 __u8 type;
1002};
1003
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001004static int
1005cifs_push_posix_locks(struct cifsFileInfo *cfile)
1006{
1007 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
1008 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1009 struct file_lock *flock, **before;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001010 unsigned int count = 0, i = 0;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001011 int rc = 0, xid, type;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001012 struct list_head locks_to_send, *el;
1013 struct lock_to_push *lck, *tmp;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001014 __u64 length;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001015
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001016 xid = get_xid();
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001017
1018 mutex_lock(&cinode->lock_mutex);
1019 if (!cinode->can_cache_brlcks) {
1020 mutex_unlock(&cinode->lock_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001021 free_xid(xid);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001022 return rc;
1023 }
1024
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001025 lock_flocks();
1026 cifs_for_each_lock(cfile->dentry->d_inode, before) {
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001027 if ((*before)->fl_flags & FL_POSIX)
1028 count++;
1029 }
1030 unlock_flocks();
1031
1032 INIT_LIST_HEAD(&locks_to_send);
1033
1034 /*
Pavel Shilovskyce858522012-03-17 09:46:55 +03001035 * Allocating count locks is enough because no FL_POSIX locks can be
1036 * added to the list while we are holding cinode->lock_mutex that
1037 * protects locking operations of this inode.
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001038 */
1039 for (; i < count; i++) {
1040 lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL);
1041 if (!lck) {
1042 rc = -ENOMEM;
1043 goto err_out;
1044 }
1045 list_add_tail(&lck->llist, &locks_to_send);
1046 }
1047
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001048 el = locks_to_send.next;
1049 lock_flocks();
1050 cifs_for_each_lock(cfile->dentry->d_inode, before) {
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001051 flock = *before;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001052 if ((flock->fl_flags & FL_POSIX) == 0)
1053 continue;
Pavel Shilovskyce858522012-03-17 09:46:55 +03001054 if (el == &locks_to_send) {
1055 /*
1056 * The list ended. We don't have enough allocated
1057 * structures - something is really wrong.
1058 */
1059 cERROR(1, "Can't push all brlocks!");
1060 break;
1061 }
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001062 length = 1 + flock->fl_end - flock->fl_start;
1063 if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK)
1064 type = CIFS_RDLCK;
1065 else
1066 type = CIFS_WRLCK;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001067 lck = list_entry(el, struct lock_to_push, llist);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001068 lck->pid = flock->fl_pid;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001069 lck->netfid = cfile->fid.netfid;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001070 lck->length = length;
1071 lck->type = type;
1072 lck->offset = flock->fl_start;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001073 el = el->next;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001074 }
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001075 unlock_flocks();
1076
1077 list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001078 int stored_rc;
1079
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001080 stored_rc = CIFSSMBPosixLock(xid, tcon, lck->netfid, lck->pid,
Jeff Laytonc5fd3632012-07-23 13:28:37 -04001081 lck->offset, lck->length, NULL,
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001082 lck->type, 0);
1083 if (stored_rc)
1084 rc = stored_rc;
1085 list_del(&lck->llist);
1086 kfree(lck);
1087 }
1088
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001089out:
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001090 cinode->can_cache_brlcks = false;
1091 mutex_unlock(&cinode->lock_mutex);
1092
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001093 free_xid(xid);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001094 return rc;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001095err_out:
1096 list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
1097 list_del(&lck->llist);
1098 kfree(lck);
1099 }
1100 goto out;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001101}
1102
1103static int
1104cifs_push_locks(struct cifsFileInfo *cfile)
1105{
1106 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
1107 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1108
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001109 if (cap_unix(tcon->ses) &&
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001110 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
1111 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
1112 return cifs_push_posix_locks(cfile);
1113
1114 return cifs_push_mandatory_locks(cfile);
1115}
1116
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001117static void
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001118cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock,
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001119 bool *wait_flag, struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120{
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001121 if (flock->fl_flags & FL_POSIX)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001122 cFYI(1, "Posix");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001123 if (flock->fl_flags & FL_FLOCK)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001124 cFYI(1, "Flock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001125 if (flock->fl_flags & FL_SLEEP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001126 cFYI(1, "Blocking lock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001127 *wait_flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 }
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001129 if (flock->fl_flags & FL_ACCESS)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001130 cFYI(1, "Process suspended by mandatory locking - "
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001131 "not implemented yet");
1132 if (flock->fl_flags & FL_LEASE)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001133 cFYI(1, "Lease on file - not implemented yet");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001134 if (flock->fl_flags &
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001136 cFYI(1, "Unknown lock flags 0x%x", flock->fl_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001138 *type = server->vals->large_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001139 if (flock->fl_type == F_WRLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001140 cFYI(1, "F_WRLCK ");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001141 *type |= server->vals->exclusive_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001142 *lock = 1;
1143 } else if (flock->fl_type == F_UNLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001144 cFYI(1, "F_UNLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001145 *type |= server->vals->unlock_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001146 *unlock = 1;
1147 /* Check if unlock includes more than one lock range */
1148 } else if (flock->fl_type == F_RDLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001149 cFYI(1, "F_RDLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001150 *type |= server->vals->shared_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001151 *lock = 1;
1152 } else if (flock->fl_type == F_EXLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001153 cFYI(1, "F_EXLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001154 *type |= server->vals->exclusive_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001155 *lock = 1;
1156 } else if (flock->fl_type == F_SHLCK) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001157 cFYI(1, "F_SHLCK");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001158 *type |= server->vals->shared_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001159 *lock = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +00001161 cFYI(1, "Unknown type of lock");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001162}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001164static int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001165cifs_mandatory_lock(unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001166 __u64 length, __u32 type, int lock, int unlock, bool wait)
1167{
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001168 return CIFSSMBLock(xid, tlink_tcon(cfile->tlink), cfile->fid.netfid,
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001169 current->tgid, length, offset, unlock, lock,
1170 (__u8)type, wait, 0);
1171}
1172
1173static int
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001174cifs_getlk(struct file *file, struct file_lock *flock, __u32 type,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001175 bool wait_flag, bool posix_lck, unsigned int xid)
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001176{
1177 int rc = 0;
1178 __u64 length = 1 + flock->fl_end - flock->fl_start;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001179 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
1180 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001181 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001182 __u16 netfid = cfile->fid.netfid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001184 if (posix_lck) {
1185 int posix_lock_type;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001186
1187 rc = cifs_posix_lock_test(file, flock);
1188 if (!rc)
1189 return rc;
1190
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001191 if (type & server->vals->shared_lock_type)
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001192 posix_lock_type = CIFS_RDLCK;
1193 else
1194 posix_lock_type = CIFS_WRLCK;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001195 rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid,
Jeff Laytonc5fd3632012-07-23 13:28:37 -04001196 flock->fl_start, length, flock,
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001197 posix_lock_type, wait_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 return rc;
1199 }
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001200
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001201 rc = cifs_lock_test(cfile, flock->fl_start, length, type, flock);
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001202 if (!rc)
1203 return rc;
1204
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001205 /* BB we could chain these into one lock request BB */
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001206 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length, type,
1207 1, 0, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001208 if (rc == 0) {
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001209 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1210 type, 0, 1, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001211 flock->fl_type = F_UNLCK;
1212 if (rc != 0)
1213 cERROR(1, "Error unlocking previously locked "
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001214 "range %d during test of lock", rc);
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001215 return 0;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001216 }
1217
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001218 if (type & server->vals->shared_lock_type) {
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001219 flock->fl_type = F_WRLCK;
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001220 return 0;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001221 }
1222
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001223 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1224 type | server->vals->shared_lock_type, 1, 0,
1225 false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001226 if (rc == 0) {
Pavel Shilovsky55157df2012-02-28 14:04:17 +03001227 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1228 type | server->vals->shared_lock_type,
1229 0, 1, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001230 flock->fl_type = F_RDLCK;
1231 if (rc != 0)
1232 cERROR(1, "Error unlocking previously locked "
1233 "range %d during test of lock", rc);
1234 } else
1235 flock->fl_type = F_WRLCK;
1236
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001237 return 0;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001238}
1239
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001240static void
1241cifs_move_llist(struct list_head *source, struct list_head *dest)
1242{
1243 struct list_head *li, *tmp;
1244 list_for_each_safe(li, tmp, source)
1245 list_move(li, dest);
1246}
1247
1248static void
1249cifs_free_llist(struct list_head *llist)
1250{
1251 struct cifsLockInfo *li, *tmp;
1252 list_for_each_entry_safe(li, tmp, llist, llist) {
1253 cifs_del_lock_waiters(li);
1254 list_del(&li->llist);
1255 kfree(li);
1256 }
1257}
1258
1259static int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001260cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
1261 unsigned int xid)
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001262{
1263 int rc = 0, stored_rc;
1264 int types[] = {LOCKING_ANDX_LARGE_FILES,
1265 LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
1266 unsigned int i;
Pavel Shilovsky0013fb42012-05-31 13:03:26 +04001267 unsigned int max_num, num, max_buf;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001268 LOCKING_ANDX_RANGE *buf, *cur;
1269 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1270 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
1271 struct cifsLockInfo *li, *tmp;
1272 __u64 length = 1 + flock->fl_end - flock->fl_start;
1273 struct list_head tmp_llist;
1274
1275 INIT_LIST_HEAD(&tmp_llist);
1276
Pavel Shilovsky0013fb42012-05-31 13:03:26 +04001277 /*
1278 * Accessing maxBuf is racy with cifs_reconnect - need to store value
1279 * and check it for zero before using.
1280 */
1281 max_buf = tcon->ses->server->maxBuf;
1282 if (!max_buf)
1283 return -EINVAL;
1284
1285 max_num = (max_buf - sizeof(struct smb_hdr)) /
1286 sizeof(LOCKING_ANDX_RANGE);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001287 buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
1288 if (!buf)
1289 return -ENOMEM;
1290
1291 mutex_lock(&cinode->lock_mutex);
1292 for (i = 0; i < 2; i++) {
1293 cur = buf;
1294 num = 0;
Pavel Shilovskyf45d3412012-09-19 06:22:43 -07001295 list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001296 if (flock->fl_start > li->offset ||
1297 (flock->fl_start + length) <
1298 (li->offset + li->length))
1299 continue;
1300 if (current->tgid != li->pid)
1301 continue;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001302 if (types[i] != li->type)
1303 continue;
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001304 if (cinode->can_cache_brlcks) {
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001305 /*
1306 * We can cache brlock requests - simply remove
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001307 * a lock from the file's list.
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001308 */
1309 list_del(&li->llist);
1310 cifs_del_lock_waiters(li);
1311 kfree(li);
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001312 continue;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001313 }
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001314 cur->Pid = cpu_to_le16(li->pid);
1315 cur->LengthLow = cpu_to_le32((u32)li->length);
1316 cur->LengthHigh = cpu_to_le32((u32)(li->length>>32));
1317 cur->OffsetLow = cpu_to_le32((u32)li->offset);
1318 cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
1319 /*
1320 * We need to save a lock here to let us add it again to
1321 * the file's list if the unlock range request fails on
1322 * the server.
1323 */
1324 list_move(&li->llist, &tmp_llist);
1325 if (++num == max_num) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001326 stored_rc = cifs_lockv(xid, tcon,
1327 cfile->fid.netfid,
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001328 li->type, num, 0, buf);
1329 if (stored_rc) {
1330 /*
1331 * We failed on the unlock range
1332 * request - add all locks from the tmp
1333 * list to the head of the file's list.
1334 */
1335 cifs_move_llist(&tmp_llist,
Pavel Shilovskyf45d3412012-09-19 06:22:43 -07001336 &cfile->llist->locks);
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001337 rc = stored_rc;
1338 } else
1339 /*
1340 * The unlock range request succeed -
1341 * free the tmp list.
1342 */
1343 cifs_free_llist(&tmp_llist);
1344 cur = buf;
1345 num = 0;
1346 } else
1347 cur++;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001348 }
1349 if (num) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001350 stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid,
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001351 types[i], num, 0, buf);
1352 if (stored_rc) {
Pavel Shilovskyf45d3412012-09-19 06:22:43 -07001353 cifs_move_llist(&tmp_llist,
1354 &cfile->llist->locks);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001355 rc = stored_rc;
1356 } else
1357 cifs_free_llist(&tmp_llist);
1358 }
1359 }
1360
1361 mutex_unlock(&cinode->lock_mutex);
1362 kfree(buf);
1363 return rc;
1364}
1365
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001366static int
Pavel Shilovskyf45d3412012-09-19 06:22:43 -07001367cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001368 bool wait_flag, bool posix_lck, int lock, int unlock,
1369 unsigned int xid)
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001370{
1371 int rc = 0;
1372 __u64 length = 1 + flock->fl_end - flock->fl_start;
1373 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
1374 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001375 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001376
1377 if (posix_lck) {
Steve French08547b02006-02-28 22:39:25 +00001378 int posix_lock_type;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001379
1380 rc = cifs_posix_lock_set(file, flock);
1381 if (!rc || rc < 0)
1382 return rc;
1383
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001384 if (type & server->vals->shared_lock_type)
Steve French08547b02006-02-28 22:39:25 +00001385 posix_lock_type = CIFS_RDLCK;
1386 else
1387 posix_lock_type = CIFS_WRLCK;
Steve French50c2f752007-07-13 00:33:32 +00001388
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001389 if (unlock == 1)
Steve Frenchbeb84dc2006-03-03 23:36:34 +00001390 posix_lock_type = CIFS_UNLCK;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001391
Pavel Shilovskyf45d3412012-09-19 06:22:43 -07001392 rc = CIFSSMBPosixLock(xid, tcon, cfile->fid.netfid,
1393 current->tgid, flock->fl_start, length,
1394 NULL, posix_lock_type, wait_flag);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001395 goto out;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001396 }
1397
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001398 if (lock) {
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001399 struct cifsLockInfo *lock;
1400
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001401 lock = cifs_lock_init(flock->fl_start, length, type);
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001402 if (!lock)
1403 return -ENOMEM;
1404
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001405 rc = cifs_lock_add_if(cfile, lock, wait_flag);
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001406 if (rc < 0)
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001407 kfree(lock);
1408 if (rc <= 0)
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001409 goto out;
1410
Pavel Shilovsky7f924472012-03-28 17:10:25 +04001411 rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length,
1412 type, 1, 0, wait_flag);
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001413 if (rc) {
1414 kfree(lock);
1415 goto out;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001416 }
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001417
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001418 cifs_lock_add(cfile, lock);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001419 } else if (unlock)
1420 rc = cifs_unlock_range(cfile, flock, xid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001421
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001422out:
1423 if (flock->fl_flags & FL_POSIX)
Steve French9ebb3892012-04-01 13:52:54 -05001424 posix_lock_file_wait(file, flock);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001425 return rc;
1426}
1427
1428int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
1429{
1430 int rc, xid;
1431 int lock = 0, unlock = 0;
1432 bool wait_flag = false;
1433 bool posix_lck = false;
1434 struct cifs_sb_info *cifs_sb;
1435 struct cifs_tcon *tcon;
1436 struct cifsInodeInfo *cinode;
1437 struct cifsFileInfo *cfile;
1438 __u16 netfid;
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001439 __u32 type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001440
1441 rc = -EACCES;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001442 xid = get_xid();
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001443
1444 cFYI(1, "Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld "
1445 "end: %lld", cmd, flock->fl_flags, flock->fl_type,
1446 flock->fl_start, flock->fl_end);
1447
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001448 cfile = (struct cifsFileInfo *)file->private_data;
1449 tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001450
1451 cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag,
1452 tcon->ses->server);
1453
1454 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001455 netfid = cfile->fid.netfid;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001456 cinode = CIFS_I(file->f_path.dentry->d_inode);
1457
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001458 if (cap_unix(tcon->ses) &&
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001459 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
1460 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
1461 posix_lck = true;
1462 /*
1463 * BB add code here to normalize offset and length to account for
1464 * negative length which we can not accept over the wire.
1465 */
1466 if (IS_GETLK(cmd)) {
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001467 rc = cifs_getlk(file, flock, type, wait_flag, posix_lck, xid);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001468 free_xid(xid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001469 return rc;
1470 }
1471
1472 if (!lock && !unlock) {
1473 /*
1474 * if no lock or unlock then nothing to do since we do not
1475 * know what it is
1476 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001477 free_xid(xid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001478 return -EOPNOTSUPP;
1479 }
1480
1481 rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock,
1482 xid);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001483 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 return rc;
1485}
1486
Jeff Layton597b0272012-03-23 14:40:56 -04001487/*
1488 * update the file size (if needed) after a write. Should be called with
1489 * the inode->i_lock held
1490 */
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001491void
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001492cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
1493 unsigned int bytes_written)
1494{
1495 loff_t end_of_write = offset + bytes_written;
1496
1497 if (end_of_write > cifsi->server_eof)
1498 cifsi->server_eof = end_of_write;
1499}
1500
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001501static ssize_t
1502cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
1503 size_t write_size, loff_t *offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504{
1505 int rc = 0;
1506 unsigned int bytes_written = 0;
1507 unsigned int total_written;
1508 struct cifs_sb_info *cifs_sb;
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001509 struct cifs_tcon *tcon;
1510 struct TCP_Server_Info *server;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001511 unsigned int xid;
Jeff Layton7da4b492010-10-15 15:34:00 -04001512 struct dentry *dentry = open_file->dentry;
1513 struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001514 struct cifs_io_parms io_parms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515
Jeff Layton7da4b492010-10-15 15:34:00 -04001516 cifs_sb = CIFS_SB(dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517
Joe Perchesb6b38f72010-04-21 03:50:45 +00001518 cFYI(1, "write %zd bytes to offset %lld of %s", write_size,
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001519 *offset, dentry->d_name.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001521 tcon = tlink_tcon(open_file->tlink);
1522 server = tcon->ses->server;
1523
1524 if (!server->ops->sync_write)
1525 return -ENOSYS;
Steve French50c2f752007-07-13 00:33:32 +00001526
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001527 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 for (total_written = 0; write_size > total_written;
1530 total_written += bytes_written) {
1531 rc = -EAGAIN;
1532 while (rc == -EAGAIN) {
Jeff Laytonca83ce32011-04-12 09:13:44 -04001533 struct kvec iov[2];
1534 unsigned int len;
1535
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 if (open_file->invalidHandle) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 /* we could deadlock if we called
1538 filemap_fdatawait from here so tell
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001539 reopen_file not to flush data to
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 server now */
Jeff Layton15886172010-10-15 15:33:59 -04001541 rc = cifs_reopen_file(open_file, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 if (rc != 0)
1543 break;
1544 }
Steve French3e844692005-10-03 13:37:24 -07001545
Jeff Laytonca83ce32011-04-12 09:13:44 -04001546 len = min((size_t)cifs_sb->wsize,
1547 write_size - total_written);
1548 /* iov[0] is reserved for smb header */
1549 iov[1].iov_base = (char *)write_data + total_written;
1550 iov[1].iov_len = len;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001551 io_parms.pid = pid;
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001552 io_parms.tcon = tcon;
1553 io_parms.offset = *offset;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001554 io_parms.length = len;
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001555 rc = server->ops->sync_write(xid, open_file, &io_parms,
1556 &bytes_written, iov, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 }
1558 if (rc || (bytes_written == 0)) {
1559 if (total_written)
1560 break;
1561 else {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001562 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 return rc;
1564 }
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001565 } else {
Jeff Layton597b0272012-03-23 14:40:56 -04001566 spin_lock(&dentry->d_inode->i_lock);
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001567 cifs_update_eof(cifsi, *offset, bytes_written);
Jeff Layton597b0272012-03-23 14:40:56 -04001568 spin_unlock(&dentry->d_inode->i_lock);
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001569 *offset += bytes_written;
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001570 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 }
1572
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001573 cifs_stats_bytes_written(tcon, total_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574
Jeff Layton7da4b492010-10-15 15:34:00 -04001575 if (total_written > 0) {
1576 spin_lock(&dentry->d_inode->i_lock);
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001577 if (*offset > dentry->d_inode->i_size)
1578 i_size_write(dentry->d_inode, *offset);
Jeff Layton7da4b492010-10-15 15:34:00 -04001579 spin_unlock(&dentry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 }
Jeff Layton7da4b492010-10-15 15:34:00 -04001581 mark_inode_dirty_sync(dentry->d_inode);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001582 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 return total_written;
1584}
1585
Jeff Layton6508d902010-09-29 19:51:11 -04001586struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1587 bool fsuid_only)
Steve French630f3f0c2007-10-25 21:17:17 +00001588{
1589 struct cifsFileInfo *open_file = NULL;
Jeff Layton6508d902010-09-29 19:51:11 -04001590 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1591
1592 /* only filter by fsuid on multiuser mounts */
1593 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1594 fsuid_only = false;
Steve French630f3f0c2007-10-25 21:17:17 +00001595
Jeff Layton44772882010-10-15 15:34:03 -04001596 spin_lock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001597 /* we could simply get the first_list_entry since write-only entries
1598 are always at the end of the list but since the first entry might
1599 have a close pending, we go through the whole list */
1600 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001601 if (fsuid_only && open_file->uid != current_fsuid())
1602 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001603 if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
Steve French630f3f0c2007-10-25 21:17:17 +00001604 if (!open_file->invalidHandle) {
1605 /* found a good file */
1606 /* lock it so it will not be closed on us */
Jeff Layton764a1b12012-07-25 14:59:54 -04001607 cifsFileInfo_get_locked(open_file);
Jeff Layton44772882010-10-15 15:34:03 -04001608 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001609 return open_file;
1610 } /* else might as well continue, and look for
1611 another, or simply have the caller reopen it
1612 again rather than trying to fix this handle */
1613 } else /* write only file */
1614 break; /* write only files are last so must be done */
1615 }
Jeff Layton44772882010-10-15 15:34:03 -04001616 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001617 return NULL;
1618}
Steve French630f3f0c2007-10-25 21:17:17 +00001619
Jeff Layton6508d902010-09-29 19:51:11 -04001620struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1621 bool fsuid_only)
Steve French6148a742005-10-05 12:23:19 -07001622{
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001623 struct cifsFileInfo *open_file, *inv_file = NULL;
Jeff Laytond3892292010-11-02 16:22:50 -04001624 struct cifs_sb_info *cifs_sb;
Jeff Layton2846d382008-09-22 21:33:33 -04001625 bool any_available = false;
Steve Frenchdd99cd82005-10-05 19:32:49 -07001626 int rc;
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001627 unsigned int refind = 0;
Steve French6148a742005-10-05 12:23:19 -07001628
Steve French60808232006-04-22 15:53:05 +00001629 /* Having a null inode here (because mapping->host was set to zero by
1630 the VFS or MM) should not happen but we had reports of on oops (due to
1631 it being zero) during stress testcases so we need to check for it */
1632
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001633 if (cifs_inode == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001634 cERROR(1, "Null inode passed to cifs_writeable_file");
Steve French60808232006-04-22 15:53:05 +00001635 dump_stack();
1636 return NULL;
1637 }
1638
Jeff Laytond3892292010-11-02 16:22:50 -04001639 cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1640
Jeff Layton6508d902010-09-29 19:51:11 -04001641 /* only filter by fsuid on multiuser mounts */
1642 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1643 fsuid_only = false;
1644
Jeff Layton44772882010-10-15 15:34:03 -04001645 spin_lock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001646refind_writable:
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001647 if (refind > MAX_REOPEN_ATT) {
1648 spin_unlock(&cifs_file_list_lock);
1649 return NULL;
1650 }
Steve French6148a742005-10-05 12:23:19 -07001651 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001652 if (!any_available && open_file->pid != current->tgid)
1653 continue;
1654 if (fsuid_only && open_file->uid != current_fsuid())
1655 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001656 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Steve French9b22b0b2007-10-02 01:11:08 +00001657 if (!open_file->invalidHandle) {
1658 /* found a good writable file */
Jeff Layton764a1b12012-07-25 14:59:54 -04001659 cifsFileInfo_get_locked(open_file);
Jeff Layton44772882010-10-15 15:34:03 -04001660 spin_unlock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001661 return open_file;
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001662 } else {
1663 if (!inv_file)
1664 inv_file = open_file;
Steve French9b22b0b2007-10-02 01:11:08 +00001665 }
Steve French6148a742005-10-05 12:23:19 -07001666 }
1667 }
Jeff Layton2846d382008-09-22 21:33:33 -04001668 /* couldn't find useable FH with same pid, try any available */
1669 if (!any_available) {
1670 any_available = true;
1671 goto refind_writable;
1672 }
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001673
1674 if (inv_file) {
1675 any_available = false;
Jeff Layton764a1b12012-07-25 14:59:54 -04001676 cifsFileInfo_get_locked(inv_file);
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001677 }
1678
Jeff Layton44772882010-10-15 15:34:03 -04001679 spin_unlock(&cifs_file_list_lock);
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001680
1681 if (inv_file) {
1682 rc = cifs_reopen_file(inv_file, false);
1683 if (!rc)
1684 return inv_file;
1685 else {
1686 spin_lock(&cifs_file_list_lock);
1687 list_move_tail(&inv_file->flist,
1688 &cifs_inode->openFileList);
1689 spin_unlock(&cifs_file_list_lock);
1690 cifsFileInfo_put(inv_file);
1691 spin_lock(&cifs_file_list_lock);
1692 ++refind;
1693 goto refind_writable;
1694 }
1695 }
1696
Steve French6148a742005-10-05 12:23:19 -07001697 return NULL;
1698}
1699
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1701{
1702 struct address_space *mapping = page->mapping;
1703 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1704 char *write_data;
1705 int rc = -EFAULT;
1706 int bytes_written = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 struct inode *inode;
Steve French6148a742005-10-05 12:23:19 -07001708 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709
1710 if (!mapping || !mapping->host)
1711 return -EFAULT;
1712
1713 inode = page->mapping->host;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714
1715 offset += (loff_t)from;
1716 write_data = kmap(page);
1717 write_data += from;
1718
1719 if ((to > PAGE_CACHE_SIZE) || (from > to)) {
1720 kunmap(page);
1721 return -EIO;
1722 }
1723
1724 /* racing with truncate? */
1725 if (offset > mapping->host->i_size) {
1726 kunmap(page);
1727 return 0; /* don't care */
1728 }
1729
1730 /* check to make sure that we are not extending the file */
1731 if (mapping->host->i_size - offset < (loff_t)to)
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001732 to = (unsigned)(mapping->host->i_size - offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733
Jeff Layton6508d902010-09-29 19:51:11 -04001734 open_file = find_writable_file(CIFS_I(mapping->host), false);
Steve French6148a742005-10-05 12:23:19 -07001735 if (open_file) {
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001736 bytes_written = cifs_write(open_file, open_file->pid,
1737 write_data, to - from, &offset);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001738 cifsFileInfo_put(open_file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 /* Does mm or vfs already set times? */
Steve French6148a742005-10-05 12:23:19 -07001740 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001741 if ((bytes_written > 0) && (offset))
Steve French6148a742005-10-05 12:23:19 -07001742 rc = 0;
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001743 else if (bytes_written < 0)
1744 rc = bytes_written;
Steve French6148a742005-10-05 12:23:19 -07001745 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001746 cFYI(1, "No writeable filehandles for inode");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 rc = -EIO;
1748 }
1749
1750 kunmap(page);
1751 return rc;
1752}
1753
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754static int cifs_writepages(struct address_space *mapping,
Steve French37c0eb42005-10-05 14:50:29 -07001755 struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756{
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001757 struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb);
1758 bool done = false, scanned = false, range_whole = false;
1759 pgoff_t end, index;
1760 struct cifs_writedata *wdata;
Pavel Shilovskyc9de5c82012-09-18 16:20:29 -07001761 struct TCP_Server_Info *server;
Steve French37c0eb42005-10-05 14:50:29 -07001762 struct page *page;
Steve French37c0eb42005-10-05 14:50:29 -07001763 int rc = 0;
Jeff Laytoneddb0792012-09-18 16:20:35 -07001764 loff_t isize = i_size_read(mapping->host);
Steve French50c2f752007-07-13 00:33:32 +00001765
Steve French37c0eb42005-10-05 14:50:29 -07001766 /*
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001767 * If wsize is smaller than the page cache size, default to writing
Steve French37c0eb42005-10-05 14:50:29 -07001768 * one page at a time via cifs_writepage
1769 */
1770 if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1771 return generic_writepages(mapping, wbc);
1772
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001773 if (wbc->range_cyclic) {
Steve French37c0eb42005-10-05 14:50:29 -07001774 index = mapping->writeback_index; /* Start from prev offset */
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001775 end = -1;
1776 } else {
1777 index = wbc->range_start >> PAGE_CACHE_SHIFT;
1778 end = wbc->range_end >> PAGE_CACHE_SHIFT;
1779 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001780 range_whole = true;
1781 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001782 }
1783retry:
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001784 while (!done && index <= end) {
1785 unsigned int i, nr_pages, found_pages;
1786 pgoff_t next = 0, tofind;
1787 struct page **pages;
Steve French37c0eb42005-10-05 14:50:29 -07001788
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001789 tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1,
1790 end - index) + 1;
Steve French37c0eb42005-10-05 14:50:29 -07001791
Jeff Laytonc2e87642012-03-23 14:40:55 -04001792 wdata = cifs_writedata_alloc((unsigned int)tofind,
1793 cifs_writev_complete);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001794 if (!wdata) {
1795 rc = -ENOMEM;
1796 break;
1797 }
1798
1799 /*
1800 * find_get_pages_tag seems to return a max of 256 on each
1801 * iteration, so we must call it several times in order to
1802 * fill the array or the wsize is effectively limited to
1803 * 256 * PAGE_CACHE_SIZE.
1804 */
1805 found_pages = 0;
1806 pages = wdata->pages;
1807 do {
1808 nr_pages = find_get_pages_tag(mapping, &index,
1809 PAGECACHE_TAG_DIRTY,
1810 tofind, pages);
1811 found_pages += nr_pages;
1812 tofind -= nr_pages;
1813 pages += nr_pages;
1814 } while (nr_pages && tofind && index <= end);
1815
1816 if (found_pages == 0) {
1817 kref_put(&wdata->refcount, cifs_writedata_release);
1818 break;
1819 }
1820
1821 nr_pages = 0;
1822 for (i = 0; i < found_pages; i++) {
1823 page = wdata->pages[i];
Steve French37c0eb42005-10-05 14:50:29 -07001824 /*
1825 * At this point we hold neither mapping->tree_lock nor
1826 * lock on the page itself: the page may be truncated or
1827 * invalidated (changing page->mapping to NULL), or even
1828 * swizzled back from swapper_space to tmpfs file
1829 * mapping
1830 */
1831
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001832 if (nr_pages == 0)
Steve French37c0eb42005-10-05 14:50:29 -07001833 lock_page(page);
Nick Piggin529ae9a2008-08-02 12:01:03 +02001834 else if (!trylock_page(page))
Steve French37c0eb42005-10-05 14:50:29 -07001835 break;
1836
1837 if (unlikely(page->mapping != mapping)) {
1838 unlock_page(page);
1839 break;
1840 }
1841
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001842 if (!wbc->range_cyclic && page->index > end) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001843 done = true;
Steve French37c0eb42005-10-05 14:50:29 -07001844 unlock_page(page);
1845 break;
1846 }
1847
1848 if (next && (page->index != next)) {
1849 /* Not next consecutive page */
1850 unlock_page(page);
1851 break;
1852 }
1853
1854 if (wbc->sync_mode != WB_SYNC_NONE)
1855 wait_on_page_writeback(page);
1856
1857 if (PageWriteback(page) ||
Linus Torvaldscb876f42006-12-23 16:19:07 -08001858 !clear_page_dirty_for_io(page)) {
Steve French37c0eb42005-10-05 14:50:29 -07001859 unlock_page(page);
1860 break;
1861 }
Steve French84d2f072005-10-12 15:32:05 -07001862
Linus Torvaldscb876f42006-12-23 16:19:07 -08001863 /*
1864 * This actually clears the dirty bit in the radix tree.
1865 * See cifs_writepage() for more commentary.
1866 */
1867 set_page_writeback(page);
1868
Jeff Laytoneddb0792012-09-18 16:20:35 -07001869 if (page_offset(page) >= isize) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001870 done = true;
Steve French84d2f072005-10-12 15:32:05 -07001871 unlock_page(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001872 end_page_writeback(page);
Steve French84d2f072005-10-12 15:32:05 -07001873 break;
1874 }
1875
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001876 wdata->pages[i] = page;
Steve French37c0eb42005-10-05 14:50:29 -07001877 next = page->index + 1;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001878 ++nr_pages;
Steve French37c0eb42005-10-05 14:50:29 -07001879 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001880
1881 /* reset index to refind any pages skipped */
1882 if (nr_pages == 0)
1883 index = wdata->pages[0]->index + 1;
1884
1885 /* put any pages we aren't going to use */
1886 for (i = nr_pages; i < found_pages; i++) {
1887 page_cache_release(wdata->pages[i]);
1888 wdata->pages[i] = NULL;
1889 }
1890
1891 /* nothing to write? */
1892 if (nr_pages == 0) {
1893 kref_put(&wdata->refcount, cifs_writedata_release);
1894 continue;
1895 }
1896
1897 wdata->sync_mode = wbc->sync_mode;
1898 wdata->nr_pages = nr_pages;
1899 wdata->offset = page_offset(wdata->pages[0]);
Jeff Laytoneddb0792012-09-18 16:20:35 -07001900 wdata->pagesz = PAGE_CACHE_SIZE;
1901 wdata->tailsz =
1902 min(isize - page_offset(wdata->pages[nr_pages - 1]),
1903 (loff_t)PAGE_CACHE_SIZE);
1904 wdata->bytes = ((nr_pages - 1) * PAGE_CACHE_SIZE) +
1905 wdata->tailsz;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001906
1907 do {
1908 if (wdata->cfile != NULL)
1909 cifsFileInfo_put(wdata->cfile);
1910 wdata->cfile = find_writable_file(CIFS_I(mapping->host),
1911 false);
1912 if (!wdata->cfile) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001913 cERROR(1, "No writable handles for inode");
Steve French23e7dd72005-10-20 13:44:56 -07001914 rc = -EBADF;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001915 break;
Steve French37c0eb42005-10-05 14:50:29 -07001916 }
Jeff Laytonfe5f5d22012-03-23 14:40:55 -04001917 wdata->pid = wdata->cfile->pid;
Pavel Shilovskyc9de5c82012-09-18 16:20:29 -07001918 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
1919 rc = server->ops->async_writev(wdata);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001920 } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN);
Jeff Laytonf3983c22010-09-22 16:17:40 -07001921
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001922 for (i = 0; i < nr_pages; ++i)
1923 unlock_page(wdata->pages[i]);
Jeff Layton941b8532011-01-11 07:24:01 -05001924
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001925 /* send failure -- clean up the mess */
1926 if (rc != 0) {
1927 for (i = 0; i < nr_pages; ++i) {
Jeff Layton941b8532011-01-11 07:24:01 -05001928 if (rc == -EAGAIN)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001929 redirty_page_for_writepage(wbc,
1930 wdata->pages[i]);
1931 else
1932 SetPageError(wdata->pages[i]);
1933 end_page_writeback(wdata->pages[i]);
1934 page_cache_release(wdata->pages[i]);
Steve French37c0eb42005-10-05 14:50:29 -07001935 }
Jeff Layton941b8532011-01-11 07:24:01 -05001936 if (rc != -EAGAIN)
1937 mapping_set_error(mapping, rc);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001938 }
1939 kref_put(&wdata->refcount, cifs_writedata_release);
Jeff Layton941b8532011-01-11 07:24:01 -05001940
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001941 wbc->nr_to_write -= nr_pages;
1942 if (wbc->nr_to_write <= 0)
1943 done = true;
Dave Kleikampb066a482008-11-18 03:49:05 +00001944
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001945 index = next;
Steve French37c0eb42005-10-05 14:50:29 -07001946 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001947
Steve French37c0eb42005-10-05 14:50:29 -07001948 if (!scanned && !done) {
1949 /*
1950 * We hit the last page and there is more work to be done: wrap
1951 * back to the start of the file
1952 */
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001953 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001954 index = 0;
1955 goto retry;
1956 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001957
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001958 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
Steve French37c0eb42005-10-05 14:50:29 -07001959 mapping->writeback_index = index;
1960
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 return rc;
1962}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001964static int
1965cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966{
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001967 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001968 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001970 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971/* BB add check for wbc flags */
1972 page_cache_get(page);
Steve Frenchad7a2922008-02-07 23:25:02 +00001973 if (!PageUptodate(page))
Joe Perchesb6b38f72010-04-21 03:50:45 +00001974 cFYI(1, "ppw - page not up to date");
Linus Torvaldscb876f42006-12-23 16:19:07 -08001975
1976 /*
1977 * Set the "writeback" flag, and clear "dirty" in the radix tree.
1978 *
1979 * A writepage() implementation always needs to do either this,
1980 * or re-dirty the page with "redirty_page_for_writepage()" in
1981 * the case of a failure.
1982 *
1983 * Just unlocking the page will cause the radix tree tag-bits
1984 * to fail to update with the state of the page correctly.
1985 */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001986 set_page_writeback(page);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001987retry_write:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04001989 if (rc == -EAGAIN && wbc->sync_mode == WB_SYNC_ALL)
1990 goto retry_write;
1991 else if (rc == -EAGAIN)
1992 redirty_page_for_writepage(wbc, page);
1993 else if (rc != 0)
1994 SetPageError(page);
1995 else
1996 SetPageUptodate(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001997 end_page_writeback(page);
1998 page_cache_release(page);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001999 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 return rc;
2001}
2002
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002003static int cifs_writepage(struct page *page, struct writeback_control *wbc)
2004{
2005 int rc = cifs_writepage_locked(page, wbc);
2006 unlock_page(page);
2007 return rc;
2008}
2009
Nick Piggind9414772008-09-24 11:32:59 -04002010static int cifs_write_end(struct file *file, struct address_space *mapping,
2011 loff_t pos, unsigned len, unsigned copied,
2012 struct page *page, void *fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013{
Nick Piggind9414772008-09-24 11:32:59 -04002014 int rc;
2015 struct inode *inode = mapping->host;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002016 struct cifsFileInfo *cfile = file->private_data;
2017 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
2018 __u32 pid;
2019
2020 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2021 pid = cfile->pid;
2022 else
2023 pid = current->tgid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024
Joe Perchesb6b38f72010-04-21 03:50:45 +00002025 cFYI(1, "write_end for page %p from pos %lld with %d bytes",
2026 page, pos, copied);
Steve Frenchad7a2922008-02-07 23:25:02 +00002027
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002028 if (PageChecked(page)) {
2029 if (copied == len)
2030 SetPageUptodate(page);
2031 ClearPageChecked(page);
2032 } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
Nick Piggind9414772008-09-24 11:32:59 -04002033 SetPageUptodate(page);
2034
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 if (!PageUptodate(page)) {
Nick Piggind9414772008-09-24 11:32:59 -04002036 char *page_data;
2037 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002038 unsigned int xid;
Nick Piggind9414772008-09-24 11:32:59 -04002039
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002040 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 /* this is probably better than directly calling
2042 partialpage_write since in this function the file handle is
2043 known which we might as well leverage */
2044 /* BB check if anything else missing out of ppw
2045 such as updating last write time */
2046 page_data = kmap(page);
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002047 rc = cifs_write(cfile, pid, page_data + offset, copied, &pos);
Nick Piggind9414772008-09-24 11:32:59 -04002048 /* if (rc < 0) should we set writebehind rc? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049 kunmap(page);
Nick Piggind9414772008-09-24 11:32:59 -04002050
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002051 free_xid(xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002052 } else {
Nick Piggind9414772008-09-24 11:32:59 -04002053 rc = copied;
2054 pos += copied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 set_page_dirty(page);
2056 }
2057
Nick Piggind9414772008-09-24 11:32:59 -04002058 if (rc > 0) {
2059 spin_lock(&inode->i_lock);
2060 if (pos > inode->i_size)
2061 i_size_write(inode, pos);
2062 spin_unlock(&inode->i_lock);
2063 }
2064
2065 unlock_page(page);
2066 page_cache_release(page);
2067
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 return rc;
2069}
2070
Josef Bacik02c24a82011-07-16 20:44:56 -04002071int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
2072 int datasync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002074 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00002076 struct cifs_tcon *tcon;
Pavel Shilovsky1d8c4c02012-09-18 16:20:27 -07002077 struct TCP_Server_Info *server;
Joe Perchesc21dfb62010-07-12 13:50:14 -07002078 struct cifsFileInfo *smbfile = file->private_data;
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002079 struct inode *inode = file->f_path.dentry->d_inode;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002080 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081
Josef Bacik02c24a82011-07-16 20:44:56 -04002082 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
2083 if (rc)
2084 return rc;
2085 mutex_lock(&inode->i_mutex);
2086
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002087 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088
Joe Perchesb6b38f72010-04-21 03:50:45 +00002089 cFYI(1, "Sync file - name: %s datasync: 0x%x",
Christoph Hellwig7ea80852010-05-26 17:53:25 +02002090 file->f_path.dentry->d_name.name, datasync);
Steve French50c2f752007-07-13 00:33:32 +00002091
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002092 if (!CIFS_I(inode)->clientCanCacheRead) {
2093 rc = cifs_invalidate_mapping(inode);
2094 if (rc) {
2095 cFYI(1, "rc: %d during invalidate phase", rc);
2096 rc = 0; /* don't care about it in fsync */
2097 }
2098 }
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002099
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002100 tcon = tlink_tcon(smbfile->tlink);
Pavel Shilovsky1d8c4c02012-09-18 16:20:27 -07002101 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
2102 server = tcon->ses->server;
2103 if (server->ops->flush)
2104 rc = server->ops->flush(xid, tcon, &smbfile->fid);
2105 else
2106 rc = -ENOSYS;
2107 }
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002108
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002109 free_xid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04002110 mutex_unlock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002111 return rc;
2112}
2113
Josef Bacik02c24a82011-07-16 20:44:56 -04002114int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002115{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002116 unsigned int xid;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002117 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00002118 struct cifs_tcon *tcon;
Pavel Shilovsky1d8c4c02012-09-18 16:20:27 -07002119 struct TCP_Server_Info *server;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002120 struct cifsFileInfo *smbfile = file->private_data;
2121 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Josef Bacik02c24a82011-07-16 20:44:56 -04002122 struct inode *inode = file->f_mapping->host;
2123
2124 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
2125 if (rc)
2126 return rc;
2127 mutex_lock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002128
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002129 xid = get_xid();
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002130
2131 cFYI(1, "Sync file - name: %s datasync: 0x%x",
2132 file->f_path.dentry->d_name.name, datasync);
2133
2134 tcon = tlink_tcon(smbfile->tlink);
Pavel Shilovsky1d8c4c02012-09-18 16:20:27 -07002135 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
2136 server = tcon->ses->server;
2137 if (server->ops->flush)
2138 rc = server->ops->flush(xid, tcon, &smbfile->fid);
2139 else
2140 rc = -ENOSYS;
2141 }
Steve Frenchb298f222009-02-21 21:17:43 +00002142
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002143 free_xid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04002144 mutex_unlock(&inode->i_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 return rc;
2146}
2147
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148/*
2149 * As file closes, flush all cached write data for this inode checking
2150 * for write behind errors.
2151 */
Miklos Szeredi75e1fcc2006-06-23 02:05:12 -07002152int cifs_flush(struct file *file, fl_owner_t id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153{
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002154 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 int rc = 0;
2156
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002157 if (file->f_mode & FMODE_WRITE)
Jeff Laytond3f13222010-10-15 15:34:07 -04002158 rc = filemap_write_and_wait(inode->i_mapping);
Steve French50c2f752007-07-13 00:33:32 +00002159
Joe Perchesb6b38f72010-04-21 03:50:45 +00002160 cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161
2162 return rc;
2163}
2164
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002165static int
2166cifs_write_allocate_pages(struct page **pages, unsigned long num_pages)
2167{
2168 int rc = 0;
2169 unsigned long i;
2170
2171 for (i = 0; i < num_pages; i++) {
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002172 pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002173 if (!pages[i]) {
2174 /*
2175 * save number of pages we have already allocated and
2176 * return with ENOMEM error
2177 */
2178 num_pages = i;
2179 rc = -ENOMEM;
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002180 break;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002181 }
2182 }
2183
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002184 if (rc) {
2185 for (i = 0; i < num_pages; i++)
2186 put_page(pages[i]);
2187 }
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002188 return rc;
2189}
2190
2191static inline
2192size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
2193{
2194 size_t num_pages;
2195 size_t clen;
2196
2197 clen = min_t(const size_t, len, wsize);
Jeff Laytona7103b92012-03-23 14:40:56 -04002198 num_pages = DIV_ROUND_UP(clen, PAGE_SIZE);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002199
2200 if (cur_len)
2201 *cur_len = clen;
2202
2203 return num_pages;
2204}
2205
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002206static void
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002207cifs_uncached_writev_complete(struct work_struct *work)
2208{
2209 int i;
2210 struct cifs_writedata *wdata = container_of(work,
2211 struct cifs_writedata, work);
2212 struct inode *inode = wdata->cfile->dentry->d_inode;
2213 struct cifsInodeInfo *cifsi = CIFS_I(inode);
2214
2215 spin_lock(&inode->i_lock);
2216 cifs_update_eof(cifsi, wdata->offset, wdata->bytes);
2217 if (cifsi->server_eof > inode->i_size)
2218 i_size_write(inode, cifsi->server_eof);
2219 spin_unlock(&inode->i_lock);
2220
2221 complete(&wdata->done);
2222
2223 if (wdata->result != -EAGAIN) {
2224 for (i = 0; i < wdata->nr_pages; i++)
2225 put_page(wdata->pages[i]);
2226 }
2227
2228 kref_put(&wdata->refcount, cifs_writedata_release);
2229}
2230
2231/* attempt to send write to server, retry on any -EAGAIN errors */
2232static int
2233cifs_uncached_retry_writev(struct cifs_writedata *wdata)
2234{
2235 int rc;
Pavel Shilovskyc9de5c82012-09-18 16:20:29 -07002236 struct TCP_Server_Info *server;
2237
2238 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002239
2240 do {
2241 if (wdata->cfile->invalidHandle) {
2242 rc = cifs_reopen_file(wdata->cfile, false);
2243 if (rc != 0)
2244 continue;
2245 }
Pavel Shilovskyc9de5c82012-09-18 16:20:29 -07002246 rc = server->ops->async_writev(wdata);
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002247 } while (rc == -EAGAIN);
2248
2249 return rc;
2250}
2251
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002252static ssize_t
2253cifs_iovec_write(struct file *file, const struct iovec *iov,
2254 unsigned long nr_segs, loff_t *poffset)
2255{
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002256 unsigned long nr_pages, i;
Pavel Shilovsky76429c12011-01-31 16:03:08 +03002257 size_t copied, len, cur_len;
2258 ssize_t total_written = 0;
Jeff Layton3af9d8f2012-04-13 17:16:59 -04002259 loff_t offset;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002260 struct iov_iter it;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002261 struct cifsFileInfo *open_file;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002262 struct cifs_tcon *tcon;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002263 struct cifs_sb_info *cifs_sb;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002264 struct cifs_writedata *wdata, *tmp;
2265 struct list_head wdata_list;
2266 int rc;
2267 pid_t pid;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002268
2269 len = iov_length(iov, nr_segs);
2270 if (!len)
2271 return 0;
2272
2273 rc = generic_write_checks(file, poffset, &len, 0);
2274 if (rc)
2275 return rc;
2276
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002277 INIT_LIST_HEAD(&wdata_list);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002278 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002279 open_file = file->private_data;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002280 tcon = tlink_tcon(open_file->tlink);
Pavel Shilovskyc9de5c82012-09-18 16:20:29 -07002281
2282 if (!tcon->ses->server->ops->async_writev)
2283 return -ENOSYS;
2284
Jeff Layton3af9d8f2012-04-13 17:16:59 -04002285 offset = *poffset;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002286
2287 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2288 pid = open_file->pid;
2289 else
2290 pid = current->tgid;
2291
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002292 iov_iter_init(&it, iov, nr_segs, len, 0);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002293 do {
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002294 size_t save_len;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002295
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002296 nr_pages = get_numpages(cifs_sb->wsize, len, &cur_len);
2297 wdata = cifs_writedata_alloc(nr_pages,
2298 cifs_uncached_writev_complete);
2299 if (!wdata) {
2300 rc = -ENOMEM;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002301 break;
2302 }
2303
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002304 rc = cifs_write_allocate_pages(wdata->pages, nr_pages);
2305 if (rc) {
2306 kfree(wdata);
2307 break;
2308 }
2309
2310 save_len = cur_len;
2311 for (i = 0; i < nr_pages; i++) {
2312 copied = min_t(const size_t, cur_len, PAGE_SIZE);
2313 copied = iov_iter_copy_from_user(wdata->pages[i], &it,
2314 0, copied);
2315 cur_len -= copied;
2316 iov_iter_advance(&it, copied);
2317 }
2318 cur_len = save_len - cur_len;
2319
2320 wdata->sync_mode = WB_SYNC_ALL;
2321 wdata->nr_pages = nr_pages;
2322 wdata->offset = (__u64)offset;
2323 wdata->cfile = cifsFileInfo_get(open_file);
2324 wdata->pid = pid;
2325 wdata->bytes = cur_len;
Jeff Laytoneddb0792012-09-18 16:20:35 -07002326 wdata->pagesz = PAGE_SIZE;
2327 wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002328 rc = cifs_uncached_retry_writev(wdata);
2329 if (rc) {
2330 kref_put(&wdata->refcount, cifs_writedata_release);
2331 break;
2332 }
2333
2334 list_add_tail(&wdata->list, &wdata_list);
2335 offset += cur_len;
2336 len -= cur_len;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002337 } while (len > 0);
2338
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002339 /*
2340 * If at least one write was successfully sent, then discard any rc
2341 * value from the later writes. If the other write succeeds, then
2342 * we'll end up returning whatever was written. If it fails, then
2343 * we'll get a new rc value from that.
2344 */
2345 if (!list_empty(&wdata_list))
2346 rc = 0;
2347
2348 /*
2349 * Wait for and collect replies for any successful sends in order of
2350 * increasing offset. Once an error is hit or we get a fatal signal
2351 * while waiting, then return without waiting for any more replies.
2352 */
2353restart_loop:
2354 list_for_each_entry_safe(wdata, tmp, &wdata_list, list) {
2355 if (!rc) {
2356 /* FIXME: freezable too? */
2357 rc = wait_for_completion_killable(&wdata->done);
2358 if (rc)
2359 rc = -EINTR;
2360 else if (wdata->result)
2361 rc = wdata->result;
2362 else
2363 total_written += wdata->bytes;
2364
2365 /* resend call if it's a retryable error */
2366 if (rc == -EAGAIN) {
2367 rc = cifs_uncached_retry_writev(wdata);
2368 goto restart_loop;
2369 }
2370 }
2371 list_del_init(&wdata->list);
2372 kref_put(&wdata->refcount, cifs_writedata_release);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002373 }
2374
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002375 if (total_written > 0)
2376 *poffset += total_written;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002377
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002378 cifs_stats_bytes_written(tcon, total_written);
2379 return total_written ? total_written : (ssize_t)rc;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002380}
2381
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03002382ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002383 unsigned long nr_segs, loff_t pos)
2384{
2385 ssize_t written;
2386 struct inode *inode;
2387
2388 inode = iocb->ki_filp->f_path.dentry->d_inode;
2389
2390 /*
2391 * BB - optimize the way when signing is disabled. We can drop this
2392 * extra memory-to-memory copying and use iovec buffers for constructing
2393 * write request.
2394 */
2395
2396 written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos);
2397 if (written > 0) {
2398 CIFS_I(inode)->invalid_mapping = true;
2399 iocb->ki_pos = pos;
2400 }
2401
2402 return written;
2403}
2404
2405ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
2406 unsigned long nr_segs, loff_t pos)
2407{
2408 struct inode *inode;
2409
2410 inode = iocb->ki_filp->f_path.dentry->d_inode;
2411
2412 if (CIFS_I(inode)->clientCanCacheAll)
2413 return generic_file_aio_write(iocb, iov, nr_segs, pos);
2414
2415 /*
2416 * In strict cache mode we need to write the data to the server exactly
2417 * from the pos to pos+len-1 rather than flush all affected pages
2418 * because it may cause a error with mandatory locks on these pages but
2419 * not on the region from pos to ppos+len-1.
2420 */
2421
2422 return cifs_user_writev(iocb, iov, nr_segs, pos);
2423}
2424
Jeff Layton0471ca32012-05-16 07:13:16 -04002425static struct cifs_readdata *
Jeff Laytonf4e49cd2012-09-18 16:20:36 -07002426cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete)
Jeff Layton0471ca32012-05-16 07:13:16 -04002427{
2428 struct cifs_readdata *rdata;
Jeff Laytonf4e49cd2012-09-18 16:20:36 -07002429
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002430 rdata = kzalloc(sizeof(*rdata) + (sizeof(struct page *) * nr_pages),
2431 GFP_KERNEL);
Jeff Layton0471ca32012-05-16 07:13:16 -04002432 if (rdata != NULL) {
Jeff Layton6993f742012-05-16 07:13:17 -04002433 kref_init(&rdata->refcount);
Jeff Layton1c892542012-05-16 07:13:17 -04002434 INIT_LIST_HEAD(&rdata->list);
2435 init_completion(&rdata->done);
Jeff Layton0471ca32012-05-16 07:13:16 -04002436 INIT_WORK(&rdata->work, complete);
Jeff Layton0471ca32012-05-16 07:13:16 -04002437 }
Jeff Laytonf4e49cd2012-09-18 16:20:36 -07002438
Jeff Layton0471ca32012-05-16 07:13:16 -04002439 return rdata;
2440}
2441
Jeff Layton6993f742012-05-16 07:13:17 -04002442void
2443cifs_readdata_release(struct kref *refcount)
Jeff Layton0471ca32012-05-16 07:13:16 -04002444{
Jeff Layton6993f742012-05-16 07:13:17 -04002445 struct cifs_readdata *rdata = container_of(refcount,
2446 struct cifs_readdata, refcount);
2447
2448 if (rdata->cfile)
2449 cifsFileInfo_put(rdata->cfile);
2450
Jeff Layton0471ca32012-05-16 07:13:16 -04002451 kfree(rdata);
2452}
2453
Jeff Layton2a1bb132012-05-16 07:13:17 -04002454static int
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002455cifs_read_allocate_pages(struct cifs_readdata *rdata, unsigned int nr_pages)
Jeff Layton1c892542012-05-16 07:13:17 -04002456{
2457 int rc = 0;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002458 struct page *page;
Jeff Layton1c892542012-05-16 07:13:17 -04002459 unsigned int i;
2460
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002461 for (i = 0; i < nr_pages; i++) {
Jeff Layton1c892542012-05-16 07:13:17 -04002462 page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
2463 if (!page) {
2464 rc = -ENOMEM;
2465 break;
2466 }
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002467 rdata->pages[i] = page;
Jeff Layton1c892542012-05-16 07:13:17 -04002468 }
2469
2470 if (rc) {
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002471 for (i = 0; i < nr_pages; i++) {
2472 put_page(rdata->pages[i]);
2473 rdata->pages[i] = NULL;
Jeff Layton1c892542012-05-16 07:13:17 -04002474 }
2475 }
2476 return rc;
2477}
2478
2479static void
2480cifs_uncached_readdata_release(struct kref *refcount)
2481{
Jeff Layton1c892542012-05-16 07:13:17 -04002482 struct cifs_readdata *rdata = container_of(refcount,
2483 struct cifs_readdata, refcount);
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002484 unsigned int i;
Jeff Layton1c892542012-05-16 07:13:17 -04002485
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002486 for (i = 0; i < rdata->nr_pages; i++) {
2487 put_page(rdata->pages[i]);
2488 rdata->pages[i] = NULL;
Jeff Layton1c892542012-05-16 07:13:17 -04002489 }
2490 cifs_readdata_release(refcount);
2491}
2492
2493static int
Jeff Layton2a1bb132012-05-16 07:13:17 -04002494cifs_retry_async_readv(struct cifs_readdata *rdata)
2495{
2496 int rc;
Pavel Shilovskyfc9c5962012-09-18 16:20:28 -07002497 struct TCP_Server_Info *server;
2498
2499 server = tlink_tcon(rdata->cfile->tlink)->ses->server;
Jeff Layton2a1bb132012-05-16 07:13:17 -04002500
2501 do {
2502 if (rdata->cfile->invalidHandle) {
2503 rc = cifs_reopen_file(rdata->cfile, true);
2504 if (rc != 0)
2505 continue;
2506 }
Pavel Shilovskyfc9c5962012-09-18 16:20:28 -07002507 rc = server->ops->async_readv(rdata);
Jeff Layton2a1bb132012-05-16 07:13:17 -04002508 } while (rc == -EAGAIN);
2509
2510 return rc;
2511}
2512
Jeff Layton1c892542012-05-16 07:13:17 -04002513/**
2514 * cifs_readdata_to_iov - copy data from pages in response to an iovec
2515 * @rdata: the readdata response with list of pages holding data
2516 * @iov: vector in which we should copy the data
2517 * @nr_segs: number of segments in vector
2518 * @offset: offset into file of the first iovec
2519 * @copied: used to return the amount of data copied to the iov
2520 *
2521 * This function copies data from a list of pages in a readdata response into
2522 * an array of iovecs. It will first calculate where the data should go
2523 * based on the info in the readdata and then copy the data into that spot.
2524 */
2525static ssize_t
2526cifs_readdata_to_iov(struct cifs_readdata *rdata, const struct iovec *iov,
2527 unsigned long nr_segs, loff_t offset, ssize_t *copied)
2528{
2529 int rc = 0;
2530 struct iov_iter ii;
2531 size_t pos = rdata->offset - offset;
Jeff Layton1c892542012-05-16 07:13:17 -04002532 ssize_t remaining = rdata->bytes;
2533 unsigned char *pdata;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002534 unsigned int i;
Jeff Layton1c892542012-05-16 07:13:17 -04002535
2536 /* set up iov_iter and advance to the correct offset */
2537 iov_iter_init(&ii, iov, nr_segs, iov_length(iov, nr_segs), 0);
2538 iov_iter_advance(&ii, pos);
2539
2540 *copied = 0;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002541 for (i = 0; i < rdata->nr_pages; i++) {
Jeff Layton1c892542012-05-16 07:13:17 -04002542 ssize_t copy;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002543 struct page *page = rdata->pages[i];
Jeff Layton1c892542012-05-16 07:13:17 -04002544
2545 /* copy a whole page or whatever's left */
2546 copy = min_t(ssize_t, remaining, PAGE_SIZE);
2547
2548 /* ...but limit it to whatever space is left in the iov */
2549 copy = min_t(ssize_t, copy, iov_iter_count(&ii));
2550
2551 /* go while there's data to be copied and no errors */
2552 if (copy && !rc) {
2553 pdata = kmap(page);
2554 rc = memcpy_toiovecend(ii.iov, pdata, ii.iov_offset,
2555 (int)copy);
2556 kunmap(page);
2557 if (!rc) {
2558 *copied += copy;
2559 remaining -= copy;
2560 iov_iter_advance(&ii, copy);
2561 }
2562 }
Jeff Layton1c892542012-05-16 07:13:17 -04002563 }
2564
2565 return rc;
2566}
2567
2568static void
2569cifs_uncached_readv_complete(struct work_struct *work)
2570{
2571 struct cifs_readdata *rdata = container_of(work,
2572 struct cifs_readdata, work);
Jeff Layton1c892542012-05-16 07:13:17 -04002573
2574 complete(&rdata->done);
2575 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
2576}
2577
2578static int
Jeff Layton8321fec2012-09-19 06:22:32 -07002579cifs_uncached_read_into_pages(struct TCP_Server_Info *server,
2580 struct cifs_readdata *rdata, unsigned int len)
Jeff Layton1c892542012-05-16 07:13:17 -04002581{
Jeff Layton8321fec2012-09-19 06:22:32 -07002582 int total_read = 0, result = 0;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002583 unsigned int i;
2584 unsigned int nr_pages = rdata->nr_pages;
Jeff Layton8321fec2012-09-19 06:22:32 -07002585 struct kvec iov;
Jeff Layton1c892542012-05-16 07:13:17 -04002586
Jeff Layton8321fec2012-09-19 06:22:32 -07002587 rdata->tailsz = PAGE_SIZE;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002588 for (i = 0; i < nr_pages; i++) {
2589 struct page *page = rdata->pages[i];
2590
Jeff Layton8321fec2012-09-19 06:22:32 -07002591 if (len >= PAGE_SIZE) {
Jeff Layton1c892542012-05-16 07:13:17 -04002592 /* enough data to fill the page */
Jeff Layton8321fec2012-09-19 06:22:32 -07002593 iov.iov_base = kmap(page);
2594 iov.iov_len = PAGE_SIZE;
2595 cFYI(1, "%u: iov_base=%p iov_len=%zu",
2596 i, iov.iov_base, iov.iov_len);
2597 len -= PAGE_SIZE;
2598 } else if (len > 0) {
Jeff Layton1c892542012-05-16 07:13:17 -04002599 /* enough for partial page, fill and zero the rest */
Jeff Layton8321fec2012-09-19 06:22:32 -07002600 iov.iov_base = kmap(page);
2601 iov.iov_len = len;
2602 cFYI(1, "%u: iov_base=%p iov_len=%zu",
2603 i, iov.iov_base, iov.iov_len);
2604 memset(iov.iov_base + len, '\0', PAGE_SIZE - len);
2605 rdata->tailsz = len;
2606 len = 0;
Jeff Layton1c892542012-05-16 07:13:17 -04002607 } else {
2608 /* no need to hold page hostage */
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002609 rdata->pages[i] = NULL;
2610 rdata->nr_pages--;
Jeff Layton1c892542012-05-16 07:13:17 -04002611 put_page(page);
Jeff Layton8321fec2012-09-19 06:22:32 -07002612 continue;
Jeff Layton1c892542012-05-16 07:13:17 -04002613 }
Jeff Layton8321fec2012-09-19 06:22:32 -07002614
2615 result = cifs_readv_from_socket(server, &iov, 1, iov.iov_len);
2616 kunmap(page);
2617 if (result < 0)
2618 break;
2619
2620 total_read += result;
Jeff Layton1c892542012-05-16 07:13:17 -04002621 }
2622
Jeff Layton8321fec2012-09-19 06:22:32 -07002623 return total_read > 0 ? total_read : result;
Jeff Layton1c892542012-05-16 07:13:17 -04002624}
2625
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002626static ssize_t
2627cifs_iovec_read(struct file *file, const struct iovec *iov,
2628 unsigned long nr_segs, loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629{
Jeff Layton1c892542012-05-16 07:13:17 -04002630 ssize_t rc;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002631 size_t len, cur_len;
Jeff Layton1c892542012-05-16 07:13:17 -04002632 ssize_t total_read = 0;
2633 loff_t offset = *poffset;
2634 unsigned int npages;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 struct cifs_sb_info *cifs_sb;
Jeff Layton1c892542012-05-16 07:13:17 -04002636 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 struct cifsFileInfo *open_file;
Jeff Layton1c892542012-05-16 07:13:17 -04002638 struct cifs_readdata *rdata, *tmp;
2639 struct list_head rdata_list;
2640 pid_t pid;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002641
2642 if (!nr_segs)
2643 return 0;
2644
2645 len = iov_length(iov, nr_segs);
2646 if (!len)
2647 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648
Jeff Layton1c892542012-05-16 07:13:17 -04002649 INIT_LIST_HEAD(&rdata_list);
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002650 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -07002651 open_file = file->private_data;
Jeff Layton1c892542012-05-16 07:13:17 -04002652 tcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653
Pavel Shilovskyfc9c5962012-09-18 16:20:28 -07002654 if (!tcon->ses->server->ops->async_readv)
2655 return -ENOSYS;
2656
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002657 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2658 pid = open_file->pid;
2659 else
2660 pid = current->tgid;
2661
Steve Frenchad7a2922008-02-07 23:25:02 +00002662 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002663 cFYI(1, "attempting read on write only file instance");
Steve Frenchad7a2922008-02-07 23:25:02 +00002664
Jeff Layton1c892542012-05-16 07:13:17 -04002665 do {
2666 cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize);
2667 npages = DIV_ROUND_UP(cur_len, PAGE_SIZE);
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002668
Jeff Layton1c892542012-05-16 07:13:17 -04002669 /* allocate a readdata struct */
2670 rdata = cifs_readdata_alloc(npages,
2671 cifs_uncached_readv_complete);
2672 if (!rdata) {
2673 rc = -ENOMEM;
2674 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002676
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002677 rc = cifs_read_allocate_pages(rdata, npages);
Jeff Layton1c892542012-05-16 07:13:17 -04002678 if (rc)
2679 goto error;
2680
2681 rdata->cfile = cifsFileInfo_get(open_file);
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002682 rdata->nr_pages = npages;
Jeff Layton1c892542012-05-16 07:13:17 -04002683 rdata->offset = offset;
2684 rdata->bytes = cur_len;
2685 rdata->pid = pid;
Jeff Layton8321fec2012-09-19 06:22:32 -07002686 rdata->pagesz = PAGE_SIZE;
2687 rdata->read_into_pages = cifs_uncached_read_into_pages;
Jeff Layton1c892542012-05-16 07:13:17 -04002688
2689 rc = cifs_retry_async_readv(rdata);
2690error:
2691 if (rc) {
2692 kref_put(&rdata->refcount,
2693 cifs_uncached_readdata_release);
2694 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 }
Jeff Layton1c892542012-05-16 07:13:17 -04002696
2697 list_add_tail(&rdata->list, &rdata_list);
2698 offset += cur_len;
2699 len -= cur_len;
2700 } while (len > 0);
2701
2702 /* if at least one read request send succeeded, then reset rc */
2703 if (!list_empty(&rdata_list))
2704 rc = 0;
2705
2706 /* the loop below should proceed in the order of increasing offsets */
2707restart_loop:
2708 list_for_each_entry_safe(rdata, tmp, &rdata_list, list) {
2709 if (!rc) {
2710 ssize_t copied;
2711
2712 /* FIXME: freezable sleep too? */
2713 rc = wait_for_completion_killable(&rdata->done);
2714 if (rc)
2715 rc = -EINTR;
2716 else if (rdata->result)
2717 rc = rdata->result;
2718 else {
2719 rc = cifs_readdata_to_iov(rdata, iov,
2720 nr_segs, *poffset,
2721 &copied);
2722 total_read += copied;
2723 }
2724
2725 /* resend call if it's a retryable error */
2726 if (rc == -EAGAIN) {
2727 rc = cifs_retry_async_readv(rdata);
2728 goto restart_loop;
2729 }
2730 }
2731 list_del_init(&rdata->list);
2732 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002734
Jeff Layton1c892542012-05-16 07:13:17 -04002735 cifs_stats_bytes_read(tcon, total_read);
2736 *poffset += total_read;
2737
Pavel Shilovsky09a47072012-09-18 16:20:29 -07002738 /* mask nodata case */
2739 if (rc == -ENODATA)
2740 rc = 0;
2741
Jeff Layton1c892542012-05-16 07:13:17 -04002742 return total_read ? total_read : rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743}
2744
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03002745ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002746 unsigned long nr_segs, loff_t pos)
2747{
2748 ssize_t read;
2749
2750 read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos);
2751 if (read > 0)
2752 iocb->ki_pos = pos;
2753
2754 return read;
2755}
2756
2757ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov,
2758 unsigned long nr_segs, loff_t pos)
2759{
2760 struct inode *inode;
2761
2762 inode = iocb->ki_filp->f_path.dentry->d_inode;
2763
2764 if (CIFS_I(inode)->clientCanCacheRead)
2765 return generic_file_aio_read(iocb, iov, nr_segs, pos);
2766
2767 /*
2768 * In strict cache mode we need to read from the server all the time
2769 * if we don't have level II oplock because the server can delay mtime
2770 * change - so we can't make a decision about inode invalidating.
2771 * And we can also fail with pagereading if there are mandatory locks
2772 * on pages affected by this read but not on the region from pos to
2773 * pos+len-1.
2774 */
2775
2776 return cifs_user_readv(iocb, iov, nr_segs, pos);
2777}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07002779static ssize_t
2780cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781{
2782 int rc = -EACCES;
2783 unsigned int bytes_read = 0;
2784 unsigned int total_read;
2785 unsigned int current_read_size;
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002786 unsigned int rsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787 struct cifs_sb_info *cifs_sb;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04002788 struct cifs_tcon *tcon;
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07002789 struct TCP_Server_Info *server;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002790 unsigned int xid;
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07002791 char *cur_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 struct cifsFileInfo *open_file;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002793 struct cifs_io_parms io_parms;
Steve Frenchec637e32005-12-12 20:53:18 -08002794 int buf_type = CIFS_NO_BUFFER;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002795 __u32 pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002797 xid = get_xid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002798 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002800 /* FIXME: set up handlers for larger reads and/or convert to async */
2801 rsize = min_t(unsigned int, cifs_sb->rsize, CIFSMaxBufSize);
2802
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302804 rc = -EBADF;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002805 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302806 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 }
Joe Perchesc21dfb62010-07-12 13:50:14 -07002808 open_file = file->private_data;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04002809 tcon = tlink_tcon(open_file->tlink);
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07002810 server = tcon->ses->server;
2811
2812 if (!server->ops->sync_read) {
2813 free_xid(xid);
2814 return -ENOSYS;
2815 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002817 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2818 pid = open_file->pid;
2819 else
2820 pid = current->tgid;
2821
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002823 cFYI(1, "attempting read on write only file instance");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07002825 for (total_read = 0, cur_offset = read_data; read_size > total_read;
2826 total_read += bytes_read, cur_offset += bytes_read) {
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002827 current_read_size = min_t(uint, read_size - total_read, rsize);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04002828 /*
2829 * For windows me and 9x we do not want to request more than it
2830 * negotiated since it will refuse the read then.
2831 */
2832 if ((tcon->ses) && !(tcon->ses->capabilities &
2833 tcon->ses->server->vals->cap_large_files)) {
Dan Carpenter7748dd62011-10-18 12:41:35 +03002834 current_read_size = min_t(uint, current_read_size,
Jeff Laytonc974bef2011-10-11 06:41:32 -04002835 CIFSMaxBufSize);
Steve Frenchf9f5c8172005-09-15 23:06:38 -07002836 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837 rc = -EAGAIN;
2838 while (rc == -EAGAIN) {
Steve Frenchcdff08e2010-10-21 22:46:14 +00002839 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04002840 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 if (rc != 0)
2842 break;
2843 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002844 io_parms.pid = pid;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04002845 io_parms.tcon = tcon;
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07002846 io_parms.offset = *offset;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002847 io_parms.length = current_read_size;
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07002848 rc = server->ops->sync_read(xid, open_file, &io_parms,
2849 &bytes_read, &cur_offset,
2850 &buf_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851 }
2852 if (rc || (bytes_read == 0)) {
2853 if (total_read) {
2854 break;
2855 } else {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002856 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857 return rc;
2858 }
2859 } else {
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04002860 cifs_stats_bytes_read(tcon, total_read);
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07002861 *offset += bytes_read;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 }
2863 }
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002864 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 return total_read;
2866}
2867
Jeff Laytonca83ce32011-04-12 09:13:44 -04002868/*
2869 * If the page is mmap'ed into a process' page tables, then we need to make
2870 * sure that it doesn't change while being written back.
2871 */
2872static int
2873cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
2874{
2875 struct page *page = vmf->page;
2876
2877 lock_page(page);
2878 return VM_FAULT_LOCKED;
2879}
2880
2881static struct vm_operations_struct cifs_file_vm_ops = {
2882 .fault = filemap_fault,
2883 .page_mkwrite = cifs_page_mkwrite,
2884};
2885
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002886int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
2887{
2888 int rc, xid;
2889 struct inode *inode = file->f_path.dentry->d_inode;
2890
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002891 xid = get_xid();
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002892
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002893 if (!CIFS_I(inode)->clientCanCacheRead) {
2894 rc = cifs_invalidate_mapping(inode);
2895 if (rc)
2896 return rc;
2897 }
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002898
2899 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04002900 if (rc == 0)
2901 vma->vm_ops = &cifs_file_vm_ops;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002902 free_xid(xid);
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03002903 return rc;
2904}
2905
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
2907{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908 int rc, xid;
2909
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002910 xid = get_xid();
Jeff Laytonabab0952010-02-12 07:44:18 -05002911 rc = cifs_revalidate_file(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002913 cFYI(1, "Validation prior to mmap failed, error=%d", rc);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002914 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915 return rc;
2916 }
2917 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04002918 if (rc == 0)
2919 vma->vm_ops = &cifs_file_vm_ops;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002920 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921 return rc;
2922}
2923
Jeff Layton0471ca32012-05-16 07:13:16 -04002924static void
2925cifs_readv_complete(struct work_struct *work)
2926{
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002927 unsigned int i;
Jeff Layton0471ca32012-05-16 07:13:16 -04002928 struct cifs_readdata *rdata = container_of(work,
2929 struct cifs_readdata, work);
Jeff Layton0471ca32012-05-16 07:13:16 -04002930
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002931 for (i = 0; i < rdata->nr_pages; i++) {
2932 struct page *page = rdata->pages[i];
2933
Jeff Layton0471ca32012-05-16 07:13:16 -04002934 lru_cache_add_file(page);
2935
2936 if (rdata->result == 0) {
Jeff Layton0471ca32012-05-16 07:13:16 -04002937 flush_dcache_page(page);
2938 SetPageUptodate(page);
2939 }
2940
2941 unlock_page(page);
2942
2943 if (rdata->result == 0)
2944 cifs_readpage_to_fscache(rdata->mapping->host, page);
2945
2946 page_cache_release(page);
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002947 rdata->pages[i] = NULL;
Jeff Layton0471ca32012-05-16 07:13:16 -04002948 }
Jeff Layton6993f742012-05-16 07:13:17 -04002949 kref_put(&rdata->refcount, cifs_readdata_release);
Jeff Layton0471ca32012-05-16 07:13:16 -04002950}
2951
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04002952static int
Jeff Layton8321fec2012-09-19 06:22:32 -07002953cifs_readpages_read_into_pages(struct TCP_Server_Info *server,
2954 struct cifs_readdata *rdata, unsigned int len)
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04002955{
Jeff Layton8321fec2012-09-19 06:22:32 -07002956 int total_read = 0, result = 0;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002957 unsigned int i;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04002958 u64 eof;
2959 pgoff_t eof_index;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002960 unsigned int nr_pages = rdata->nr_pages;
Jeff Layton8321fec2012-09-19 06:22:32 -07002961 struct kvec iov;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04002962
2963 /* determine the eof that the server (probably) has */
2964 eof = CIFS_I(rdata->mapping->host)->server_eof;
2965 eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
2966 cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
2967
Jeff Layton8321fec2012-09-19 06:22:32 -07002968 rdata->tailsz = PAGE_CACHE_SIZE;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002969 for (i = 0; i < nr_pages; i++) {
2970 struct page *page = rdata->pages[i];
2971
Jeff Layton8321fec2012-09-19 06:22:32 -07002972 if (len >= PAGE_CACHE_SIZE) {
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04002973 /* enough data to fill the page */
Jeff Layton8321fec2012-09-19 06:22:32 -07002974 iov.iov_base = kmap(page);
2975 iov.iov_len = PAGE_CACHE_SIZE;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04002976 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
Jeff Layton8321fec2012-09-19 06:22:32 -07002977 i, page->index, iov.iov_base, iov.iov_len);
2978 len -= PAGE_CACHE_SIZE;
2979 } else if (len > 0) {
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04002980 /* enough for partial page, fill and zero the rest */
Jeff Layton8321fec2012-09-19 06:22:32 -07002981 iov.iov_base = kmap(page);
2982 iov.iov_len = len;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04002983 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
Jeff Layton8321fec2012-09-19 06:22:32 -07002984 i, page->index, iov.iov_base, iov.iov_len);
2985 memset(iov.iov_base + len,
2986 '\0', PAGE_CACHE_SIZE - len);
2987 rdata->tailsz = len;
2988 len = 0;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04002989 } else if (page->index > eof_index) {
2990 /*
2991 * The VFS will not try to do readahead past the
2992 * i_size, but it's possible that we have outstanding
2993 * writes with gaps in the middle and the i_size hasn't
2994 * caught up yet. Populate those with zeroed out pages
2995 * to prevent the VFS from repeatedly attempting to
2996 * fill them until the writes are flushed.
2997 */
2998 zero_user(page, 0, PAGE_CACHE_SIZE);
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04002999 lru_cache_add_file(page);
3000 flush_dcache_page(page);
3001 SetPageUptodate(page);
3002 unlock_page(page);
3003 page_cache_release(page);
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003004 rdata->pages[i] = NULL;
3005 rdata->nr_pages--;
Jeff Layton8321fec2012-09-19 06:22:32 -07003006 continue;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003007 } else {
3008 /* no need to hold page hostage */
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003009 lru_cache_add_file(page);
3010 unlock_page(page);
3011 page_cache_release(page);
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003012 rdata->pages[i] = NULL;
3013 rdata->nr_pages--;
Jeff Layton8321fec2012-09-19 06:22:32 -07003014 continue;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003015 }
Jeff Layton8321fec2012-09-19 06:22:32 -07003016
3017 result = cifs_readv_from_socket(server, &iov, 1, iov.iov_len);
3018 kunmap(page);
3019 if (result < 0)
3020 break;
3021
3022 total_read += result;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003023 }
3024
Jeff Layton8321fec2012-09-19 06:22:32 -07003025 return total_read > 0 ? total_read : result;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003026}
3027
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028static int cifs_readpages(struct file *file, struct address_space *mapping,
3029 struct list_head *page_list, unsigned num_pages)
3030{
Jeff Layton690c5e32011-10-19 15:30:16 -04003031 int rc;
3032 struct list_head tmplist;
3033 struct cifsFileInfo *open_file = file->private_data;
3034 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
3035 unsigned int rsize = cifs_sb->rsize;
3036 pid_t pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037
Jeff Layton690c5e32011-10-19 15:30:16 -04003038 /*
3039 * Give up immediately if rsize is too small to read an entire page.
3040 * The VFS will fall back to readpage. We should never reach this
3041 * point however since we set ra_pages to 0 when the rsize is smaller
3042 * than a cache page.
3043 */
3044 if (unlikely(rsize < PAGE_CACHE_SIZE))
3045 return 0;
Steve Frenchbfa0d752005-08-31 21:50:37 -07003046
Suresh Jayaraman56698232010-07-05 18:13:25 +05303047 /*
3048 * Reads as many pages as possible from fscache. Returns -ENOBUFS
3049 * immediately if the cookie is negative
3050 */
3051 rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
3052 &num_pages);
3053 if (rc == 0)
Jeff Layton690c5e32011-10-19 15:30:16 -04003054 return rc;
Suresh Jayaraman56698232010-07-05 18:13:25 +05303055
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003056 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
3057 pid = open_file->pid;
3058 else
3059 pid = current->tgid;
3060
Jeff Layton690c5e32011-10-19 15:30:16 -04003061 rc = 0;
3062 INIT_LIST_HEAD(&tmplist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063
Jeff Layton690c5e32011-10-19 15:30:16 -04003064 cFYI(1, "%s: file=%p mapping=%p num_pages=%u", __func__, file,
3065 mapping, num_pages);
3066
3067 /*
3068 * Start with the page at end of list and move it to private
3069 * list. Do the same with any following pages until we hit
3070 * the rsize limit, hit an index discontinuity, or run out of
3071 * pages. Issue the async read and then start the loop again
3072 * until the list is empty.
3073 *
3074 * Note that list order is important. The page_list is in
3075 * the order of declining indexes. When we put the pages in
3076 * the rdata->pages, then we want them in increasing order.
3077 */
3078 while (!list_empty(page_list)) {
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003079 unsigned int i;
Jeff Layton690c5e32011-10-19 15:30:16 -04003080 unsigned int bytes = PAGE_CACHE_SIZE;
3081 unsigned int expected_index;
3082 unsigned int nr_pages = 1;
3083 loff_t offset;
3084 struct page *page, *tpage;
3085 struct cifs_readdata *rdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003086
3087 page = list_entry(page_list->prev, struct page, lru);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088
Jeff Layton690c5e32011-10-19 15:30:16 -04003089 /*
3090 * Lock the page and put it in the cache. Since no one else
3091 * should have access to this page, we're safe to simply set
3092 * PG_locked without checking it first.
3093 */
3094 __set_page_locked(page);
3095 rc = add_to_page_cache_locked(page, mapping,
3096 page->index, GFP_KERNEL);
3097
3098 /* give up if we can't stick it in the cache */
3099 if (rc) {
3100 __clear_page_locked(page);
3101 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103
Jeff Layton690c5e32011-10-19 15:30:16 -04003104 /* move first page to the tmplist */
3105 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
3106 list_move_tail(&page->lru, &tmplist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107
Jeff Layton690c5e32011-10-19 15:30:16 -04003108 /* now try and add more pages onto the request */
3109 expected_index = page->index + 1;
3110 list_for_each_entry_safe_reverse(page, tpage, page_list, lru) {
3111 /* discontinuity ? */
3112 if (page->index != expected_index)
3113 break;
3114
3115 /* would this page push the read over the rsize? */
3116 if (bytes + PAGE_CACHE_SIZE > rsize)
3117 break;
3118
3119 __set_page_locked(page);
3120 if (add_to_page_cache_locked(page, mapping,
3121 page->index, GFP_KERNEL)) {
3122 __clear_page_locked(page);
3123 break;
3124 }
3125 list_move_tail(&page->lru, &tmplist);
3126 bytes += PAGE_CACHE_SIZE;
3127 expected_index++;
3128 nr_pages++;
3129 }
3130
Jeff Layton0471ca32012-05-16 07:13:16 -04003131 rdata = cifs_readdata_alloc(nr_pages, cifs_readv_complete);
Jeff Layton690c5e32011-10-19 15:30:16 -04003132 if (!rdata) {
3133 /* best to give up if we're out of mem */
3134 list_for_each_entry_safe(page, tpage, &tmplist, lru) {
3135 list_del(&page->lru);
3136 lru_cache_add_file(page);
3137 unlock_page(page);
3138 page_cache_release(page);
3139 }
3140 rc = -ENOMEM;
3141 break;
3142 }
3143
Jeff Layton6993f742012-05-16 07:13:17 -04003144 rdata->cfile = cifsFileInfo_get(open_file);
Jeff Layton690c5e32011-10-19 15:30:16 -04003145 rdata->mapping = mapping;
3146 rdata->offset = offset;
3147 rdata->bytes = bytes;
3148 rdata->pid = pid;
Jeff Layton8321fec2012-09-19 06:22:32 -07003149 rdata->pagesz = PAGE_CACHE_SIZE;
3150 rdata->read_into_pages = cifs_readpages_read_into_pages;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003151
3152 list_for_each_entry_safe(page, tpage, &tmplist, lru) {
3153 list_del(&page->lru);
3154 rdata->pages[rdata->nr_pages++] = page;
3155 }
Jeff Layton690c5e32011-10-19 15:30:16 -04003156
Jeff Layton2a1bb132012-05-16 07:13:17 -04003157 rc = cifs_retry_async_readv(rdata);
Jeff Layton690c5e32011-10-19 15:30:16 -04003158 if (rc != 0) {
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003159 for (i = 0; i < rdata->nr_pages; i++) {
3160 page = rdata->pages[i];
Jeff Layton690c5e32011-10-19 15:30:16 -04003161 lru_cache_add_file(page);
3162 unlock_page(page);
3163 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 }
Jeff Layton6993f742012-05-16 07:13:17 -04003165 kref_put(&rdata->refcount, cifs_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166 break;
3167 }
Jeff Layton6993f742012-05-16 07:13:17 -04003168
3169 kref_put(&rdata->refcount, cifs_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170 }
3171
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 return rc;
3173}
3174
3175static int cifs_readpage_worker(struct file *file, struct page *page,
3176 loff_t *poffset)
3177{
3178 char *read_data;
3179 int rc;
3180
Suresh Jayaraman56698232010-07-05 18:13:25 +05303181 /* Is the page cached? */
3182 rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page);
3183 if (rc == 0)
3184 goto read_complete;
3185
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186 page_cache_get(page);
3187 read_data = kmap(page);
3188 /* for reads over a certain size could initiate async read ahead */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003189
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003191
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192 if (rc < 0)
3193 goto io_error;
3194 else
Joe Perchesb6b38f72010-04-21 03:50:45 +00003195 cFYI(1, "Bytes read %d", rc);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003196
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08003197 file->f_path.dentry->d_inode->i_atime =
3198 current_fs_time(file->f_path.dentry->d_inode->i_sb);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003199
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 if (PAGE_CACHE_SIZE > rc)
3201 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
3202
3203 flush_dcache_page(page);
3204 SetPageUptodate(page);
Suresh Jayaraman9dc06552010-07-05 18:13:11 +05303205
3206 /* send this page to the cache */
3207 cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page);
3208
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209 rc = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003210
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211io_error:
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003212 kunmap(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213 page_cache_release(page);
Suresh Jayaraman56698232010-07-05 18:13:25 +05303214
3215read_complete:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216 return rc;
3217}
3218
3219static int cifs_readpage(struct file *file, struct page *page)
3220{
3221 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
3222 int rc = -EACCES;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003223 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003225 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226
3227 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05303228 rc = -EBADF;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003229 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05303230 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231 }
3232
Jeff Laytonac3aa2f2012-07-23 13:14:28 -04003233 cFYI(1, "readpage %p at offset %d 0x%x",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003234 page, (int)offset, (int)offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235
3236 rc = cifs_readpage_worker(file, page, &offset);
3237
3238 unlock_page(page);
3239
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003240 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003241 return rc;
3242}
3243
Steve Frencha403a0a2007-07-26 15:54:16 +00003244static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
3245{
3246 struct cifsFileInfo *open_file;
3247
Jeff Layton44772882010-10-15 15:34:03 -04003248 spin_lock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003249 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton2e396b82010-10-15 15:34:01 -04003250 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Jeff Layton44772882010-10-15 15:34:03 -04003251 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003252 return 1;
3253 }
3254 }
Jeff Layton44772882010-10-15 15:34:03 -04003255 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003256 return 0;
3257}
3258
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259/* We do not want to update the file size from server for inodes
3260 open for write - to avoid races with writepage extending
3261 the file - in the future we could consider allowing
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003262 refreshing the inode only on increases in the file size
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263 but this is tricky to do without racing with writebehind
3264 page caching in the current Linux kernel design */
Steve French4b18f2a2008-04-29 00:06:05 +00003265bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003266{
Steve Frencha403a0a2007-07-26 15:54:16 +00003267 if (!cifsInode)
Steve French4b18f2a2008-04-29 00:06:05 +00003268 return true;
Steve French23e7dd72005-10-20 13:44:56 -07003269
Steve Frencha403a0a2007-07-26 15:54:16 +00003270 if (is_inode_writable(cifsInode)) {
3271 /* This inode is open for write at least once */
Steve Frenchc32a0b62006-01-12 14:41:28 -08003272 struct cifs_sb_info *cifs_sb;
3273
Steve Frenchc32a0b62006-01-12 14:41:28 -08003274 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
Steve Frenchad7a2922008-02-07 23:25:02 +00003275 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003276 /* since no page cache to corrupt on directio
Steve Frenchc32a0b62006-01-12 14:41:28 -08003277 we can change size safely */
Steve French4b18f2a2008-04-29 00:06:05 +00003278 return true;
Steve Frenchc32a0b62006-01-12 14:41:28 -08003279 }
3280
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003281 if (i_size_read(&cifsInode->vfs_inode) < end_of_file)
Steve French4b18f2a2008-04-29 00:06:05 +00003282 return true;
Steve French7ba52632007-02-08 18:14:13 +00003283
Steve French4b18f2a2008-04-29 00:06:05 +00003284 return false;
Steve French23e7dd72005-10-20 13:44:56 -07003285 } else
Steve French4b18f2a2008-04-29 00:06:05 +00003286 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287}
3288
Nick Piggind9414772008-09-24 11:32:59 -04003289static int cifs_write_begin(struct file *file, struct address_space *mapping,
3290 loff_t pos, unsigned len, unsigned flags,
3291 struct page **pagep, void **fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292{
Nick Piggind9414772008-09-24 11:32:59 -04003293 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
3294 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003295 loff_t page_start = pos & PAGE_MASK;
3296 loff_t i_size;
3297 struct page *page;
3298 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299
Joe Perchesb6b38f72010-04-21 03:50:45 +00003300 cFYI(1, "write_begin from %lld len %d", (long long)pos, len);
Nick Piggind9414772008-09-24 11:32:59 -04003301
Nick Piggin54566b22009-01-04 12:00:53 -08003302 page = grab_cache_page_write_begin(mapping, index, flags);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003303 if (!page) {
3304 rc = -ENOMEM;
3305 goto out;
3306 }
Nick Piggind9414772008-09-24 11:32:59 -04003307
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003308 if (PageUptodate(page))
3309 goto out;
Steve French8a236262007-03-06 00:31:00 +00003310
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003311 /*
3312 * If we write a full page it will be up to date, no need to read from
3313 * the server. If the write is short, we'll end up doing a sync write
3314 * instead.
3315 */
3316 if (len == PAGE_CACHE_SIZE)
3317 goto out;
3318
3319 /*
3320 * optimize away the read when we have an oplock, and we're not
3321 * expecting to use any of the data we'd be reading in. That
3322 * is, when the page lies beyond the EOF, or straddles the EOF
3323 * and the write will cover all of the existing data.
3324 */
3325 if (CIFS_I(mapping->host)->clientCanCacheRead) {
3326 i_size = i_size_read(mapping->host);
3327 if (page_start >= i_size ||
3328 (offset == 0 && (pos + len) >= i_size)) {
3329 zero_user_segments(page, 0, offset,
3330 offset + len,
3331 PAGE_CACHE_SIZE);
3332 /*
3333 * PageChecked means that the parts of the page
3334 * to which we're not writing are considered up
3335 * to date. Once the data is copied to the
3336 * page, it can be set uptodate.
3337 */
3338 SetPageChecked(page);
3339 goto out;
3340 }
3341 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342
Nick Piggind9414772008-09-24 11:32:59 -04003343 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003344 /*
3345 * might as well read a page, it is fast enough. If we get
3346 * an error, we don't need to return it. cifs_write_end will
3347 * do a sync write instead since PG_uptodate isn't set.
3348 */
3349 cifs_readpage_worker(file, page, &page_start);
Steve French8a236262007-03-06 00:31:00 +00003350 } else {
3351 /* we could try using another file handle if there is one -
3352 but how would we lock it to prevent close of that handle
3353 racing with this read? In any case
Nick Piggind9414772008-09-24 11:32:59 -04003354 this will be written out by write_end so is fine */
Steve French8a236262007-03-06 00:31:00 +00003355 }
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003356out:
3357 *pagep = page;
3358 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359}
3360
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303361static int cifs_release_page(struct page *page, gfp_t gfp)
3362{
3363 if (PagePrivate(page))
3364 return 0;
3365
3366 return cifs_fscache_release_page(page, gfp);
3367}
3368
3369static void cifs_invalidate_page(struct page *page, unsigned long offset)
3370{
3371 struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
3372
3373 if (offset == 0)
3374 cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
3375}
3376
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003377static int cifs_launder_page(struct page *page)
3378{
3379 int rc = 0;
3380 loff_t range_start = page_offset(page);
3381 loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
3382 struct writeback_control wbc = {
3383 .sync_mode = WB_SYNC_ALL,
3384 .nr_to_write = 0,
3385 .range_start = range_start,
3386 .range_end = range_end,
3387 };
3388
3389 cFYI(1, "Launder page: %p", page);
3390
3391 if (clear_page_dirty_for_io(page))
3392 rc = cifs_writepage_locked(page, &wbc);
3393
3394 cifs_fscache_invalidate_page(page, page->mapping->host);
3395 return rc;
3396}
3397
Tejun Heo9b646972010-07-20 22:09:02 +02003398void cifs_oplock_break(struct work_struct *work)
Jeff Layton3bc303c2009-09-21 06:47:50 -04003399{
3400 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
3401 oplock_break);
Jeff Laytona5e18bc2010-10-11 15:07:18 -04003402 struct inode *inode = cfile->dentry->d_inode;
Jeff Layton3bc303c2009-09-21 06:47:50 -04003403 struct cifsInodeInfo *cinode = CIFS_I(inode);
Pavel Shilovsky95a3f2f2012-09-18 16:20:33 -07003404 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04003405 int rc = 0;
Jeff Layton3bc303c2009-09-21 06:47:50 -04003406
3407 if (inode && S_ISREG(inode->i_mode)) {
Steve Frenchd54ff732010-04-27 04:38:15 +00003408 if (cinode->clientCanCacheRead)
Al Viro8737c932009-12-24 06:47:55 -05003409 break_lease(inode, O_RDONLY);
Steve Frenchd54ff732010-04-27 04:38:15 +00003410 else
Al Viro8737c932009-12-24 06:47:55 -05003411 break_lease(inode, O_WRONLY);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003412 rc = filemap_fdatawrite(inode->i_mapping);
3413 if (cinode->clientCanCacheRead == 0) {
Jeff Laytoneb4b7562010-10-22 14:52:29 -04003414 rc = filemap_fdatawait(inode->i_mapping);
3415 mapping_set_error(inode->i_mapping, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003416 invalidate_remote_inode(inode);
3417 }
Joe Perchesb6b38f72010-04-21 03:50:45 +00003418 cFYI(1, "Oplock flush inode %p rc %d", inode, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003419 }
3420
Pavel Shilovsky85160e02011-10-22 15:33:29 +04003421 rc = cifs_push_locks(cfile);
3422 if (rc)
3423 cERROR(1, "Push locks rc = %d", rc);
3424
Jeff Layton3bc303c2009-09-21 06:47:50 -04003425 /*
3426 * releasing stale oplock after recent reconnect of smb session using
3427 * a now incorrect file handle is not a data integrity issue but do
3428 * not bother sending an oplock release if session to server still is
3429 * disconnected since oplock already released by the server
3430 */
Steve Frenchcdff08e2010-10-21 22:46:14 +00003431 if (!cfile->oplock_break_cancelled) {
Pavel Shilovsky95a3f2f2012-09-18 16:20:33 -07003432 rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
3433 cinode);
Joe Perchesb6b38f72010-04-21 03:50:45 +00003434 cFYI(1, "Oplock release rc = %d", rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003435 }
Jeff Layton3bc303c2009-09-21 06:47:50 -04003436}
3437
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07003438const struct address_space_operations cifs_addr_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439 .readpage = cifs_readpage,
3440 .readpages = cifs_readpages,
3441 .writepage = cifs_writepage,
Steve French37c0eb42005-10-05 14:50:29 -07003442 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04003443 .write_begin = cifs_write_begin,
3444 .write_end = cifs_write_end,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303446 .releasepage = cifs_release_page,
3447 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003448 .launder_page = cifs_launder_page,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449};
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003450
3451/*
3452 * cifs_readpages requires the server to support a buffer large enough to
3453 * contain the header plus one complete page of data. Otherwise, we need
3454 * to leave cifs_readpages out of the address space operations.
3455 */
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07003456const struct address_space_operations cifs_addr_ops_smallbuf = {
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003457 .readpage = cifs_readpage,
3458 .writepage = cifs_writepage,
3459 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04003460 .write_begin = cifs_write_begin,
3461 .write_end = cifs_write_end,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003462 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303463 .releasepage = cifs_release_page,
3464 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003465 .launder_page = cifs_launder_page,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003466};