blob: 4d8ba8d491e5d0be27bfbf8506175f7ffd8ce476 [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
Steve French07b92d02013-02-18 10:34:26 -060046
Linus Torvalds1da177e2005-04-16 15:20:36 -070047static inline int cifs_convert_flags(unsigned int flags)
48{
49 if ((flags & O_ACCMODE) == O_RDONLY)
50 return GENERIC_READ;
51 else if ((flags & O_ACCMODE) == O_WRONLY)
52 return GENERIC_WRITE;
53 else if ((flags & O_ACCMODE) == O_RDWR) {
54 /* GENERIC_ALL is too much permission to request
55 can cause unnecessary access denied on create */
56 /* return GENERIC_ALL; */
57 return (GENERIC_READ | GENERIC_WRITE);
58 }
59
Jeff Laytone10f7b52008-05-14 10:21:33 -070060 return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
61 FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA |
62 FILE_READ_DATA);
Steve French7fc8f4e2009-02-23 20:43:11 +000063}
Jeff Laytone10f7b52008-05-14 10:21:33 -070064
Jeff Layton608712f2010-10-15 15:33:56 -040065static u32 cifs_posix_convert_flags(unsigned int flags)
Steve French7fc8f4e2009-02-23 20:43:11 +000066{
Jeff Layton608712f2010-10-15 15:33:56 -040067 u32 posix_flags = 0;
Jeff Laytone10f7b52008-05-14 10:21:33 -070068
Steve French7fc8f4e2009-02-23 20:43:11 +000069 if ((flags & O_ACCMODE) == O_RDONLY)
Jeff Layton608712f2010-10-15 15:33:56 -040070 posix_flags = SMB_O_RDONLY;
Steve French7fc8f4e2009-02-23 20:43:11 +000071 else if ((flags & O_ACCMODE) == O_WRONLY)
Jeff Layton608712f2010-10-15 15:33:56 -040072 posix_flags = SMB_O_WRONLY;
73 else if ((flags & O_ACCMODE) == O_RDWR)
74 posix_flags = SMB_O_RDWR;
75
Steve French07b92d02013-02-18 10:34:26 -060076 if (flags & O_CREAT) {
Jeff Layton608712f2010-10-15 15:33:56 -040077 posix_flags |= SMB_O_CREAT;
Steve French07b92d02013-02-18 10:34:26 -060078 if (flags & O_EXCL)
79 posix_flags |= SMB_O_EXCL;
80 } else if (flags & O_EXCL)
Joe Perchesf96637b2013-05-04 22:12:25 -050081 cifs_dbg(FYI, "Application %s pid %d has incorrectly set O_EXCL flag but not O_CREAT on file open. Ignoring O_EXCL\n",
82 current->comm, current->tgid);
Steve French07b92d02013-02-18 10:34:26 -060083
Jeff Layton608712f2010-10-15 15:33:56 -040084 if (flags & O_TRUNC)
85 posix_flags |= SMB_O_TRUNC;
86 /* be safe and imply O_SYNC for O_DSYNC */
Christoph Hellwig6b2f3d12009-10-27 11:05:28 +010087 if (flags & O_DSYNC)
Jeff Layton608712f2010-10-15 15:33:56 -040088 posix_flags |= SMB_O_SYNC;
Steve French7fc8f4e2009-02-23 20:43:11 +000089 if (flags & O_DIRECTORY)
Jeff Layton608712f2010-10-15 15:33:56 -040090 posix_flags |= SMB_O_DIRECTORY;
Steve French7fc8f4e2009-02-23 20:43:11 +000091 if (flags & O_NOFOLLOW)
Jeff Layton608712f2010-10-15 15:33:56 -040092 posix_flags |= SMB_O_NOFOLLOW;
Steve French7fc8f4e2009-02-23 20:43:11 +000093 if (flags & O_DIRECT)
Jeff Layton608712f2010-10-15 15:33:56 -040094 posix_flags |= SMB_O_DIRECT;
Steve French7fc8f4e2009-02-23 20:43:11 +000095
96 return posix_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097}
98
99static inline int cifs_get_disposition(unsigned int flags)
100{
101 if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
102 return FILE_CREATE;
103 else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
104 return FILE_OVERWRITE_IF;
105 else if ((flags & O_CREAT) == O_CREAT)
106 return FILE_OPEN_IF;
Steve French55aa2e02006-05-30 18:09:31 +0000107 else if ((flags & O_TRUNC) == O_TRUNC)
108 return FILE_OVERWRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 else
110 return FILE_OPEN;
111}
112
Jeff Layton608712f2010-10-15 15:33:56 -0400113int cifs_posix_open(char *full_path, struct inode **pinode,
114 struct super_block *sb, int mode, unsigned int f_flags,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400115 __u32 *poplock, __u16 *pnetfid, unsigned int xid)
Jeff Layton608712f2010-10-15 15:33:56 -0400116{
117 int rc;
118 FILE_UNIX_BASIC_INFO *presp_data;
119 __u32 posix_flags = 0;
120 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
121 struct cifs_fattr fattr;
122 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000123 struct cifs_tcon *tcon;
Jeff Layton608712f2010-10-15 15:33:56 -0400124
Joe Perchesf96637b2013-05-04 22:12:25 -0500125 cifs_dbg(FYI, "posix open %s\n", full_path);
Jeff Layton608712f2010-10-15 15:33:56 -0400126
127 presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
128 if (presp_data == NULL)
129 return -ENOMEM;
130
131 tlink = cifs_sb_tlink(cifs_sb);
132 if (IS_ERR(tlink)) {
133 rc = PTR_ERR(tlink);
134 goto posix_open_ret;
135 }
136
137 tcon = tlink_tcon(tlink);
138 mode &= ~current_umask();
139
140 posix_flags = cifs_posix_convert_flags(f_flags);
141 rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data,
142 poplock, full_path, cifs_sb->local_nls,
143 cifs_sb->mnt_cifs_flags &
144 CIFS_MOUNT_MAP_SPECIAL_CHR);
145 cifs_put_tlink(tlink);
146
147 if (rc)
148 goto posix_open_ret;
149
150 if (presp_data->Type == cpu_to_le32(-1))
151 goto posix_open_ret; /* open ok, caller does qpathinfo */
152
153 if (!pinode)
154 goto posix_open_ret; /* caller does not need info */
155
156 cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
157
158 /* get new inode and set it up */
159 if (*pinode == NULL) {
160 cifs_fill_uniqueid(sb, &fattr);
161 *pinode = cifs_iget(sb, &fattr);
162 if (!*pinode) {
163 rc = -ENOMEM;
164 goto posix_open_ret;
165 }
166 } else {
167 cifs_fattr_to_inode(*pinode, &fattr);
168 }
169
170posix_open_ret:
171 kfree(presp_data);
172 return rc;
173}
174
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300175static int
176cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700177 struct cifs_tcon *tcon, unsigned int f_flags, __u32 *oplock,
178 struct cifs_fid *fid, unsigned int xid)
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300179{
180 int rc;
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700181 int desired_access;
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300182 int disposition;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500183 int create_options = CREATE_NOT_DIR;
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300184 FILE_ALL_INFO *buf;
Pavel Shilovskyb8c32db2012-09-19 06:22:44 -0700185 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300186
Pavel Shilovskyb8c32db2012-09-19 06:22:44 -0700187 if (!server->ops->open)
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700188 return -ENOSYS;
189
190 desired_access = cifs_convert_flags(f_flags);
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300191
192/*********************************************************************
193 * open flag mapping table:
194 *
195 * POSIX Flag CIFS Disposition
196 * ---------- ----------------
197 * O_CREAT FILE_OPEN_IF
198 * O_CREAT | O_EXCL FILE_CREATE
199 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
200 * O_TRUNC FILE_OVERWRITE
201 * none of the above FILE_OPEN
202 *
203 * Note that there is not a direct match between disposition
204 * FILE_SUPERSEDE (ie create whether or not file exists although
205 * O_CREAT | O_TRUNC is similar but truncates the existing
206 * file rather than creating a new file as FILE_SUPERSEDE does
207 * (which uses the attributes / metadata passed in on open call)
208 *?
209 *? O_SYNC is a reasonable match to CIFS writethrough flag
210 *? and the read write flags match reasonably. O_LARGEFILE
211 *? is irrelevant because largefile support is always used
212 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
213 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
214 *********************************************************************/
215
216 disposition = cifs_get_disposition(f_flags);
217
218 /* BB pass O_SYNC flag through on file attributes .. BB */
219
220 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
221 if (!buf)
222 return -ENOMEM;
223
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500224 if (backup_cred(cifs_sb))
225 create_options |= CREATE_OPEN_BACKUP_INTENT;
226
Pavel Shilovskyb8c32db2012-09-19 06:22:44 -0700227 rc = server->ops->open(xid, tcon, full_path, disposition,
228 desired_access, create_options, fid, oplock, buf,
229 cifs_sb);
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300230
231 if (rc)
232 goto out;
233
234 if (tcon->unix_ext)
235 rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
236 xid);
237 else
238 rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700239 xid, &fid->netfid);
Pavel Shilovskyeeb910a2010-11-25 15:12:39 +0300240
241out:
242 kfree(buf);
243 return rc;
244}
245
Pavel Shilovsky63b7d3a2012-12-24 14:41:19 +0400246static bool
247cifs_has_mand_locks(struct cifsInodeInfo *cinode)
248{
249 struct cifs_fid_locks *cur;
250 bool has_locks = false;
251
252 down_read(&cinode->lock_sem);
253 list_for_each_entry(cur, &cinode->llist, llist) {
254 if (!list_empty(&cur->locks)) {
255 has_locks = true;
256 break;
257 }
258 }
259 up_read(&cinode->lock_sem);
260 return has_locks;
261}
262
Jeff Layton15ecb432010-10-15 15:34:02 -0400263struct cifsFileInfo *
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700264cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
Jeff Layton15ecb432010-10-15 15:34:02 -0400265 struct tcon_link *tlink, __u32 oplock)
266{
267 struct dentry *dentry = file->f_path.dentry;
268 struct inode *inode = dentry->d_inode;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700269 struct cifsInodeInfo *cinode = CIFS_I(inode);
270 struct cifsFileInfo *cfile;
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700271 struct cifs_fid_locks *fdlocks;
Pavel Shilovsky233839b2012-09-19 06:22:45 -0700272 struct cifs_tcon *tcon = tlink_tcon(tlink);
Pavel Shilovsky63b7d3a2012-12-24 14:41:19 +0400273 struct TCP_Server_Info *server = tcon->ses->server;
Jeff Layton15ecb432010-10-15 15:34:02 -0400274
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700275 cfile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
276 if (cfile == NULL)
277 return cfile;
Jeff Layton15ecb432010-10-15 15:34:02 -0400278
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700279 fdlocks = kzalloc(sizeof(struct cifs_fid_locks), GFP_KERNEL);
280 if (!fdlocks) {
281 kfree(cfile);
282 return NULL;
283 }
284
285 INIT_LIST_HEAD(&fdlocks->locks);
286 fdlocks->cfile = cfile;
287 cfile->llist = fdlocks;
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700288 down_write(&cinode->lock_sem);
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700289 list_add(&fdlocks->llist, &cinode->llist);
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700290 up_write(&cinode->lock_sem);
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700291
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700292 cfile->count = 1;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700293 cfile->pid = current->tgid;
294 cfile->uid = current_fsuid();
295 cfile->dentry = dget(dentry);
296 cfile->f_flags = file->f_flags;
297 cfile->invalidHandle = false;
298 cfile->tlink = cifs_get_tlink(tlink);
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700299 INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700300 mutex_init(&cfile->fh_mutex);
Jeff Layton15ecb432010-10-15 15:34:02 -0400301
Mateusz Guzik24261fc2013-03-08 16:30:03 +0100302 cifs_sb_active(inode->i_sb);
303
Pavel Shilovsky63b7d3a2012-12-24 14:41:19 +0400304 /*
305 * If the server returned a read oplock and we have mandatory brlocks,
306 * set oplock level to None.
307 */
308 if (oplock == server->vals->oplock_read &&
309 cifs_has_mand_locks(cinode)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500310 cifs_dbg(FYI, "Reset oplock val from read to None due to mand locks\n");
Pavel Shilovsky63b7d3a2012-12-24 14:41:19 +0400311 oplock = 0;
312 }
313
Jeff Layton44772882010-10-15 15:34:03 -0400314 spin_lock(&cifs_file_list_lock);
Pavel Shilovsky63b7d3a2012-12-24 14:41:19 +0400315 if (fid->pending_open->oplock != CIFS_OPLOCK_NO_CHANGE && oplock)
Pavel Shilovsky233839b2012-09-19 06:22:45 -0700316 oplock = fid->pending_open->oplock;
317 list_del(&fid->pending_open->olist);
318
Pavel Shilovsky63b7d3a2012-12-24 14:41:19 +0400319 server->ops->set_fid(cfile, fid, oplock);
Pavel Shilovsky233839b2012-09-19 06:22:45 -0700320
321 list_add(&cfile->tlist, &tcon->openFileList);
Jeff Layton15ecb432010-10-15 15:34:02 -0400322 /* if readable file instance put first in list*/
323 if (file->f_mode & FMODE_READ)
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700324 list_add(&cfile->flist, &cinode->openFileList);
Jeff Layton15ecb432010-10-15 15:34:02 -0400325 else
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700326 list_add_tail(&cfile->flist, &cinode->openFileList);
Jeff Layton44772882010-10-15 15:34:03 -0400327 spin_unlock(&cifs_file_list_lock);
Jeff Layton15ecb432010-10-15 15:34:02 -0400328
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700329 file->private_data = cfile;
330 return cfile;
Jeff Layton15ecb432010-10-15 15:34:02 -0400331}
332
Jeff Layton764a1b12012-07-25 14:59:54 -0400333struct cifsFileInfo *
334cifsFileInfo_get(struct cifsFileInfo *cifs_file)
335{
336 spin_lock(&cifs_file_list_lock);
337 cifsFileInfo_get_locked(cifs_file);
338 spin_unlock(&cifs_file_list_lock);
339 return cifs_file;
340}
341
Steve Frenchcdff08e2010-10-21 22:46:14 +0000342/*
343 * Release a reference on the file private data. This may involve closing
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400344 * the filehandle out on the server. Must be called without holding
345 * cifs_file_list_lock.
Steve Frenchcdff08e2010-10-21 22:46:14 +0000346 */
Jeff Laytonb33879a2010-10-15 15:34:04 -0400347void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
348{
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300349 struct inode *inode = cifs_file->dentry->d_inode;
Steve French96daf2b2011-05-27 04:34:02 +0000350 struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
Pavel Shilovsky233839b2012-09-19 06:22:45 -0700351 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300352 struct cifsInodeInfo *cifsi = CIFS_I(inode);
Mateusz Guzik24261fc2013-03-08 16:30:03 +0100353 struct super_block *sb = inode->i_sb;
354 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000355 struct cifsLockInfo *li, *tmp;
Pavel Shilovsky233839b2012-09-19 06:22:45 -0700356 struct cifs_fid fid;
357 struct cifs_pending_open open;
Steve Frenchcdff08e2010-10-21 22:46:14 +0000358
359 spin_lock(&cifs_file_list_lock);
Jeff Layton5f6dbc92010-10-15 15:34:06 -0400360 if (--cifs_file->count > 0) {
Steve Frenchcdff08e2010-10-21 22:46:14 +0000361 spin_unlock(&cifs_file_list_lock);
362 return;
Jeff Laytonb33879a2010-10-15 15:34:04 -0400363 }
Steve Frenchcdff08e2010-10-21 22:46:14 +0000364
Pavel Shilovsky233839b2012-09-19 06:22:45 -0700365 if (server->ops->get_lease_key)
366 server->ops->get_lease_key(inode, &fid);
367
368 /* store open in pending opens to make sure we don't miss lease break */
369 cifs_add_pending_open_locked(&fid, cifs_file->tlink, &open);
370
Steve Frenchcdff08e2010-10-21 22:46:14 +0000371 /* remove it from the lists */
372 list_del(&cifs_file->flist);
373 list_del(&cifs_file->tlist);
374
375 if (list_empty(&cifsi->openFileList)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500376 cifs_dbg(FYI, "closing last open instance for inode %p\n",
377 cifs_file->dentry->d_inode);
Pavel Shilovsky25364132012-09-18 16:20:27 -0700378 /*
379 * In strict cache mode we need invalidate mapping on the last
380 * close because it may cause a error when we open this file
381 * again and get at least level II oplock.
382 */
Pavel Shilovsky4f8ba8a2010-11-21 22:36:12 +0300383 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
384 CIFS_I(inode)->invalid_mapping = true;
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300385 cifs_set_oplock_level(cifsi, 0);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000386 }
387 spin_unlock(&cifs_file_list_lock);
388
Jeff Laytonad635942011-07-26 12:20:17 -0400389 cancel_work_sync(&cifs_file->oplock_break);
390
Steve Frenchcdff08e2010-10-21 22:46:14 +0000391 if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
Pavel Shilovsky0ff78a22012-09-18 16:20:26 -0700392 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400393 unsigned int xid;
Pavel Shilovsky0ff78a22012-09-18 16:20:26 -0700394
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400395 xid = get_xid();
Pavel Shilovsky0ff78a22012-09-18 16:20:26 -0700396 if (server->ops->close)
Pavel Shilovsky760ad0c2012-09-25 11:00:07 +0400397 server->ops->close(xid, tcon, &cifs_file->fid);
398 _free_xid(xid);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000399 }
400
Pavel Shilovsky233839b2012-09-19 06:22:45 -0700401 cifs_del_pending_open(&open);
402
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700403 /*
404 * Delete any outstanding lock records. We'll lose them when the file
Steve Frenchcdff08e2010-10-21 22:46:14 +0000405 * is closed anyway.
406 */
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700407 down_write(&cifsi->lock_sem);
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700408 list_for_each_entry_safe(li, tmp, &cifs_file->llist->locks, llist) {
Steve Frenchcdff08e2010-10-21 22:46:14 +0000409 list_del(&li->llist);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400410 cifs_del_lock_waiters(li);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000411 kfree(li);
412 }
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700413 list_del(&cifs_file->llist->llist);
414 kfree(cifs_file->llist);
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700415 up_write(&cifsi->lock_sem);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000416
417 cifs_put_tlink(cifs_file->tlink);
418 dput(cifs_file->dentry);
Mateusz Guzik24261fc2013-03-08 16:30:03 +0100419 cifs_sb_deactive(sb);
Steve Frenchcdff08e2010-10-21 22:46:14 +0000420 kfree(cifs_file);
Jeff Laytonb33879a2010-10-15 15:34:04 -0400421}
422
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423int cifs_open(struct inode *inode, struct file *file)
Pavel Shilovsky233839b2012-09-19 06:22:45 -0700424
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425{
426 int rc = -EACCES;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400427 unsigned int xid;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400428 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 struct cifs_sb_info *cifs_sb;
Pavel Shilovskyb8c32db2012-09-19 06:22:44 -0700430 struct TCP_Server_Info *server;
Steve French96daf2b2011-05-27 04:34:02 +0000431 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400432 struct tcon_link *tlink;
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700433 struct cifsFileInfo *cfile = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 char *full_path = NULL;
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300435 bool posix_open_ok = false;
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700436 struct cifs_fid fid;
Pavel Shilovsky233839b2012-09-19 06:22:45 -0700437 struct cifs_pending_open open;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400439 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440
441 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400442 tlink = cifs_sb_tlink(cifs_sb);
443 if (IS_ERR(tlink)) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400444 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400445 return PTR_ERR(tlink);
446 }
447 tcon = tlink_tcon(tlink);
Pavel Shilovskyb8c32db2012-09-19 06:22:44 -0700448 server = tcon->ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -0800450 full_path = build_path_from_dentry(file->f_path.dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530452 rc = -ENOMEM;
Jeff Layton232341b2010-08-05 13:58:38 -0400453 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 }
455
Joe Perchesf96637b2013-05-04 22:12:25 -0500456 cifs_dbg(FYI, "inode = 0x%p file flags are 0x%x for %s\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +0000457 inode, file->f_flags, full_path);
Steve French276a74a2009-03-03 18:00:34 +0000458
Pavel Shilovsky233839b2012-09-19 06:22:45 -0700459 if (server->oplocks)
Steve French276a74a2009-03-03 18:00:34 +0000460 oplock = REQ_OPLOCK;
461 else
462 oplock = 0;
463
Steve French64cc2c62009-03-04 19:54:08 +0000464 if (!tcon->broken_posix_open && tcon->unix_ext &&
Pavel Shilovsky29e20f92012-07-13 13:58:14 +0400465 cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
466 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Steve French276a74a2009-03-03 18:00:34 +0000467 /* can not refresh inode info since size could be stale */
Jeff Layton2422f672010-06-16 13:40:16 -0400468 rc = cifs_posix_open(full_path, &inode, inode->i_sb,
Steve Frenchfa588e02010-04-22 19:21:55 +0000469 cifs_sb->mnt_file_mode /* ignored */,
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700470 file->f_flags, &oplock, &fid.netfid, xid);
Steve French276a74a2009-03-03 18:00:34 +0000471 if (rc == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500472 cifs_dbg(FYI, "posix open succeeded\n");
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300473 posix_open_ok = true;
Steve French64cc2c62009-03-04 19:54:08 +0000474 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
475 if (tcon->ses->serverNOS)
Joe Perchesf96637b2013-05-04 22:12:25 -0500476 cifs_dbg(VFS, "server %s of type %s returned unexpected error on SMB posix open, disabling posix open support. Check if server update available.\n",
477 tcon->ses->serverName,
478 tcon->ses->serverNOS);
Steve French64cc2c62009-03-04 19:54:08 +0000479 tcon->broken_posix_open = true;
Steve French276a74a2009-03-03 18:00:34 +0000480 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
481 (rc != -EOPNOTSUPP)) /* path not found or net err */
482 goto out;
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700483 /*
484 * Else fallthrough to retry open the old way on network i/o
485 * or DFS errors.
486 */
Steve French276a74a2009-03-03 18:00:34 +0000487 }
488
Pavel Shilovsky233839b2012-09-19 06:22:45 -0700489 if (server->ops->get_lease_key)
490 server->ops->get_lease_key(inode, &fid);
491
492 cifs_add_pending_open(&fid, tlink, &open);
493
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300494 if (!posix_open_ok) {
Pavel Shilovskyb8c32db2012-09-19 06:22:44 -0700495 if (server->ops->get_lease_key)
496 server->ops->get_lease_key(inode, &fid);
497
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300498 rc = cifs_nt_open(full_path, inode, cifs_sb, tcon,
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700499 file->f_flags, &oplock, &fid, xid);
Pavel Shilovsky233839b2012-09-19 06:22:45 -0700500 if (rc) {
501 cifs_del_pending_open(&open);
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300502 goto out;
Pavel Shilovsky233839b2012-09-19 06:22:45 -0700503 }
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300504 }
Jeff Layton47c78b72010-06-16 13:40:17 -0400505
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700506 cfile = cifs_new_fileinfo(&fid, file, tlink, oplock);
507 if (cfile == NULL) {
Pavel Shilovskyb8c32db2012-09-19 06:22:44 -0700508 if (server->ops->close)
509 server->ops->close(xid, tcon, &fid);
Pavel Shilovsky233839b2012-09-19 06:22:45 -0700510 cifs_del_pending_open(&open);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 rc = -ENOMEM;
512 goto out;
513 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530515 cifs_fscache_set_inode_cookie(inode, file);
516
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300517 if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) {
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700518 /*
519 * Time to set mode which we can not set earlier due to
520 * problems creating new read-only files.
521 */
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300522 struct cifs_unix_set_info_args args = {
523 .mode = inode->i_mode,
Eric W. Biederman49418b22013-02-06 00:57:56 -0800524 .uid = INVALID_UID, /* no change */
525 .gid = INVALID_GID, /* no change */
Pavel Shilovsky7e12edd2010-11-25 17:20:20 +0300526 .ctime = NO_CHANGE_64,
527 .atime = NO_CHANGE_64,
528 .mtime = NO_CHANGE_64,
529 .device = 0,
530 };
Pavel Shilovskyfb1214e2012-09-18 16:20:26 -0700531 CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid.netfid,
532 cfile->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 }
534
535out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400537 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400538 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 return rc;
540}
541
Pavel Shilovskyf152fd52012-11-22 17:10:57 +0400542static int cifs_push_posix_locks(struct cifsFileInfo *cfile);
543
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700544/*
545 * Try to reacquire byte range locks that were released when session
Pavel Shilovskyf152fd52012-11-22 17:10:57 +0400546 * to server was lost.
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700547 */
Pavel Shilovskyf152fd52012-11-22 17:10:57 +0400548static int
549cifs_relock_file(struct cifsFileInfo *cfile)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550{
Pavel Shilovskyf152fd52012-11-22 17:10:57 +0400551 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
552 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
553 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 int rc = 0;
555
Pavel Shilovskyf152fd52012-11-22 17:10:57 +0400556 /* we are going to update can_cache_brlcks here - need a write access */
557 down_write(&cinode->lock_sem);
558 if (cinode->can_cache_brlcks) {
559 /* can cache locks - no need to push them */
560 up_write(&cinode->lock_sem);
561 return rc;
562 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563
Pavel Shilovskyf152fd52012-11-22 17:10:57 +0400564 if (cap_unix(tcon->ses) &&
565 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
566 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
567 rc = cifs_push_posix_locks(cfile);
568 else
569 rc = tcon->ses->server->ops->push_mand_locks(cfile);
570
571 up_write(&cinode->lock_sem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 return rc;
573}
574
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700575static int
576cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577{
578 int rc = -EACCES;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400579 unsigned int xid;
Jeff Layton590a3fe2009-09-12 11:54:28 -0400580 __u32 oplock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 struct cifs_sb_info *cifs_sb;
Steve French96daf2b2011-05-27 04:34:02 +0000582 struct cifs_tcon *tcon;
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700583 struct TCP_Server_Info *server;
584 struct cifsInodeInfo *cinode;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000585 struct inode *inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 char *full_path = NULL;
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700587 int desired_access;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 int disposition = FILE_OPEN;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500589 int create_options = CREATE_NOT_DIR;
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700590 struct cifs_fid fid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400592 xid = get_xid();
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700593 mutex_lock(&cfile->fh_mutex);
594 if (!cfile->invalidHandle) {
595 mutex_unlock(&cfile->fh_mutex);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530596 rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400597 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530598 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 }
600
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700601 inode = cfile->dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700603 tcon = tlink_tcon(cfile->tlink);
604 server = tcon->ses->server;
Steve French3a9f4622007-04-04 17:10:24 +0000605
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700606 /*
607 * Can not grab rename sem here because various ops, including those
608 * that already have the rename sem can end up causing writepage to get
609 * called and if the server was down that means we end up here, and we
610 * can never tell if the caller already has the rename_sem.
611 */
612 full_path = build_path_from_dentry(cfile->dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 if (full_path == NULL) {
Steve French3a9f4622007-04-04 17:10:24 +0000614 rc = -ENOMEM;
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700615 mutex_unlock(&cfile->fh_mutex);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400616 free_xid(xid);
Steve French3a9f4622007-04-04 17:10:24 +0000617 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 }
619
Joe Perchesf96637b2013-05-04 22:12:25 -0500620 cifs_dbg(FYI, "inode = 0x%p file flags 0x%x for %s\n",
621 inode, cfile->f_flags, full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622
Pavel Shilovsky10b9b982012-03-20 12:55:09 +0300623 if (tcon->ses->server->oplocks)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 oplock = REQ_OPLOCK;
625 else
Steve French4b18f2a2008-04-29 00:06:05 +0000626 oplock = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
Pavel Shilovsky29e20f92012-07-13 13:58:14 +0400628 if (tcon->unix_ext && cap_unix(tcon->ses) &&
Steve French7fc8f4e2009-02-23 20:43:11 +0000629 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
Pavel Shilovsky29e20f92012-07-13 13:58:14 +0400630 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton608712f2010-10-15 15:33:56 -0400631 /*
632 * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
633 * original open. Must mask them off for a reopen.
634 */
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700635 unsigned int oflags = cfile->f_flags &
Jeff Layton15886172010-10-15 15:33:59 -0400636 ~(O_CREAT | O_EXCL | O_TRUNC);
Jeff Layton608712f2010-10-15 15:33:56 -0400637
Jeff Layton2422f672010-06-16 13:40:16 -0400638 rc = cifs_posix_open(full_path, NULL, inode->i_sb,
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700639 cifs_sb->mnt_file_mode /* ignored */,
640 oflags, &oplock, &fid.netfid, xid);
Steve French7fc8f4e2009-02-23 20:43:11 +0000641 if (rc == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500642 cifs_dbg(FYI, "posix reopen succeeded\n");
Steve French7fc8f4e2009-02-23 20:43:11 +0000643 goto reopen_success;
644 }
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700645 /*
646 * fallthrough to retry open the old way on errors, especially
647 * in the reconnect path it is important to retry hard
648 */
Steve French7fc8f4e2009-02-23 20:43:11 +0000649 }
650
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700651 desired_access = cifs_convert_flags(cfile->f_flags);
Steve French7fc8f4e2009-02-23 20:43:11 +0000652
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500653 if (backup_cred(cifs_sb))
654 create_options |= CREATE_OPEN_BACKUP_INTENT;
655
Pavel Shilovskyb8c32db2012-09-19 06:22:44 -0700656 if (server->ops->get_lease_key)
657 server->ops->get_lease_key(inode, &fid);
658
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700659 /*
660 * Can not refresh inode by passing in file_info buf to be returned by
661 * CIFSSMBOpen and then calling get_inode_info with returned buf since
662 * file might have write behind data that needs to be flushed and server
663 * version of file size can be stale. If we knew for sure that inode was
664 * not dirty locally we could do this.
665 */
666 rc = server->ops->open(xid, tcon, full_path, disposition,
667 desired_access, create_options, &fid, &oplock,
668 NULL, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 if (rc) {
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700670 mutex_unlock(&cfile->fh_mutex);
Joe Perchesf96637b2013-05-04 22:12:25 -0500671 cifs_dbg(FYI, "cifs_reopen returned 0x%x\n", rc);
672 cifs_dbg(FYI, "oplock: %d\n", oplock);
Jeff Layton15886172010-10-15 15:33:59 -0400673 goto reopen_error_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 }
Jeff Layton15886172010-10-15 15:33:59 -0400675
676reopen_success:
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700677 cfile->invalidHandle = false;
678 mutex_unlock(&cfile->fh_mutex);
679 cinode = CIFS_I(inode);
Jeff Layton15886172010-10-15 15:33:59 -0400680
681 if (can_flush) {
682 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -0400683 mapping_set_error(inode->i_mapping, rc);
Jeff Layton15886172010-10-15 15:33:59 -0400684
Jeff Layton15886172010-10-15 15:33:59 -0400685 if (tcon->unix_ext)
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700686 rc = cifs_get_inode_info_unix(&inode, full_path,
687 inode->i_sb, xid);
Jeff Layton15886172010-10-15 15:33:59 -0400688 else
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700689 rc = cifs_get_inode_info(&inode, full_path, NULL,
690 inode->i_sb, xid, NULL);
691 }
692 /*
693 * Else we are writing out data to server already and could deadlock if
694 * we tried to flush data, and since we do not know if we have data that
695 * would invalidate the current end of file on the server we can not go
696 * to the server to get the new inode info.
697 */
Pavel Shilovskye66673e2010-11-02 12:00:42 +0300698
Pavel Shilovsky2ae78ba2012-09-18 16:20:27 -0700699 server->ops->set_fid(cfile, &fid, oplock);
700 cifs_relock_file(cfile);
Jeff Layton15886172010-10-15 15:33:59 -0400701
702reopen_error_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400704 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 return rc;
706}
707
708int cifs_close(struct inode *inode, struct file *file)
709{
Jeff Layton77970692011-04-05 16:23:47 -0700710 if (file->private_data != NULL) {
711 cifsFileInfo_put(file->private_data);
712 file->private_data = NULL;
713 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714
Steve Frenchcdff08e2010-10-21 22:46:14 +0000715 /* return code from the ->release op is always ignored */
716 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717}
718
719int cifs_closedir(struct inode *inode, struct file *file)
720{
721 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400722 unsigned int xid;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700723 struct cifsFileInfo *cfile = file->private_data;
Pavel Shilovsky92fc65a2012-09-18 16:20:32 -0700724 struct cifs_tcon *tcon;
725 struct TCP_Server_Info *server;
726 char *buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727
Joe Perchesf96637b2013-05-04 22:12:25 -0500728 cifs_dbg(FYI, "Closedir inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
Pavel Shilovsky92fc65a2012-09-18 16:20:32 -0700730 if (cfile == NULL)
731 return rc;
732
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400733 xid = get_xid();
Pavel Shilovsky92fc65a2012-09-18 16:20:32 -0700734 tcon = tlink_tcon(cfile->tlink);
735 server = tcon->ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736
Joe Perchesf96637b2013-05-04 22:12:25 -0500737 cifs_dbg(FYI, "Freeing private data in close dir\n");
Pavel Shilovsky92fc65a2012-09-18 16:20:32 -0700738 spin_lock(&cifs_file_list_lock);
739 if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
740 cfile->invalidHandle = true;
741 spin_unlock(&cifs_file_list_lock);
742 if (server->ops->close_dir)
743 rc = server->ops->close_dir(xid, tcon, &cfile->fid);
744 else
745 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -0500746 cifs_dbg(FYI, "Closing uncompleted readdir with rc %d\n", rc);
Pavel Shilovsky92fc65a2012-09-18 16:20:32 -0700747 /* not much we can do if it fails anyway, ignore rc */
748 rc = 0;
749 } else
750 spin_unlock(&cifs_file_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
Pavel Shilovsky92fc65a2012-09-18 16:20:32 -0700752 buf = cfile->srch_inf.ntwrk_buf_start;
753 if (buf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500754 cifs_dbg(FYI, "closedir free smb buf in srch struct\n");
Pavel Shilovsky92fc65a2012-09-18 16:20:32 -0700755 cfile->srch_inf.ntwrk_buf_start = NULL;
756 if (cfile->srch_inf.smallBuf)
757 cifs_small_buf_release(buf);
758 else
759 cifs_buf_release(buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 }
Pavel Shilovsky92fc65a2012-09-18 16:20:32 -0700761
762 cifs_put_tlink(cfile->tlink);
763 kfree(file->private_data);
764 file->private_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 /* BB can we lock the filestruct while this is going on? */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400766 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 return rc;
768}
769
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400770static struct cifsLockInfo *
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300771cifs_lock_init(__u64 offset, __u64 length, __u8 type)
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000772{
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400773 struct cifsLockInfo *lock =
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000774 kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400775 if (!lock)
776 return lock;
777 lock->offset = offset;
778 lock->length = length;
779 lock->type = type;
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400780 lock->pid = current->tgid;
781 INIT_LIST_HEAD(&lock->blist);
782 init_waitqueue_head(&lock->block_q);
783 return lock;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400784}
785
Pavel Shilovskyf7ba7fe2012-09-19 06:22:43 -0700786void
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400787cifs_del_lock_waiters(struct cifsLockInfo *lock)
788{
789 struct cifsLockInfo *li, *tmp;
790 list_for_each_entry_safe(li, tmp, &lock->blist, blist) {
791 list_del_init(&li->blist);
792 wake_up(&li->block_q);
793 }
794}
795
Pavel Shilovsky081c0412012-11-27 18:38:53 +0400796#define CIFS_LOCK_OP 0
797#define CIFS_READ_OP 1
798#define CIFS_WRITE_OP 2
799
800/* @rw_check : 0 - no op, 1 - read, 2 - write */
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400801static bool
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700802cifs_find_fid_lock_conflict(struct cifs_fid_locks *fdlocks, __u64 offset,
803 __u64 length, __u8 type, struct cifsFileInfo *cfile,
Pavel Shilovsky081c0412012-11-27 18:38:53 +0400804 struct cifsLockInfo **conf_lock, int rw_check)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400805{
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300806 struct cifsLockInfo *li;
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700807 struct cifsFileInfo *cur_cfile = fdlocks->cfile;
Pavel Shilovsky106dc532012-02-28 14:23:34 +0300808 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400809
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700810 list_for_each_entry(li, &fdlocks->locks, llist) {
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400811 if (offset + length <= li->offset ||
812 offset >= li->offset + li->length)
813 continue;
Pavel Shilovsky081c0412012-11-27 18:38:53 +0400814 if (rw_check != CIFS_LOCK_OP && current->tgid == li->pid &&
815 server->ops->compare_fids(cfile, cur_cfile)) {
816 /* shared lock prevents write op through the same fid */
817 if (!(li->type & server->vals->shared_lock_type) ||
818 rw_check != CIFS_WRITE_OP)
819 continue;
820 }
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700821 if ((type & server->vals->shared_lock_type) &&
822 ((server->ops->compare_fids(cfile, cur_cfile) &&
823 current->tgid == li->pid) || type == li->type))
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400824 continue;
Pavel Shilovsky579f9052012-09-19 06:22:44 -0700825 if (conf_lock)
826 *conf_lock = li;
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700827 return true;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400828 }
829 return false;
830}
831
Pavel Shilovsky579f9052012-09-19 06:22:44 -0700832bool
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300833cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
Pavel Shilovsky579f9052012-09-19 06:22:44 -0700834 __u8 type, struct cifsLockInfo **conf_lock,
Pavel Shilovsky081c0412012-11-27 18:38:53 +0400835 int rw_check)
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400836{
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300837 bool rc = false;
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700838 struct cifs_fid_locks *cur;
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300839 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300840
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700841 list_for_each_entry(cur, &cinode->llist, llist) {
842 rc = cifs_find_fid_lock_conflict(cur, offset, length, type,
Pavel Shilovsky579f9052012-09-19 06:22:44 -0700843 cfile, conf_lock, rw_check);
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300844 if (rc)
845 break;
846 }
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300847
848 return rc;
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400849}
850
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300851/*
852 * Check if there is another lock that prevents us to set the lock (mandatory
853 * style). If such a lock exists, update the flock structure with its
854 * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks
855 * or leave it the same if we can't. Returns 0 if we don't need to request to
856 * the server or 1 otherwise.
857 */
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400858static int
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300859cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
860 __u8 type, struct file_lock *flock)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400861{
862 int rc = 0;
863 struct cifsLockInfo *conf_lock;
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300864 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovsky106dc532012-02-28 14:23:34 +0300865 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400866 bool exist;
867
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700868 down_read(&cinode->lock_sem);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400869
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300870 exist = cifs_find_lock_conflict(cfile, offset, length, type,
Pavel Shilovsky081c0412012-11-27 18:38:53 +0400871 &conf_lock, CIFS_LOCK_OP);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400872 if (exist) {
873 flock->fl_start = conf_lock->offset;
874 flock->fl_end = conf_lock->offset + conf_lock->length - 1;
875 flock->fl_pid = conf_lock->pid;
Pavel Shilovsky106dc532012-02-28 14:23:34 +0300876 if (conf_lock->type & server->vals->shared_lock_type)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400877 flock->fl_type = F_RDLCK;
878 else
879 flock->fl_type = F_WRLCK;
880 } else if (!cinode->can_cache_brlcks)
881 rc = 1;
882 else
883 flock->fl_type = F_UNLCK;
884
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700885 up_read(&cinode->lock_sem);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400886 return rc;
887}
888
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400889static void
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300890cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400891{
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300892 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700893 down_write(&cinode->lock_sem);
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700894 list_add_tail(&lock->llist, &cfile->llist->locks);
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700895 up_write(&cinode->lock_sem);
Jeremy Allison7ee1af72006-08-02 21:56:33 +0000896}
897
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300898/*
899 * Set the byte-range lock (mandatory style). Returns:
900 * 1) 0, if we set the lock and don't need to request to the server;
901 * 2) 1, if no locks prevent us but we need to request to the server;
902 * 3) -EACCESS, if there is a lock that prevents us and wait is false.
903 */
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400904static int
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300905cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock,
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400906 bool wait)
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400907{
Pavel Shilovsky161ebf92011-10-29 17:17:58 +0400908 struct cifsLockInfo *conf_lock;
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +0300909 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400910 bool exist;
911 int rc = 0;
912
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400913try_again:
914 exist = false;
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700915 down_write(&cinode->lock_sem);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400916
Pavel Shilovsky55157df2012-02-28 14:04:17 +0300917 exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length,
Pavel Shilovsky081c0412012-11-27 18:38:53 +0400918 lock->type, &conf_lock, CIFS_LOCK_OP);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400919 if (!exist && cinode->can_cache_brlcks) {
Pavel Shilovskyf45d3412012-09-19 06:22:43 -0700920 list_add_tail(&lock->llist, &cfile->llist->locks);
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700921 up_write(&cinode->lock_sem);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400922 return rc;
923 }
924
925 if (!exist)
926 rc = 1;
927 else if (!wait)
928 rc = -EACCES;
929 else {
930 list_add_tail(&lock->blist, &conf_lock->blist);
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700931 up_write(&cinode->lock_sem);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400932 rc = wait_event_interruptible(lock->block_q,
933 (lock->blist.prev == &lock->blist) &&
934 (lock->blist.next == &lock->blist));
935 if (!rc)
936 goto try_again;
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700937 down_write(&cinode->lock_sem);
Pavel Shilovskya88b4702011-10-29 17:17:59 +0400938 list_del_init(&lock->blist);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400939 }
940
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700941 up_write(&cinode->lock_sem);
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400942 return rc;
943}
944
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300945/*
946 * Check if there is another lock that prevents us to set the lock (posix
947 * style). If such a lock exists, update the flock structure with its
948 * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks
949 * or leave it the same if we can't. Returns 0 if we don't need to request to
950 * the server or 1 otherwise.
951 */
Pavel Shilovsky85160e02011-10-22 15:33:29 +0400952static int
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400953cifs_posix_lock_test(struct file *file, struct file_lock *flock)
954{
955 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -0500956 struct cifsInodeInfo *cinode = CIFS_I(file_inode(file));
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400957 unsigned char saved_type = flock->fl_type;
958
Pavel Shilovsky50792762011-10-29 17:17:57 +0400959 if ((flock->fl_flags & FL_POSIX) == 0)
960 return 1;
961
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700962 down_read(&cinode->lock_sem);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400963 posix_test_lock(file, flock);
964
965 if (flock->fl_type == F_UNLCK && !cinode->can_cache_brlcks) {
966 flock->fl_type = saved_type;
967 rc = 1;
968 }
969
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700970 up_read(&cinode->lock_sem);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400971 return rc;
972}
973
Pavel Shilovsky9a5101c2011-11-07 16:11:24 +0300974/*
975 * Set the byte-range lock (posix style). Returns:
976 * 1) 0, if we set the lock and don't need to request to the server;
977 * 2) 1, if we need to request to the server;
978 * 3) <0, if the error occurs while setting the lock.
979 */
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400980static int
981cifs_posix_lock_set(struct file *file, struct file_lock *flock)
982{
Al Viro496ad9a2013-01-23 17:07:38 -0500983 struct cifsInodeInfo *cinode = CIFS_I(file_inode(file));
Pavel Shilovsky50792762011-10-29 17:17:57 +0400984 int rc = 1;
985
986 if ((flock->fl_flags & FL_POSIX) == 0)
987 return rc;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400988
Pavel Shilovsky66189be2012-03-28 21:56:19 +0400989try_again:
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700990 down_write(&cinode->lock_sem);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400991 if (!cinode->can_cache_brlcks) {
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700992 up_write(&cinode->lock_sem);
Pavel Shilovsky50792762011-10-29 17:17:57 +0400993 return rc;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +0400994 }
Pavel Shilovsky66189be2012-03-28 21:56:19 +0400995
996 rc = posix_lock_file(file, flock, NULL);
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -0700997 up_write(&cinode->lock_sem);
Pavel Shilovsky66189be2012-03-28 21:56:19 +0400998 if (rc == FILE_LOCK_DEFERRED) {
999 rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next);
1000 if (!rc)
1001 goto try_again;
1002 locks_delete_block(flock);
1003 }
Steve French9ebb3892012-04-01 13:52:54 -05001004 return rc;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001005}
1006
Pavel Shilovskyd39a4f72012-09-19 06:22:43 -07001007int
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001008cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001009{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001010 unsigned int xid;
1011 int rc = 0, stored_rc;
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001012 struct cifsLockInfo *li, *tmp;
1013 struct cifs_tcon *tcon;
Pavel Shilovsky0013fb42012-05-31 13:03:26 +04001014 unsigned int num, max_num, max_buf;
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +04001015 LOCKING_ANDX_RANGE *buf, *cur;
1016 int types[] = {LOCKING_ANDX_LARGE_FILES,
1017 LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
1018 int i;
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001019
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001020 xid = get_xid();
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001021 tcon = tlink_tcon(cfile->tlink);
1022
Pavel Shilovsky0013fb42012-05-31 13:03:26 +04001023 /*
1024 * Accessing maxBuf is racy with cifs_reconnect - need to store value
1025 * and check it for zero before using.
1026 */
1027 max_buf = tcon->ses->server->maxBuf;
1028 if (!max_buf) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001029 free_xid(xid);
Pavel Shilovsky0013fb42012-05-31 13:03:26 +04001030 return -EINVAL;
1031 }
1032
1033 max_num = (max_buf - sizeof(struct smb_hdr)) /
1034 sizeof(LOCKING_ANDX_RANGE);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +04001035 buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
1036 if (!buf) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001037 free_xid(xid);
Pavel Shilovskye2f28862012-08-29 21:13:38 +04001038 return -ENOMEM;
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +04001039 }
1040
1041 for (i = 0; i < 2; i++) {
1042 cur = buf;
1043 num = 0;
Pavel Shilovskyf45d3412012-09-19 06:22:43 -07001044 list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +04001045 if (li->type != types[i])
1046 continue;
1047 cur->Pid = cpu_to_le16(li->pid);
1048 cur->LengthLow = cpu_to_le32((u32)li->length);
1049 cur->LengthHigh = cpu_to_le32((u32)(li->length>>32));
1050 cur->OffsetLow = cpu_to_le32((u32)li->offset);
1051 cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
1052 if (++num == max_num) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001053 stored_rc = cifs_lockv(xid, tcon,
1054 cfile->fid.netfid,
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001055 (__u8)li->type, 0, num,
1056 buf);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +04001057 if (stored_rc)
1058 rc = stored_rc;
1059 cur = buf;
1060 num = 0;
1061 } else
1062 cur++;
1063 }
1064
1065 if (num) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001066 stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid,
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001067 (__u8)types[i], 0, num, buf);
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +04001068 if (stored_rc)
1069 rc = stored_rc;
1070 }
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001071 }
1072
Pavel Shilovsky32b9aaf2011-10-22 15:33:32 +04001073 kfree(buf);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001074 free_xid(xid);
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001075 return rc;
1076}
1077
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001078/* copied from fs/locks.c with a name change */
1079#define cifs_for_each_lock(inode, lockp) \
1080 for (lockp = &inode->i_flock; *lockp != NULL; \
1081 lockp = &(*lockp)->fl_next)
1082
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001083struct lock_to_push {
1084 struct list_head llist;
1085 __u64 offset;
1086 __u64 length;
1087 __u32 pid;
1088 __u16 netfid;
1089 __u8 type;
1090};
1091
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001092static int
Pavel Shilovskyb8db9282012-11-22 17:07:16 +04001093cifs_push_posix_locks(struct cifsFileInfo *cfile)
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001094{
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001095 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1096 struct file_lock *flock, **before;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001097 unsigned int count = 0, i = 0;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001098 int rc = 0, xid, type;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001099 struct list_head locks_to_send, *el;
1100 struct lock_to_push *lck, *tmp;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001101 __u64 length;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001102
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001103 xid = get_xid();
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001104
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001105 lock_flocks();
1106 cifs_for_each_lock(cfile->dentry->d_inode, before) {
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001107 if ((*before)->fl_flags & FL_POSIX)
1108 count++;
1109 }
1110 unlock_flocks();
1111
1112 INIT_LIST_HEAD(&locks_to_send);
1113
1114 /*
Pavel Shilovskyce858522012-03-17 09:46:55 +03001115 * Allocating count locks is enough because no FL_POSIX locks can be
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -07001116 * added to the list while we are holding cinode->lock_sem that
Pavel Shilovskyce858522012-03-17 09:46:55 +03001117 * protects locking operations of this inode.
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001118 */
1119 for (; i < count; i++) {
1120 lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL);
1121 if (!lck) {
1122 rc = -ENOMEM;
1123 goto err_out;
1124 }
1125 list_add_tail(&lck->llist, &locks_to_send);
1126 }
1127
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001128 el = locks_to_send.next;
1129 lock_flocks();
1130 cifs_for_each_lock(cfile->dentry->d_inode, before) {
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001131 flock = *before;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001132 if ((flock->fl_flags & FL_POSIX) == 0)
1133 continue;
Pavel Shilovskyce858522012-03-17 09:46:55 +03001134 if (el == &locks_to_send) {
1135 /*
1136 * The list ended. We don't have enough allocated
1137 * structures - something is really wrong.
1138 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001139 cifs_dbg(VFS, "Can't push all brlocks!\n");
Pavel Shilovskyce858522012-03-17 09:46:55 +03001140 break;
1141 }
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001142 length = 1 + flock->fl_end - flock->fl_start;
1143 if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK)
1144 type = CIFS_RDLCK;
1145 else
1146 type = CIFS_WRLCK;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001147 lck = list_entry(el, struct lock_to_push, llist);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001148 lck->pid = flock->fl_pid;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001149 lck->netfid = cfile->fid.netfid;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001150 lck->length = length;
1151 lck->type = type;
1152 lck->offset = flock->fl_start;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001153 el = el->next;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001154 }
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001155 unlock_flocks();
1156
1157 list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001158 int stored_rc;
1159
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001160 stored_rc = CIFSSMBPosixLock(xid, tcon, lck->netfid, lck->pid,
Jeff Laytonc5fd3632012-07-23 13:28:37 -04001161 lck->offset, lck->length, NULL,
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001162 lck->type, 0);
1163 if (stored_rc)
1164 rc = stored_rc;
1165 list_del(&lck->llist);
1166 kfree(lck);
1167 }
1168
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001169out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001170 free_xid(xid);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001171 return rc;
Pavel Shilovskyd5751462012-03-05 09:39:20 +03001172err_out:
1173 list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
1174 list_del(&lck->llist);
1175 kfree(lck);
1176 }
1177 goto out;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001178}
1179
1180static int
Pavel Shilovskyb8db9282012-11-22 17:07:16 +04001181cifs_push_locks(struct cifsFileInfo *cfile)
Pavel Shilovsky9ec3c882012-11-22 17:00:10 +04001182{
Pavel Shilovskyb8db9282012-11-22 17:07:16 +04001183 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
Pavel Shilovsky9ec3c882012-11-22 17:00:10 +04001184 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
Pavel Shilovskyb8db9282012-11-22 17:07:16 +04001185 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky9ec3c882012-11-22 17:00:10 +04001186 int rc = 0;
1187
1188 /* we are going to update can_cache_brlcks here - need a write access */
1189 down_write(&cinode->lock_sem);
1190 if (!cinode->can_cache_brlcks) {
1191 up_write(&cinode->lock_sem);
1192 return rc;
1193 }
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001194
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001195 if (cap_unix(tcon->ses) &&
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001196 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
1197 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
Pavel Shilovskyb8db9282012-11-22 17:07:16 +04001198 rc = cifs_push_posix_locks(cfile);
1199 else
1200 rc = tcon->ses->server->ops->push_mand_locks(cfile);
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001201
Pavel Shilovskyb8db9282012-11-22 17:07:16 +04001202 cinode->can_cache_brlcks = false;
1203 up_write(&cinode->lock_sem);
1204 return rc;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001205}
1206
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001207static void
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001208cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock,
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001209 bool *wait_flag, struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210{
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001211 if (flock->fl_flags & FL_POSIX)
Joe Perchesf96637b2013-05-04 22:12:25 -05001212 cifs_dbg(FYI, "Posix\n");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001213 if (flock->fl_flags & FL_FLOCK)
Joe Perchesf96637b2013-05-04 22:12:25 -05001214 cifs_dbg(FYI, "Flock\n");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001215 if (flock->fl_flags & FL_SLEEP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001216 cifs_dbg(FYI, "Blocking lock\n");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001217 *wait_flag = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 }
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001219 if (flock->fl_flags & FL_ACCESS)
Joe Perchesf96637b2013-05-04 22:12:25 -05001220 cifs_dbg(FYI, "Process suspended by mandatory locking - not implemented yet\n");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001221 if (flock->fl_flags & FL_LEASE)
Joe Perchesf96637b2013-05-04 22:12:25 -05001222 cifs_dbg(FYI, "Lease on file - not implemented yet\n");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001223 if (flock->fl_flags &
Jeff Layton3d6d8542012-09-19 06:22:46 -07001224 (~(FL_POSIX | FL_FLOCK | FL_SLEEP |
1225 FL_ACCESS | FL_LEASE | FL_CLOSE)))
Joe Perchesf96637b2013-05-04 22:12:25 -05001226 cifs_dbg(FYI, "Unknown lock flags 0x%x\n", flock->fl_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001228 *type = server->vals->large_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001229 if (flock->fl_type == F_WRLCK) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001230 cifs_dbg(FYI, "F_WRLCK\n");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001231 *type |= server->vals->exclusive_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001232 *lock = 1;
1233 } else if (flock->fl_type == F_UNLCK) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001234 cifs_dbg(FYI, "F_UNLCK\n");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001235 *type |= server->vals->unlock_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001236 *unlock = 1;
1237 /* Check if unlock includes more than one lock range */
1238 } else if (flock->fl_type == F_RDLCK) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001239 cifs_dbg(FYI, "F_RDLCK\n");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001240 *type |= server->vals->shared_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001241 *lock = 1;
1242 } else if (flock->fl_type == F_EXLCK) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001243 cifs_dbg(FYI, "F_EXLCK\n");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001244 *type |= server->vals->exclusive_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001245 *lock = 1;
1246 } else if (flock->fl_type == F_SHLCK) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001247 cifs_dbg(FYI, "F_SHLCK\n");
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001248 *type |= server->vals->shared_lock_type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001249 *lock = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05001251 cifs_dbg(FYI, "Unknown type of lock\n");
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001252}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001254static int
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001255cifs_getlk(struct file *file, struct file_lock *flock, __u32 type,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001256 bool wait_flag, bool posix_lck, unsigned int xid)
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001257{
1258 int rc = 0;
1259 __u64 length = 1 + flock->fl_end - flock->fl_start;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001260 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
1261 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001262 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001263 __u16 netfid = cfile->fid.netfid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001265 if (posix_lck) {
1266 int posix_lock_type;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001267
1268 rc = cifs_posix_lock_test(file, flock);
1269 if (!rc)
1270 return rc;
1271
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001272 if (type & server->vals->shared_lock_type)
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001273 posix_lock_type = CIFS_RDLCK;
1274 else
1275 posix_lock_type = CIFS_WRLCK;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001276 rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid,
Jeff Laytonc5fd3632012-07-23 13:28:37 -04001277 flock->fl_start, length, flock,
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001278 posix_lock_type, wait_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 return rc;
1280 }
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001281
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001282 rc = cifs_lock_test(cfile, flock->fl_start, length, type, flock);
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001283 if (!rc)
1284 return rc;
1285
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001286 /* BB we could chain these into one lock request BB */
Pavel Shilovskyd39a4f72012-09-19 06:22:43 -07001287 rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length, type,
1288 1, 0, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001289 if (rc == 0) {
Pavel Shilovskyd39a4f72012-09-19 06:22:43 -07001290 rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
1291 type, 0, 1, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001292 flock->fl_type = F_UNLCK;
1293 if (rc != 0)
Joe Perchesf96637b2013-05-04 22:12:25 -05001294 cifs_dbg(VFS, "Error unlocking previously locked range %d during test of lock\n",
1295 rc);
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001296 return 0;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001297 }
1298
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001299 if (type & server->vals->shared_lock_type) {
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001300 flock->fl_type = F_WRLCK;
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001301 return 0;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001302 }
1303
Pavel Shilovskyd39a4f72012-09-19 06:22:43 -07001304 type &= ~server->vals->exclusive_lock_type;
1305
1306 rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
1307 type | server->vals->shared_lock_type,
1308 1, 0, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001309 if (rc == 0) {
Pavel Shilovskyd39a4f72012-09-19 06:22:43 -07001310 rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
1311 type | server->vals->shared_lock_type, 0, 1, false);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001312 flock->fl_type = F_RDLCK;
1313 if (rc != 0)
Joe Perchesf96637b2013-05-04 22:12:25 -05001314 cifs_dbg(VFS, "Error unlocking previously locked range %d during test of lock\n",
1315 rc);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001316 } else
1317 flock->fl_type = F_WRLCK;
1318
Pavel Shilovskya88b4702011-10-29 17:17:59 +04001319 return 0;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001320}
1321
Pavel Shilovskyf7ba7fe2012-09-19 06:22:43 -07001322void
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001323cifs_move_llist(struct list_head *source, struct list_head *dest)
1324{
1325 struct list_head *li, *tmp;
1326 list_for_each_safe(li, tmp, source)
1327 list_move(li, dest);
1328}
1329
Pavel Shilovskyf7ba7fe2012-09-19 06:22:43 -07001330void
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001331cifs_free_llist(struct list_head *llist)
1332{
1333 struct cifsLockInfo *li, *tmp;
1334 list_for_each_entry_safe(li, tmp, llist, llist) {
1335 cifs_del_lock_waiters(li);
1336 list_del(&li->llist);
1337 kfree(li);
1338 }
1339}
1340
Pavel Shilovskyd39a4f72012-09-19 06:22:43 -07001341int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001342cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
1343 unsigned int xid)
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001344{
1345 int rc = 0, stored_rc;
1346 int types[] = {LOCKING_ANDX_LARGE_FILES,
1347 LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
1348 unsigned int i;
Pavel Shilovsky0013fb42012-05-31 13:03:26 +04001349 unsigned int max_num, num, max_buf;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001350 LOCKING_ANDX_RANGE *buf, *cur;
1351 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1352 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
1353 struct cifsLockInfo *li, *tmp;
1354 __u64 length = 1 + flock->fl_end - flock->fl_start;
1355 struct list_head tmp_llist;
1356
1357 INIT_LIST_HEAD(&tmp_llist);
1358
Pavel Shilovsky0013fb42012-05-31 13:03:26 +04001359 /*
1360 * Accessing maxBuf is racy with cifs_reconnect - need to store value
1361 * and check it for zero before using.
1362 */
1363 max_buf = tcon->ses->server->maxBuf;
1364 if (!max_buf)
1365 return -EINVAL;
1366
1367 max_num = (max_buf - sizeof(struct smb_hdr)) /
1368 sizeof(LOCKING_ANDX_RANGE);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001369 buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
1370 if (!buf)
1371 return -ENOMEM;
1372
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -07001373 down_write(&cinode->lock_sem);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001374 for (i = 0; i < 2; i++) {
1375 cur = buf;
1376 num = 0;
Pavel Shilovskyf45d3412012-09-19 06:22:43 -07001377 list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001378 if (flock->fl_start > li->offset ||
1379 (flock->fl_start + length) <
1380 (li->offset + li->length))
1381 continue;
1382 if (current->tgid != li->pid)
1383 continue;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001384 if (types[i] != li->type)
1385 continue;
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001386 if (cinode->can_cache_brlcks) {
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001387 /*
1388 * We can cache brlock requests - simply remove
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001389 * a lock from the file's list.
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001390 */
1391 list_del(&li->llist);
1392 cifs_del_lock_waiters(li);
1393 kfree(li);
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001394 continue;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001395 }
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001396 cur->Pid = cpu_to_le16(li->pid);
1397 cur->LengthLow = cpu_to_le32((u32)li->length);
1398 cur->LengthHigh = cpu_to_le32((u32)(li->length>>32));
1399 cur->OffsetLow = cpu_to_le32((u32)li->offset);
1400 cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
1401 /*
1402 * We need to save a lock here to let us add it again to
1403 * the file's list if the unlock range request fails on
1404 * the server.
1405 */
1406 list_move(&li->llist, &tmp_llist);
1407 if (++num == max_num) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001408 stored_rc = cifs_lockv(xid, tcon,
1409 cfile->fid.netfid,
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001410 li->type, num, 0, buf);
1411 if (stored_rc) {
1412 /*
1413 * We failed on the unlock range
1414 * request - add all locks from the tmp
1415 * list to the head of the file's list.
1416 */
1417 cifs_move_llist(&tmp_llist,
Pavel Shilovskyf45d3412012-09-19 06:22:43 -07001418 &cfile->llist->locks);
Pavel Shilovskyea319d52012-05-31 13:59:36 +04001419 rc = stored_rc;
1420 } else
1421 /*
1422 * The unlock range request succeed -
1423 * free the tmp list.
1424 */
1425 cifs_free_llist(&tmp_llist);
1426 cur = buf;
1427 num = 0;
1428 } else
1429 cur++;
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001430 }
1431 if (num) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001432 stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid,
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001433 types[i], num, 0, buf);
1434 if (stored_rc) {
Pavel Shilovskyf45d3412012-09-19 06:22:43 -07001435 cifs_move_llist(&tmp_llist,
1436 &cfile->llist->locks);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001437 rc = stored_rc;
1438 } else
1439 cifs_free_llist(&tmp_llist);
1440 }
1441 }
1442
Pavel Shilovsky1b4b55a2012-09-19 06:22:44 -07001443 up_write(&cinode->lock_sem);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001444 kfree(buf);
1445 return rc;
1446}
1447
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001448static int
Pavel Shilovskyf45d3412012-09-19 06:22:43 -07001449cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001450 bool wait_flag, bool posix_lck, int lock, int unlock,
1451 unsigned int xid)
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001452{
1453 int rc = 0;
1454 __u64 length = 1 + flock->fl_end - flock->fl_start;
1455 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
1456 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001457 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovsky63b7d3a2012-12-24 14:41:19 +04001458 struct inode *inode = cfile->dentry->d_inode;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001459
1460 if (posix_lck) {
Steve French08547b02006-02-28 22:39:25 +00001461 int posix_lock_type;
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001462
1463 rc = cifs_posix_lock_set(file, flock);
1464 if (!rc || rc < 0)
1465 return rc;
1466
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001467 if (type & server->vals->shared_lock_type)
Steve French08547b02006-02-28 22:39:25 +00001468 posix_lock_type = CIFS_RDLCK;
1469 else
1470 posix_lock_type = CIFS_WRLCK;
Steve French50c2f752007-07-13 00:33:32 +00001471
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001472 if (unlock == 1)
Steve Frenchbeb84dc2006-03-03 23:36:34 +00001473 posix_lock_type = CIFS_UNLCK;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001474
Pavel Shilovskyf45d3412012-09-19 06:22:43 -07001475 rc = CIFSSMBPosixLock(xid, tcon, cfile->fid.netfid,
1476 current->tgid, flock->fl_start, length,
1477 NULL, posix_lock_type, wait_flag);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001478 goto out;
Jeremy Allison7ee1af72006-08-02 21:56:33 +00001479 }
1480
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001481 if (lock) {
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001482 struct cifsLockInfo *lock;
1483
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001484 lock = cifs_lock_init(flock->fl_start, length, type);
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001485 if (!lock)
1486 return -ENOMEM;
1487
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001488 rc = cifs_lock_add_if(cfile, lock, wait_flag);
Pavel Shilovsky21cb2d92012-11-22 18:56:39 +04001489 if (rc < 0) {
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001490 kfree(lock);
Pavel Shilovsky21cb2d92012-11-22 18:56:39 +04001491 return rc;
1492 }
1493 if (!rc)
Pavel Shilovsky85160e02011-10-22 15:33:29 +04001494 goto out;
1495
Pavel Shilovsky63b7d3a2012-12-24 14:41:19 +04001496 /*
1497 * Windows 7 server can delay breaking lease from read to None
1498 * if we set a byte-range lock on a file - break it explicitly
1499 * before sending the lock to the server to be sure the next
1500 * read won't conflict with non-overlapted locks due to
1501 * pagereading.
1502 */
1503 if (!CIFS_I(inode)->clientCanCacheAll &&
1504 CIFS_I(inode)->clientCanCacheRead) {
1505 cifs_invalidate_mapping(inode);
Joe Perchesf96637b2013-05-04 22:12:25 -05001506 cifs_dbg(FYI, "Set no oplock for inode=%p due to mand locks\n",
1507 inode);
Pavel Shilovsky63b7d3a2012-12-24 14:41:19 +04001508 CIFS_I(inode)->clientCanCacheRead = false;
1509 }
1510
Pavel Shilovskyd39a4f72012-09-19 06:22:43 -07001511 rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
1512 type, 1, 0, wait_flag);
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001513 if (rc) {
1514 kfree(lock);
Pavel Shilovsky21cb2d92012-11-22 18:56:39 +04001515 return rc;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001516 }
Pavel Shilovsky161ebf92011-10-29 17:17:58 +04001517
Pavel Shilovskyfbd35ac2012-02-24 15:41:06 +03001518 cifs_lock_add(cfile, lock);
Pavel Shilovsky9ee305b2011-10-22 15:33:31 +04001519 } else if (unlock)
Pavel Shilovskyd39a4f72012-09-19 06:22:43 -07001520 rc = server->ops->mand_unlock_range(cfile, flock, xid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001521
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001522out:
1523 if (flock->fl_flags & FL_POSIX)
Steve French9ebb3892012-04-01 13:52:54 -05001524 posix_lock_file_wait(file, flock);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001525 return rc;
1526}
1527
1528int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
1529{
1530 int rc, xid;
1531 int lock = 0, unlock = 0;
1532 bool wait_flag = false;
1533 bool posix_lck = false;
1534 struct cifs_sb_info *cifs_sb;
1535 struct cifs_tcon *tcon;
1536 struct cifsInodeInfo *cinode;
1537 struct cifsFileInfo *cfile;
1538 __u16 netfid;
Pavel Shilovsky04a6aa82012-02-28 14:16:55 +03001539 __u32 type;
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001540
1541 rc = -EACCES;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001542 xid = get_xid();
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001543
Joe Perchesf96637b2013-05-04 22:12:25 -05001544 cifs_dbg(FYI, "Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld\n",
1545 cmd, flock->fl_flags, flock->fl_type,
1546 flock->fl_start, flock->fl_end);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001547
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001548 cfile = (struct cifsFileInfo *)file->private_data;
1549 tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky106dc532012-02-28 14:23:34 +03001550
1551 cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag,
1552 tcon->ses->server);
1553
1554 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07001555 netfid = cfile->fid.netfid;
Al Viro496ad9a2013-01-23 17:07:38 -05001556 cinode = CIFS_I(file_inode(file));
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001557
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001558 if (cap_unix(tcon->ses) &&
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001559 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
1560 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
1561 posix_lck = true;
1562 /*
1563 * BB add code here to normalize offset and length to account for
1564 * negative length which we can not accept over the wire.
1565 */
1566 if (IS_GETLK(cmd)) {
Pavel Shilovsky4f6bcec2011-10-22 15:33:30 +04001567 rc = cifs_getlk(file, flock, type, wait_flag, posix_lck, xid);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001568 free_xid(xid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001569 return rc;
1570 }
1571
1572 if (!lock && !unlock) {
1573 /*
1574 * if no lock or unlock then nothing to do since we do not
1575 * know what it is
1576 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001577 free_xid(xid);
Pavel Shilovsky03776f42010-08-17 11:26:00 +04001578 return -EOPNOTSUPP;
1579 }
1580
1581 rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock,
1582 xid);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001583 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 return rc;
1585}
1586
Jeff Layton597b0272012-03-23 14:40:56 -04001587/*
1588 * update the file size (if needed) after a write. Should be called with
1589 * the inode->i_lock held
1590 */
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05001591void
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001592cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
1593 unsigned int bytes_written)
1594{
1595 loff_t end_of_write = offset + bytes_written;
1596
1597 if (end_of_write > cifsi->server_eof)
1598 cifsi->server_eof = end_of_write;
1599}
1600
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001601static ssize_t
1602cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
1603 size_t write_size, loff_t *offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604{
1605 int rc = 0;
1606 unsigned int bytes_written = 0;
1607 unsigned int total_written;
1608 struct cifs_sb_info *cifs_sb;
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001609 struct cifs_tcon *tcon;
1610 struct TCP_Server_Info *server;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001611 unsigned int xid;
Jeff Layton7da4b492010-10-15 15:34:00 -04001612 struct dentry *dentry = open_file->dentry;
1613 struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001614 struct cifs_io_parms io_parms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615
Jeff Layton7da4b492010-10-15 15:34:00 -04001616 cifs_sb = CIFS_SB(dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617
Joe Perchesf96637b2013-05-04 22:12:25 -05001618 cifs_dbg(FYI, "write %zd bytes to offset %lld of %s\n",
1619 write_size, *offset, dentry->d_name.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001621 tcon = tlink_tcon(open_file->tlink);
1622 server = tcon->ses->server;
1623
1624 if (!server->ops->sync_write)
1625 return -ENOSYS;
Steve French50c2f752007-07-13 00:33:32 +00001626
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001627 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 for (total_written = 0; write_size > total_written;
1630 total_written += bytes_written) {
1631 rc = -EAGAIN;
1632 while (rc == -EAGAIN) {
Jeff Laytonca83ce32011-04-12 09:13:44 -04001633 struct kvec iov[2];
1634 unsigned int len;
1635
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636 if (open_file->invalidHandle) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 /* we could deadlock if we called
1638 filemap_fdatawait from here so tell
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001639 reopen_file not to flush data to
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 server now */
Jeff Layton15886172010-10-15 15:33:59 -04001641 rc = cifs_reopen_file(open_file, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 if (rc != 0)
1643 break;
1644 }
Steve French3e844692005-10-03 13:37:24 -07001645
Jeff Laytonca83ce32011-04-12 09:13:44 -04001646 len = min((size_t)cifs_sb->wsize,
1647 write_size - total_written);
1648 /* iov[0] is reserved for smb header */
1649 iov[1].iov_base = (char *)write_data + total_written;
1650 iov[1].iov_len = len;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001651 io_parms.pid = pid;
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001652 io_parms.tcon = tcon;
1653 io_parms.offset = *offset;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001654 io_parms.length = len;
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001655 rc = server->ops->sync_write(xid, open_file, &io_parms,
1656 &bytes_written, iov, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 }
1658 if (rc || (bytes_written == 0)) {
1659 if (total_written)
1660 break;
1661 else {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001662 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 return rc;
1664 }
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001665 } else {
Jeff Layton597b0272012-03-23 14:40:56 -04001666 spin_lock(&dentry->d_inode->i_lock);
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001667 cifs_update_eof(cifsi, *offset, bytes_written);
Jeff Layton597b0272012-03-23 14:40:56 -04001668 spin_unlock(&dentry->d_inode->i_lock);
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001669 *offset += bytes_written;
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001670 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 }
1672
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001673 cifs_stats_bytes_written(tcon, total_written);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674
Jeff Layton7da4b492010-10-15 15:34:00 -04001675 if (total_written > 0) {
1676 spin_lock(&dentry->d_inode->i_lock);
Pavel Shilovskyba9ad7252012-09-18 16:20:30 -07001677 if (*offset > dentry->d_inode->i_size)
1678 i_size_write(dentry->d_inode, *offset);
Jeff Layton7da4b492010-10-15 15:34:00 -04001679 spin_unlock(&dentry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 }
Jeff Layton7da4b492010-10-15 15:34:00 -04001681 mark_inode_dirty_sync(dentry->d_inode);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001682 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 return total_written;
1684}
1685
Jeff Layton6508d902010-09-29 19:51:11 -04001686struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1687 bool fsuid_only)
Steve French630f3f0c2007-10-25 21:17:17 +00001688{
1689 struct cifsFileInfo *open_file = NULL;
Jeff Layton6508d902010-09-29 19:51:11 -04001690 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1691
1692 /* only filter by fsuid on multiuser mounts */
1693 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1694 fsuid_only = false;
Steve French630f3f0c2007-10-25 21:17:17 +00001695
Jeff Layton44772882010-10-15 15:34:03 -04001696 spin_lock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001697 /* we could simply get the first_list_entry since write-only entries
1698 are always at the end of the list but since the first entry might
1699 have a close pending, we go through the whole list */
1700 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Eric W. Biedermanfef59fd2013-02-06 02:23:02 -08001701 if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
Jeff Layton6508d902010-09-29 19:51:11 -04001702 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001703 if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
Steve French630f3f0c2007-10-25 21:17:17 +00001704 if (!open_file->invalidHandle) {
1705 /* found a good file */
1706 /* lock it so it will not be closed on us */
Jeff Layton764a1b12012-07-25 14:59:54 -04001707 cifsFileInfo_get_locked(open_file);
Jeff Layton44772882010-10-15 15:34:03 -04001708 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001709 return open_file;
1710 } /* else might as well continue, and look for
1711 another, or simply have the caller reopen it
1712 again rather than trying to fix this handle */
1713 } else /* write only file */
1714 break; /* write only files are last so must be done */
1715 }
Jeff Layton44772882010-10-15 15:34:03 -04001716 spin_unlock(&cifs_file_list_lock);
Steve French630f3f0c2007-10-25 21:17:17 +00001717 return NULL;
1718}
Steve French630f3f0c2007-10-25 21:17:17 +00001719
Jeff Layton6508d902010-09-29 19:51:11 -04001720struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1721 bool fsuid_only)
Steve French6148a742005-10-05 12:23:19 -07001722{
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001723 struct cifsFileInfo *open_file, *inv_file = NULL;
Jeff Laytond3892292010-11-02 16:22:50 -04001724 struct cifs_sb_info *cifs_sb;
Jeff Layton2846d382008-09-22 21:33:33 -04001725 bool any_available = false;
Steve Frenchdd99cd82005-10-05 19:32:49 -07001726 int rc;
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001727 unsigned int refind = 0;
Steve French6148a742005-10-05 12:23:19 -07001728
Steve French60808232006-04-22 15:53:05 +00001729 /* Having a null inode here (because mapping->host was set to zero by
1730 the VFS or MM) should not happen but we had reports of on oops (due to
1731 it being zero) during stress testcases so we need to check for it */
1732
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001733 if (cifs_inode == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001734 cifs_dbg(VFS, "Null inode passed to cifs_writeable_file\n");
Steve French60808232006-04-22 15:53:05 +00001735 dump_stack();
1736 return NULL;
1737 }
1738
Jeff Laytond3892292010-11-02 16:22:50 -04001739 cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
1740
Jeff Layton6508d902010-09-29 19:51:11 -04001741 /* only filter by fsuid on multiuser mounts */
1742 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1743 fsuid_only = false;
1744
Jeff Layton44772882010-10-15 15:34:03 -04001745 spin_lock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001746refind_writable:
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001747 if (refind > MAX_REOPEN_ATT) {
1748 spin_unlock(&cifs_file_list_lock);
1749 return NULL;
1750 }
Steve French6148a742005-10-05 12:23:19 -07001751 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton6508d902010-09-29 19:51:11 -04001752 if (!any_available && open_file->pid != current->tgid)
1753 continue;
Eric W. Biedermanfef59fd2013-02-06 02:23:02 -08001754 if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
Jeff Layton6508d902010-09-29 19:51:11 -04001755 continue;
Jeff Layton2e396b82010-10-15 15:34:01 -04001756 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Steve French9b22b0b2007-10-02 01:11:08 +00001757 if (!open_file->invalidHandle) {
1758 /* found a good writable file */
Jeff Layton764a1b12012-07-25 14:59:54 -04001759 cifsFileInfo_get_locked(open_file);
Jeff Layton44772882010-10-15 15:34:03 -04001760 spin_unlock(&cifs_file_list_lock);
Steve French9b22b0b2007-10-02 01:11:08 +00001761 return open_file;
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001762 } else {
1763 if (!inv_file)
1764 inv_file = open_file;
Steve French9b22b0b2007-10-02 01:11:08 +00001765 }
Steve French6148a742005-10-05 12:23:19 -07001766 }
1767 }
Jeff Layton2846d382008-09-22 21:33:33 -04001768 /* couldn't find useable FH with same pid, try any available */
1769 if (!any_available) {
1770 any_available = true;
1771 goto refind_writable;
1772 }
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001773
1774 if (inv_file) {
1775 any_available = false;
Jeff Layton764a1b12012-07-25 14:59:54 -04001776 cifsFileInfo_get_locked(inv_file);
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001777 }
1778
Jeff Layton44772882010-10-15 15:34:03 -04001779 spin_unlock(&cifs_file_list_lock);
Shirish Pargaonkar2c0c2a02012-05-21 09:20:12 -05001780
1781 if (inv_file) {
1782 rc = cifs_reopen_file(inv_file, false);
1783 if (!rc)
1784 return inv_file;
1785 else {
1786 spin_lock(&cifs_file_list_lock);
1787 list_move_tail(&inv_file->flist,
1788 &cifs_inode->openFileList);
1789 spin_unlock(&cifs_file_list_lock);
1790 cifsFileInfo_put(inv_file);
1791 spin_lock(&cifs_file_list_lock);
1792 ++refind;
1793 goto refind_writable;
1794 }
1795 }
1796
Steve French6148a742005-10-05 12:23:19 -07001797 return NULL;
1798}
1799
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1801{
1802 struct address_space *mapping = page->mapping;
1803 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1804 char *write_data;
1805 int rc = -EFAULT;
1806 int bytes_written = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 struct inode *inode;
Steve French6148a742005-10-05 12:23:19 -07001808 struct cifsFileInfo *open_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809
1810 if (!mapping || !mapping->host)
1811 return -EFAULT;
1812
1813 inode = page->mapping->host;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814
1815 offset += (loff_t)from;
1816 write_data = kmap(page);
1817 write_data += from;
1818
1819 if ((to > PAGE_CACHE_SIZE) || (from > to)) {
1820 kunmap(page);
1821 return -EIO;
1822 }
1823
1824 /* racing with truncate? */
1825 if (offset > mapping->host->i_size) {
1826 kunmap(page);
1827 return 0; /* don't care */
1828 }
1829
1830 /* check to make sure that we are not extending the file */
1831 if (mapping->host->i_size - offset < (loff_t)to)
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001832 to = (unsigned)(mapping->host->i_size - offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833
Jeff Layton6508d902010-09-29 19:51:11 -04001834 open_file = find_writable_file(CIFS_I(mapping->host), false);
Steve French6148a742005-10-05 12:23:19 -07001835 if (open_file) {
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001836 bytes_written = cifs_write(open_file, open_file->pid,
1837 write_data, to - from, &offset);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001838 cifsFileInfo_put(open_file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 /* Does mm or vfs already set times? */
Steve French6148a742005-10-05 12:23:19 -07001840 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001841 if ((bytes_written > 0) && (offset))
Steve French6148a742005-10-05 12:23:19 -07001842 rc = 0;
Steve Frenchbb5a9a02007-12-31 04:21:29 +00001843 else if (bytes_written < 0)
1844 rc = bytes_written;
Steve French6148a742005-10-05 12:23:19 -07001845 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001846 cifs_dbg(FYI, "No writeable filehandles for inode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 rc = -EIO;
1848 }
1849
1850 kunmap(page);
1851 return rc;
1852}
1853
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854static int cifs_writepages(struct address_space *mapping,
Steve French37c0eb42005-10-05 14:50:29 -07001855 struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856{
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001857 struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb);
1858 bool done = false, scanned = false, range_whole = false;
1859 pgoff_t end, index;
1860 struct cifs_writedata *wdata;
Pavel Shilovskyc9de5c82012-09-18 16:20:29 -07001861 struct TCP_Server_Info *server;
Steve French37c0eb42005-10-05 14:50:29 -07001862 struct page *page;
Steve French37c0eb42005-10-05 14:50:29 -07001863 int rc = 0;
Steve French50c2f752007-07-13 00:33:32 +00001864
Steve French37c0eb42005-10-05 14:50:29 -07001865 /*
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001866 * If wsize is smaller than the page cache size, default to writing
Steve French37c0eb42005-10-05 14:50:29 -07001867 * one page at a time via cifs_writepage
1868 */
1869 if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1870 return generic_writepages(mapping, wbc);
1871
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001872 if (wbc->range_cyclic) {
Steve French37c0eb42005-10-05 14:50:29 -07001873 index = mapping->writeback_index; /* Start from prev offset */
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001874 end = -1;
1875 } else {
1876 index = wbc->range_start >> PAGE_CACHE_SHIFT;
1877 end = wbc->range_end >> PAGE_CACHE_SHIFT;
1878 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001879 range_whole = true;
1880 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07001881 }
1882retry:
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001883 while (!done && index <= end) {
1884 unsigned int i, nr_pages, found_pages;
1885 pgoff_t next = 0, tofind;
1886 struct page **pages;
Steve French37c0eb42005-10-05 14:50:29 -07001887
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001888 tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1,
1889 end - index) + 1;
Steve French37c0eb42005-10-05 14:50:29 -07001890
Jeff Laytonc2e87642012-03-23 14:40:55 -04001891 wdata = cifs_writedata_alloc((unsigned int)tofind,
1892 cifs_writev_complete);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001893 if (!wdata) {
1894 rc = -ENOMEM;
1895 break;
1896 }
1897
1898 /*
1899 * find_get_pages_tag seems to return a max of 256 on each
1900 * iteration, so we must call it several times in order to
1901 * fill the array or the wsize is effectively limited to
1902 * 256 * PAGE_CACHE_SIZE.
1903 */
1904 found_pages = 0;
1905 pages = wdata->pages;
1906 do {
1907 nr_pages = find_get_pages_tag(mapping, &index,
1908 PAGECACHE_TAG_DIRTY,
1909 tofind, pages);
1910 found_pages += nr_pages;
1911 tofind -= nr_pages;
1912 pages += nr_pages;
1913 } while (nr_pages && tofind && index <= end);
1914
1915 if (found_pages == 0) {
1916 kref_put(&wdata->refcount, cifs_writedata_release);
1917 break;
1918 }
1919
1920 nr_pages = 0;
1921 for (i = 0; i < found_pages; i++) {
1922 page = wdata->pages[i];
Steve French37c0eb42005-10-05 14:50:29 -07001923 /*
1924 * At this point we hold neither mapping->tree_lock nor
1925 * lock on the page itself: the page may be truncated or
1926 * invalidated (changing page->mapping to NULL), or even
1927 * swizzled back from swapper_space to tmpfs file
1928 * mapping
1929 */
1930
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001931 if (nr_pages == 0)
Steve French37c0eb42005-10-05 14:50:29 -07001932 lock_page(page);
Nick Piggin529ae9a2008-08-02 12:01:03 +02001933 else if (!trylock_page(page))
Steve French37c0eb42005-10-05 14:50:29 -07001934 break;
1935
1936 if (unlikely(page->mapping != mapping)) {
1937 unlock_page(page);
1938 break;
1939 }
1940
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07001941 if (!wbc->range_cyclic && page->index > end) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001942 done = true;
Steve French37c0eb42005-10-05 14:50:29 -07001943 unlock_page(page);
1944 break;
1945 }
1946
1947 if (next && (page->index != next)) {
1948 /* Not next consecutive page */
1949 unlock_page(page);
1950 break;
1951 }
1952
1953 if (wbc->sync_mode != WB_SYNC_NONE)
1954 wait_on_page_writeback(page);
1955
1956 if (PageWriteback(page) ||
Linus Torvaldscb876f42006-12-23 16:19:07 -08001957 !clear_page_dirty_for_io(page)) {
Steve French37c0eb42005-10-05 14:50:29 -07001958 unlock_page(page);
1959 break;
1960 }
Steve French84d2f072005-10-12 15:32:05 -07001961
Linus Torvaldscb876f42006-12-23 16:19:07 -08001962 /*
1963 * This actually clears the dirty bit in the radix tree.
1964 * See cifs_writepage() for more commentary.
1965 */
1966 set_page_writeback(page);
1967
Jeff Layton3a98b862012-11-26 09:48:41 -05001968 if (page_offset(page) >= i_size_read(mapping->host)) {
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001969 done = true;
Steve French84d2f072005-10-12 15:32:05 -07001970 unlock_page(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08001971 end_page_writeback(page);
Steve French84d2f072005-10-12 15:32:05 -07001972 break;
1973 }
1974
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001975 wdata->pages[i] = page;
Steve French37c0eb42005-10-05 14:50:29 -07001976 next = page->index + 1;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001977 ++nr_pages;
Steve French37c0eb42005-10-05 14:50:29 -07001978 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04001979
1980 /* reset index to refind any pages skipped */
1981 if (nr_pages == 0)
1982 index = wdata->pages[0]->index + 1;
1983
1984 /* put any pages we aren't going to use */
1985 for (i = nr_pages; i < found_pages; i++) {
1986 page_cache_release(wdata->pages[i]);
1987 wdata->pages[i] = NULL;
1988 }
1989
1990 /* nothing to write? */
1991 if (nr_pages == 0) {
1992 kref_put(&wdata->refcount, cifs_writedata_release);
1993 continue;
1994 }
1995
1996 wdata->sync_mode = wbc->sync_mode;
1997 wdata->nr_pages = nr_pages;
1998 wdata->offset = page_offset(wdata->pages[0]);
Jeff Laytoneddb0792012-09-18 16:20:35 -07001999 wdata->pagesz = PAGE_CACHE_SIZE;
2000 wdata->tailsz =
Jeff Layton3a98b862012-11-26 09:48:41 -05002001 min(i_size_read(mapping->host) -
2002 page_offset(wdata->pages[nr_pages - 1]),
Jeff Laytoneddb0792012-09-18 16:20:35 -07002003 (loff_t)PAGE_CACHE_SIZE);
2004 wdata->bytes = ((nr_pages - 1) * PAGE_CACHE_SIZE) +
2005 wdata->tailsz;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04002006
2007 do {
2008 if (wdata->cfile != NULL)
2009 cifsFileInfo_put(wdata->cfile);
2010 wdata->cfile = find_writable_file(CIFS_I(mapping->host),
2011 false);
2012 if (!wdata->cfile) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002013 cifs_dbg(VFS, "No writable handles for inode\n");
Steve French23e7dd72005-10-20 13:44:56 -07002014 rc = -EBADF;
Jeff Laytonc3d17b62011-05-19 16:22:57 -04002015 break;
Steve French37c0eb42005-10-05 14:50:29 -07002016 }
Jeff Laytonfe5f5d22012-03-23 14:40:55 -04002017 wdata->pid = wdata->cfile->pid;
Pavel Shilovskyc9de5c82012-09-18 16:20:29 -07002018 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
2019 rc = server->ops->async_writev(wdata);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04002020 } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN);
Jeff Laytonf3983c22010-09-22 16:17:40 -07002021
Jeff Laytonc3d17b62011-05-19 16:22:57 -04002022 for (i = 0; i < nr_pages; ++i)
2023 unlock_page(wdata->pages[i]);
Jeff Layton941b8532011-01-11 07:24:01 -05002024
Jeff Laytonc3d17b62011-05-19 16:22:57 -04002025 /* send failure -- clean up the mess */
2026 if (rc != 0) {
2027 for (i = 0; i < nr_pages; ++i) {
Jeff Layton941b8532011-01-11 07:24:01 -05002028 if (rc == -EAGAIN)
Jeff Laytonc3d17b62011-05-19 16:22:57 -04002029 redirty_page_for_writepage(wbc,
2030 wdata->pages[i]);
2031 else
2032 SetPageError(wdata->pages[i]);
2033 end_page_writeback(wdata->pages[i]);
2034 page_cache_release(wdata->pages[i]);
Steve French37c0eb42005-10-05 14:50:29 -07002035 }
Jeff Layton941b8532011-01-11 07:24:01 -05002036 if (rc != -EAGAIN)
2037 mapping_set_error(mapping, rc);
Jeff Laytonc3d17b62011-05-19 16:22:57 -04002038 }
2039 kref_put(&wdata->refcount, cifs_writedata_release);
Jeff Layton941b8532011-01-11 07:24:01 -05002040
Jeff Laytonc3d17b62011-05-19 16:22:57 -04002041 wbc->nr_to_write -= nr_pages;
2042 if (wbc->nr_to_write <= 0)
2043 done = true;
Dave Kleikampb066a482008-11-18 03:49:05 +00002044
Jeff Laytonc3d17b62011-05-19 16:22:57 -04002045 index = next;
Steve French37c0eb42005-10-05 14:50:29 -07002046 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04002047
Steve French37c0eb42005-10-05 14:50:29 -07002048 if (!scanned && !done) {
2049 /*
2050 * We hit the last page and there is more work to be done: wrap
2051 * back to the start of the file
2052 */
Jeff Laytonc3d17b62011-05-19 16:22:57 -04002053 scanned = true;
Steve French37c0eb42005-10-05 14:50:29 -07002054 index = 0;
2055 goto retry;
2056 }
Jeff Laytonc3d17b62011-05-19 16:22:57 -04002057
OGAWA Hirofumi111ebb62006-06-23 02:03:26 -07002058 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
Steve French37c0eb42005-10-05 14:50:29 -07002059 mapping->writeback_index = index;
2060
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 return rc;
2062}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002064static int
2065cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066{
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002067 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002068 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002070 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071/* BB add check for wbc flags */
2072 page_cache_get(page);
Steve Frenchad7a2922008-02-07 23:25:02 +00002073 if (!PageUptodate(page))
Joe Perchesf96637b2013-05-04 22:12:25 -05002074 cifs_dbg(FYI, "ppw - page not up to date\n");
Linus Torvaldscb876f42006-12-23 16:19:07 -08002075
2076 /*
2077 * Set the "writeback" flag, and clear "dirty" in the radix tree.
2078 *
2079 * A writepage() implementation always needs to do either this,
2080 * or re-dirty the page with "redirty_page_for_writepage()" in
2081 * the case of a failure.
2082 *
2083 * Just unlocking the page will cause the radix tree tag-bits
2084 * to fail to update with the state of the page correctly.
2085 */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002086 set_page_writeback(page);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002087retry_write:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002089 if (rc == -EAGAIN && wbc->sync_mode == WB_SYNC_ALL)
2090 goto retry_write;
2091 else if (rc == -EAGAIN)
2092 redirty_page_for_writepage(wbc, page);
2093 else if (rc != 0)
2094 SetPageError(page);
2095 else
2096 SetPageUptodate(page);
Linus Torvaldscb876f42006-12-23 16:19:07 -08002097 end_page_writeback(page);
2098 page_cache_release(page);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002099 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 return rc;
2101}
2102
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04002103static int cifs_writepage(struct page *page, struct writeback_control *wbc)
2104{
2105 int rc = cifs_writepage_locked(page, wbc);
2106 unlock_page(page);
2107 return rc;
2108}
2109
Nick Piggind9414772008-09-24 11:32:59 -04002110static int cifs_write_end(struct file *file, struct address_space *mapping,
2111 loff_t pos, unsigned len, unsigned copied,
2112 struct page *page, void *fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113{
Nick Piggind9414772008-09-24 11:32:59 -04002114 int rc;
2115 struct inode *inode = mapping->host;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002116 struct cifsFileInfo *cfile = file->private_data;
2117 struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
2118 __u32 pid;
2119
2120 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2121 pid = cfile->pid;
2122 else
2123 pid = current->tgid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124
Joe Perchesf96637b2013-05-04 22:12:25 -05002125 cifs_dbg(FYI, "write_end for page %p from pos %lld with %d bytes\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002126 page, pos, copied);
Steve Frenchad7a2922008-02-07 23:25:02 +00002127
Jeff Laytona98ee8c2008-11-26 19:32:33 +00002128 if (PageChecked(page)) {
2129 if (copied == len)
2130 SetPageUptodate(page);
2131 ClearPageChecked(page);
2132 } else if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
Nick Piggind9414772008-09-24 11:32:59 -04002133 SetPageUptodate(page);
2134
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 if (!PageUptodate(page)) {
Nick Piggind9414772008-09-24 11:32:59 -04002136 char *page_data;
2137 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002138 unsigned int xid;
Nick Piggind9414772008-09-24 11:32:59 -04002139
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002140 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 /* this is probably better than directly calling
2142 partialpage_write since in this function the file handle is
2143 known which we might as well leverage */
2144 /* BB check if anything else missing out of ppw
2145 such as updating last write time */
2146 page_data = kmap(page);
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002147 rc = cifs_write(cfile, pid, page_data + offset, copied, &pos);
Nick Piggind9414772008-09-24 11:32:59 -04002148 /* if (rc < 0) should we set writebehind rc? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 kunmap(page);
Nick Piggind9414772008-09-24 11:32:59 -04002150
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002151 free_xid(xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002152 } else {
Nick Piggind9414772008-09-24 11:32:59 -04002153 rc = copied;
2154 pos += copied;
Pavel Shilovskyca8aa292012-12-21 15:05:47 +04002155 set_page_dirty(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 }
2157
Nick Piggind9414772008-09-24 11:32:59 -04002158 if (rc > 0) {
2159 spin_lock(&inode->i_lock);
2160 if (pos > inode->i_size)
2161 i_size_write(inode, pos);
2162 spin_unlock(&inode->i_lock);
2163 }
2164
2165 unlock_page(page);
2166 page_cache_release(page);
2167
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 return rc;
2169}
2170
Josef Bacik02c24a82011-07-16 20:44:56 -04002171int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
2172 int datasync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002174 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00002176 struct cifs_tcon *tcon;
Pavel Shilovsky1d8c4c02012-09-18 16:20:27 -07002177 struct TCP_Server_Info *server;
Joe Perchesc21dfb62010-07-12 13:50:14 -07002178 struct cifsFileInfo *smbfile = file->private_data;
Al Viro496ad9a2013-01-23 17:07:38 -05002179 struct inode *inode = file_inode(file);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002180 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181
Josef Bacik02c24a82011-07-16 20:44:56 -04002182 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
2183 if (rc)
2184 return rc;
2185 mutex_lock(&inode->i_mutex);
2186
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002187 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188
Joe Perchesf96637b2013-05-04 22:12:25 -05002189 cifs_dbg(FYI, "Sync file - name: %s datasync: 0x%x\n",
2190 file->f_path.dentry->d_name.name, datasync);
Steve French50c2f752007-07-13 00:33:32 +00002191
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002192 if (!CIFS_I(inode)->clientCanCacheRead) {
2193 rc = cifs_invalidate_mapping(inode);
2194 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002195 cifs_dbg(FYI, "rc: %d during invalidate phase\n", rc);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002196 rc = 0; /* don't care about it in fsync */
2197 }
2198 }
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002199
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002200 tcon = tlink_tcon(smbfile->tlink);
Pavel Shilovsky1d8c4c02012-09-18 16:20:27 -07002201 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
2202 server = tcon->ses->server;
2203 if (server->ops->flush)
2204 rc = server->ops->flush(xid, tcon, &smbfile->fid);
2205 else
2206 rc = -ENOSYS;
2207 }
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002208
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002209 free_xid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04002210 mutex_unlock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002211 return rc;
2212}
2213
Josef Bacik02c24a82011-07-16 20:44:56 -04002214int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002215{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002216 unsigned int xid;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002217 int rc = 0;
Steve French96daf2b2011-05-27 04:34:02 +00002218 struct cifs_tcon *tcon;
Pavel Shilovsky1d8c4c02012-09-18 16:20:27 -07002219 struct TCP_Server_Info *server;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002220 struct cifsFileInfo *smbfile = file->private_data;
2221 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Josef Bacik02c24a82011-07-16 20:44:56 -04002222 struct inode *inode = file->f_mapping->host;
2223
2224 rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
2225 if (rc)
2226 return rc;
2227 mutex_lock(&inode->i_mutex);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002228
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002229 xid = get_xid();
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002230
Joe Perchesf96637b2013-05-04 22:12:25 -05002231 cifs_dbg(FYI, "Sync file - name: %s datasync: 0x%x\n",
2232 file->f_path.dentry->d_name.name, datasync);
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +03002233
2234 tcon = tlink_tcon(smbfile->tlink);
Pavel Shilovsky1d8c4c02012-09-18 16:20:27 -07002235 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
2236 server = tcon->ses->server;
2237 if (server->ops->flush)
2238 rc = server->ops->flush(xid, tcon, &smbfile->fid);
2239 else
2240 rc = -ENOSYS;
2241 }
Steve Frenchb298f222009-02-21 21:17:43 +00002242
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002243 free_xid(xid);
Josef Bacik02c24a82011-07-16 20:44:56 -04002244 mutex_unlock(&inode->i_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 return rc;
2246}
2247
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248/*
2249 * As file closes, flush all cached write data for this inode checking
2250 * for write behind errors.
2251 */
Miklos Szeredi75e1fcc2006-06-23 02:05:12 -07002252int cifs_flush(struct file *file, fl_owner_t id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253{
Al Viro496ad9a2013-01-23 17:07:38 -05002254 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 int rc = 0;
2256
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002257 if (file->f_mode & FMODE_WRITE)
Jeff Laytond3f13222010-10-15 15:34:07 -04002258 rc = filemap_write_and_wait(inode->i_mapping);
Steve French50c2f752007-07-13 00:33:32 +00002259
Joe Perchesf96637b2013-05-04 22:12:25 -05002260 cifs_dbg(FYI, "Flush inode %p file %p rc %d\n", inode, file, rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261
2262 return rc;
2263}
2264
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002265static int
2266cifs_write_allocate_pages(struct page **pages, unsigned long num_pages)
2267{
2268 int rc = 0;
2269 unsigned long i;
2270
2271 for (i = 0; i < num_pages; i++) {
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002272 pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002273 if (!pages[i]) {
2274 /*
2275 * save number of pages we have already allocated and
2276 * return with ENOMEM error
2277 */
2278 num_pages = i;
2279 rc = -ENOMEM;
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002280 break;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002281 }
2282 }
2283
Jeff Laytone94f7ba2012-03-23 14:40:56 -04002284 if (rc) {
2285 for (i = 0; i < num_pages; i++)
2286 put_page(pages[i]);
2287 }
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002288 return rc;
2289}
2290
2291static inline
2292size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
2293{
2294 size_t num_pages;
2295 size_t clen;
2296
2297 clen = min_t(const size_t, len, wsize);
Jeff Laytona7103b92012-03-23 14:40:56 -04002298 num_pages = DIV_ROUND_UP(clen, PAGE_SIZE);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002299
2300 if (cur_len)
2301 *cur_len = clen;
2302
2303 return num_pages;
2304}
2305
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002306static void
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002307cifs_uncached_writev_complete(struct work_struct *work)
2308{
2309 int i;
2310 struct cifs_writedata *wdata = container_of(work,
2311 struct cifs_writedata, work);
2312 struct inode *inode = wdata->cfile->dentry->d_inode;
2313 struct cifsInodeInfo *cifsi = CIFS_I(inode);
2314
2315 spin_lock(&inode->i_lock);
2316 cifs_update_eof(cifsi, wdata->offset, wdata->bytes);
2317 if (cifsi->server_eof > inode->i_size)
2318 i_size_write(inode, cifsi->server_eof);
2319 spin_unlock(&inode->i_lock);
2320
2321 complete(&wdata->done);
2322
2323 if (wdata->result != -EAGAIN) {
2324 for (i = 0; i < wdata->nr_pages; i++)
2325 put_page(wdata->pages[i]);
2326 }
2327
2328 kref_put(&wdata->refcount, cifs_writedata_release);
2329}
2330
2331/* attempt to send write to server, retry on any -EAGAIN errors */
2332static int
2333cifs_uncached_retry_writev(struct cifs_writedata *wdata)
2334{
2335 int rc;
Pavel Shilovskyc9de5c82012-09-18 16:20:29 -07002336 struct TCP_Server_Info *server;
2337
2338 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002339
2340 do {
2341 if (wdata->cfile->invalidHandle) {
2342 rc = cifs_reopen_file(wdata->cfile, false);
2343 if (rc != 0)
2344 continue;
2345 }
Pavel Shilovskyc9de5c82012-09-18 16:20:29 -07002346 rc = server->ops->async_writev(wdata);
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002347 } while (rc == -EAGAIN);
2348
2349 return rc;
2350}
2351
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002352static ssize_t
2353cifs_iovec_write(struct file *file, const struct iovec *iov,
2354 unsigned long nr_segs, loff_t *poffset)
2355{
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002356 unsigned long nr_pages, i;
Pavel Shilovsky76429c12011-01-31 16:03:08 +03002357 size_t copied, len, cur_len;
2358 ssize_t total_written = 0;
Jeff Layton3af9d8f2012-04-13 17:16:59 -04002359 loff_t offset;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002360 struct iov_iter it;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002361 struct cifsFileInfo *open_file;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002362 struct cifs_tcon *tcon;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002363 struct cifs_sb_info *cifs_sb;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002364 struct cifs_writedata *wdata, *tmp;
2365 struct list_head wdata_list;
2366 int rc;
2367 pid_t pid;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002368
2369 len = iov_length(iov, nr_segs);
2370 if (!len)
2371 return 0;
2372
2373 rc = generic_write_checks(file, poffset, &len, 0);
2374 if (rc)
2375 return rc;
2376
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002377 INIT_LIST_HEAD(&wdata_list);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002378 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002379 open_file = file->private_data;
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002380 tcon = tlink_tcon(open_file->tlink);
Pavel Shilovskyc9de5c82012-09-18 16:20:29 -07002381
2382 if (!tcon->ses->server->ops->async_writev)
2383 return -ENOSYS;
2384
Jeff Layton3af9d8f2012-04-13 17:16:59 -04002385 offset = *poffset;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002386
2387 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2388 pid = open_file->pid;
2389 else
2390 pid = current->tgid;
2391
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002392 iov_iter_init(&it, iov, nr_segs, len, 0);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002393 do {
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002394 size_t save_len;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002395
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002396 nr_pages = get_numpages(cifs_sb->wsize, len, &cur_len);
2397 wdata = cifs_writedata_alloc(nr_pages,
2398 cifs_uncached_writev_complete);
2399 if (!wdata) {
2400 rc = -ENOMEM;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002401 break;
2402 }
2403
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002404 rc = cifs_write_allocate_pages(wdata->pages, nr_pages);
2405 if (rc) {
2406 kfree(wdata);
2407 break;
2408 }
2409
2410 save_len = cur_len;
2411 for (i = 0; i < nr_pages; i++) {
2412 copied = min_t(const size_t, cur_len, PAGE_SIZE);
2413 copied = iov_iter_copy_from_user(wdata->pages[i], &it,
2414 0, copied);
2415 cur_len -= copied;
2416 iov_iter_advance(&it, copied);
2417 }
2418 cur_len = save_len - cur_len;
2419
2420 wdata->sync_mode = WB_SYNC_ALL;
2421 wdata->nr_pages = nr_pages;
2422 wdata->offset = (__u64)offset;
2423 wdata->cfile = cifsFileInfo_get(open_file);
2424 wdata->pid = pid;
2425 wdata->bytes = cur_len;
Jeff Laytoneddb0792012-09-18 16:20:35 -07002426 wdata->pagesz = PAGE_SIZE;
2427 wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002428 rc = cifs_uncached_retry_writev(wdata);
2429 if (rc) {
2430 kref_put(&wdata->refcount, cifs_writedata_release);
2431 break;
2432 }
2433
2434 list_add_tail(&wdata->list, &wdata_list);
2435 offset += cur_len;
2436 len -= cur_len;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002437 } while (len > 0);
2438
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002439 /*
2440 * If at least one write was successfully sent, then discard any rc
2441 * value from the later writes. If the other write succeeds, then
2442 * we'll end up returning whatever was written. If it fails, then
2443 * we'll get a new rc value from that.
2444 */
2445 if (!list_empty(&wdata_list))
2446 rc = 0;
2447
2448 /*
2449 * Wait for and collect replies for any successful sends in order of
2450 * increasing offset. Once an error is hit or we get a fatal signal
2451 * while waiting, then return without waiting for any more replies.
2452 */
2453restart_loop:
2454 list_for_each_entry_safe(wdata, tmp, &wdata_list, list) {
2455 if (!rc) {
2456 /* FIXME: freezable too? */
2457 rc = wait_for_completion_killable(&wdata->done);
2458 if (rc)
2459 rc = -EINTR;
2460 else if (wdata->result)
2461 rc = wdata->result;
2462 else
2463 total_written += wdata->bytes;
2464
2465 /* resend call if it's a retryable error */
2466 if (rc == -EAGAIN) {
2467 rc = cifs_uncached_retry_writev(wdata);
2468 goto restart_loop;
2469 }
2470 }
2471 list_del_init(&wdata->list);
2472 kref_put(&wdata->refcount, cifs_writedata_release);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002473 }
2474
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002475 if (total_written > 0)
2476 *poffset += total_written;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002477
Jeff Laytonda82f7e2012-03-23 14:40:56 -04002478 cifs_stats_bytes_written(tcon, total_written);
2479 return total_written ? total_written : (ssize_t)rc;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002480}
2481
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03002482ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002483 unsigned long nr_segs, loff_t pos)
2484{
2485 ssize_t written;
2486 struct inode *inode;
2487
Al Viro496ad9a2013-01-23 17:07:38 -05002488 inode = file_inode(iocb->ki_filp);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002489
2490 /*
2491 * BB - optimize the way when signing is disabled. We can drop this
2492 * extra memory-to-memory copying and use iovec buffers for constructing
2493 * write request.
2494 */
2495
2496 written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos);
2497 if (written > 0) {
2498 CIFS_I(inode)->invalid_mapping = true;
2499 iocb->ki_pos = pos;
2500 }
2501
2502 return written;
2503}
2504
Pavel Shilovsky579f9052012-09-19 06:22:44 -07002505static ssize_t
Pavel Shilovskyca8aa292012-12-21 15:05:47 +04002506cifs_writev(struct kiocb *iocb, const struct iovec *iov,
2507 unsigned long nr_segs, loff_t pos)
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002508{
Pavel Shilovsky579f9052012-09-19 06:22:44 -07002509 struct file *file = iocb->ki_filp;
2510 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
2511 struct inode *inode = file->f_mapping->host;
2512 struct cifsInodeInfo *cinode = CIFS_I(inode);
2513 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
2514 ssize_t rc = -EACCES;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002515
Pavel Shilovsky579f9052012-09-19 06:22:44 -07002516 BUG_ON(iocb->ki_pos != pos);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002517
Pavel Shilovsky579f9052012-09-19 06:22:44 -07002518 /*
2519 * We need to hold the sem to be sure nobody modifies lock list
2520 * with a brlock that prevents writing.
2521 */
2522 down_read(&cinode->lock_sem);
2523 if (!cifs_find_lock_conflict(cfile, pos, iov_length(iov, nr_segs),
2524 server->vals->exclusive_lock_type, NULL,
Pavel Shilovsky081c0412012-11-27 18:38:53 +04002525 CIFS_WRITE_OP)) {
Pavel Shilovsky579f9052012-09-19 06:22:44 -07002526 mutex_lock(&inode->i_mutex);
2527 rc = __generic_file_aio_write(iocb, iov, nr_segs,
Pavel Shilovskyca8aa292012-12-21 15:05:47 +04002528 &iocb->ki_pos);
Pavel Shilovsky579f9052012-09-19 06:22:44 -07002529 mutex_unlock(&inode->i_mutex);
2530 }
2531
2532 if (rc > 0 || rc == -EIOCBQUEUED) {
2533 ssize_t err;
2534
2535 err = generic_write_sync(file, pos, rc);
2536 if (err < 0 && rc > 0)
2537 rc = err;
2538 }
2539
2540 up_read(&cinode->lock_sem);
Pavel Shilovsky579f9052012-09-19 06:22:44 -07002541 return rc;
2542}
2543
2544ssize_t
2545cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
2546 unsigned long nr_segs, loff_t pos)
2547{
Al Viro496ad9a2013-01-23 17:07:38 -05002548 struct inode *inode = file_inode(iocb->ki_filp);
Pavel Shilovsky579f9052012-09-19 06:22:44 -07002549 struct cifsInodeInfo *cinode = CIFS_I(inode);
2550 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
2551 struct cifsFileInfo *cfile = (struct cifsFileInfo *)
2552 iocb->ki_filp->private_data;
2553 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky88cf75a2012-12-21 15:07:52 +04002554 ssize_t written;
Pavel Shilovskyca8aa292012-12-21 15:05:47 +04002555
Pavel Shilovsky88cf75a2012-12-21 15:07:52 +04002556 if (cinode->clientCanCacheAll) {
2557 if (cap_unix(tcon->ses) &&
2558 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))
2559 && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
2560 return generic_file_aio_write(iocb, iov, nr_segs, pos);
2561 return cifs_writev(iocb, iov, nr_segs, pos);
Pavel Shilovskyc299dd02012-12-06 22:07:52 +04002562 }
Pavel Shilovskyca8aa292012-12-21 15:05:47 +04002563 /*
2564 * For non-oplocked files in strict cache mode we need to write the data
2565 * to the server exactly from the pos to pos+len-1 rather than flush all
2566 * affected pages because it may cause a error with mandatory locks on
2567 * these pages but not on the region from pos to ppos+len-1.
2568 */
Pavel Shilovsky88cf75a2012-12-21 15:07:52 +04002569 written = cifs_user_writev(iocb, iov, nr_segs, pos);
2570 if (written > 0 && cinode->clientCanCacheRead) {
2571 /*
2572 * Windows 7 server can delay breaking level2 oplock if a write
2573 * request comes - break it on the client to prevent reading
2574 * an old data.
2575 */
2576 cifs_invalidate_mapping(inode);
Joe Perchesf96637b2013-05-04 22:12:25 -05002577 cifs_dbg(FYI, "Set no oplock for inode=%p after a write operation\n",
2578 inode);
Pavel Shilovsky88cf75a2012-12-21 15:07:52 +04002579 cinode->clientCanCacheRead = false;
2580 }
2581 return written;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -05002582}
2583
Jeff Layton0471ca32012-05-16 07:13:16 -04002584static struct cifs_readdata *
Jeff Laytonf4e49cd2012-09-18 16:20:36 -07002585cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete)
Jeff Layton0471ca32012-05-16 07:13:16 -04002586{
2587 struct cifs_readdata *rdata;
Jeff Laytonf4e49cd2012-09-18 16:20:36 -07002588
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002589 rdata = kzalloc(sizeof(*rdata) + (sizeof(struct page *) * nr_pages),
2590 GFP_KERNEL);
Jeff Layton0471ca32012-05-16 07:13:16 -04002591 if (rdata != NULL) {
Jeff Layton6993f742012-05-16 07:13:17 -04002592 kref_init(&rdata->refcount);
Jeff Layton1c892542012-05-16 07:13:17 -04002593 INIT_LIST_HEAD(&rdata->list);
2594 init_completion(&rdata->done);
Jeff Layton0471ca32012-05-16 07:13:16 -04002595 INIT_WORK(&rdata->work, complete);
Jeff Layton0471ca32012-05-16 07:13:16 -04002596 }
Jeff Laytonf4e49cd2012-09-18 16:20:36 -07002597
Jeff Layton0471ca32012-05-16 07:13:16 -04002598 return rdata;
2599}
2600
Jeff Layton6993f742012-05-16 07:13:17 -04002601void
2602cifs_readdata_release(struct kref *refcount)
Jeff Layton0471ca32012-05-16 07:13:16 -04002603{
Jeff Layton6993f742012-05-16 07:13:17 -04002604 struct cifs_readdata *rdata = container_of(refcount,
2605 struct cifs_readdata, refcount);
2606
2607 if (rdata->cfile)
2608 cifsFileInfo_put(rdata->cfile);
2609
Jeff Layton0471ca32012-05-16 07:13:16 -04002610 kfree(rdata);
2611}
2612
Jeff Layton2a1bb132012-05-16 07:13:17 -04002613static int
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002614cifs_read_allocate_pages(struct cifs_readdata *rdata, unsigned int nr_pages)
Jeff Layton1c892542012-05-16 07:13:17 -04002615{
2616 int rc = 0;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002617 struct page *page;
Jeff Layton1c892542012-05-16 07:13:17 -04002618 unsigned int i;
2619
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002620 for (i = 0; i < nr_pages; i++) {
Jeff Layton1c892542012-05-16 07:13:17 -04002621 page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
2622 if (!page) {
2623 rc = -ENOMEM;
2624 break;
2625 }
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002626 rdata->pages[i] = page;
Jeff Layton1c892542012-05-16 07:13:17 -04002627 }
2628
2629 if (rc) {
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002630 for (i = 0; i < nr_pages; i++) {
2631 put_page(rdata->pages[i]);
2632 rdata->pages[i] = NULL;
Jeff Layton1c892542012-05-16 07:13:17 -04002633 }
2634 }
2635 return rc;
2636}
2637
2638static void
2639cifs_uncached_readdata_release(struct kref *refcount)
2640{
Jeff Layton1c892542012-05-16 07:13:17 -04002641 struct cifs_readdata *rdata = container_of(refcount,
2642 struct cifs_readdata, refcount);
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002643 unsigned int i;
Jeff Layton1c892542012-05-16 07:13:17 -04002644
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002645 for (i = 0; i < rdata->nr_pages; i++) {
2646 put_page(rdata->pages[i]);
2647 rdata->pages[i] = NULL;
Jeff Layton1c892542012-05-16 07:13:17 -04002648 }
2649 cifs_readdata_release(refcount);
2650}
2651
2652static int
Jeff Layton2a1bb132012-05-16 07:13:17 -04002653cifs_retry_async_readv(struct cifs_readdata *rdata)
2654{
2655 int rc;
Pavel Shilovskyfc9c5962012-09-18 16:20:28 -07002656 struct TCP_Server_Info *server;
2657
2658 server = tlink_tcon(rdata->cfile->tlink)->ses->server;
Jeff Layton2a1bb132012-05-16 07:13:17 -04002659
2660 do {
2661 if (rdata->cfile->invalidHandle) {
2662 rc = cifs_reopen_file(rdata->cfile, true);
2663 if (rc != 0)
2664 continue;
2665 }
Pavel Shilovskyfc9c5962012-09-18 16:20:28 -07002666 rc = server->ops->async_readv(rdata);
Jeff Layton2a1bb132012-05-16 07:13:17 -04002667 } while (rc == -EAGAIN);
2668
2669 return rc;
2670}
2671
Jeff Layton1c892542012-05-16 07:13:17 -04002672/**
2673 * cifs_readdata_to_iov - copy data from pages in response to an iovec
2674 * @rdata: the readdata response with list of pages holding data
2675 * @iov: vector in which we should copy the data
2676 * @nr_segs: number of segments in vector
2677 * @offset: offset into file of the first iovec
2678 * @copied: used to return the amount of data copied to the iov
2679 *
2680 * This function copies data from a list of pages in a readdata response into
2681 * an array of iovecs. It will first calculate where the data should go
2682 * based on the info in the readdata and then copy the data into that spot.
2683 */
2684static ssize_t
2685cifs_readdata_to_iov(struct cifs_readdata *rdata, const struct iovec *iov,
2686 unsigned long nr_segs, loff_t offset, ssize_t *copied)
2687{
2688 int rc = 0;
2689 struct iov_iter ii;
2690 size_t pos = rdata->offset - offset;
Jeff Layton1c892542012-05-16 07:13:17 -04002691 ssize_t remaining = rdata->bytes;
2692 unsigned char *pdata;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002693 unsigned int i;
Jeff Layton1c892542012-05-16 07:13:17 -04002694
2695 /* set up iov_iter and advance to the correct offset */
2696 iov_iter_init(&ii, iov, nr_segs, iov_length(iov, nr_segs), 0);
2697 iov_iter_advance(&ii, pos);
2698
2699 *copied = 0;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002700 for (i = 0; i < rdata->nr_pages; i++) {
Jeff Layton1c892542012-05-16 07:13:17 -04002701 ssize_t copy;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002702 struct page *page = rdata->pages[i];
Jeff Layton1c892542012-05-16 07:13:17 -04002703
2704 /* copy a whole page or whatever's left */
2705 copy = min_t(ssize_t, remaining, PAGE_SIZE);
2706
2707 /* ...but limit it to whatever space is left in the iov */
2708 copy = min_t(ssize_t, copy, iov_iter_count(&ii));
2709
2710 /* go while there's data to be copied and no errors */
2711 if (copy && !rc) {
2712 pdata = kmap(page);
2713 rc = memcpy_toiovecend(ii.iov, pdata, ii.iov_offset,
2714 (int)copy);
2715 kunmap(page);
2716 if (!rc) {
2717 *copied += copy;
2718 remaining -= copy;
2719 iov_iter_advance(&ii, copy);
2720 }
2721 }
Jeff Layton1c892542012-05-16 07:13:17 -04002722 }
2723
2724 return rc;
2725}
2726
2727static void
2728cifs_uncached_readv_complete(struct work_struct *work)
2729{
2730 struct cifs_readdata *rdata = container_of(work,
2731 struct cifs_readdata, work);
Jeff Layton1c892542012-05-16 07:13:17 -04002732
2733 complete(&rdata->done);
2734 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
2735}
2736
2737static int
Jeff Layton8321fec2012-09-19 06:22:32 -07002738cifs_uncached_read_into_pages(struct TCP_Server_Info *server,
2739 struct cifs_readdata *rdata, unsigned int len)
Jeff Layton1c892542012-05-16 07:13:17 -04002740{
Jeff Layton8321fec2012-09-19 06:22:32 -07002741 int total_read = 0, result = 0;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002742 unsigned int i;
2743 unsigned int nr_pages = rdata->nr_pages;
Jeff Layton8321fec2012-09-19 06:22:32 -07002744 struct kvec iov;
Jeff Layton1c892542012-05-16 07:13:17 -04002745
Jeff Layton8321fec2012-09-19 06:22:32 -07002746 rdata->tailsz = PAGE_SIZE;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002747 for (i = 0; i < nr_pages; i++) {
2748 struct page *page = rdata->pages[i];
2749
Jeff Layton8321fec2012-09-19 06:22:32 -07002750 if (len >= PAGE_SIZE) {
Jeff Layton1c892542012-05-16 07:13:17 -04002751 /* enough data to fill the page */
Jeff Layton8321fec2012-09-19 06:22:32 -07002752 iov.iov_base = kmap(page);
2753 iov.iov_len = PAGE_SIZE;
Joe Perchesf96637b2013-05-04 22:12:25 -05002754 cifs_dbg(FYI, "%u: iov_base=%p iov_len=%zu\n",
2755 i, iov.iov_base, iov.iov_len);
Jeff Layton8321fec2012-09-19 06:22:32 -07002756 len -= PAGE_SIZE;
2757 } else if (len > 0) {
Jeff Layton1c892542012-05-16 07:13:17 -04002758 /* enough for partial page, fill and zero the rest */
Jeff Layton8321fec2012-09-19 06:22:32 -07002759 iov.iov_base = kmap(page);
2760 iov.iov_len = len;
Joe Perchesf96637b2013-05-04 22:12:25 -05002761 cifs_dbg(FYI, "%u: iov_base=%p iov_len=%zu\n",
2762 i, iov.iov_base, iov.iov_len);
Jeff Layton8321fec2012-09-19 06:22:32 -07002763 memset(iov.iov_base + len, '\0', PAGE_SIZE - len);
2764 rdata->tailsz = len;
2765 len = 0;
Jeff Layton1c892542012-05-16 07:13:17 -04002766 } else {
2767 /* no need to hold page hostage */
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002768 rdata->pages[i] = NULL;
2769 rdata->nr_pages--;
Jeff Layton1c892542012-05-16 07:13:17 -04002770 put_page(page);
Jeff Layton8321fec2012-09-19 06:22:32 -07002771 continue;
Jeff Layton1c892542012-05-16 07:13:17 -04002772 }
Jeff Layton8321fec2012-09-19 06:22:32 -07002773
2774 result = cifs_readv_from_socket(server, &iov, 1, iov.iov_len);
2775 kunmap(page);
2776 if (result < 0)
2777 break;
2778
2779 total_read += result;
Jeff Layton1c892542012-05-16 07:13:17 -04002780 }
2781
Jeff Layton8321fec2012-09-19 06:22:32 -07002782 return total_read > 0 ? total_read : result;
Jeff Layton1c892542012-05-16 07:13:17 -04002783}
2784
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002785static ssize_t
2786cifs_iovec_read(struct file *file, const struct iovec *iov,
2787 unsigned long nr_segs, loff_t *poffset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788{
Jeff Layton1c892542012-05-16 07:13:17 -04002789 ssize_t rc;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002790 size_t len, cur_len;
Jeff Layton1c892542012-05-16 07:13:17 -04002791 ssize_t total_read = 0;
2792 loff_t offset = *poffset;
2793 unsigned int npages;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 struct cifs_sb_info *cifs_sb;
Jeff Layton1c892542012-05-16 07:13:17 -04002795 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796 struct cifsFileInfo *open_file;
Jeff Layton1c892542012-05-16 07:13:17 -04002797 struct cifs_readdata *rdata, *tmp;
2798 struct list_head rdata_list;
2799 pid_t pid;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002800
2801 if (!nr_segs)
2802 return 0;
2803
2804 len = iov_length(iov, nr_segs);
2805 if (!len)
2806 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807
Jeff Layton1c892542012-05-16 07:13:17 -04002808 INIT_LIST_HEAD(&rdata_list);
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002809 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -07002810 open_file = file->private_data;
Jeff Layton1c892542012-05-16 07:13:17 -04002811 tcon = tlink_tcon(open_file->tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812
Pavel Shilovskyfc9c5962012-09-18 16:20:28 -07002813 if (!tcon->ses->server->ops->async_readv)
2814 return -ENOSYS;
2815
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002816 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2817 pid = open_file->pid;
2818 else
2819 pid = current->tgid;
2820
Steve Frenchad7a2922008-02-07 23:25:02 +00002821 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesf96637b2013-05-04 22:12:25 -05002822 cifs_dbg(FYI, "attempting read on write only file instance\n");
Steve Frenchad7a2922008-02-07 23:25:02 +00002823
Jeff Layton1c892542012-05-16 07:13:17 -04002824 do {
2825 cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize);
2826 npages = DIV_ROUND_UP(cur_len, PAGE_SIZE);
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002827
Jeff Layton1c892542012-05-16 07:13:17 -04002828 /* allocate a readdata struct */
2829 rdata = cifs_readdata_alloc(npages,
2830 cifs_uncached_readv_complete);
2831 if (!rdata) {
2832 rc = -ENOMEM;
2833 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002835
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002836 rc = cifs_read_allocate_pages(rdata, npages);
Jeff Layton1c892542012-05-16 07:13:17 -04002837 if (rc)
2838 goto error;
2839
2840 rdata->cfile = cifsFileInfo_get(open_file);
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07002841 rdata->nr_pages = npages;
Jeff Layton1c892542012-05-16 07:13:17 -04002842 rdata->offset = offset;
2843 rdata->bytes = cur_len;
2844 rdata->pid = pid;
Jeff Layton8321fec2012-09-19 06:22:32 -07002845 rdata->pagesz = PAGE_SIZE;
2846 rdata->read_into_pages = cifs_uncached_read_into_pages;
Jeff Layton1c892542012-05-16 07:13:17 -04002847
2848 rc = cifs_retry_async_readv(rdata);
2849error:
2850 if (rc) {
2851 kref_put(&rdata->refcount,
2852 cifs_uncached_readdata_release);
2853 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854 }
Jeff Layton1c892542012-05-16 07:13:17 -04002855
2856 list_add_tail(&rdata->list, &rdata_list);
2857 offset += cur_len;
2858 len -= cur_len;
2859 } while (len > 0);
2860
2861 /* if at least one read request send succeeded, then reset rc */
2862 if (!list_empty(&rdata_list))
2863 rc = 0;
2864
2865 /* the loop below should proceed in the order of increasing offsets */
2866restart_loop:
2867 list_for_each_entry_safe(rdata, tmp, &rdata_list, list) {
2868 if (!rc) {
2869 ssize_t copied;
2870
2871 /* FIXME: freezable sleep too? */
2872 rc = wait_for_completion_killable(&rdata->done);
2873 if (rc)
2874 rc = -EINTR;
2875 else if (rdata->result)
2876 rc = rdata->result;
2877 else {
2878 rc = cifs_readdata_to_iov(rdata, iov,
2879 nr_segs, *poffset,
2880 &copied);
2881 total_read += copied;
2882 }
2883
2884 /* resend call if it's a retryable error */
2885 if (rc == -EAGAIN) {
2886 rc = cifs_retry_async_readv(rdata);
2887 goto restart_loop;
2888 }
2889 }
2890 list_del_init(&rdata->list);
2891 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892 }
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002893
Jeff Layton1c892542012-05-16 07:13:17 -04002894 cifs_stats_bytes_read(tcon, total_read);
2895 *poffset += total_read;
2896
Pavel Shilovsky09a47072012-09-18 16:20:29 -07002897 /* mask nodata case */
2898 if (rc == -ENODATA)
2899 rc = 0;
2900
Jeff Layton1c892542012-05-16 07:13:17 -04002901 return total_read ? total_read : rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902}
2903
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +03002904ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov,
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002905 unsigned long nr_segs, loff_t pos)
2906{
2907 ssize_t read;
2908
2909 read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos);
2910 if (read > 0)
2911 iocb->ki_pos = pos;
2912
2913 return read;
2914}
2915
Pavel Shilovsky579f9052012-09-19 06:22:44 -07002916ssize_t
2917cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov,
2918 unsigned long nr_segs, loff_t pos)
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002919{
Al Viro496ad9a2013-01-23 17:07:38 -05002920 struct inode *inode = file_inode(iocb->ki_filp);
Pavel Shilovsky579f9052012-09-19 06:22:44 -07002921 struct cifsInodeInfo *cinode = CIFS_I(inode);
2922 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
2923 struct cifsFileInfo *cfile = (struct cifsFileInfo *)
2924 iocb->ki_filp->private_data;
2925 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
2926 int rc = -EACCES;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002927
2928 /*
2929 * In strict cache mode we need to read from the server all the time
2930 * if we don't have level II oplock because the server can delay mtime
2931 * change - so we can't make a decision about inode invalidating.
2932 * And we can also fail with pagereading if there are mandatory locks
2933 * on pages affected by this read but not on the region from pos to
2934 * pos+len-1.
2935 */
Pavel Shilovsky579f9052012-09-19 06:22:44 -07002936 if (!cinode->clientCanCacheRead)
2937 return cifs_user_readv(iocb, iov, nr_segs, pos);
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002938
Pavel Shilovsky579f9052012-09-19 06:22:44 -07002939 if (cap_unix(tcon->ses) &&
2940 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
2941 ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
2942 return generic_file_aio_read(iocb, iov, nr_segs, pos);
2943
2944 /*
2945 * We need to hold the sem to be sure nobody modifies lock list
2946 * with a brlock that prevents reading.
2947 */
2948 down_read(&cinode->lock_sem);
2949 if (!cifs_find_lock_conflict(cfile, pos, iov_length(iov, nr_segs),
2950 tcon->ses->server->vals->shared_lock_type,
Pavel Shilovsky081c0412012-11-27 18:38:53 +04002951 NULL, CIFS_READ_OP))
Pavel Shilovsky579f9052012-09-19 06:22:44 -07002952 rc = generic_file_aio_read(iocb, iov, nr_segs, pos);
2953 up_read(&cinode->lock_sem);
2954 return rc;
Pavel Shilovskya70307e2010-12-14 11:50:41 +03002955}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07002957static ssize_t
2958cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959{
2960 int rc = -EACCES;
2961 unsigned int bytes_read = 0;
2962 unsigned int total_read;
2963 unsigned int current_read_size;
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002964 unsigned int rsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965 struct cifs_sb_info *cifs_sb;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04002966 struct cifs_tcon *tcon;
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07002967 struct TCP_Server_Info *server;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002968 unsigned int xid;
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07002969 char *cur_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970 struct cifsFileInfo *open_file;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002971 struct cifs_io_parms io_parms;
Steve Frenchec637e32005-12-12 20:53:18 -08002972 int buf_type = CIFS_NO_BUFFER;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002973 __u32 pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002975 xid = get_xid();
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -08002976 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002978 /* FIXME: set up handlers for larger reads and/or convert to async */
2979 rsize = min_t(unsigned int, cifs_sb->rsize, CIFSMaxBufSize);
2980
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302982 rc = -EBADF;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002983 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302984 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 }
Joe Perchesc21dfb62010-07-12 13:50:14 -07002986 open_file = file->private_data;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04002987 tcon = tlink_tcon(open_file->tlink);
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07002988 server = tcon->ses->server;
2989
2990 if (!server->ops->sync_read) {
2991 free_xid(xid);
2992 return -ENOSYS;
2993 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002995 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
2996 pid = open_file->pid;
2997 else
2998 pid = current->tgid;
2999
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
Joe Perchesf96637b2013-05-04 22:12:25 -05003001 cifs_dbg(FYI, "attempting read on write only file instance\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07003003 for (total_read = 0, cur_offset = read_data; read_size > total_read;
3004 total_read += bytes_read, cur_offset += bytes_read) {
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003005 current_read_size = min_t(uint, read_size - total_read, rsize);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003006 /*
3007 * For windows me and 9x we do not want to request more than it
3008 * negotiated since it will refuse the read then.
3009 */
3010 if ((tcon->ses) && !(tcon->ses->capabilities &
3011 tcon->ses->server->vals->cap_large_files)) {
Dan Carpenter7748dd62011-10-18 12:41:35 +03003012 current_read_size = min_t(uint, current_read_size,
Jeff Laytonc974bef2011-10-11 06:41:32 -04003013 CIFSMaxBufSize);
Steve Frenchf9f5c8172005-09-15 23:06:38 -07003014 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 rc = -EAGAIN;
3016 while (rc == -EAGAIN) {
Steve Frenchcdff08e2010-10-21 22:46:14 +00003017 if (open_file->invalidHandle) {
Jeff Layton15886172010-10-15 15:33:59 -04003018 rc = cifs_reopen_file(open_file, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019 if (rc != 0)
3020 break;
3021 }
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003022 io_parms.pid = pid;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003023 io_parms.tcon = tcon;
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07003024 io_parms.offset = *offset;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003025 io_parms.length = current_read_size;
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07003026 rc = server->ops->sync_read(xid, open_file, &io_parms,
3027 &bytes_read, &cur_offset,
3028 &buf_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 }
3030 if (rc || (bytes_read == 0)) {
3031 if (total_read) {
3032 break;
3033 } else {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003034 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 return rc;
3036 }
3037 } else {
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003038 cifs_stats_bytes_read(tcon, total_read);
Pavel Shilovskyf9c6e232012-09-18 16:20:29 -07003039 *offset += bytes_read;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040 }
3041 }
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003042 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043 return total_read;
3044}
3045
Jeff Laytonca83ce32011-04-12 09:13:44 -04003046/*
3047 * If the page is mmap'ed into a process' page tables, then we need to make
3048 * sure that it doesn't change while being written back.
3049 */
3050static int
3051cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
3052{
3053 struct page *page = vmf->page;
3054
3055 lock_page(page);
3056 return VM_FAULT_LOCKED;
3057}
3058
3059static struct vm_operations_struct cifs_file_vm_ops = {
3060 .fault = filemap_fault,
3061 .page_mkwrite = cifs_page_mkwrite,
Konstantin Khlebnikov0b173bc2012-10-08 16:28:46 -07003062 .remap_pages = generic_file_remap_pages,
Jeff Laytonca83ce32011-04-12 09:13:44 -04003063};
3064
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03003065int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
3066{
3067 int rc, xid;
Al Viro496ad9a2013-01-23 17:07:38 -05003068 struct inode *inode = file_inode(file);
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03003069
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003070 xid = get_xid();
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03003071
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04003072 if (!CIFS_I(inode)->clientCanCacheRead) {
3073 rc = cifs_invalidate_mapping(inode);
3074 if (rc)
3075 return rc;
3076 }
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03003077
3078 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04003079 if (rc == 0)
3080 vma->vm_ops = &cifs_file_vm_ops;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003081 free_xid(xid);
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +03003082 return rc;
3083}
3084
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
3086{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087 int rc, xid;
3088
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003089 xid = get_xid();
Jeff Laytonabab0952010-02-12 07:44:18 -05003090 rc = cifs_revalidate_file(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003092 cifs_dbg(FYI, "Validation prior to mmap failed, error=%d\n",
3093 rc);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003094 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095 return rc;
3096 }
3097 rc = generic_file_mmap(file, vma);
Jeff Laytonca83ce32011-04-12 09:13:44 -04003098 if (rc == 0)
3099 vma->vm_ops = &cifs_file_vm_ops;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003100 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101 return rc;
3102}
3103
Jeff Layton0471ca32012-05-16 07:13:16 -04003104static void
3105cifs_readv_complete(struct work_struct *work)
3106{
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003107 unsigned int i;
Jeff Layton0471ca32012-05-16 07:13:16 -04003108 struct cifs_readdata *rdata = container_of(work,
3109 struct cifs_readdata, work);
Jeff Layton0471ca32012-05-16 07:13:16 -04003110
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003111 for (i = 0; i < rdata->nr_pages; i++) {
3112 struct page *page = rdata->pages[i];
3113
Jeff Layton0471ca32012-05-16 07:13:16 -04003114 lru_cache_add_file(page);
3115
3116 if (rdata->result == 0) {
Jeff Layton0471ca32012-05-16 07:13:16 -04003117 flush_dcache_page(page);
3118 SetPageUptodate(page);
3119 }
3120
3121 unlock_page(page);
3122
3123 if (rdata->result == 0)
3124 cifs_readpage_to_fscache(rdata->mapping->host, page);
3125
3126 page_cache_release(page);
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003127 rdata->pages[i] = NULL;
Jeff Layton0471ca32012-05-16 07:13:16 -04003128 }
Jeff Layton6993f742012-05-16 07:13:17 -04003129 kref_put(&rdata->refcount, cifs_readdata_release);
Jeff Layton0471ca32012-05-16 07:13:16 -04003130}
3131
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003132static int
Jeff Layton8321fec2012-09-19 06:22:32 -07003133cifs_readpages_read_into_pages(struct TCP_Server_Info *server,
3134 struct cifs_readdata *rdata, unsigned int len)
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003135{
Jeff Layton8321fec2012-09-19 06:22:32 -07003136 int total_read = 0, result = 0;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003137 unsigned int i;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003138 u64 eof;
3139 pgoff_t eof_index;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003140 unsigned int nr_pages = rdata->nr_pages;
Jeff Layton8321fec2012-09-19 06:22:32 -07003141 struct kvec iov;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003142
3143 /* determine the eof that the server (probably) has */
3144 eof = CIFS_I(rdata->mapping->host)->server_eof;
3145 eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05003146 cifs_dbg(FYI, "eof=%llu eof_index=%lu\n", eof, eof_index);
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003147
Jeff Layton8321fec2012-09-19 06:22:32 -07003148 rdata->tailsz = PAGE_CACHE_SIZE;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003149 for (i = 0; i < nr_pages; i++) {
3150 struct page *page = rdata->pages[i];
3151
Jeff Layton8321fec2012-09-19 06:22:32 -07003152 if (len >= PAGE_CACHE_SIZE) {
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003153 /* enough data to fill the page */
Jeff Layton8321fec2012-09-19 06:22:32 -07003154 iov.iov_base = kmap(page);
3155 iov.iov_len = PAGE_CACHE_SIZE;
Joe Perchesf96637b2013-05-04 22:12:25 -05003156 cifs_dbg(FYI, "%u: idx=%lu iov_base=%p iov_len=%zu\n",
3157 i, page->index, iov.iov_base, iov.iov_len);
Jeff Layton8321fec2012-09-19 06:22:32 -07003158 len -= PAGE_CACHE_SIZE;
3159 } else if (len > 0) {
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003160 /* enough for partial page, fill and zero the rest */
Jeff Layton8321fec2012-09-19 06:22:32 -07003161 iov.iov_base = kmap(page);
3162 iov.iov_len = len;
Joe Perchesf96637b2013-05-04 22:12:25 -05003163 cifs_dbg(FYI, "%u: idx=%lu iov_base=%p iov_len=%zu\n",
3164 i, page->index, iov.iov_base, iov.iov_len);
Jeff Layton8321fec2012-09-19 06:22:32 -07003165 memset(iov.iov_base + len,
3166 '\0', PAGE_CACHE_SIZE - len);
3167 rdata->tailsz = len;
3168 len = 0;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003169 } else if (page->index > eof_index) {
3170 /*
3171 * The VFS will not try to do readahead past the
3172 * i_size, but it's possible that we have outstanding
3173 * writes with gaps in the middle and the i_size hasn't
3174 * caught up yet. Populate those with zeroed out pages
3175 * to prevent the VFS from repeatedly attempting to
3176 * fill them until the writes are flushed.
3177 */
3178 zero_user(page, 0, PAGE_CACHE_SIZE);
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003179 lru_cache_add_file(page);
3180 flush_dcache_page(page);
3181 SetPageUptodate(page);
3182 unlock_page(page);
3183 page_cache_release(page);
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003184 rdata->pages[i] = NULL;
3185 rdata->nr_pages--;
Jeff Layton8321fec2012-09-19 06:22:32 -07003186 continue;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003187 } else {
3188 /* no need to hold page hostage */
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003189 lru_cache_add_file(page);
3190 unlock_page(page);
3191 page_cache_release(page);
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003192 rdata->pages[i] = NULL;
3193 rdata->nr_pages--;
Jeff Layton8321fec2012-09-19 06:22:32 -07003194 continue;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003195 }
Jeff Layton8321fec2012-09-19 06:22:32 -07003196
3197 result = cifs_readv_from_socket(server, &iov, 1, iov.iov_len);
3198 kunmap(page);
3199 if (result < 0)
3200 break;
3201
3202 total_read += result;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003203 }
3204
Jeff Layton8321fec2012-09-19 06:22:32 -07003205 return total_read > 0 ? total_read : result;
Jeff Layton8d5ce4d2012-05-16 07:13:16 -04003206}
3207
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208static int cifs_readpages(struct file *file, struct address_space *mapping,
3209 struct list_head *page_list, unsigned num_pages)
3210{
Jeff Layton690c5e32011-10-19 15:30:16 -04003211 int rc;
3212 struct list_head tmplist;
3213 struct cifsFileInfo *open_file = file->private_data;
3214 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
3215 unsigned int rsize = cifs_sb->rsize;
3216 pid_t pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217
Jeff Layton690c5e32011-10-19 15:30:16 -04003218 /*
3219 * Give up immediately if rsize is too small to read an entire page.
3220 * The VFS will fall back to readpage. We should never reach this
3221 * point however since we set ra_pages to 0 when the rsize is smaller
3222 * than a cache page.
3223 */
3224 if (unlikely(rsize < PAGE_CACHE_SIZE))
3225 return 0;
Steve Frenchbfa0d752005-08-31 21:50:37 -07003226
Suresh Jayaraman56698232010-07-05 18:13:25 +05303227 /*
3228 * Reads as many pages as possible from fscache. Returns -ENOBUFS
3229 * immediately if the cookie is negative
3230 */
3231 rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
3232 &num_pages);
3233 if (rc == 0)
Jeff Layton690c5e32011-10-19 15:30:16 -04003234 return rc;
Suresh Jayaraman56698232010-07-05 18:13:25 +05303235
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003236 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
3237 pid = open_file->pid;
3238 else
3239 pid = current->tgid;
3240
Jeff Layton690c5e32011-10-19 15:30:16 -04003241 rc = 0;
3242 INIT_LIST_HEAD(&tmplist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243
Joe Perchesf96637b2013-05-04 22:12:25 -05003244 cifs_dbg(FYI, "%s: file=%p mapping=%p num_pages=%u\n",
3245 __func__, file, mapping, num_pages);
Jeff Layton690c5e32011-10-19 15:30:16 -04003246
3247 /*
3248 * Start with the page at end of list and move it to private
3249 * list. Do the same with any following pages until we hit
3250 * the rsize limit, hit an index discontinuity, or run out of
3251 * pages. Issue the async read and then start the loop again
3252 * until the list is empty.
3253 *
3254 * Note that list order is important. The page_list is in
3255 * the order of declining indexes. When we put the pages in
3256 * the rdata->pages, then we want them in increasing order.
3257 */
3258 while (!list_empty(page_list)) {
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003259 unsigned int i;
Jeff Layton690c5e32011-10-19 15:30:16 -04003260 unsigned int bytes = PAGE_CACHE_SIZE;
3261 unsigned int expected_index;
3262 unsigned int nr_pages = 1;
3263 loff_t offset;
3264 struct page *page, *tpage;
3265 struct cifs_readdata *rdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003266
3267 page = list_entry(page_list->prev, struct page, lru);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268
Jeff Layton690c5e32011-10-19 15:30:16 -04003269 /*
3270 * Lock the page and put it in the cache. Since no one else
3271 * should have access to this page, we're safe to simply set
3272 * PG_locked without checking it first.
3273 */
3274 __set_page_locked(page);
3275 rc = add_to_page_cache_locked(page, mapping,
3276 page->index, GFP_KERNEL);
3277
3278 /* give up if we can't stick it in the cache */
3279 if (rc) {
3280 __clear_page_locked(page);
3281 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283
Jeff Layton690c5e32011-10-19 15:30:16 -04003284 /* move first page to the tmplist */
3285 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
3286 list_move_tail(&page->lru, &tmplist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287
Jeff Layton690c5e32011-10-19 15:30:16 -04003288 /* now try and add more pages onto the request */
3289 expected_index = page->index + 1;
3290 list_for_each_entry_safe_reverse(page, tpage, page_list, lru) {
3291 /* discontinuity ? */
3292 if (page->index != expected_index)
3293 break;
3294
3295 /* would this page push the read over the rsize? */
3296 if (bytes + PAGE_CACHE_SIZE > rsize)
3297 break;
3298
3299 __set_page_locked(page);
3300 if (add_to_page_cache_locked(page, mapping,
3301 page->index, GFP_KERNEL)) {
3302 __clear_page_locked(page);
3303 break;
3304 }
3305 list_move_tail(&page->lru, &tmplist);
3306 bytes += PAGE_CACHE_SIZE;
3307 expected_index++;
3308 nr_pages++;
3309 }
3310
Jeff Layton0471ca32012-05-16 07:13:16 -04003311 rdata = cifs_readdata_alloc(nr_pages, cifs_readv_complete);
Jeff Layton690c5e32011-10-19 15:30:16 -04003312 if (!rdata) {
3313 /* best to give up if we're out of mem */
3314 list_for_each_entry_safe(page, tpage, &tmplist, lru) {
3315 list_del(&page->lru);
3316 lru_cache_add_file(page);
3317 unlock_page(page);
3318 page_cache_release(page);
3319 }
3320 rc = -ENOMEM;
3321 break;
3322 }
3323
Jeff Layton6993f742012-05-16 07:13:17 -04003324 rdata->cfile = cifsFileInfo_get(open_file);
Jeff Layton690c5e32011-10-19 15:30:16 -04003325 rdata->mapping = mapping;
3326 rdata->offset = offset;
3327 rdata->bytes = bytes;
3328 rdata->pid = pid;
Jeff Layton8321fec2012-09-19 06:22:32 -07003329 rdata->pagesz = PAGE_CACHE_SIZE;
3330 rdata->read_into_pages = cifs_readpages_read_into_pages;
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003331
3332 list_for_each_entry_safe(page, tpage, &tmplist, lru) {
3333 list_del(&page->lru);
3334 rdata->pages[rdata->nr_pages++] = page;
3335 }
Jeff Layton690c5e32011-10-19 15:30:16 -04003336
Jeff Layton2a1bb132012-05-16 07:13:17 -04003337 rc = cifs_retry_async_readv(rdata);
Jeff Layton690c5e32011-10-19 15:30:16 -04003338 if (rc != 0) {
Jeff Laytonc5fab6f2012-09-19 06:22:30 -07003339 for (i = 0; i < rdata->nr_pages; i++) {
3340 page = rdata->pages[i];
Jeff Layton690c5e32011-10-19 15:30:16 -04003341 lru_cache_add_file(page);
3342 unlock_page(page);
3343 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344 }
Jeff Layton6993f742012-05-16 07:13:17 -04003345 kref_put(&rdata->refcount, cifs_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346 break;
3347 }
Jeff Layton6993f742012-05-16 07:13:17 -04003348
3349 kref_put(&rdata->refcount, cifs_readdata_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350 }
3351
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352 return rc;
3353}
3354
3355static int cifs_readpage_worker(struct file *file, struct page *page,
3356 loff_t *poffset)
3357{
3358 char *read_data;
3359 int rc;
3360
Suresh Jayaraman56698232010-07-05 18:13:25 +05303361 /* Is the page cached? */
Al Viro496ad9a2013-01-23 17:07:38 -05003362 rc = cifs_readpage_from_fscache(file_inode(file), page);
Suresh Jayaraman56698232010-07-05 18:13:25 +05303363 if (rc == 0)
3364 goto read_complete;
3365
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366 page_cache_get(page);
3367 read_data = kmap(page);
3368 /* for reads over a certain size could initiate async read ahead */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003369
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003371
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372 if (rc < 0)
3373 goto io_error;
3374 else
Joe Perchesf96637b2013-05-04 22:12:25 -05003375 cifs_dbg(FYI, "Bytes read %d\n", rc);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003376
Al Viro496ad9a2013-01-23 17:07:38 -05003377 file_inode(file)->i_atime =
3378 current_fs_time(file_inode(file)->i_sb);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003379
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380 if (PAGE_CACHE_SIZE > rc)
3381 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
3382
3383 flush_dcache_page(page);
3384 SetPageUptodate(page);
Suresh Jayaraman9dc06552010-07-05 18:13:11 +05303385
3386 /* send this page to the cache */
Al Viro496ad9a2013-01-23 17:07:38 -05003387 cifs_readpage_to_fscache(file_inode(file), page);
Suresh Jayaraman9dc06552010-07-05 18:13:11 +05303388
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389 rc = 0;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003390
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391io_error:
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003392 kunmap(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393 page_cache_release(page);
Suresh Jayaraman56698232010-07-05 18:13:25 +05303394
3395read_complete:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396 return rc;
3397}
3398
3399static int cifs_readpage(struct file *file, struct page *page)
3400{
3401 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
3402 int rc = -EACCES;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003403 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003405 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406
3407 if (file->private_data == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05303408 rc = -EBADF;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003409 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05303410 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411 }
3412
Joe Perchesf96637b2013-05-04 22:12:25 -05003413 cifs_dbg(FYI, "readpage %p at offset %d 0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003414 page, (int)offset, (int)offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415
3416 rc = cifs_readpage_worker(file, page, &offset);
3417
3418 unlock_page(page);
3419
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003420 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421 return rc;
3422}
3423
Steve Frencha403a0a2007-07-26 15:54:16 +00003424static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
3425{
3426 struct cifsFileInfo *open_file;
3427
Jeff Layton44772882010-10-15 15:34:03 -04003428 spin_lock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003429 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
Jeff Layton2e396b82010-10-15 15:34:01 -04003430 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
Jeff Layton44772882010-10-15 15:34:03 -04003431 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003432 return 1;
3433 }
3434 }
Jeff Layton44772882010-10-15 15:34:03 -04003435 spin_unlock(&cifs_file_list_lock);
Steve Frencha403a0a2007-07-26 15:54:16 +00003436 return 0;
3437}
3438
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439/* We do not want to update the file size from server for inodes
3440 open for write - to avoid races with writepage extending
3441 the file - in the future we could consider allowing
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003442 refreshing the inode only on increases in the file size
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443 but this is tricky to do without racing with writebehind
3444 page caching in the current Linux kernel design */
Steve French4b18f2a2008-04-29 00:06:05 +00003445bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446{
Steve Frencha403a0a2007-07-26 15:54:16 +00003447 if (!cifsInode)
Steve French4b18f2a2008-04-29 00:06:05 +00003448 return true;
Steve French23e7dd72005-10-20 13:44:56 -07003449
Steve Frencha403a0a2007-07-26 15:54:16 +00003450 if (is_inode_writable(cifsInode)) {
3451 /* This inode is open for write at least once */
Steve Frenchc32a0b62006-01-12 14:41:28 -08003452 struct cifs_sb_info *cifs_sb;
3453
Steve Frenchc32a0b62006-01-12 14:41:28 -08003454 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
Steve Frenchad7a2922008-02-07 23:25:02 +00003455 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003456 /* since no page cache to corrupt on directio
Steve Frenchc32a0b62006-01-12 14:41:28 -08003457 we can change size safely */
Steve French4b18f2a2008-04-29 00:06:05 +00003458 return true;
Steve Frenchc32a0b62006-01-12 14:41:28 -08003459 }
3460
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003461 if (i_size_read(&cifsInode->vfs_inode) < end_of_file)
Steve French4b18f2a2008-04-29 00:06:05 +00003462 return true;
Steve French7ba52632007-02-08 18:14:13 +00003463
Steve French4b18f2a2008-04-29 00:06:05 +00003464 return false;
Steve French23e7dd72005-10-20 13:44:56 -07003465 } else
Steve French4b18f2a2008-04-29 00:06:05 +00003466 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467}
3468
Nick Piggind9414772008-09-24 11:32:59 -04003469static int cifs_write_begin(struct file *file, struct address_space *mapping,
3470 loff_t pos, unsigned len, unsigned flags,
3471 struct page **pagep, void **fsdata)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472{
Nick Piggind9414772008-09-24 11:32:59 -04003473 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
3474 loff_t offset = pos & (PAGE_CACHE_SIZE - 1);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003475 loff_t page_start = pos & PAGE_MASK;
3476 loff_t i_size;
3477 struct page *page;
3478 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479
Joe Perchesf96637b2013-05-04 22:12:25 -05003480 cifs_dbg(FYI, "write_begin from %lld len %d\n", (long long)pos, len);
Nick Piggind9414772008-09-24 11:32:59 -04003481
Nick Piggin54566b22009-01-04 12:00:53 -08003482 page = grab_cache_page_write_begin(mapping, index, flags);
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003483 if (!page) {
3484 rc = -ENOMEM;
3485 goto out;
3486 }
Nick Piggind9414772008-09-24 11:32:59 -04003487
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003488 if (PageUptodate(page))
3489 goto out;
Steve French8a236262007-03-06 00:31:00 +00003490
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003491 /*
3492 * If we write a full page it will be up to date, no need to read from
3493 * the server. If the write is short, we'll end up doing a sync write
3494 * instead.
3495 */
3496 if (len == PAGE_CACHE_SIZE)
3497 goto out;
3498
3499 /*
3500 * optimize away the read when we have an oplock, and we're not
3501 * expecting to use any of the data we'd be reading in. That
3502 * is, when the page lies beyond the EOF, or straddles the EOF
3503 * and the write will cover all of the existing data.
3504 */
3505 if (CIFS_I(mapping->host)->clientCanCacheRead) {
3506 i_size = i_size_read(mapping->host);
3507 if (page_start >= i_size ||
3508 (offset == 0 && (pos + len) >= i_size)) {
3509 zero_user_segments(page, 0, offset,
3510 offset + len,
3511 PAGE_CACHE_SIZE);
3512 /*
3513 * PageChecked means that the parts of the page
3514 * to which we're not writing are considered up
3515 * to date. Once the data is copied to the
3516 * page, it can be set uptodate.
3517 */
3518 SetPageChecked(page);
3519 goto out;
3520 }
3521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522
Nick Piggind9414772008-09-24 11:32:59 -04003523 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003524 /*
3525 * might as well read a page, it is fast enough. If we get
3526 * an error, we don't need to return it. cifs_write_end will
3527 * do a sync write instead since PG_uptodate isn't set.
3528 */
3529 cifs_readpage_worker(file, page, &page_start);
Steve French8a236262007-03-06 00:31:00 +00003530 } else {
3531 /* we could try using another file handle if there is one -
3532 but how would we lock it to prevent close of that handle
3533 racing with this read? In any case
Nick Piggind9414772008-09-24 11:32:59 -04003534 this will be written out by write_end so is fine */
Steve French8a236262007-03-06 00:31:00 +00003535 }
Jeff Laytona98ee8c2008-11-26 19:32:33 +00003536out:
3537 *pagep = page;
3538 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539}
3540
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303541static int cifs_release_page(struct page *page, gfp_t gfp)
3542{
3543 if (PagePrivate(page))
3544 return 0;
3545
3546 return cifs_fscache_release_page(page, gfp);
3547}
3548
Lukas Czernerd47992f2013-05-21 23:17:23 -04003549static void cifs_invalidate_page(struct page *page, unsigned int offset,
3550 unsigned int length)
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303551{
3552 struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
3553
Lukas Czernerd47992f2013-05-21 23:17:23 -04003554 if (offset == 0 && length == PAGE_CACHE_SIZE)
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303555 cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
3556}
3557
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003558static int cifs_launder_page(struct page *page)
3559{
3560 int rc = 0;
3561 loff_t range_start = page_offset(page);
3562 loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
3563 struct writeback_control wbc = {
3564 .sync_mode = WB_SYNC_ALL,
3565 .nr_to_write = 0,
3566 .range_start = range_start,
3567 .range_end = range_end,
3568 };
3569
Joe Perchesf96637b2013-05-04 22:12:25 -05003570 cifs_dbg(FYI, "Launder page: %p\n", page);
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003571
3572 if (clear_page_dirty_for_io(page))
3573 rc = cifs_writepage_locked(page, &wbc);
3574
3575 cifs_fscache_invalidate_page(page, page->mapping->host);
3576 return rc;
3577}
3578
Tejun Heo9b646972010-07-20 22:09:02 +02003579void cifs_oplock_break(struct work_struct *work)
Jeff Layton3bc303c2009-09-21 06:47:50 -04003580{
3581 struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
3582 oplock_break);
Jeff Laytona5e18bc2010-10-11 15:07:18 -04003583 struct inode *inode = cfile->dentry->d_inode;
Jeff Layton3bc303c2009-09-21 06:47:50 -04003584 struct cifsInodeInfo *cinode = CIFS_I(inode);
Pavel Shilovsky95a3f2f2012-09-18 16:20:33 -07003585 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04003586 int rc = 0;
Jeff Layton3bc303c2009-09-21 06:47:50 -04003587
Pavel Shilovsky63b7d3a2012-12-24 14:41:19 +04003588 if (!cinode->clientCanCacheAll && cinode->clientCanCacheRead &&
3589 cifs_has_mand_locks(cinode)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003590 cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand locks\n",
3591 inode);
Pavel Shilovsky63b7d3a2012-12-24 14:41:19 +04003592 cinode->clientCanCacheRead = false;
3593 }
3594
Jeff Layton3bc303c2009-09-21 06:47:50 -04003595 if (inode && S_ISREG(inode->i_mode)) {
Steve Frenchd54ff732010-04-27 04:38:15 +00003596 if (cinode->clientCanCacheRead)
Al Viro8737c932009-12-24 06:47:55 -05003597 break_lease(inode, O_RDONLY);
Steve Frenchd54ff732010-04-27 04:38:15 +00003598 else
Al Viro8737c932009-12-24 06:47:55 -05003599 break_lease(inode, O_WRONLY);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003600 rc = filemap_fdatawrite(inode->i_mapping);
3601 if (cinode->clientCanCacheRead == 0) {
Jeff Laytoneb4b7562010-10-22 14:52:29 -04003602 rc = filemap_fdatawait(inode->i_mapping);
3603 mapping_set_error(inode->i_mapping, rc);
Pavel Shilovsky03eca702012-12-06 21:24:33 +04003604 cifs_invalidate_mapping(inode);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003605 }
Joe Perchesf96637b2013-05-04 22:12:25 -05003606 cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003607 }
3608
Pavel Shilovsky85160e02011-10-22 15:33:29 +04003609 rc = cifs_push_locks(cfile);
3610 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003611 cifs_dbg(VFS, "Push locks rc = %d\n", rc);
Pavel Shilovsky85160e02011-10-22 15:33:29 +04003612
Jeff Layton3bc303c2009-09-21 06:47:50 -04003613 /*
3614 * releasing stale oplock after recent reconnect of smb session using
3615 * a now incorrect file handle is not a data integrity issue but do
3616 * not bother sending an oplock release if session to server still is
3617 * disconnected since oplock already released by the server
3618 */
Steve Frenchcdff08e2010-10-21 22:46:14 +00003619 if (!cfile->oplock_break_cancelled) {
Pavel Shilovsky95a3f2f2012-09-18 16:20:33 -07003620 rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
3621 cinode);
Joe Perchesf96637b2013-05-04 22:12:25 -05003622 cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
Jeff Layton3bc303c2009-09-21 06:47:50 -04003623 }
Jeff Layton3bc303c2009-09-21 06:47:50 -04003624}
3625
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07003626const struct address_space_operations cifs_addr_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627 .readpage = cifs_readpage,
3628 .readpages = cifs_readpages,
3629 .writepage = cifs_writepage,
Steve French37c0eb42005-10-05 14:50:29 -07003630 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04003631 .write_begin = cifs_write_begin,
3632 .write_end = cifs_write_end,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303634 .releasepage = cifs_release_page,
3635 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003636 .launder_page = cifs_launder_page,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637};
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003638
3639/*
3640 * cifs_readpages requires the server to support a buffer large enough to
3641 * contain the header plus one complete page of data. Otherwise, we need
3642 * to leave cifs_readpages out of the address space operations.
3643 */
Christoph Hellwigf5e54d62006-06-28 04:26:44 -07003644const struct address_space_operations cifs_addr_ops_smallbuf = {
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003645 .readpage = cifs_readpage,
3646 .writepage = cifs_writepage,
3647 .writepages = cifs_writepages,
Nick Piggind9414772008-09-24 11:32:59 -04003648 .write_begin = cifs_write_begin,
3649 .write_end = cifs_write_end,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003650 .set_page_dirty = __set_page_dirty_nobuffers,
Suresh Jayaraman85f2d6b2010-07-05 18:13:00 +05303651 .releasepage = cifs_release_page,
3652 .invalidatepage = cifs_invalidate_page,
Pavel Shilovsky9ad15062011-04-08 05:29:10 +04003653 .launder_page = cifs_launder_page,
Dave Kleikamp273d81d2006-06-01 19:41:23 +00003654};