diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 1055 |
1 files changed, 615 insertions, 440 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 71e9ad9f5961..7d7bbdc4c8e7 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -169,16 +169,20 @@ posix_open_ret: | |||
169 | 169 | ||
170 | static int | 170 | static int |
171 | cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, | 171 | cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, |
172 | struct cifs_tcon *tcon, unsigned int f_flags, __u32 *poplock, | 172 | struct cifs_tcon *tcon, unsigned int f_flags, __u32 *oplock, |
173 | __u16 *pnetfid, unsigned int xid) | 173 | struct cifs_fid *fid, unsigned int xid) |
174 | { | 174 | { |
175 | int rc; | 175 | int rc; |
176 | int desiredAccess; | 176 | int desired_access; |
177 | int disposition; | 177 | int disposition; |
178 | int create_options = CREATE_NOT_DIR; | 178 | int create_options = CREATE_NOT_DIR; |
179 | FILE_ALL_INFO *buf; | 179 | FILE_ALL_INFO *buf; |
180 | struct TCP_Server_Info *server = tcon->ses->server; | ||
181 | |||
182 | if (!server->ops->open) | ||
183 | return -ENOSYS; | ||
180 | 184 | ||
181 | desiredAccess = cifs_convert_flags(f_flags); | 185 | desired_access = cifs_convert_flags(f_flags); |
182 | 186 | ||
183 | /********************************************************************* | 187 | /********************************************************************* |
184 | * open flag mapping table: | 188 | * open flag mapping table: |
@@ -215,16 +219,9 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, | |||
215 | if (backup_cred(cifs_sb)) | 219 | if (backup_cred(cifs_sb)) |
216 | create_options |= CREATE_OPEN_BACKUP_INTENT; | 220 | create_options |= CREATE_OPEN_BACKUP_INTENT; |
217 | 221 | ||
218 | if (tcon->ses->capabilities & CAP_NT_SMBS) | 222 | rc = server->ops->open(xid, tcon, full_path, disposition, |
219 | rc = CIFSSMBOpen(xid, tcon, full_path, disposition, | 223 | desired_access, create_options, fid, oplock, buf, |
220 | desiredAccess, create_options, pnetfid, poplock, buf, | 224 | cifs_sb); |
221 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags | ||
222 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
223 | else | ||
224 | rc = SMBLegacyOpen(xid, tcon, full_path, disposition, | ||
225 | desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf, | ||
226 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags | ||
227 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
228 | 225 | ||
229 | if (rc) | 226 | if (rc) |
230 | goto out; | 227 | goto out; |
@@ -234,7 +231,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, | |||
234 | xid); | 231 | xid); |
235 | else | 232 | else |
236 | rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, | 233 | rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, |
237 | xid, pnetfid); | 234 | xid, &fid->netfid); |
238 | 235 | ||
239 | out: | 236 | out: |
240 | kfree(buf); | 237 | kfree(buf); |
@@ -242,48 +239,62 @@ out: | |||
242 | } | 239 | } |
243 | 240 | ||
244 | struct cifsFileInfo * | 241 | struct cifsFileInfo * |
245 | cifs_new_fileinfo(__u16 fileHandle, struct file *file, | 242 | cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, |
246 | struct tcon_link *tlink, __u32 oplock) | 243 | struct tcon_link *tlink, __u32 oplock) |
247 | { | 244 | { |
248 | struct dentry *dentry = file->f_path.dentry; | 245 | struct dentry *dentry = file->f_path.dentry; |
249 | struct inode *inode = dentry->d_inode; | 246 | struct inode *inode = dentry->d_inode; |
250 | struct cifsInodeInfo *pCifsInode = CIFS_I(inode); | 247 | struct cifsInodeInfo *cinode = CIFS_I(inode); |
251 | struct cifsFileInfo *pCifsFile; | 248 | struct cifsFileInfo *cfile; |
252 | 249 | struct cifs_fid_locks *fdlocks; | |
253 | pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); | 250 | struct cifs_tcon *tcon = tlink_tcon(tlink); |
254 | if (pCifsFile == NULL) | 251 | |
255 | return pCifsFile; | 252 | cfile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); |
256 | 253 | if (cfile == NULL) | |
257 | pCifsFile->count = 1; | 254 | return cfile; |
258 | pCifsFile->netfid = fileHandle; | 255 | |
259 | pCifsFile->pid = current->tgid; | 256 | fdlocks = kzalloc(sizeof(struct cifs_fid_locks), GFP_KERNEL); |
260 | pCifsFile->uid = current_fsuid(); | 257 | if (!fdlocks) { |
261 | pCifsFile->dentry = dget(dentry); | 258 | kfree(cfile); |
262 | pCifsFile->f_flags = file->f_flags; | 259 | return NULL; |
263 | pCifsFile->invalidHandle = false; | 260 | } |
264 | pCifsFile->tlink = cifs_get_tlink(tlink); | 261 | |
265 | mutex_init(&pCifsFile->fh_mutex); | 262 | INIT_LIST_HEAD(&fdlocks->locks); |
266 | INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break); | 263 | fdlocks->cfile = cfile; |
267 | INIT_LIST_HEAD(&pCifsFile->llist); | 264 | cfile->llist = fdlocks; |
265 | down_write(&cinode->lock_sem); | ||
266 | list_add(&fdlocks->llist, &cinode->llist); | ||
267 | up_write(&cinode->lock_sem); | ||
268 | |||
269 | cfile->count = 1; | ||
270 | cfile->pid = current->tgid; | ||
271 | cfile->uid = current_fsuid(); | ||
272 | cfile->dentry = dget(dentry); | ||
273 | cfile->f_flags = file->f_flags; | ||
274 | cfile->invalidHandle = false; | ||
275 | cfile->tlink = cifs_get_tlink(tlink); | ||
276 | INIT_WORK(&cfile->oplock_break, cifs_oplock_break); | ||
277 | mutex_init(&cfile->fh_mutex); | ||
268 | 278 | ||
269 | spin_lock(&cifs_file_list_lock); | 279 | spin_lock(&cifs_file_list_lock); |
270 | list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList)); | 280 | if (fid->pending_open->oplock != CIFS_OPLOCK_NO_CHANGE) |
281 | oplock = fid->pending_open->oplock; | ||
282 | list_del(&fid->pending_open->olist); | ||
283 | |||
284 | tlink_tcon(tlink)->ses->server->ops->set_fid(cfile, fid, oplock); | ||
285 | |||
286 | list_add(&cfile->tlist, &tcon->openFileList); | ||
271 | /* if readable file instance put first in list*/ | 287 | /* if readable file instance put first in list*/ |
272 | if (file->f_mode & FMODE_READ) | 288 | if (file->f_mode & FMODE_READ) |
273 | list_add(&pCifsFile->flist, &pCifsInode->openFileList); | 289 | list_add(&cfile->flist, &cinode->openFileList); |
274 | else | 290 | else |
275 | list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList); | 291 | list_add_tail(&cfile->flist, &cinode->openFileList); |
276 | spin_unlock(&cifs_file_list_lock); | 292 | spin_unlock(&cifs_file_list_lock); |
277 | 293 | ||
278 | cifs_set_oplock_level(pCifsInode, oplock); | 294 | file->private_data = cfile; |
279 | pCifsInode->can_cache_brlcks = pCifsInode->clientCanCacheAll; | 295 | return cfile; |
280 | |||
281 | file->private_data = pCifsFile; | ||
282 | return pCifsFile; | ||
283 | } | 296 | } |
284 | 297 | ||
285 | static void cifs_del_lock_waiters(struct cifsLockInfo *lock); | ||
286 | |||
287 | struct cifsFileInfo * | 298 | struct cifsFileInfo * |
288 | cifsFileInfo_get(struct cifsFileInfo *cifs_file) | 299 | cifsFileInfo_get(struct cifsFileInfo *cifs_file) |
289 | { | 300 | { |
@@ -302,9 +313,12 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
302 | { | 313 | { |
303 | struct inode *inode = cifs_file->dentry->d_inode; | 314 | struct inode *inode = cifs_file->dentry->d_inode; |
304 | struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink); | 315 | struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink); |
316 | struct TCP_Server_Info *server = tcon->ses->server; | ||
305 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | 317 | struct cifsInodeInfo *cifsi = CIFS_I(inode); |
306 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 318 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
307 | struct cifsLockInfo *li, *tmp; | 319 | struct cifsLockInfo *li, *tmp; |
320 | struct cifs_fid fid; | ||
321 | struct cifs_pending_open open; | ||
308 | 322 | ||
309 | spin_lock(&cifs_file_list_lock); | 323 | spin_lock(&cifs_file_list_lock); |
310 | if (--cifs_file->count > 0) { | 324 | if (--cifs_file->count > 0) { |
@@ -312,6 +326,12 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
312 | return; | 326 | return; |
313 | } | 327 | } |
314 | 328 | ||
329 | if (server->ops->get_lease_key) | ||
330 | server->ops->get_lease_key(inode, &fid); | ||
331 | |||
332 | /* store open in pending opens to make sure we don't miss lease break */ | ||
333 | cifs_add_pending_open_locked(&fid, cifs_file->tlink, &open); | ||
334 | |||
315 | /* remove it from the lists */ | 335 | /* remove it from the lists */ |
316 | list_del(&cifs_file->flist); | 336 | list_del(&cifs_file->flist); |
317 | list_del(&cifs_file->tlist); | 337 | list_del(&cifs_file->tlist); |
@@ -319,13 +339,13 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
319 | if (list_empty(&cifsi->openFileList)) { | 339 | if (list_empty(&cifsi->openFileList)) { |
320 | cFYI(1, "closing last open instance for inode %p", | 340 | cFYI(1, "closing last open instance for inode %p", |
321 | cifs_file->dentry->d_inode); | 341 | cifs_file->dentry->d_inode); |
322 | 342 | /* | |
323 | /* in strict cache mode we need invalidate mapping on the last | 343 | * In strict cache mode we need invalidate mapping on the last |
324 | close because it may cause a error when we open this file | 344 | * close because it may cause a error when we open this file |
325 | again and get at least level II oplock */ | 345 | * again and get at least level II oplock. |
346 | */ | ||
326 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) | 347 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) |
327 | CIFS_I(inode)->invalid_mapping = true; | 348 | CIFS_I(inode)->invalid_mapping = true; |
328 | |||
329 | cifs_set_oplock_level(cifsi, 0); | 349 | cifs_set_oplock_level(cifsi, 0); |
330 | } | 350 | } |
331 | spin_unlock(&cifs_file_list_lock); | 351 | spin_unlock(&cifs_file_list_lock); |
@@ -333,23 +353,30 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
333 | cancel_work_sync(&cifs_file->oplock_break); | 353 | cancel_work_sync(&cifs_file->oplock_break); |
334 | 354 | ||
335 | if (!tcon->need_reconnect && !cifs_file->invalidHandle) { | 355 | if (!tcon->need_reconnect && !cifs_file->invalidHandle) { |
356 | struct TCP_Server_Info *server = tcon->ses->server; | ||
336 | unsigned int xid; | 357 | unsigned int xid; |
337 | int rc; | 358 | |
338 | xid = get_xid(); | 359 | xid = get_xid(); |
339 | rc = CIFSSMBClose(xid, tcon, cifs_file->netfid); | 360 | if (server->ops->close) |
340 | free_xid(xid); | 361 | server->ops->close(xid, tcon, &cifs_file->fid); |
362 | _free_xid(xid); | ||
341 | } | 363 | } |
342 | 364 | ||
343 | /* Delete any outstanding lock records. We'll lose them when the file | 365 | cifs_del_pending_open(&open); |
366 | |||
367 | /* | ||
368 | * Delete any outstanding lock records. We'll lose them when the file | ||
344 | * is closed anyway. | 369 | * is closed anyway. |
345 | */ | 370 | */ |
346 | mutex_lock(&cifsi->lock_mutex); | 371 | down_write(&cifsi->lock_sem); |
347 | list_for_each_entry_safe(li, tmp, &cifs_file->llist, llist) { | 372 | list_for_each_entry_safe(li, tmp, &cifs_file->llist->locks, llist) { |
348 | list_del(&li->llist); | 373 | list_del(&li->llist); |
349 | cifs_del_lock_waiters(li); | 374 | cifs_del_lock_waiters(li); |
350 | kfree(li); | 375 | kfree(li); |
351 | } | 376 | } |
352 | mutex_unlock(&cifsi->lock_mutex); | 377 | list_del(&cifs_file->llist->llist); |
378 | kfree(cifs_file->llist); | ||
379 | up_write(&cifsi->lock_sem); | ||
353 | 380 | ||
354 | cifs_put_tlink(cifs_file->tlink); | 381 | cifs_put_tlink(cifs_file->tlink); |
355 | dput(cifs_file->dentry); | 382 | dput(cifs_file->dentry); |
@@ -357,17 +384,20 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
357 | } | 384 | } |
358 | 385 | ||
359 | int cifs_open(struct inode *inode, struct file *file) | 386 | int cifs_open(struct inode *inode, struct file *file) |
387 | |||
360 | { | 388 | { |
361 | int rc = -EACCES; | 389 | int rc = -EACCES; |
362 | unsigned int xid; | 390 | unsigned int xid; |
363 | __u32 oplock; | 391 | __u32 oplock; |
364 | struct cifs_sb_info *cifs_sb; | 392 | struct cifs_sb_info *cifs_sb; |
393 | struct TCP_Server_Info *server; | ||
365 | struct cifs_tcon *tcon; | 394 | struct cifs_tcon *tcon; |
366 | struct tcon_link *tlink; | 395 | struct tcon_link *tlink; |
367 | struct cifsFileInfo *pCifsFile = NULL; | 396 | struct cifsFileInfo *cfile = NULL; |
368 | char *full_path = NULL; | 397 | char *full_path = NULL; |
369 | bool posix_open_ok = false; | 398 | bool posix_open_ok = false; |
370 | __u16 netfid; | 399 | struct cifs_fid fid; |
400 | struct cifs_pending_open open; | ||
371 | 401 | ||
372 | xid = get_xid(); | 402 | xid = get_xid(); |
373 | 403 | ||
@@ -378,6 +408,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
378 | return PTR_ERR(tlink); | 408 | return PTR_ERR(tlink); |
379 | } | 409 | } |
380 | tcon = tlink_tcon(tlink); | 410 | tcon = tlink_tcon(tlink); |
411 | server = tcon->ses->server; | ||
381 | 412 | ||
382 | full_path = build_path_from_dentry(file->f_path.dentry); | 413 | full_path = build_path_from_dentry(file->f_path.dentry); |
383 | if (full_path == NULL) { | 414 | if (full_path == NULL) { |
@@ -388,7 +419,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
388 | cFYI(1, "inode = 0x%p file flags are 0x%x for %s", | 419 | cFYI(1, "inode = 0x%p file flags are 0x%x for %s", |
389 | inode, file->f_flags, full_path); | 420 | inode, file->f_flags, full_path); |
390 | 421 | ||
391 | if (tcon->ses->server->oplocks) | 422 | if (server->oplocks) |
392 | oplock = REQ_OPLOCK; | 423 | oplock = REQ_OPLOCK; |
393 | else | 424 | else |
394 | oplock = 0; | 425 | oplock = 0; |
@@ -399,7 +430,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
399 | /* can not refresh inode info since size could be stale */ | 430 | /* can not refresh inode info since size could be stale */ |
400 | rc = cifs_posix_open(full_path, &inode, inode->i_sb, | 431 | rc = cifs_posix_open(full_path, &inode, inode->i_sb, |
401 | cifs_sb->mnt_file_mode /* ignored */, | 432 | cifs_sb->mnt_file_mode /* ignored */, |
402 | file->f_flags, &oplock, &netfid, xid); | 433 | file->f_flags, &oplock, &fid.netfid, xid); |
403 | if (rc == 0) { | 434 | if (rc == 0) { |
404 | cFYI(1, "posix open succeeded"); | 435 | cFYI(1, "posix open succeeded"); |
405 | posix_open_ok = true; | 436 | posix_open_ok = true; |
@@ -415,20 +446,34 @@ int cifs_open(struct inode *inode, struct file *file) | |||
415 | } else if ((rc != -EIO) && (rc != -EREMOTE) && | 446 | } else if ((rc != -EIO) && (rc != -EREMOTE) && |
416 | (rc != -EOPNOTSUPP)) /* path not found or net err */ | 447 | (rc != -EOPNOTSUPP)) /* path not found or net err */ |
417 | goto out; | 448 | goto out; |
418 | /* else fallthrough to retry open the old way on network i/o | 449 | /* |
419 | or DFS errors */ | 450 | * Else fallthrough to retry open the old way on network i/o |
451 | * or DFS errors. | ||
452 | */ | ||
420 | } | 453 | } |
421 | 454 | ||
455 | if (server->ops->get_lease_key) | ||
456 | server->ops->get_lease_key(inode, &fid); | ||
457 | |||
458 | cifs_add_pending_open(&fid, tlink, &open); | ||
459 | |||
422 | if (!posix_open_ok) { | 460 | if (!posix_open_ok) { |
461 | if (server->ops->get_lease_key) | ||
462 | server->ops->get_lease_key(inode, &fid); | ||
463 | |||
423 | rc = cifs_nt_open(full_path, inode, cifs_sb, tcon, | 464 | rc = cifs_nt_open(full_path, inode, cifs_sb, tcon, |
424 | file->f_flags, &oplock, &netfid, xid); | 465 | file->f_flags, &oplock, &fid, xid); |
425 | if (rc) | 466 | if (rc) { |
467 | cifs_del_pending_open(&open); | ||
426 | goto out; | 468 | goto out; |
469 | } | ||
427 | } | 470 | } |
428 | 471 | ||
429 | pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock); | 472 | cfile = cifs_new_fileinfo(&fid, file, tlink, oplock); |
430 | if (pCifsFile == NULL) { | 473 | if (cfile == NULL) { |
431 | CIFSSMBClose(xid, tcon, netfid); | 474 | if (server->ops->close) |
475 | server->ops->close(xid, tcon, &fid); | ||
476 | cifs_del_pending_open(&open); | ||
432 | rc = -ENOMEM; | 477 | rc = -ENOMEM; |
433 | goto out; | 478 | goto out; |
434 | } | 479 | } |
@@ -436,8 +481,10 @@ int cifs_open(struct inode *inode, struct file *file) | |||
436 | cifs_fscache_set_inode_cookie(inode, file); | 481 | cifs_fscache_set_inode_cookie(inode, file); |
437 | 482 | ||
438 | if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) { | 483 | if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) { |
439 | /* time to set mode which we can not set earlier due to | 484 | /* |
440 | problems creating new read-only files */ | 485 | * Time to set mode which we can not set earlier due to |
486 | * problems creating new read-only files. | ||
487 | */ | ||
441 | struct cifs_unix_set_info_args args = { | 488 | struct cifs_unix_set_info_args args = { |
442 | .mode = inode->i_mode, | 489 | .mode = inode->i_mode, |
443 | .uid = NO_CHANGE_64, | 490 | .uid = NO_CHANGE_64, |
@@ -447,8 +494,8 @@ int cifs_open(struct inode *inode, struct file *file) | |||
447 | .mtime = NO_CHANGE_64, | 494 | .mtime = NO_CHANGE_64, |
448 | .device = 0, | 495 | .device = 0, |
449 | }; | 496 | }; |
450 | CIFSSMBUnixSetFileInfo(xid, tcon, &args, netfid, | 497 | CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid.netfid, |
451 | pCifsFile->pid); | 498 | cfile->pid); |
452 | } | 499 | } |
453 | 500 | ||
454 | out: | 501 | out: |
@@ -458,59 +505,66 @@ out: | |||
458 | return rc; | 505 | return rc; |
459 | } | 506 | } |
460 | 507 | ||
461 | /* Try to reacquire byte range locks that were released when session */ | 508 | /* |
462 | /* to server was lost */ | 509 | * Try to reacquire byte range locks that were released when session |
510 | * to server was lost | ||
511 | */ | ||
463 | static int cifs_relock_file(struct cifsFileInfo *cifsFile) | 512 | static int cifs_relock_file(struct cifsFileInfo *cifsFile) |
464 | { | 513 | { |
465 | int rc = 0; | 514 | int rc = 0; |
466 | 515 | ||
467 | /* BB list all locks open on this file and relock */ | 516 | /* BB list all locks open on this file and relock */ |
468 | 517 | ||
469 | return rc; | 518 | return rc; |
470 | } | 519 | } |
471 | 520 | ||
472 | static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush) | 521 | static int |
522 | cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) | ||
473 | { | 523 | { |
474 | int rc = -EACCES; | 524 | int rc = -EACCES; |
475 | unsigned int xid; | 525 | unsigned int xid; |
476 | __u32 oplock; | 526 | __u32 oplock; |
477 | struct cifs_sb_info *cifs_sb; | 527 | struct cifs_sb_info *cifs_sb; |
478 | struct cifs_tcon *tcon; | 528 | struct cifs_tcon *tcon; |
479 | struct cifsInodeInfo *pCifsInode; | 529 | struct TCP_Server_Info *server; |
530 | struct cifsInodeInfo *cinode; | ||
480 | struct inode *inode; | 531 | struct inode *inode; |
481 | char *full_path = NULL; | 532 | char *full_path = NULL; |
482 | int desiredAccess; | 533 | int desired_access; |
483 | int disposition = FILE_OPEN; | 534 | int disposition = FILE_OPEN; |
484 | int create_options = CREATE_NOT_DIR; | 535 | int create_options = CREATE_NOT_DIR; |
485 | __u16 netfid; | 536 | struct cifs_fid fid; |
486 | 537 | ||
487 | xid = get_xid(); | 538 | xid = get_xid(); |
488 | mutex_lock(&pCifsFile->fh_mutex); | 539 | mutex_lock(&cfile->fh_mutex); |
489 | if (!pCifsFile->invalidHandle) { | 540 | if (!cfile->invalidHandle) { |
490 | mutex_unlock(&pCifsFile->fh_mutex); | 541 | mutex_unlock(&cfile->fh_mutex); |
491 | rc = 0; | 542 | rc = 0; |
492 | free_xid(xid); | 543 | free_xid(xid); |
493 | return rc; | 544 | return rc; |
494 | } | 545 | } |
495 | 546 | ||
496 | inode = pCifsFile->dentry->d_inode; | 547 | inode = cfile->dentry->d_inode; |
497 | cifs_sb = CIFS_SB(inode->i_sb); | 548 | cifs_sb = CIFS_SB(inode->i_sb); |
498 | tcon = tlink_tcon(pCifsFile->tlink); | 549 | tcon = tlink_tcon(cfile->tlink); |
550 | server = tcon->ses->server; | ||
499 | 551 | ||
500 | /* can not grab rename sem here because various ops, including | 552 | /* |
501 | those that already have the rename sem can end up causing writepage | 553 | * Can not grab rename sem here because various ops, including those |
502 | to get called and if the server was down that means we end up here, | 554 | * that already have the rename sem can end up causing writepage to get |
503 | and we can never tell if the caller already has the rename_sem */ | 555 | * called and if the server was down that means we end up here, and we |
504 | full_path = build_path_from_dentry(pCifsFile->dentry); | 556 | * can never tell if the caller already has the rename_sem. |
557 | */ | ||
558 | full_path = build_path_from_dentry(cfile->dentry); | ||
505 | if (full_path == NULL) { | 559 | if (full_path == NULL) { |
506 | rc = -ENOMEM; | 560 | rc = -ENOMEM; |
507 | mutex_unlock(&pCifsFile->fh_mutex); | 561 | mutex_unlock(&cfile->fh_mutex); |
508 | free_xid(xid); | 562 | free_xid(xid); |
509 | return rc; | 563 | return rc; |
510 | } | 564 | } |
511 | 565 | ||
512 | cFYI(1, "inode = 0x%p file flags 0x%x for %s", | 566 | cFYI(1, "inode = 0x%p file flags 0x%x for %s", inode, cfile->f_flags, |
513 | inode, pCifsFile->f_flags, full_path); | 567 | full_path); |
514 | 568 | ||
515 | if (tcon->ses->server->oplocks) | 569 | if (tcon->ses->server->oplocks) |
516 | oplock = REQ_OPLOCK; | 570 | oplock = REQ_OPLOCK; |
@@ -524,69 +578,72 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush) | |||
524 | * O_CREAT, O_EXCL and O_TRUNC already had their effect on the | 578 | * O_CREAT, O_EXCL and O_TRUNC already had their effect on the |
525 | * original open. Must mask them off for a reopen. | 579 | * original open. Must mask them off for a reopen. |
526 | */ | 580 | */ |
527 | unsigned int oflags = pCifsFile->f_flags & | 581 | unsigned int oflags = cfile->f_flags & |
528 | ~(O_CREAT | O_EXCL | O_TRUNC); | 582 | ~(O_CREAT | O_EXCL | O_TRUNC); |
529 | 583 | ||
530 | rc = cifs_posix_open(full_path, NULL, inode->i_sb, | 584 | rc = cifs_posix_open(full_path, NULL, inode->i_sb, |
531 | cifs_sb->mnt_file_mode /* ignored */, | 585 | cifs_sb->mnt_file_mode /* ignored */, |
532 | oflags, &oplock, &netfid, xid); | 586 | oflags, &oplock, &fid.netfid, xid); |
533 | if (rc == 0) { | 587 | if (rc == 0) { |
534 | cFYI(1, "posix reopen succeeded"); | 588 | cFYI(1, "posix reopen succeeded"); |
535 | goto reopen_success; | 589 | goto reopen_success; |
536 | } | 590 | } |
537 | /* fallthrough to retry open the old way on errors, especially | 591 | /* |
538 | in the reconnect path it is important to retry hard */ | 592 | * fallthrough to retry open the old way on errors, especially |
593 | * in the reconnect path it is important to retry hard | ||
594 | */ | ||
539 | } | 595 | } |
540 | 596 | ||
541 | desiredAccess = cifs_convert_flags(pCifsFile->f_flags); | 597 | desired_access = cifs_convert_flags(cfile->f_flags); |
542 | 598 | ||
543 | if (backup_cred(cifs_sb)) | 599 | if (backup_cred(cifs_sb)) |
544 | create_options |= CREATE_OPEN_BACKUP_INTENT; | 600 | create_options |= CREATE_OPEN_BACKUP_INTENT; |
545 | 601 | ||
546 | /* Can not refresh inode by passing in file_info buf to be returned | 602 | if (server->ops->get_lease_key) |
547 | by SMBOpen and then calling get_inode_info with returned buf | 603 | server->ops->get_lease_key(inode, &fid); |
548 | since file might have write behind data that needs to be flushed | ||
549 | and server version of file size can be stale. If we knew for sure | ||
550 | that inode was not dirty locally we could do this */ | ||
551 | 604 | ||
552 | rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess, | 605 | /* |
553 | create_options, &netfid, &oplock, NULL, | 606 | * Can not refresh inode by passing in file_info buf to be returned by |
554 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 607 | * CIFSSMBOpen and then calling get_inode_info with returned buf since |
555 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 608 | * file might have write behind data that needs to be flushed and server |
609 | * version of file size can be stale. If we knew for sure that inode was | ||
610 | * not dirty locally we could do this. | ||
611 | */ | ||
612 | rc = server->ops->open(xid, tcon, full_path, disposition, | ||
613 | desired_access, create_options, &fid, &oplock, | ||
614 | NULL, cifs_sb); | ||
556 | if (rc) { | 615 | if (rc) { |
557 | mutex_unlock(&pCifsFile->fh_mutex); | 616 | mutex_unlock(&cfile->fh_mutex); |
558 | cFYI(1, "cifs_open returned 0x%x", rc); | 617 | cFYI(1, "cifs_reopen returned 0x%x", rc); |
559 | cFYI(1, "oplock: %d", oplock); | 618 | cFYI(1, "oplock: %d", oplock); |
560 | goto reopen_error_exit; | 619 | goto reopen_error_exit; |
561 | } | 620 | } |
562 | 621 | ||
563 | reopen_success: | 622 | reopen_success: |
564 | pCifsFile->netfid = netfid; | 623 | cfile->invalidHandle = false; |
565 | pCifsFile->invalidHandle = false; | 624 | mutex_unlock(&cfile->fh_mutex); |
566 | mutex_unlock(&pCifsFile->fh_mutex); | 625 | cinode = CIFS_I(inode); |
567 | pCifsInode = CIFS_I(inode); | ||
568 | 626 | ||
569 | if (can_flush) { | 627 | if (can_flush) { |
570 | rc = filemap_write_and_wait(inode->i_mapping); | 628 | rc = filemap_write_and_wait(inode->i_mapping); |
571 | mapping_set_error(inode->i_mapping, rc); | 629 | mapping_set_error(inode->i_mapping, rc); |
572 | 630 | ||
573 | if (tcon->unix_ext) | 631 | if (tcon->unix_ext) |
574 | rc = cifs_get_inode_info_unix(&inode, | 632 | rc = cifs_get_inode_info_unix(&inode, full_path, |
575 | full_path, inode->i_sb, xid); | 633 | inode->i_sb, xid); |
576 | else | 634 | else |
577 | rc = cifs_get_inode_info(&inode, | 635 | rc = cifs_get_inode_info(&inode, full_path, NULL, |
578 | full_path, NULL, inode->i_sb, | 636 | inode->i_sb, xid, NULL); |
579 | xid, NULL); | 637 | } |
580 | } /* else we are writing out data to server already | 638 | /* |
581 | and could deadlock if we tried to flush data, and | 639 | * Else we are writing out data to server already and could deadlock if |
582 | since we do not know if we have data that would | 640 | * we tried to flush data, and since we do not know if we have data that |
583 | invalidate the current end of file on the server | 641 | * would invalidate the current end of file on the server we can not go |
584 | we can not go to the server to get the new inod | 642 | * to the server to get the new inode info. |
585 | info */ | 643 | */ |
586 | |||
587 | cifs_set_oplock_level(pCifsInode, oplock); | ||
588 | 644 | ||
589 | cifs_relock_file(pCifsFile); | 645 | server->ops->set_fid(cfile, &fid, oplock); |
646 | cifs_relock_file(cfile); | ||
590 | 647 | ||
591 | reopen_error_exit: | 648 | reopen_error_exit: |
592 | kfree(full_path); | 649 | kfree(full_path); |
@@ -609,42 +666,48 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
609 | { | 666 | { |
610 | int rc = 0; | 667 | int rc = 0; |
611 | unsigned int xid; | 668 | unsigned int xid; |
612 | struct cifsFileInfo *pCFileStruct = file->private_data; | 669 | struct cifsFileInfo *cfile = file->private_data; |
613 | char *ptmp; | 670 | struct cifs_tcon *tcon; |
671 | struct TCP_Server_Info *server; | ||
672 | char *buf; | ||
614 | 673 | ||
615 | cFYI(1, "Closedir inode = 0x%p", inode); | 674 | cFYI(1, "Closedir inode = 0x%p", inode); |
616 | 675 | ||
676 | if (cfile == NULL) | ||
677 | return rc; | ||
678 | |||
617 | xid = get_xid(); | 679 | xid = get_xid(); |
680 | tcon = tlink_tcon(cfile->tlink); | ||
681 | server = tcon->ses->server; | ||
618 | 682 | ||
619 | if (pCFileStruct) { | 683 | cFYI(1, "Freeing private data in close dir"); |
620 | struct cifs_tcon *pTcon = tlink_tcon(pCFileStruct->tlink); | 684 | spin_lock(&cifs_file_list_lock); |
685 | if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) { | ||
686 | cfile->invalidHandle = true; | ||
687 | spin_unlock(&cifs_file_list_lock); | ||
688 | if (server->ops->close_dir) | ||
689 | rc = server->ops->close_dir(xid, tcon, &cfile->fid); | ||
690 | else | ||
691 | rc = -ENOSYS; | ||
692 | cFYI(1, "Closing uncompleted readdir with rc %d", rc); | ||
693 | /* not much we can do if it fails anyway, ignore rc */ | ||
694 | rc = 0; | ||
695 | } else | ||
696 | spin_unlock(&cifs_file_list_lock); | ||
621 | 697 | ||
622 | cFYI(1, "Freeing private data in close dir"); | 698 | buf = cfile->srch_inf.ntwrk_buf_start; |
623 | spin_lock(&cifs_file_list_lock); | 699 | if (buf) { |
624 | if (!pCFileStruct->srch_inf.endOfSearch && | 700 | cFYI(1, "closedir free smb buf in srch struct"); |
625 | !pCFileStruct->invalidHandle) { | 701 | cfile->srch_inf.ntwrk_buf_start = NULL; |
626 | pCFileStruct->invalidHandle = true; | 702 | if (cfile->srch_inf.smallBuf) |
627 | spin_unlock(&cifs_file_list_lock); | 703 | cifs_small_buf_release(buf); |
628 | rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid); | 704 | else |
629 | cFYI(1, "Closing uncompleted readdir with rc %d", | 705 | cifs_buf_release(buf); |
630 | rc); | ||
631 | /* not much we can do if it fails anyway, ignore rc */ | ||
632 | rc = 0; | ||
633 | } else | ||
634 | spin_unlock(&cifs_file_list_lock); | ||
635 | ptmp = pCFileStruct->srch_inf.ntwrk_buf_start; | ||
636 | if (ptmp) { | ||
637 | cFYI(1, "closedir free smb buf in srch struct"); | ||
638 | pCFileStruct->srch_inf.ntwrk_buf_start = NULL; | ||
639 | if (pCFileStruct->srch_inf.smallBuf) | ||
640 | cifs_small_buf_release(ptmp); | ||
641 | else | ||
642 | cifs_buf_release(ptmp); | ||
643 | } | ||
644 | cifs_put_tlink(pCFileStruct->tlink); | ||
645 | kfree(file->private_data); | ||
646 | file->private_data = NULL; | ||
647 | } | 706 | } |
707 | |||
708 | cifs_put_tlink(cfile->tlink); | ||
709 | kfree(file->private_data); | ||
710 | file->private_data = NULL; | ||
648 | /* BB can we lock the filestruct while this is going on? */ | 711 | /* BB can we lock the filestruct while this is going on? */ |
649 | free_xid(xid); | 712 | free_xid(xid); |
650 | return rc; | 713 | return rc; |
@@ -666,7 +729,7 @@ cifs_lock_init(__u64 offset, __u64 length, __u8 type) | |||
666 | return lock; | 729 | return lock; |
667 | } | 730 | } |
668 | 731 | ||
669 | static void | 732 | void |
670 | cifs_del_lock_waiters(struct cifsLockInfo *lock) | 733 | cifs_del_lock_waiters(struct cifsLockInfo *lock) |
671 | { | 734 | { |
672 | struct cifsLockInfo *li, *tmp; | 735 | struct cifsLockInfo *li, *tmp; |
@@ -677,45 +740,47 @@ cifs_del_lock_waiters(struct cifsLockInfo *lock) | |||
677 | } | 740 | } |
678 | 741 | ||
679 | static bool | 742 | static bool |
680 | cifs_find_fid_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, | 743 | cifs_find_fid_lock_conflict(struct cifs_fid_locks *fdlocks, __u64 offset, |
681 | __u64 length, __u8 type, struct cifsFileInfo *cur, | 744 | __u64 length, __u8 type, struct cifsFileInfo *cfile, |
682 | struct cifsLockInfo **conf_lock) | 745 | struct cifsLockInfo **conf_lock, bool rw_check) |
683 | { | 746 | { |
684 | struct cifsLockInfo *li; | 747 | struct cifsLockInfo *li; |
748 | struct cifsFileInfo *cur_cfile = fdlocks->cfile; | ||
685 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; | 749 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; |
686 | 750 | ||
687 | list_for_each_entry(li, &cfile->llist, llist) { | 751 | list_for_each_entry(li, &fdlocks->locks, llist) { |
688 | if (offset + length <= li->offset || | 752 | if (offset + length <= li->offset || |
689 | offset >= li->offset + li->length) | 753 | offset >= li->offset + li->length) |
690 | continue; | 754 | continue; |
691 | else if ((type & server->vals->shared_lock_type) && | 755 | if (rw_check && server->ops->compare_fids(cfile, cur_cfile) && |
692 | ((server->ops->compare_fids(cur, cfile) && | 756 | current->tgid == li->pid) |
693 | current->tgid == li->pid) || type == li->type)) | ||
694 | continue; | 757 | continue; |
695 | else { | 758 | if ((type & server->vals->shared_lock_type) && |
759 | ((server->ops->compare_fids(cfile, cur_cfile) && | ||
760 | current->tgid == li->pid) || type == li->type)) | ||
761 | continue; | ||
762 | if (conf_lock) | ||
696 | *conf_lock = li; | 763 | *conf_lock = li; |
697 | return true; | 764 | return true; |
698 | } | ||
699 | } | 765 | } |
700 | return false; | 766 | return false; |
701 | } | 767 | } |
702 | 768 | ||
703 | static bool | 769 | bool |
704 | cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, __u64 length, | 770 | cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, __u64 length, |
705 | __u8 type, struct cifsLockInfo **conf_lock) | 771 | __u8 type, struct cifsLockInfo **conf_lock, |
772 | bool rw_check) | ||
706 | { | 773 | { |
707 | bool rc = false; | 774 | bool rc = false; |
708 | struct cifsFileInfo *fid, *tmp; | 775 | struct cifs_fid_locks *cur; |
709 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); | 776 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); |
710 | 777 | ||
711 | spin_lock(&cifs_file_list_lock); | 778 | list_for_each_entry(cur, &cinode->llist, llist) { |
712 | list_for_each_entry_safe(fid, tmp, &cinode->openFileList, flist) { | 779 | rc = cifs_find_fid_lock_conflict(cur, offset, length, type, |
713 | rc = cifs_find_fid_lock_conflict(fid, offset, length, type, | 780 | cfile, conf_lock, rw_check); |
714 | cfile, conf_lock); | ||
715 | if (rc) | 781 | if (rc) |
716 | break; | 782 | break; |
717 | } | 783 | } |
718 | spin_unlock(&cifs_file_list_lock); | ||
719 | 784 | ||
720 | return rc; | 785 | return rc; |
721 | } | 786 | } |
@@ -737,10 +802,10 @@ cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length, | |||
737 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; | 802 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; |
738 | bool exist; | 803 | bool exist; |
739 | 804 | ||
740 | mutex_lock(&cinode->lock_mutex); | 805 | down_read(&cinode->lock_sem); |
741 | 806 | ||
742 | exist = cifs_find_lock_conflict(cfile, offset, length, type, | 807 | exist = cifs_find_lock_conflict(cfile, offset, length, type, |
743 | &conf_lock); | 808 | &conf_lock, false); |
744 | if (exist) { | 809 | if (exist) { |
745 | flock->fl_start = conf_lock->offset; | 810 | flock->fl_start = conf_lock->offset; |
746 | flock->fl_end = conf_lock->offset + conf_lock->length - 1; | 811 | flock->fl_end = conf_lock->offset + conf_lock->length - 1; |
@@ -754,7 +819,7 @@ cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length, | |||
754 | else | 819 | else |
755 | flock->fl_type = F_UNLCK; | 820 | flock->fl_type = F_UNLCK; |
756 | 821 | ||
757 | mutex_unlock(&cinode->lock_mutex); | 822 | up_read(&cinode->lock_sem); |
758 | return rc; | 823 | return rc; |
759 | } | 824 | } |
760 | 825 | ||
@@ -762,9 +827,9 @@ static void | |||
762 | cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock) | 827 | cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock) |
763 | { | 828 | { |
764 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); | 829 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); |
765 | mutex_lock(&cinode->lock_mutex); | 830 | down_write(&cinode->lock_sem); |
766 | list_add_tail(&lock->llist, &cfile->llist); | 831 | list_add_tail(&lock->llist, &cfile->llist->locks); |
767 | mutex_unlock(&cinode->lock_mutex); | 832 | up_write(&cinode->lock_sem); |
768 | } | 833 | } |
769 | 834 | ||
770 | /* | 835 | /* |
@@ -784,13 +849,13 @@ cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock, | |||
784 | 849 | ||
785 | try_again: | 850 | try_again: |
786 | exist = false; | 851 | exist = false; |
787 | mutex_lock(&cinode->lock_mutex); | 852 | down_write(&cinode->lock_sem); |
788 | 853 | ||
789 | exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length, | 854 | exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length, |
790 | lock->type, &conf_lock); | 855 | lock->type, &conf_lock, false); |
791 | if (!exist && cinode->can_cache_brlcks) { | 856 | if (!exist && cinode->can_cache_brlcks) { |
792 | list_add_tail(&lock->llist, &cfile->llist); | 857 | list_add_tail(&lock->llist, &cfile->llist->locks); |
793 | mutex_unlock(&cinode->lock_mutex); | 858 | up_write(&cinode->lock_sem); |
794 | return rc; | 859 | return rc; |
795 | } | 860 | } |
796 | 861 | ||
@@ -800,17 +865,17 @@ try_again: | |||
800 | rc = -EACCES; | 865 | rc = -EACCES; |
801 | else { | 866 | else { |
802 | list_add_tail(&lock->blist, &conf_lock->blist); | 867 | list_add_tail(&lock->blist, &conf_lock->blist); |
803 | mutex_unlock(&cinode->lock_mutex); | 868 | up_write(&cinode->lock_sem); |
804 | rc = wait_event_interruptible(lock->block_q, | 869 | rc = wait_event_interruptible(lock->block_q, |
805 | (lock->blist.prev == &lock->blist) && | 870 | (lock->blist.prev == &lock->blist) && |
806 | (lock->blist.next == &lock->blist)); | 871 | (lock->blist.next == &lock->blist)); |
807 | if (!rc) | 872 | if (!rc) |
808 | goto try_again; | 873 | goto try_again; |
809 | mutex_lock(&cinode->lock_mutex); | 874 | down_write(&cinode->lock_sem); |
810 | list_del_init(&lock->blist); | 875 | list_del_init(&lock->blist); |
811 | } | 876 | } |
812 | 877 | ||
813 | mutex_unlock(&cinode->lock_mutex); | 878 | up_write(&cinode->lock_sem); |
814 | return rc; | 879 | return rc; |
815 | } | 880 | } |
816 | 881 | ||
@@ -831,7 +896,7 @@ cifs_posix_lock_test(struct file *file, struct file_lock *flock) | |||
831 | if ((flock->fl_flags & FL_POSIX) == 0) | 896 | if ((flock->fl_flags & FL_POSIX) == 0) |
832 | return 1; | 897 | return 1; |
833 | 898 | ||
834 | mutex_lock(&cinode->lock_mutex); | 899 | down_read(&cinode->lock_sem); |
835 | posix_test_lock(file, flock); | 900 | posix_test_lock(file, flock); |
836 | 901 | ||
837 | if (flock->fl_type == F_UNLCK && !cinode->can_cache_brlcks) { | 902 | if (flock->fl_type == F_UNLCK && !cinode->can_cache_brlcks) { |
@@ -839,7 +904,7 @@ cifs_posix_lock_test(struct file *file, struct file_lock *flock) | |||
839 | rc = 1; | 904 | rc = 1; |
840 | } | 905 | } |
841 | 906 | ||
842 | mutex_unlock(&cinode->lock_mutex); | 907 | up_read(&cinode->lock_sem); |
843 | return rc; | 908 | return rc; |
844 | } | 909 | } |
845 | 910 | ||
@@ -859,14 +924,14 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock) | |||
859 | return rc; | 924 | return rc; |
860 | 925 | ||
861 | try_again: | 926 | try_again: |
862 | mutex_lock(&cinode->lock_mutex); | 927 | down_write(&cinode->lock_sem); |
863 | if (!cinode->can_cache_brlcks) { | 928 | if (!cinode->can_cache_brlcks) { |
864 | mutex_unlock(&cinode->lock_mutex); | 929 | up_write(&cinode->lock_sem); |
865 | return rc; | 930 | return rc; |
866 | } | 931 | } |
867 | 932 | ||
868 | rc = posix_lock_file(file, flock, NULL); | 933 | rc = posix_lock_file(file, flock, NULL); |
869 | mutex_unlock(&cinode->lock_mutex); | 934 | up_write(&cinode->lock_sem); |
870 | if (rc == FILE_LOCK_DEFERRED) { | 935 | if (rc == FILE_LOCK_DEFERRED) { |
871 | rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next); | 936 | rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next); |
872 | if (!rc) | 937 | if (!rc) |
@@ -876,7 +941,7 @@ try_again: | |||
876 | return rc; | 941 | return rc; |
877 | } | 942 | } |
878 | 943 | ||
879 | static int | 944 | int |
880 | cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | 945 | cifs_push_mandatory_locks(struct cifsFileInfo *cfile) |
881 | { | 946 | { |
882 | unsigned int xid; | 947 | unsigned int xid; |
@@ -893,9 +958,10 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
893 | xid = get_xid(); | 958 | xid = get_xid(); |
894 | tcon = tlink_tcon(cfile->tlink); | 959 | tcon = tlink_tcon(cfile->tlink); |
895 | 960 | ||
896 | mutex_lock(&cinode->lock_mutex); | 961 | /* we are going to update can_cache_brlcks here - need a write access */ |
962 | down_write(&cinode->lock_sem); | ||
897 | if (!cinode->can_cache_brlcks) { | 963 | if (!cinode->can_cache_brlcks) { |
898 | mutex_unlock(&cinode->lock_mutex); | 964 | up_write(&cinode->lock_sem); |
899 | free_xid(xid); | 965 | free_xid(xid); |
900 | return rc; | 966 | return rc; |
901 | } | 967 | } |
@@ -906,7 +972,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
906 | */ | 972 | */ |
907 | max_buf = tcon->ses->server->maxBuf; | 973 | max_buf = tcon->ses->server->maxBuf; |
908 | if (!max_buf) { | 974 | if (!max_buf) { |
909 | mutex_unlock(&cinode->lock_mutex); | 975 | up_write(&cinode->lock_sem); |
910 | free_xid(xid); | 976 | free_xid(xid); |
911 | return -EINVAL; | 977 | return -EINVAL; |
912 | } | 978 | } |
@@ -915,7 +981,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
915 | sizeof(LOCKING_ANDX_RANGE); | 981 | sizeof(LOCKING_ANDX_RANGE); |
916 | buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); | 982 | buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); |
917 | if (!buf) { | 983 | if (!buf) { |
918 | mutex_unlock(&cinode->lock_mutex); | 984 | up_write(&cinode->lock_sem); |
919 | free_xid(xid); | 985 | free_xid(xid); |
920 | return -ENOMEM; | 986 | return -ENOMEM; |
921 | } | 987 | } |
@@ -923,7 +989,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
923 | for (i = 0; i < 2; i++) { | 989 | for (i = 0; i < 2; i++) { |
924 | cur = buf; | 990 | cur = buf; |
925 | num = 0; | 991 | num = 0; |
926 | list_for_each_entry_safe(li, tmp, &cfile->llist, llist) { | 992 | list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) { |
927 | if (li->type != types[i]) | 993 | if (li->type != types[i]) |
928 | continue; | 994 | continue; |
929 | cur->Pid = cpu_to_le16(li->pid); | 995 | cur->Pid = cpu_to_le16(li->pid); |
@@ -932,7 +998,8 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
932 | cur->OffsetLow = cpu_to_le32((u32)li->offset); | 998 | cur->OffsetLow = cpu_to_le32((u32)li->offset); |
933 | cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32)); | 999 | cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32)); |
934 | if (++num == max_num) { | 1000 | if (++num == max_num) { |
935 | stored_rc = cifs_lockv(xid, tcon, cfile->netfid, | 1001 | stored_rc = cifs_lockv(xid, tcon, |
1002 | cfile->fid.netfid, | ||
936 | (__u8)li->type, 0, num, | 1003 | (__u8)li->type, 0, num, |
937 | buf); | 1004 | buf); |
938 | if (stored_rc) | 1005 | if (stored_rc) |
@@ -944,7 +1011,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
944 | } | 1011 | } |
945 | 1012 | ||
946 | if (num) { | 1013 | if (num) { |
947 | stored_rc = cifs_lockv(xid, tcon, cfile->netfid, | 1014 | stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid, |
948 | (__u8)types[i], 0, num, buf); | 1015 | (__u8)types[i], 0, num, buf); |
949 | if (stored_rc) | 1016 | if (stored_rc) |
950 | rc = stored_rc; | 1017 | rc = stored_rc; |
@@ -952,7 +1019,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
952 | } | 1019 | } |
953 | 1020 | ||
954 | cinode->can_cache_brlcks = false; | 1021 | cinode->can_cache_brlcks = false; |
955 | mutex_unlock(&cinode->lock_mutex); | 1022 | up_write(&cinode->lock_sem); |
956 | 1023 | ||
957 | kfree(buf); | 1024 | kfree(buf); |
958 | free_xid(xid); | 1025 | free_xid(xid); |
@@ -987,9 +1054,10 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | |||
987 | 1054 | ||
988 | xid = get_xid(); | 1055 | xid = get_xid(); |
989 | 1056 | ||
990 | mutex_lock(&cinode->lock_mutex); | 1057 | /* we are going to update can_cache_brlcks here - need a write access */ |
1058 | down_write(&cinode->lock_sem); | ||
991 | if (!cinode->can_cache_brlcks) { | 1059 | if (!cinode->can_cache_brlcks) { |
992 | mutex_unlock(&cinode->lock_mutex); | 1060 | up_write(&cinode->lock_sem); |
993 | free_xid(xid); | 1061 | free_xid(xid); |
994 | return rc; | 1062 | return rc; |
995 | } | 1063 | } |
@@ -1005,7 +1073,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | |||
1005 | 1073 | ||
1006 | /* | 1074 | /* |
1007 | * Allocating count locks is enough because no FL_POSIX locks can be | 1075 | * Allocating count locks is enough because no FL_POSIX locks can be |
1008 | * added to the list while we are holding cinode->lock_mutex that | 1076 | * added to the list while we are holding cinode->lock_sem that |
1009 | * protects locking operations of this inode. | 1077 | * protects locking operations of this inode. |
1010 | */ | 1078 | */ |
1011 | for (; i < count; i++) { | 1079 | for (; i < count; i++) { |
@@ -1038,7 +1106,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | |||
1038 | type = CIFS_WRLCK; | 1106 | type = CIFS_WRLCK; |
1039 | lck = list_entry(el, struct lock_to_push, llist); | 1107 | lck = list_entry(el, struct lock_to_push, llist); |
1040 | lck->pid = flock->fl_pid; | 1108 | lck->pid = flock->fl_pid; |
1041 | lck->netfid = cfile->netfid; | 1109 | lck->netfid = cfile->fid.netfid; |
1042 | lck->length = length; | 1110 | lck->length = length; |
1043 | lck->type = type; | 1111 | lck->type = type; |
1044 | lck->offset = flock->fl_start; | 1112 | lck->offset = flock->fl_start; |
@@ -1060,7 +1128,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | |||
1060 | 1128 | ||
1061 | out: | 1129 | out: |
1062 | cinode->can_cache_brlcks = false; | 1130 | cinode->can_cache_brlcks = false; |
1063 | mutex_unlock(&cinode->lock_mutex); | 1131 | up_write(&cinode->lock_sem); |
1064 | 1132 | ||
1065 | free_xid(xid); | 1133 | free_xid(xid); |
1066 | return rc; | 1134 | return rc; |
@@ -1083,7 +1151,7 @@ cifs_push_locks(struct cifsFileInfo *cfile) | |||
1083 | ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) | 1151 | ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) |
1084 | return cifs_push_posix_locks(cfile); | 1152 | return cifs_push_posix_locks(cfile); |
1085 | 1153 | ||
1086 | return cifs_push_mandatory_locks(cfile); | 1154 | return tcon->ses->server->ops->push_mand_locks(cfile); |
1087 | } | 1155 | } |
1088 | 1156 | ||
1089 | static void | 1157 | static void |
@@ -1104,7 +1172,8 @@ cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock, | |||
1104 | if (flock->fl_flags & FL_LEASE) | 1172 | if (flock->fl_flags & FL_LEASE) |
1105 | cFYI(1, "Lease on file - not implemented yet"); | 1173 | cFYI(1, "Lease on file - not implemented yet"); |
1106 | if (flock->fl_flags & | 1174 | if (flock->fl_flags & |
1107 | (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE))) | 1175 | (~(FL_POSIX | FL_FLOCK | FL_SLEEP | |
1176 | FL_ACCESS | FL_LEASE | FL_CLOSE))) | ||
1108 | cFYI(1, "Unknown lock flags 0x%x", flock->fl_flags); | 1177 | cFYI(1, "Unknown lock flags 0x%x", flock->fl_flags); |
1109 | 1178 | ||
1110 | *type = server->vals->large_lock_type; | 1179 | *type = server->vals->large_lock_type; |
@@ -1134,15 +1203,6 @@ cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock, | |||
1134 | } | 1203 | } |
1135 | 1204 | ||
1136 | static int | 1205 | static int |
1137 | cifs_mandatory_lock(unsigned int xid, struct cifsFileInfo *cfile, __u64 offset, | ||
1138 | __u64 length, __u32 type, int lock, int unlock, bool wait) | ||
1139 | { | ||
1140 | return CIFSSMBLock(xid, tlink_tcon(cfile->tlink), cfile->netfid, | ||
1141 | current->tgid, length, offset, unlock, lock, | ||
1142 | (__u8)type, wait, 0); | ||
1143 | } | ||
1144 | |||
1145 | static int | ||
1146 | cifs_getlk(struct file *file, struct file_lock *flock, __u32 type, | 1206 | cifs_getlk(struct file *file, struct file_lock *flock, __u32 type, |
1147 | bool wait_flag, bool posix_lck, unsigned int xid) | 1207 | bool wait_flag, bool posix_lck, unsigned int xid) |
1148 | { | 1208 | { |
@@ -1151,7 +1211,7 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type, | |||
1151 | struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; | 1211 | struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; |
1152 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | 1212 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
1153 | struct TCP_Server_Info *server = tcon->ses->server; | 1213 | struct TCP_Server_Info *server = tcon->ses->server; |
1154 | __u16 netfid = cfile->netfid; | 1214 | __u16 netfid = cfile->fid.netfid; |
1155 | 1215 | ||
1156 | if (posix_lck) { | 1216 | if (posix_lck) { |
1157 | int posix_lock_type; | 1217 | int posix_lock_type; |
@@ -1175,11 +1235,11 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type, | |||
1175 | return rc; | 1235 | return rc; |
1176 | 1236 | ||
1177 | /* BB we could chain these into one lock request BB */ | 1237 | /* BB we could chain these into one lock request BB */ |
1178 | rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length, type, | 1238 | rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length, type, |
1179 | 1, 0, false); | 1239 | 1, 0, false); |
1180 | if (rc == 0) { | 1240 | if (rc == 0) { |
1181 | rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length, | 1241 | rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length, |
1182 | type, 0, 1, false); | 1242 | type, 0, 1, false); |
1183 | flock->fl_type = F_UNLCK; | 1243 | flock->fl_type = F_UNLCK; |
1184 | if (rc != 0) | 1244 | if (rc != 0) |
1185 | cERROR(1, "Error unlocking previously locked " | 1245 | cERROR(1, "Error unlocking previously locked " |
@@ -1192,13 +1252,14 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type, | |||
1192 | return 0; | 1252 | return 0; |
1193 | } | 1253 | } |
1194 | 1254 | ||
1195 | rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length, | 1255 | type &= ~server->vals->exclusive_lock_type; |
1196 | type | server->vals->shared_lock_type, 1, 0, | 1256 | |
1197 | false); | 1257 | rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length, |
1258 | type | server->vals->shared_lock_type, | ||
1259 | 1, 0, false); | ||
1198 | if (rc == 0) { | 1260 | if (rc == 0) { |
1199 | rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length, | 1261 | rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length, |
1200 | type | server->vals->shared_lock_type, | 1262 | type | server->vals->shared_lock_type, 0, 1, false); |
1201 | 0, 1, false); | ||
1202 | flock->fl_type = F_RDLCK; | 1263 | flock->fl_type = F_RDLCK; |
1203 | if (rc != 0) | 1264 | if (rc != 0) |
1204 | cERROR(1, "Error unlocking previously locked " | 1265 | cERROR(1, "Error unlocking previously locked " |
@@ -1209,7 +1270,7 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type, | |||
1209 | return 0; | 1270 | return 0; |
1210 | } | 1271 | } |
1211 | 1272 | ||
1212 | static void | 1273 | void |
1213 | cifs_move_llist(struct list_head *source, struct list_head *dest) | 1274 | cifs_move_llist(struct list_head *source, struct list_head *dest) |
1214 | { | 1275 | { |
1215 | struct list_head *li, *tmp; | 1276 | struct list_head *li, *tmp; |
@@ -1217,7 +1278,7 @@ cifs_move_llist(struct list_head *source, struct list_head *dest) | |||
1217 | list_move(li, dest); | 1278 | list_move(li, dest); |
1218 | } | 1279 | } |
1219 | 1280 | ||
1220 | static void | 1281 | void |
1221 | cifs_free_llist(struct list_head *llist) | 1282 | cifs_free_llist(struct list_head *llist) |
1222 | { | 1283 | { |
1223 | struct cifsLockInfo *li, *tmp; | 1284 | struct cifsLockInfo *li, *tmp; |
@@ -1228,7 +1289,7 @@ cifs_free_llist(struct list_head *llist) | |||
1228 | } | 1289 | } |
1229 | } | 1290 | } |
1230 | 1291 | ||
1231 | static int | 1292 | int |
1232 | cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, | 1293 | cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, |
1233 | unsigned int xid) | 1294 | unsigned int xid) |
1234 | { | 1295 | { |
@@ -1260,11 +1321,11 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, | |||
1260 | if (!buf) | 1321 | if (!buf) |
1261 | return -ENOMEM; | 1322 | return -ENOMEM; |
1262 | 1323 | ||
1263 | mutex_lock(&cinode->lock_mutex); | 1324 | down_write(&cinode->lock_sem); |
1264 | for (i = 0; i < 2; i++) { | 1325 | for (i = 0; i < 2; i++) { |
1265 | cur = buf; | 1326 | cur = buf; |
1266 | num = 0; | 1327 | num = 0; |
1267 | list_for_each_entry_safe(li, tmp, &cfile->llist, llist) { | 1328 | list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) { |
1268 | if (flock->fl_start > li->offset || | 1329 | if (flock->fl_start > li->offset || |
1269 | (flock->fl_start + length) < | 1330 | (flock->fl_start + length) < |
1270 | (li->offset + li->length)) | 1331 | (li->offset + li->length)) |
@@ -1295,7 +1356,8 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, | |||
1295 | */ | 1356 | */ |
1296 | list_move(&li->llist, &tmp_llist); | 1357 | list_move(&li->llist, &tmp_llist); |
1297 | if (++num == max_num) { | 1358 | if (++num == max_num) { |
1298 | stored_rc = cifs_lockv(xid, tcon, cfile->netfid, | 1359 | stored_rc = cifs_lockv(xid, tcon, |
1360 | cfile->fid.netfid, | ||
1299 | li->type, num, 0, buf); | 1361 | li->type, num, 0, buf); |
1300 | if (stored_rc) { | 1362 | if (stored_rc) { |
1301 | /* | 1363 | /* |
@@ -1304,7 +1366,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, | |||
1304 | * list to the head of the file's list. | 1366 | * list to the head of the file's list. |
1305 | */ | 1367 | */ |
1306 | cifs_move_llist(&tmp_llist, | 1368 | cifs_move_llist(&tmp_llist, |
1307 | &cfile->llist); | 1369 | &cfile->llist->locks); |
1308 | rc = stored_rc; | 1370 | rc = stored_rc; |
1309 | } else | 1371 | } else |
1310 | /* | 1372 | /* |
@@ -1318,23 +1380,24 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, | |||
1318 | cur++; | 1380 | cur++; |
1319 | } | 1381 | } |
1320 | if (num) { | 1382 | if (num) { |
1321 | stored_rc = cifs_lockv(xid, tcon, cfile->netfid, | 1383 | stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid, |
1322 | types[i], num, 0, buf); | 1384 | types[i], num, 0, buf); |
1323 | if (stored_rc) { | 1385 | if (stored_rc) { |
1324 | cifs_move_llist(&tmp_llist, &cfile->llist); | 1386 | cifs_move_llist(&tmp_llist, |
1387 | &cfile->llist->locks); | ||
1325 | rc = stored_rc; | 1388 | rc = stored_rc; |
1326 | } else | 1389 | } else |
1327 | cifs_free_llist(&tmp_llist); | 1390 | cifs_free_llist(&tmp_llist); |
1328 | } | 1391 | } |
1329 | } | 1392 | } |
1330 | 1393 | ||
1331 | mutex_unlock(&cinode->lock_mutex); | 1394 | up_write(&cinode->lock_sem); |
1332 | kfree(buf); | 1395 | kfree(buf); |
1333 | return rc; | 1396 | return rc; |
1334 | } | 1397 | } |
1335 | 1398 | ||
1336 | static int | 1399 | static int |
1337 | cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, | 1400 | cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, |
1338 | bool wait_flag, bool posix_lck, int lock, int unlock, | 1401 | bool wait_flag, bool posix_lck, int lock, int unlock, |
1339 | unsigned int xid) | 1402 | unsigned int xid) |
1340 | { | 1403 | { |
@@ -1343,7 +1406,6 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, | |||
1343 | struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; | 1406 | struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; |
1344 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | 1407 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
1345 | struct TCP_Server_Info *server = tcon->ses->server; | 1408 | struct TCP_Server_Info *server = tcon->ses->server; |
1346 | __u16 netfid = cfile->netfid; | ||
1347 | 1409 | ||
1348 | if (posix_lck) { | 1410 | if (posix_lck) { |
1349 | int posix_lock_type; | 1411 | int posix_lock_type; |
@@ -1360,9 +1422,9 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, | |||
1360 | if (unlock == 1) | 1422 | if (unlock == 1) |
1361 | posix_lock_type = CIFS_UNLCK; | 1423 | posix_lock_type = CIFS_UNLCK; |
1362 | 1424 | ||
1363 | rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid, | 1425 | rc = CIFSSMBPosixLock(xid, tcon, cfile->fid.netfid, |
1364 | flock->fl_start, length, NULL, | 1426 | current->tgid, flock->fl_start, length, |
1365 | posix_lock_type, wait_flag); | 1427 | NULL, posix_lock_type, wait_flag); |
1366 | goto out; | 1428 | goto out; |
1367 | } | 1429 | } |
1368 | 1430 | ||
@@ -1379,8 +1441,8 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, | |||
1379 | if (rc <= 0) | 1441 | if (rc <= 0) |
1380 | goto out; | 1442 | goto out; |
1381 | 1443 | ||
1382 | rc = cifs_mandatory_lock(xid, cfile, flock->fl_start, length, | 1444 | rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length, |
1383 | type, 1, 0, wait_flag); | 1445 | type, 1, 0, wait_flag); |
1384 | if (rc) { | 1446 | if (rc) { |
1385 | kfree(lock); | 1447 | kfree(lock); |
1386 | goto out; | 1448 | goto out; |
@@ -1388,7 +1450,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, | |||
1388 | 1450 | ||
1389 | cifs_lock_add(cfile, lock); | 1451 | cifs_lock_add(cfile, lock); |
1390 | } else if (unlock) | 1452 | } else if (unlock) |
1391 | rc = cifs_unlock_range(cfile, flock, xid); | 1453 | rc = server->ops->mand_unlock_range(cfile, flock, xid); |
1392 | 1454 | ||
1393 | out: | 1455 | out: |
1394 | if (flock->fl_flags & FL_POSIX) | 1456 | if (flock->fl_flags & FL_POSIX) |
@@ -1423,7 +1485,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) | |||
1423 | tcon->ses->server); | 1485 | tcon->ses->server); |
1424 | 1486 | ||
1425 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1487 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
1426 | netfid = cfile->netfid; | 1488 | netfid = cfile->fid.netfid; |
1427 | cinode = CIFS_I(file->f_path.dentry->d_inode); | 1489 | cinode = CIFS_I(file->f_path.dentry->d_inode); |
1428 | 1490 | ||
1429 | if (cap_unix(tcon->ses) && | 1491 | if (cap_unix(tcon->ses) && |
@@ -1469,15 +1531,16 @@ cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | |||
1469 | cifsi->server_eof = end_of_write; | 1531 | cifsi->server_eof = end_of_write; |
1470 | } | 1532 | } |
1471 | 1533 | ||
1472 | static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid, | 1534 | static ssize_t |
1473 | const char *write_data, size_t write_size, | 1535 | cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data, |
1474 | loff_t *poffset) | 1536 | size_t write_size, loff_t *offset) |
1475 | { | 1537 | { |
1476 | int rc = 0; | 1538 | int rc = 0; |
1477 | unsigned int bytes_written = 0; | 1539 | unsigned int bytes_written = 0; |
1478 | unsigned int total_written; | 1540 | unsigned int total_written; |
1479 | struct cifs_sb_info *cifs_sb; | 1541 | struct cifs_sb_info *cifs_sb; |
1480 | struct cifs_tcon *pTcon; | 1542 | struct cifs_tcon *tcon; |
1543 | struct TCP_Server_Info *server; | ||
1481 | unsigned int xid; | 1544 | unsigned int xid; |
1482 | struct dentry *dentry = open_file->dentry; | 1545 | struct dentry *dentry = open_file->dentry; |
1483 | struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); | 1546 | struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); |
@@ -1486,9 +1549,13 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid, | |||
1486 | cifs_sb = CIFS_SB(dentry->d_sb); | 1549 | cifs_sb = CIFS_SB(dentry->d_sb); |
1487 | 1550 | ||
1488 | cFYI(1, "write %zd bytes to offset %lld of %s", write_size, | 1551 | cFYI(1, "write %zd bytes to offset %lld of %s", write_size, |
1489 | *poffset, dentry->d_name.name); | 1552 | *offset, dentry->d_name.name); |
1490 | 1553 | ||
1491 | pTcon = tlink_tcon(open_file->tlink); | 1554 | tcon = tlink_tcon(open_file->tlink); |
1555 | server = tcon->ses->server; | ||
1556 | |||
1557 | if (!server->ops->sync_write) | ||
1558 | return -ENOSYS; | ||
1492 | 1559 | ||
1493 | xid = get_xid(); | 1560 | xid = get_xid(); |
1494 | 1561 | ||
@@ -1514,13 +1581,12 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid, | |||
1514 | /* iov[0] is reserved for smb header */ | 1581 | /* iov[0] is reserved for smb header */ |
1515 | iov[1].iov_base = (char *)write_data + total_written; | 1582 | iov[1].iov_base = (char *)write_data + total_written; |
1516 | iov[1].iov_len = len; | 1583 | iov[1].iov_len = len; |
1517 | io_parms.netfid = open_file->netfid; | ||
1518 | io_parms.pid = pid; | 1584 | io_parms.pid = pid; |
1519 | io_parms.tcon = pTcon; | 1585 | io_parms.tcon = tcon; |
1520 | io_parms.offset = *poffset; | 1586 | io_parms.offset = *offset; |
1521 | io_parms.length = len; | 1587 | io_parms.length = len; |
1522 | rc = CIFSSMBWrite2(xid, &io_parms, &bytes_written, iov, | 1588 | rc = server->ops->sync_write(xid, open_file, &io_parms, |
1523 | 1, 0); | 1589 | &bytes_written, iov, 1); |
1524 | } | 1590 | } |
1525 | if (rc || (bytes_written == 0)) { | 1591 | if (rc || (bytes_written == 0)) { |
1526 | if (total_written) | 1592 | if (total_written) |
@@ -1531,18 +1597,18 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid, | |||
1531 | } | 1597 | } |
1532 | } else { | 1598 | } else { |
1533 | spin_lock(&dentry->d_inode->i_lock); | 1599 | spin_lock(&dentry->d_inode->i_lock); |
1534 | cifs_update_eof(cifsi, *poffset, bytes_written); | 1600 | cifs_update_eof(cifsi, *offset, bytes_written); |
1535 | spin_unlock(&dentry->d_inode->i_lock); | 1601 | spin_unlock(&dentry->d_inode->i_lock); |
1536 | *poffset += bytes_written; | 1602 | *offset += bytes_written; |
1537 | } | 1603 | } |
1538 | } | 1604 | } |
1539 | 1605 | ||
1540 | cifs_stats_bytes_written(pTcon, total_written); | 1606 | cifs_stats_bytes_written(tcon, total_written); |
1541 | 1607 | ||
1542 | if (total_written > 0) { | 1608 | if (total_written > 0) { |
1543 | spin_lock(&dentry->d_inode->i_lock); | 1609 | spin_lock(&dentry->d_inode->i_lock); |
1544 | if (*poffset > dentry->d_inode->i_size) | 1610 | if (*offset > dentry->d_inode->i_size) |
1545 | i_size_write(dentry->d_inode, *poffset); | 1611 | i_size_write(dentry->d_inode, *offset); |
1546 | spin_unlock(&dentry->d_inode->i_lock); | 1612 | spin_unlock(&dentry->d_inode->i_lock); |
1547 | } | 1613 | } |
1548 | mark_inode_dirty_sync(dentry->d_inode); | 1614 | mark_inode_dirty_sync(dentry->d_inode); |
@@ -1718,27 +1784,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | |||
1718 | return rc; | 1784 | return rc; |
1719 | } | 1785 | } |
1720 | 1786 | ||
1721 | /* | ||
1722 | * Marshal up the iov array, reserving the first one for the header. Also, | ||
1723 | * set wdata->bytes. | ||
1724 | */ | ||
1725 | static void | ||
1726 | cifs_writepages_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata) | ||
1727 | { | ||
1728 | int i; | ||
1729 | struct inode *inode = wdata->cfile->dentry->d_inode; | ||
1730 | loff_t size = i_size_read(inode); | ||
1731 | |||
1732 | /* marshal up the pages into iov array */ | ||
1733 | wdata->bytes = 0; | ||
1734 | for (i = 0; i < wdata->nr_pages; i++) { | ||
1735 | iov[i + 1].iov_len = min(size - page_offset(wdata->pages[i]), | ||
1736 | (loff_t)PAGE_CACHE_SIZE); | ||
1737 | iov[i + 1].iov_base = kmap(wdata->pages[i]); | ||
1738 | wdata->bytes += iov[i + 1].iov_len; | ||
1739 | } | ||
1740 | } | ||
1741 | |||
1742 | static int cifs_writepages(struct address_space *mapping, | 1787 | static int cifs_writepages(struct address_space *mapping, |
1743 | struct writeback_control *wbc) | 1788 | struct writeback_control *wbc) |
1744 | { | 1789 | { |
@@ -1746,8 +1791,10 @@ static int cifs_writepages(struct address_space *mapping, | |||
1746 | bool done = false, scanned = false, range_whole = false; | 1791 | bool done = false, scanned = false, range_whole = false; |
1747 | pgoff_t end, index; | 1792 | pgoff_t end, index; |
1748 | struct cifs_writedata *wdata; | 1793 | struct cifs_writedata *wdata; |
1794 | struct TCP_Server_Info *server; | ||
1749 | struct page *page; | 1795 | struct page *page; |
1750 | int rc = 0; | 1796 | int rc = 0; |
1797 | loff_t isize = i_size_read(mapping->host); | ||
1751 | 1798 | ||
1752 | /* | 1799 | /* |
1753 | * If wsize is smaller than the page cache size, default to writing | 1800 | * If wsize is smaller than the page cache size, default to writing |
@@ -1852,7 +1899,7 @@ retry: | |||
1852 | */ | 1899 | */ |
1853 | set_page_writeback(page); | 1900 | set_page_writeback(page); |
1854 | 1901 | ||
1855 | if (page_offset(page) >= mapping->host->i_size) { | 1902 | if (page_offset(page) >= isize) { |
1856 | done = true; | 1903 | done = true; |
1857 | unlock_page(page); | 1904 | unlock_page(page); |
1858 | end_page_writeback(page); | 1905 | end_page_writeback(page); |
@@ -1883,7 +1930,12 @@ retry: | |||
1883 | wdata->sync_mode = wbc->sync_mode; | 1930 | wdata->sync_mode = wbc->sync_mode; |
1884 | wdata->nr_pages = nr_pages; | 1931 | wdata->nr_pages = nr_pages; |
1885 | wdata->offset = page_offset(wdata->pages[0]); | 1932 | wdata->offset = page_offset(wdata->pages[0]); |
1886 | wdata->marshal_iov = cifs_writepages_marshal_iov; | 1933 | wdata->pagesz = PAGE_CACHE_SIZE; |
1934 | wdata->tailsz = | ||
1935 | min(isize - page_offset(wdata->pages[nr_pages - 1]), | ||
1936 | (loff_t)PAGE_CACHE_SIZE); | ||
1937 | wdata->bytes = ((nr_pages - 1) * PAGE_CACHE_SIZE) + | ||
1938 | wdata->tailsz; | ||
1887 | 1939 | ||
1888 | do { | 1940 | do { |
1889 | if (wdata->cfile != NULL) | 1941 | if (wdata->cfile != NULL) |
@@ -1896,7 +1948,8 @@ retry: | |||
1896 | break; | 1948 | break; |
1897 | } | 1949 | } |
1898 | wdata->pid = wdata->cfile->pid; | 1950 | wdata->pid = wdata->cfile->pid; |
1899 | rc = cifs_async_writev(wdata); | 1951 | server = tlink_tcon(wdata->cfile->tlink)->ses->server; |
1952 | rc = server->ops->async_writev(wdata); | ||
1900 | } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN); | 1953 | } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN); |
1901 | 1954 | ||
1902 | for (i = 0; i < nr_pages; ++i) | 1955 | for (i = 0; i < nr_pages; ++i) |
@@ -2054,6 +2107,7 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end, | |||
2054 | unsigned int xid; | 2107 | unsigned int xid; |
2055 | int rc = 0; | 2108 | int rc = 0; |
2056 | struct cifs_tcon *tcon; | 2109 | struct cifs_tcon *tcon; |
2110 | struct TCP_Server_Info *server; | ||
2057 | struct cifsFileInfo *smbfile = file->private_data; | 2111 | struct cifsFileInfo *smbfile = file->private_data; |
2058 | struct inode *inode = file->f_path.dentry->d_inode; | 2112 | struct inode *inode = file->f_path.dentry->d_inode; |
2059 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 2113 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
@@ -2077,8 +2131,13 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end, | |||
2077 | } | 2131 | } |
2078 | 2132 | ||
2079 | tcon = tlink_tcon(smbfile->tlink); | 2133 | tcon = tlink_tcon(smbfile->tlink); |
2080 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | 2134 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { |
2081 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | 2135 | server = tcon->ses->server; |
2136 | if (server->ops->flush) | ||
2137 | rc = server->ops->flush(xid, tcon, &smbfile->fid); | ||
2138 | else | ||
2139 | rc = -ENOSYS; | ||
2140 | } | ||
2082 | 2141 | ||
2083 | free_xid(xid); | 2142 | free_xid(xid); |
2084 | mutex_unlock(&inode->i_mutex); | 2143 | mutex_unlock(&inode->i_mutex); |
@@ -2090,6 +2149,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
2090 | unsigned int xid; | 2149 | unsigned int xid; |
2091 | int rc = 0; | 2150 | int rc = 0; |
2092 | struct cifs_tcon *tcon; | 2151 | struct cifs_tcon *tcon; |
2152 | struct TCP_Server_Info *server; | ||
2093 | struct cifsFileInfo *smbfile = file->private_data; | 2153 | struct cifsFileInfo *smbfile = file->private_data; |
2094 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 2154 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
2095 | struct inode *inode = file->f_mapping->host; | 2155 | struct inode *inode = file->f_mapping->host; |
@@ -2105,8 +2165,13 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
2105 | file->f_path.dentry->d_name.name, datasync); | 2165 | file->f_path.dentry->d_name.name, datasync); |
2106 | 2166 | ||
2107 | tcon = tlink_tcon(smbfile->tlink); | 2167 | tcon = tlink_tcon(smbfile->tlink); |
2108 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | 2168 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { |
2109 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | 2169 | server = tcon->ses->server; |
2170 | if (server->ops->flush) | ||
2171 | rc = server->ops->flush(xid, tcon, &smbfile->fid); | ||
2172 | else | ||
2173 | rc = -ENOSYS; | ||
2174 | } | ||
2110 | 2175 | ||
2111 | free_xid(xid); | 2176 | free_xid(xid); |
2112 | mutex_unlock(&inode->i_mutex); | 2177 | mutex_unlock(&inode->i_mutex); |
@@ -2172,20 +2237,6 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len) | |||
2172 | } | 2237 | } |
2173 | 2238 | ||
2174 | static void | 2239 | static void |
2175 | cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata) | ||
2176 | { | ||
2177 | int i; | ||
2178 | size_t bytes = wdata->bytes; | ||
2179 | |||
2180 | /* marshal up the pages into iov array */ | ||
2181 | for (i = 0; i < wdata->nr_pages; i++) { | ||
2182 | iov[i + 1].iov_len = min_t(size_t, bytes, PAGE_SIZE); | ||
2183 | iov[i + 1].iov_base = kmap(wdata->pages[i]); | ||
2184 | bytes -= iov[i + 1].iov_len; | ||
2185 | } | ||
2186 | } | ||
2187 | |||
2188 | static void | ||
2189 | cifs_uncached_writev_complete(struct work_struct *work) | 2240 | cifs_uncached_writev_complete(struct work_struct *work) |
2190 | { | 2241 | { |
2191 | int i; | 2242 | int i; |
@@ -2215,6 +2266,9 @@ static int | |||
2215 | cifs_uncached_retry_writev(struct cifs_writedata *wdata) | 2266 | cifs_uncached_retry_writev(struct cifs_writedata *wdata) |
2216 | { | 2267 | { |
2217 | int rc; | 2268 | int rc; |
2269 | struct TCP_Server_Info *server; | ||
2270 | |||
2271 | server = tlink_tcon(wdata->cfile->tlink)->ses->server; | ||
2218 | 2272 | ||
2219 | do { | 2273 | do { |
2220 | if (wdata->cfile->invalidHandle) { | 2274 | if (wdata->cfile->invalidHandle) { |
@@ -2222,7 +2276,7 @@ cifs_uncached_retry_writev(struct cifs_writedata *wdata) | |||
2222 | if (rc != 0) | 2276 | if (rc != 0) |
2223 | continue; | 2277 | continue; |
2224 | } | 2278 | } |
2225 | rc = cifs_async_writev(wdata); | 2279 | rc = server->ops->async_writev(wdata); |
2226 | } while (rc == -EAGAIN); | 2280 | } while (rc == -EAGAIN); |
2227 | 2281 | ||
2228 | return rc; | 2282 | return rc; |
@@ -2257,6 +2311,10 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | |||
2257 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 2311 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
2258 | open_file = file->private_data; | 2312 | open_file = file->private_data; |
2259 | tcon = tlink_tcon(open_file->tlink); | 2313 | tcon = tlink_tcon(open_file->tlink); |
2314 | |||
2315 | if (!tcon->ses->server->ops->async_writev) | ||
2316 | return -ENOSYS; | ||
2317 | |||
2260 | offset = *poffset; | 2318 | offset = *poffset; |
2261 | 2319 | ||
2262 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) | 2320 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) |
@@ -2298,7 +2356,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | |||
2298 | wdata->cfile = cifsFileInfo_get(open_file); | 2356 | wdata->cfile = cifsFileInfo_get(open_file); |
2299 | wdata->pid = pid; | 2357 | wdata->pid = pid; |
2300 | wdata->bytes = cur_len; | 2358 | wdata->bytes = cur_len; |
2301 | wdata->marshal_iov = cifs_uncached_marshal_iov; | 2359 | wdata->pagesz = PAGE_SIZE; |
2360 | wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); | ||
2302 | rc = cifs_uncached_retry_writev(wdata); | 2361 | rc = cifs_uncached_retry_writev(wdata); |
2303 | if (rc) { | 2362 | if (rc) { |
2304 | kref_put(&wdata->refcount, cifs_writedata_release); | 2363 | kref_put(&wdata->refcount, cifs_writedata_release); |
@@ -2376,40 +2435,110 @@ ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, | |||
2376 | return written; | 2435 | return written; |
2377 | } | 2436 | } |
2378 | 2437 | ||
2379 | ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, | 2438 | static ssize_t |
2380 | unsigned long nr_segs, loff_t pos) | 2439 | cifs_writev(struct kiocb *iocb, const struct iovec *iov, |
2440 | unsigned long nr_segs, loff_t pos) | ||
2381 | { | 2441 | { |
2382 | struct inode *inode; | 2442 | struct file *file = iocb->ki_filp; |
2443 | struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; | ||
2444 | struct inode *inode = file->f_mapping->host; | ||
2445 | struct cifsInodeInfo *cinode = CIFS_I(inode); | ||
2446 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; | ||
2447 | ssize_t rc = -EACCES; | ||
2383 | 2448 | ||
2384 | inode = iocb->ki_filp->f_path.dentry->d_inode; | 2449 | BUG_ON(iocb->ki_pos != pos); |
2385 | 2450 | ||
2386 | if (CIFS_I(inode)->clientCanCacheAll) | 2451 | sb_start_write(inode->i_sb); |
2387 | return generic_file_aio_write(iocb, iov, nr_segs, pos); | 2452 | |
2453 | /* | ||
2454 | * We need to hold the sem to be sure nobody modifies lock list | ||
2455 | * with a brlock that prevents writing. | ||
2456 | */ | ||
2457 | down_read(&cinode->lock_sem); | ||
2458 | if (!cifs_find_lock_conflict(cfile, pos, iov_length(iov, nr_segs), | ||
2459 | server->vals->exclusive_lock_type, NULL, | ||
2460 | true)) { | ||
2461 | mutex_lock(&inode->i_mutex); | ||
2462 | rc = __generic_file_aio_write(iocb, iov, nr_segs, | ||
2463 | &iocb->ki_pos); | ||
2464 | mutex_unlock(&inode->i_mutex); | ||
2465 | } | ||
2466 | |||
2467 | if (rc > 0 || rc == -EIOCBQUEUED) { | ||
2468 | ssize_t err; | ||
2469 | |||
2470 | err = generic_write_sync(file, pos, rc); | ||
2471 | if (err < 0 && rc > 0) | ||
2472 | rc = err; | ||
2473 | } | ||
2474 | |||
2475 | up_read(&cinode->lock_sem); | ||
2476 | sb_end_write(inode->i_sb); | ||
2477 | return rc; | ||
2478 | } | ||
2479 | |||
2480 | ssize_t | ||
2481 | cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, | ||
2482 | unsigned long nr_segs, loff_t pos) | ||
2483 | { | ||
2484 | struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; | ||
2485 | struct cifsInodeInfo *cinode = CIFS_I(inode); | ||
2486 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
2487 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) | ||
2488 | iocb->ki_filp->private_data; | ||
2489 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | ||
2388 | 2490 | ||
2491 | #ifdef CONFIG_CIFS_SMB2 | ||
2389 | /* | 2492 | /* |
2390 | * In strict cache mode we need to write the data to the server exactly | 2493 | * If we have an oplock for read and want to write a data to the file |
2391 | * from the pos to pos+len-1 rather than flush all affected pages | 2494 | * we need to store it in the page cache and then push it to the server |
2392 | * because it may cause a error with mandatory locks on these pages but | 2495 | * to be sure the next read will get a valid data. |
2393 | * not on the region from pos to ppos+len-1. | ||
2394 | */ | 2496 | */ |
2497 | if (!cinode->clientCanCacheAll && cinode->clientCanCacheRead) { | ||
2498 | ssize_t written; | ||
2499 | int rc; | ||
2395 | 2500 | ||
2396 | return cifs_user_writev(iocb, iov, nr_segs, pos); | 2501 | written = generic_file_aio_write(iocb, iov, nr_segs, pos); |
2502 | rc = filemap_fdatawrite(inode->i_mapping); | ||
2503 | if (rc) | ||
2504 | return (ssize_t)rc; | ||
2505 | |||
2506 | return written; | ||
2507 | } | ||
2508 | #endif | ||
2509 | |||
2510 | /* | ||
2511 | * For non-oplocked files in strict cache mode we need to write the data | ||
2512 | * to the server exactly from the pos to pos+len-1 rather than flush all | ||
2513 | * affected pages because it may cause a error with mandatory locks on | ||
2514 | * these pages but not on the region from pos to ppos+len-1. | ||
2515 | */ | ||
2516 | |||
2517 | if (!cinode->clientCanCacheAll) | ||
2518 | return cifs_user_writev(iocb, iov, nr_segs, pos); | ||
2519 | |||
2520 | if (cap_unix(tcon->ses) && | ||
2521 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && | ||
2522 | ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) | ||
2523 | return generic_file_aio_write(iocb, iov, nr_segs, pos); | ||
2524 | |||
2525 | return cifs_writev(iocb, iov, nr_segs, pos); | ||
2397 | } | 2526 | } |
2398 | 2527 | ||
2399 | static struct cifs_readdata * | 2528 | static struct cifs_readdata * |
2400 | cifs_readdata_alloc(unsigned int nr_vecs, work_func_t complete) | 2529 | cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete) |
2401 | { | 2530 | { |
2402 | struct cifs_readdata *rdata; | 2531 | struct cifs_readdata *rdata; |
2403 | 2532 | ||
2404 | rdata = kzalloc(sizeof(*rdata) + | 2533 | rdata = kzalloc(sizeof(*rdata) + (sizeof(struct page *) * nr_pages), |
2405 | sizeof(struct kvec) * nr_vecs, GFP_KERNEL); | 2534 | GFP_KERNEL); |
2406 | if (rdata != NULL) { | 2535 | if (rdata != NULL) { |
2407 | kref_init(&rdata->refcount); | 2536 | kref_init(&rdata->refcount); |
2408 | INIT_LIST_HEAD(&rdata->list); | 2537 | INIT_LIST_HEAD(&rdata->list); |
2409 | init_completion(&rdata->done); | 2538 | init_completion(&rdata->done); |
2410 | INIT_WORK(&rdata->work, complete); | 2539 | INIT_WORK(&rdata->work, complete); |
2411 | INIT_LIST_HEAD(&rdata->pages); | ||
2412 | } | 2540 | } |
2541 | |||
2413 | return rdata; | 2542 | return rdata; |
2414 | } | 2543 | } |
2415 | 2544 | ||
@@ -2426,25 +2555,25 @@ cifs_readdata_release(struct kref *refcount) | |||
2426 | } | 2555 | } |
2427 | 2556 | ||
2428 | static int | 2557 | static int |
2429 | cifs_read_allocate_pages(struct list_head *list, unsigned int npages) | 2558 | cifs_read_allocate_pages(struct cifs_readdata *rdata, unsigned int nr_pages) |
2430 | { | 2559 | { |
2431 | int rc = 0; | 2560 | int rc = 0; |
2432 | struct page *page, *tpage; | 2561 | struct page *page; |
2433 | unsigned int i; | 2562 | unsigned int i; |
2434 | 2563 | ||
2435 | for (i = 0; i < npages; i++) { | 2564 | for (i = 0; i < nr_pages; i++) { |
2436 | page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM); | 2565 | page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM); |
2437 | if (!page) { | 2566 | if (!page) { |
2438 | rc = -ENOMEM; | 2567 | rc = -ENOMEM; |
2439 | break; | 2568 | break; |
2440 | } | 2569 | } |
2441 | list_add(&page->lru, list); | 2570 | rdata->pages[i] = page; |
2442 | } | 2571 | } |
2443 | 2572 | ||
2444 | if (rc) { | 2573 | if (rc) { |
2445 | list_for_each_entry_safe(page, tpage, list, lru) { | 2574 | for (i = 0; i < nr_pages; i++) { |
2446 | list_del(&page->lru); | 2575 | put_page(rdata->pages[i]); |
2447 | put_page(page); | 2576 | rdata->pages[i] = NULL; |
2448 | } | 2577 | } |
2449 | } | 2578 | } |
2450 | return rc; | 2579 | return rc; |
@@ -2453,13 +2582,13 @@ cifs_read_allocate_pages(struct list_head *list, unsigned int npages) | |||
2453 | static void | 2582 | static void |
2454 | cifs_uncached_readdata_release(struct kref *refcount) | 2583 | cifs_uncached_readdata_release(struct kref *refcount) |
2455 | { | 2584 | { |
2456 | struct page *page, *tpage; | ||
2457 | struct cifs_readdata *rdata = container_of(refcount, | 2585 | struct cifs_readdata *rdata = container_of(refcount, |
2458 | struct cifs_readdata, refcount); | 2586 | struct cifs_readdata, refcount); |
2587 | unsigned int i; | ||
2459 | 2588 | ||
2460 | list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { | 2589 | for (i = 0; i < rdata->nr_pages; i++) { |
2461 | list_del(&page->lru); | 2590 | put_page(rdata->pages[i]); |
2462 | put_page(page); | 2591 | rdata->pages[i] = NULL; |
2463 | } | 2592 | } |
2464 | cifs_readdata_release(refcount); | 2593 | cifs_readdata_release(refcount); |
2465 | } | 2594 | } |
@@ -2468,6 +2597,9 @@ static int | |||
2468 | cifs_retry_async_readv(struct cifs_readdata *rdata) | 2597 | cifs_retry_async_readv(struct cifs_readdata *rdata) |
2469 | { | 2598 | { |
2470 | int rc; | 2599 | int rc; |
2600 | struct TCP_Server_Info *server; | ||
2601 | |||
2602 | server = tlink_tcon(rdata->cfile->tlink)->ses->server; | ||
2471 | 2603 | ||
2472 | do { | 2604 | do { |
2473 | if (rdata->cfile->invalidHandle) { | 2605 | if (rdata->cfile->invalidHandle) { |
@@ -2475,7 +2607,7 @@ cifs_retry_async_readv(struct cifs_readdata *rdata) | |||
2475 | if (rc != 0) | 2607 | if (rc != 0) |
2476 | continue; | 2608 | continue; |
2477 | } | 2609 | } |
2478 | rc = cifs_async_readv(rdata); | 2610 | rc = server->ops->async_readv(rdata); |
2479 | } while (rc == -EAGAIN); | 2611 | } while (rc == -EAGAIN); |
2480 | 2612 | ||
2481 | return rc; | 2613 | return rc; |
@@ -2500,17 +2632,18 @@ cifs_readdata_to_iov(struct cifs_readdata *rdata, const struct iovec *iov, | |||
2500 | int rc = 0; | 2632 | int rc = 0; |
2501 | struct iov_iter ii; | 2633 | struct iov_iter ii; |
2502 | size_t pos = rdata->offset - offset; | 2634 | size_t pos = rdata->offset - offset; |
2503 | struct page *page, *tpage; | ||
2504 | ssize_t remaining = rdata->bytes; | 2635 | ssize_t remaining = rdata->bytes; |
2505 | unsigned char *pdata; | 2636 | unsigned char *pdata; |
2637 | unsigned int i; | ||
2506 | 2638 | ||
2507 | /* set up iov_iter and advance to the correct offset */ | 2639 | /* set up iov_iter and advance to the correct offset */ |
2508 | iov_iter_init(&ii, iov, nr_segs, iov_length(iov, nr_segs), 0); | 2640 | iov_iter_init(&ii, iov, nr_segs, iov_length(iov, nr_segs), 0); |
2509 | iov_iter_advance(&ii, pos); | 2641 | iov_iter_advance(&ii, pos); |
2510 | 2642 | ||
2511 | *copied = 0; | 2643 | *copied = 0; |
2512 | list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { | 2644 | for (i = 0; i < rdata->nr_pages; i++) { |
2513 | ssize_t copy; | 2645 | ssize_t copy; |
2646 | struct page *page = rdata->pages[i]; | ||
2514 | 2647 | ||
2515 | /* copy a whole page or whatever's left */ | 2648 | /* copy a whole page or whatever's left */ |
2516 | copy = min_t(ssize_t, remaining, PAGE_SIZE); | 2649 | copy = min_t(ssize_t, remaining, PAGE_SIZE); |
@@ -2530,9 +2663,6 @@ cifs_readdata_to_iov(struct cifs_readdata *rdata, const struct iovec *iov, | |||
2530 | iov_iter_advance(&ii, copy); | 2663 | iov_iter_advance(&ii, copy); |
2531 | } | 2664 | } |
2532 | } | 2665 | } |
2533 | |||
2534 | list_del(&page->lru); | ||
2535 | put_page(page); | ||
2536 | } | 2666 | } |
2537 | 2667 | ||
2538 | return rc; | 2668 | return rc; |
@@ -2544,59 +2674,56 @@ cifs_uncached_readv_complete(struct work_struct *work) | |||
2544 | struct cifs_readdata *rdata = container_of(work, | 2674 | struct cifs_readdata *rdata = container_of(work, |
2545 | struct cifs_readdata, work); | 2675 | struct cifs_readdata, work); |
2546 | 2676 | ||
2547 | /* if the result is non-zero then the pages weren't kmapped */ | ||
2548 | if (rdata->result == 0) { | ||
2549 | struct page *page; | ||
2550 | |||
2551 | list_for_each_entry(page, &rdata->pages, lru) | ||
2552 | kunmap(page); | ||
2553 | } | ||
2554 | |||
2555 | complete(&rdata->done); | 2677 | complete(&rdata->done); |
2556 | kref_put(&rdata->refcount, cifs_uncached_readdata_release); | 2678 | kref_put(&rdata->refcount, cifs_uncached_readdata_release); |
2557 | } | 2679 | } |
2558 | 2680 | ||
2559 | static int | 2681 | static int |
2560 | cifs_uncached_read_marshal_iov(struct cifs_readdata *rdata, | 2682 | cifs_uncached_read_into_pages(struct TCP_Server_Info *server, |
2561 | unsigned int remaining) | 2683 | struct cifs_readdata *rdata, unsigned int len) |
2562 | { | 2684 | { |
2563 | int len = 0; | 2685 | int total_read = 0, result = 0; |
2564 | struct page *page, *tpage; | 2686 | unsigned int i; |
2687 | unsigned int nr_pages = rdata->nr_pages; | ||
2688 | struct kvec iov; | ||
2689 | |||
2690 | rdata->tailsz = PAGE_SIZE; | ||
2691 | for (i = 0; i < nr_pages; i++) { | ||
2692 | struct page *page = rdata->pages[i]; | ||
2565 | 2693 | ||
2566 | rdata->nr_iov = 1; | 2694 | if (len >= PAGE_SIZE) { |
2567 | list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { | ||
2568 | if (remaining >= PAGE_SIZE) { | ||
2569 | /* enough data to fill the page */ | 2695 | /* enough data to fill the page */ |
2570 | rdata->iov[rdata->nr_iov].iov_base = kmap(page); | 2696 | iov.iov_base = kmap(page); |
2571 | rdata->iov[rdata->nr_iov].iov_len = PAGE_SIZE; | 2697 | iov.iov_len = PAGE_SIZE; |
2572 | cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu", | 2698 | cFYI(1, "%u: iov_base=%p iov_len=%zu", |
2573 | rdata->nr_iov, page->index, | 2699 | i, iov.iov_base, iov.iov_len); |
2574 | rdata->iov[rdata->nr_iov].iov_base, | 2700 | len -= PAGE_SIZE; |
2575 | rdata->iov[rdata->nr_iov].iov_len); | 2701 | } else if (len > 0) { |
2576 | ++rdata->nr_iov; | ||
2577 | len += PAGE_SIZE; | ||
2578 | remaining -= PAGE_SIZE; | ||
2579 | } else if (remaining > 0) { | ||
2580 | /* enough for partial page, fill and zero the rest */ | 2702 | /* enough for partial page, fill and zero the rest */ |
2581 | rdata->iov[rdata->nr_iov].iov_base = kmap(page); | 2703 | iov.iov_base = kmap(page); |
2582 | rdata->iov[rdata->nr_iov].iov_len = remaining; | 2704 | iov.iov_len = len; |
2583 | cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu", | 2705 | cFYI(1, "%u: iov_base=%p iov_len=%zu", |
2584 | rdata->nr_iov, page->index, | 2706 | i, iov.iov_base, iov.iov_len); |
2585 | rdata->iov[rdata->nr_iov].iov_base, | 2707 | memset(iov.iov_base + len, '\0', PAGE_SIZE - len); |
2586 | rdata->iov[rdata->nr_iov].iov_len); | 2708 | rdata->tailsz = len; |
2587 | memset(rdata->iov[rdata->nr_iov].iov_base + remaining, | 2709 | len = 0; |
2588 | '\0', PAGE_SIZE - remaining); | ||
2589 | ++rdata->nr_iov; | ||
2590 | len += remaining; | ||
2591 | remaining = 0; | ||
2592 | } else { | 2710 | } else { |
2593 | /* no need to hold page hostage */ | 2711 | /* no need to hold page hostage */ |
2594 | list_del(&page->lru); | 2712 | rdata->pages[i] = NULL; |
2713 | rdata->nr_pages--; | ||
2595 | put_page(page); | 2714 | put_page(page); |
2715 | continue; | ||
2596 | } | 2716 | } |
2717 | |||
2718 | result = cifs_readv_from_socket(server, &iov, 1, iov.iov_len); | ||
2719 | kunmap(page); | ||
2720 | if (result < 0) | ||
2721 | break; | ||
2722 | |||
2723 | total_read += result; | ||
2597 | } | 2724 | } |
2598 | 2725 | ||
2599 | return len; | 2726 | return total_read > 0 ? total_read : result; |
2600 | } | 2727 | } |
2601 | 2728 | ||
2602 | static ssize_t | 2729 | static ssize_t |
@@ -2627,6 +2754,9 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, | |||
2627 | open_file = file->private_data; | 2754 | open_file = file->private_data; |
2628 | tcon = tlink_tcon(open_file->tlink); | 2755 | tcon = tlink_tcon(open_file->tlink); |
2629 | 2756 | ||
2757 | if (!tcon->ses->server->ops->async_readv) | ||
2758 | return -ENOSYS; | ||
2759 | |||
2630 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) | 2760 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) |
2631 | pid = open_file->pid; | 2761 | pid = open_file->pid; |
2632 | else | 2762 | else |
@@ -2647,15 +2777,17 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, | |||
2647 | goto error; | 2777 | goto error; |
2648 | } | 2778 | } |
2649 | 2779 | ||
2650 | rc = cifs_read_allocate_pages(&rdata->pages, npages); | 2780 | rc = cifs_read_allocate_pages(rdata, npages); |
2651 | if (rc) | 2781 | if (rc) |
2652 | goto error; | 2782 | goto error; |
2653 | 2783 | ||
2654 | rdata->cfile = cifsFileInfo_get(open_file); | 2784 | rdata->cfile = cifsFileInfo_get(open_file); |
2785 | rdata->nr_pages = npages; | ||
2655 | rdata->offset = offset; | 2786 | rdata->offset = offset; |
2656 | rdata->bytes = cur_len; | 2787 | rdata->bytes = cur_len; |
2657 | rdata->pid = pid; | 2788 | rdata->pid = pid; |
2658 | rdata->marshal_iov = cifs_uncached_read_marshal_iov; | 2789 | rdata->pagesz = PAGE_SIZE; |
2790 | rdata->read_into_pages = cifs_uncached_read_into_pages; | ||
2659 | 2791 | ||
2660 | rc = cifs_retry_async_readv(rdata); | 2792 | rc = cifs_retry_async_readv(rdata); |
2661 | error: | 2793 | error: |
@@ -2706,6 +2838,10 @@ restart_loop: | |||
2706 | cifs_stats_bytes_read(tcon, total_read); | 2838 | cifs_stats_bytes_read(tcon, total_read); |
2707 | *poffset += total_read; | 2839 | *poffset += total_read; |
2708 | 2840 | ||
2841 | /* mask nodata case */ | ||
2842 | if (rc == -ENODATA) | ||
2843 | rc = 0; | ||
2844 | |||
2709 | return total_read ? total_read : rc; | 2845 | return total_read ? total_read : rc; |
2710 | } | 2846 | } |
2711 | 2847 | ||
@@ -2721,15 +2857,17 @@ ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, | |||
2721 | return read; | 2857 | return read; |
2722 | } | 2858 | } |
2723 | 2859 | ||
2724 | ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, | 2860 | ssize_t |
2725 | unsigned long nr_segs, loff_t pos) | 2861 | cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, |
2862 | unsigned long nr_segs, loff_t pos) | ||
2726 | { | 2863 | { |
2727 | struct inode *inode; | 2864 | struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; |
2728 | 2865 | struct cifsInodeInfo *cinode = CIFS_I(inode); | |
2729 | inode = iocb->ki_filp->f_path.dentry->d_inode; | 2866 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
2730 | 2867 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) | |
2731 | if (CIFS_I(inode)->clientCanCacheRead) | 2868 | iocb->ki_filp->private_data; |
2732 | return generic_file_aio_read(iocb, iov, nr_segs, pos); | 2869 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
2870 | int rc = -EACCES; | ||
2733 | 2871 | ||
2734 | /* | 2872 | /* |
2735 | * In strict cache mode we need to read from the server all the time | 2873 | * In strict cache mode we need to read from the server all the time |
@@ -2739,12 +2877,29 @@ ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, | |||
2739 | * on pages affected by this read but not on the region from pos to | 2877 | * on pages affected by this read but not on the region from pos to |
2740 | * pos+len-1. | 2878 | * pos+len-1. |
2741 | */ | 2879 | */ |
2880 | if (!cinode->clientCanCacheRead) | ||
2881 | return cifs_user_readv(iocb, iov, nr_segs, pos); | ||
2882 | |||
2883 | if (cap_unix(tcon->ses) && | ||
2884 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && | ||
2885 | ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) | ||
2886 | return generic_file_aio_read(iocb, iov, nr_segs, pos); | ||
2742 | 2887 | ||
2743 | return cifs_user_readv(iocb, iov, nr_segs, pos); | 2888 | /* |
2889 | * We need to hold the sem to be sure nobody modifies lock list | ||
2890 | * with a brlock that prevents reading. | ||
2891 | */ | ||
2892 | down_read(&cinode->lock_sem); | ||
2893 | if (!cifs_find_lock_conflict(cfile, pos, iov_length(iov, nr_segs), | ||
2894 | tcon->ses->server->vals->shared_lock_type, | ||
2895 | NULL, true)) | ||
2896 | rc = generic_file_aio_read(iocb, iov, nr_segs, pos); | ||
2897 | up_read(&cinode->lock_sem); | ||
2898 | return rc; | ||
2744 | } | 2899 | } |
2745 | 2900 | ||
2746 | static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | 2901 | static ssize_t |
2747 | loff_t *poffset) | 2902 | cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) |
2748 | { | 2903 | { |
2749 | int rc = -EACCES; | 2904 | int rc = -EACCES; |
2750 | unsigned int bytes_read = 0; | 2905 | unsigned int bytes_read = 0; |
@@ -2753,8 +2908,9 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
2753 | unsigned int rsize; | 2908 | unsigned int rsize; |
2754 | struct cifs_sb_info *cifs_sb; | 2909 | struct cifs_sb_info *cifs_sb; |
2755 | struct cifs_tcon *tcon; | 2910 | struct cifs_tcon *tcon; |
2911 | struct TCP_Server_Info *server; | ||
2756 | unsigned int xid; | 2912 | unsigned int xid; |
2757 | char *current_offset; | 2913 | char *cur_offset; |
2758 | struct cifsFileInfo *open_file; | 2914 | struct cifsFileInfo *open_file; |
2759 | struct cifs_io_parms io_parms; | 2915 | struct cifs_io_parms io_parms; |
2760 | int buf_type = CIFS_NO_BUFFER; | 2916 | int buf_type = CIFS_NO_BUFFER; |
@@ -2773,6 +2929,12 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
2773 | } | 2929 | } |
2774 | open_file = file->private_data; | 2930 | open_file = file->private_data; |
2775 | tcon = tlink_tcon(open_file->tlink); | 2931 | tcon = tlink_tcon(open_file->tlink); |
2932 | server = tcon->ses->server; | ||
2933 | |||
2934 | if (!server->ops->sync_read) { | ||
2935 | free_xid(xid); | ||
2936 | return -ENOSYS; | ||
2937 | } | ||
2776 | 2938 | ||
2777 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) | 2939 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) |
2778 | pid = open_file->pid; | 2940 | pid = open_file->pid; |
@@ -2782,9 +2944,8 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
2782 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 2944 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) |
2783 | cFYI(1, "attempting read on write only file instance"); | 2945 | cFYI(1, "attempting read on write only file instance"); |
2784 | 2946 | ||
2785 | for (total_read = 0, current_offset = read_data; | 2947 | for (total_read = 0, cur_offset = read_data; read_size > total_read; |
2786 | read_size > total_read; | 2948 | total_read += bytes_read, cur_offset += bytes_read) { |
2787 | total_read += bytes_read, current_offset += bytes_read) { | ||
2788 | current_read_size = min_t(uint, read_size - total_read, rsize); | 2949 | current_read_size = min_t(uint, read_size - total_read, rsize); |
2789 | /* | 2950 | /* |
2790 | * For windows me and 9x we do not want to request more than it | 2951 | * For windows me and 9x we do not want to request more than it |
@@ -2802,13 +2963,13 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
2802 | if (rc != 0) | 2963 | if (rc != 0) |
2803 | break; | 2964 | break; |
2804 | } | 2965 | } |
2805 | io_parms.netfid = open_file->netfid; | ||
2806 | io_parms.pid = pid; | 2966 | io_parms.pid = pid; |
2807 | io_parms.tcon = tcon; | 2967 | io_parms.tcon = tcon; |
2808 | io_parms.offset = *poffset; | 2968 | io_parms.offset = *offset; |
2809 | io_parms.length = current_read_size; | 2969 | io_parms.length = current_read_size; |
2810 | rc = CIFSSMBRead(xid, &io_parms, &bytes_read, | 2970 | rc = server->ops->sync_read(xid, open_file, &io_parms, |
2811 | ¤t_offset, &buf_type); | 2971 | &bytes_read, &cur_offset, |
2972 | &buf_type); | ||
2812 | } | 2973 | } |
2813 | if (rc || (bytes_read == 0)) { | 2974 | if (rc || (bytes_read == 0)) { |
2814 | if (total_read) { | 2975 | if (total_read) { |
@@ -2819,7 +2980,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
2819 | } | 2980 | } |
2820 | } else { | 2981 | } else { |
2821 | cifs_stats_bytes_read(tcon, total_read); | 2982 | cifs_stats_bytes_read(tcon, total_read); |
2822 | *poffset += bytes_read; | 2983 | *offset += bytes_read; |
2823 | } | 2984 | } |
2824 | } | 2985 | } |
2825 | free_xid(xid); | 2986 | free_xid(xid); |
@@ -2885,16 +3046,16 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
2885 | static void | 3046 | static void |
2886 | cifs_readv_complete(struct work_struct *work) | 3047 | cifs_readv_complete(struct work_struct *work) |
2887 | { | 3048 | { |
3049 | unsigned int i; | ||
2888 | struct cifs_readdata *rdata = container_of(work, | 3050 | struct cifs_readdata *rdata = container_of(work, |
2889 | struct cifs_readdata, work); | 3051 | struct cifs_readdata, work); |
2890 | struct page *page, *tpage; | ||
2891 | 3052 | ||
2892 | list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { | 3053 | for (i = 0; i < rdata->nr_pages; i++) { |
2893 | list_del(&page->lru); | 3054 | struct page *page = rdata->pages[i]; |
3055 | |||
2894 | lru_cache_add_file(page); | 3056 | lru_cache_add_file(page); |
2895 | 3057 | ||
2896 | if (rdata->result == 0) { | 3058 | if (rdata->result == 0) { |
2897 | kunmap(page); | ||
2898 | flush_dcache_page(page); | 3059 | flush_dcache_page(page); |
2899 | SetPageUptodate(page); | 3060 | SetPageUptodate(page); |
2900 | } | 3061 | } |
@@ -2905,49 +3066,48 @@ cifs_readv_complete(struct work_struct *work) | |||
2905 | cifs_readpage_to_fscache(rdata->mapping->host, page); | 3066 | cifs_readpage_to_fscache(rdata->mapping->host, page); |
2906 | 3067 | ||
2907 | page_cache_release(page); | 3068 | page_cache_release(page); |
3069 | rdata->pages[i] = NULL; | ||
2908 | } | 3070 | } |
2909 | kref_put(&rdata->refcount, cifs_readdata_release); | 3071 | kref_put(&rdata->refcount, cifs_readdata_release); |
2910 | } | 3072 | } |
2911 | 3073 | ||
2912 | static int | 3074 | static int |
2913 | cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining) | 3075 | cifs_readpages_read_into_pages(struct TCP_Server_Info *server, |
3076 | struct cifs_readdata *rdata, unsigned int len) | ||
2914 | { | 3077 | { |
2915 | int len = 0; | 3078 | int total_read = 0, result = 0; |
2916 | struct page *page, *tpage; | 3079 | unsigned int i; |
2917 | u64 eof; | 3080 | u64 eof; |
2918 | pgoff_t eof_index; | 3081 | pgoff_t eof_index; |
3082 | unsigned int nr_pages = rdata->nr_pages; | ||
3083 | struct kvec iov; | ||
2919 | 3084 | ||
2920 | /* determine the eof that the server (probably) has */ | 3085 | /* determine the eof that the server (probably) has */ |
2921 | eof = CIFS_I(rdata->mapping->host)->server_eof; | 3086 | eof = CIFS_I(rdata->mapping->host)->server_eof; |
2922 | eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0; | 3087 | eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0; |
2923 | cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index); | 3088 | cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index); |
2924 | 3089 | ||
2925 | rdata->nr_iov = 1; | 3090 | rdata->tailsz = PAGE_CACHE_SIZE; |
2926 | list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { | 3091 | for (i = 0; i < nr_pages; i++) { |
2927 | if (remaining >= PAGE_CACHE_SIZE) { | 3092 | struct page *page = rdata->pages[i]; |
3093 | |||
3094 | if (len >= PAGE_CACHE_SIZE) { | ||
2928 | /* enough data to fill the page */ | 3095 | /* enough data to fill the page */ |
2929 | rdata->iov[rdata->nr_iov].iov_base = kmap(page); | 3096 | iov.iov_base = kmap(page); |
2930 | rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE; | 3097 | iov.iov_len = PAGE_CACHE_SIZE; |
2931 | cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu", | 3098 | cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu", |
2932 | rdata->nr_iov, page->index, | 3099 | i, page->index, iov.iov_base, iov.iov_len); |
2933 | rdata->iov[rdata->nr_iov].iov_base, | 3100 | len -= PAGE_CACHE_SIZE; |
2934 | rdata->iov[rdata->nr_iov].iov_len); | 3101 | } else if (len > 0) { |
2935 | ++rdata->nr_iov; | ||
2936 | len += PAGE_CACHE_SIZE; | ||
2937 | remaining -= PAGE_CACHE_SIZE; | ||
2938 | } else if (remaining > 0) { | ||
2939 | /* enough for partial page, fill and zero the rest */ | 3102 | /* enough for partial page, fill and zero the rest */ |
2940 | rdata->iov[rdata->nr_iov].iov_base = kmap(page); | 3103 | iov.iov_base = kmap(page); |
2941 | rdata->iov[rdata->nr_iov].iov_len = remaining; | 3104 | iov.iov_len = len; |
2942 | cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu", | 3105 | cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu", |
2943 | rdata->nr_iov, page->index, | 3106 | i, page->index, iov.iov_base, iov.iov_len); |
2944 | rdata->iov[rdata->nr_iov].iov_base, | 3107 | memset(iov.iov_base + len, |
2945 | rdata->iov[rdata->nr_iov].iov_len); | 3108 | '\0', PAGE_CACHE_SIZE - len); |
2946 | memset(rdata->iov[rdata->nr_iov].iov_base + remaining, | 3109 | rdata->tailsz = len; |
2947 | '\0', PAGE_CACHE_SIZE - remaining); | 3110 | len = 0; |
2948 | ++rdata->nr_iov; | ||
2949 | len += remaining; | ||
2950 | remaining = 0; | ||
2951 | } else if (page->index > eof_index) { | 3111 | } else if (page->index > eof_index) { |
2952 | /* | 3112 | /* |
2953 | * The VFS will not try to do readahead past the | 3113 | * The VFS will not try to do readahead past the |
@@ -2958,22 +3118,33 @@ cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining) | |||
2958 | * fill them until the writes are flushed. | 3118 | * fill them until the writes are flushed. |
2959 | */ | 3119 | */ |
2960 | zero_user(page, 0, PAGE_CACHE_SIZE); | 3120 | zero_user(page, 0, PAGE_CACHE_SIZE); |
2961 | list_del(&page->lru); | ||
2962 | lru_cache_add_file(page); | 3121 | lru_cache_add_file(page); |
2963 | flush_dcache_page(page); | 3122 | flush_dcache_page(page); |
2964 | SetPageUptodate(page); | 3123 | SetPageUptodate(page); |
2965 | unlock_page(page); | 3124 | unlock_page(page); |
2966 | page_cache_release(page); | 3125 | page_cache_release(page); |
3126 | rdata->pages[i] = NULL; | ||
3127 | rdata->nr_pages--; | ||
3128 | continue; | ||
2967 | } else { | 3129 | } else { |
2968 | /* no need to hold page hostage */ | 3130 | /* no need to hold page hostage */ |
2969 | list_del(&page->lru); | ||
2970 | lru_cache_add_file(page); | 3131 | lru_cache_add_file(page); |
2971 | unlock_page(page); | 3132 | unlock_page(page); |
2972 | page_cache_release(page); | 3133 | page_cache_release(page); |
3134 | rdata->pages[i] = NULL; | ||
3135 | rdata->nr_pages--; | ||
3136 | continue; | ||
2973 | } | 3137 | } |
3138 | |||
3139 | result = cifs_readv_from_socket(server, &iov, 1, iov.iov_len); | ||
3140 | kunmap(page); | ||
3141 | if (result < 0) | ||
3142 | break; | ||
3143 | |||
3144 | total_read += result; | ||
2974 | } | 3145 | } |
2975 | 3146 | ||
2976 | return len; | 3147 | return total_read > 0 ? total_read : result; |
2977 | } | 3148 | } |
2978 | 3149 | ||
2979 | static int cifs_readpages(struct file *file, struct address_space *mapping, | 3150 | static int cifs_readpages(struct file *file, struct address_space *mapping, |
@@ -3027,6 +3198,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
3027 | * the rdata->pages, then we want them in increasing order. | 3198 | * the rdata->pages, then we want them in increasing order. |
3028 | */ | 3199 | */ |
3029 | while (!list_empty(page_list)) { | 3200 | while (!list_empty(page_list)) { |
3201 | unsigned int i; | ||
3030 | unsigned int bytes = PAGE_CACHE_SIZE; | 3202 | unsigned int bytes = PAGE_CACHE_SIZE; |
3031 | unsigned int expected_index; | 3203 | unsigned int expected_index; |
3032 | unsigned int nr_pages = 1; | 3204 | unsigned int nr_pages = 1; |
@@ -3096,14 +3268,18 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
3096 | rdata->offset = offset; | 3268 | rdata->offset = offset; |
3097 | rdata->bytes = bytes; | 3269 | rdata->bytes = bytes; |
3098 | rdata->pid = pid; | 3270 | rdata->pid = pid; |
3099 | rdata->marshal_iov = cifs_readpages_marshal_iov; | 3271 | rdata->pagesz = PAGE_CACHE_SIZE; |
3100 | list_splice_init(&tmplist, &rdata->pages); | 3272 | rdata->read_into_pages = cifs_readpages_read_into_pages; |
3273 | |||
3274 | list_for_each_entry_safe(page, tpage, &tmplist, lru) { | ||
3275 | list_del(&page->lru); | ||
3276 | rdata->pages[rdata->nr_pages++] = page; | ||
3277 | } | ||
3101 | 3278 | ||
3102 | rc = cifs_retry_async_readv(rdata); | 3279 | rc = cifs_retry_async_readv(rdata); |
3103 | if (rc != 0) { | 3280 | if (rc != 0) { |
3104 | list_for_each_entry_safe(page, tpage, &rdata->pages, | 3281 | for (i = 0; i < rdata->nr_pages; i++) { |
3105 | lru) { | 3282 | page = rdata->pages[i]; |
3106 | list_del(&page->lru); | ||
3107 | lru_cache_add_file(page); | 3283 | lru_cache_add_file(page); |
3108 | unlock_page(page); | 3284 | unlock_page(page); |
3109 | page_cache_release(page); | 3285 | page_cache_release(page); |
@@ -3347,6 +3523,7 @@ void cifs_oplock_break(struct work_struct *work) | |||
3347 | oplock_break); | 3523 | oplock_break); |
3348 | struct inode *inode = cfile->dentry->d_inode; | 3524 | struct inode *inode = cfile->dentry->d_inode; |
3349 | struct cifsInodeInfo *cinode = CIFS_I(inode); | 3525 | struct cifsInodeInfo *cinode = CIFS_I(inode); |
3526 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | ||
3350 | int rc = 0; | 3527 | int rc = 0; |
3351 | 3528 | ||
3352 | if (inode && S_ISREG(inode->i_mode)) { | 3529 | if (inode && S_ISREG(inode->i_mode)) { |
@@ -3374,10 +3551,8 @@ void cifs_oplock_break(struct work_struct *work) | |||
3374 | * disconnected since oplock already released by the server | 3551 | * disconnected since oplock already released by the server |
3375 | */ | 3552 | */ |
3376 | if (!cfile->oplock_break_cancelled) { | 3553 | if (!cfile->oplock_break_cancelled) { |
3377 | rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, | 3554 | rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid, |
3378 | current->tgid, 0, 0, 0, 0, | 3555 | cinode); |
3379 | LOCKING_ANDX_OPLOCK_RELEASE, false, | ||
3380 | cinode->clientCanCacheRead ? 1 : 0); | ||
3381 | cFYI(1, "Oplock release rc = %d", rc); | 3556 | cFYI(1, "Oplock release rc = %d", rc); |
3382 | } | 3557 | } |
3383 | } | 3558 | } |