diff options
author | Pavel Shilovsky <pshilovsky@samba.org> | 2012-09-18 19:20:27 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-09-24 22:46:27 -0400 |
commit | 2ae78ba85cd7b4c3a164434ab1f6c9e515c6fa1d (patch) | |
tree | 0993d53ef7625ee5349f7fcecccd056f930bd6ca /fs/cifs/file.c | |
parent | 253641388a49259f6bfefecfb14fa057ca58dc21 (diff) |
CIFS: Move reopen code to ops struct
Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 121 |
1 files changed, 64 insertions, 57 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index dbca2b293e55..628ee17007f8 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -459,59 +459,66 @@ out: | |||
459 | return rc; | 459 | return rc; |
460 | } | 460 | } |
461 | 461 | ||
462 | /* Try to reacquire byte range locks that were released when session */ | 462 | /* |
463 | /* to server was lost */ | 463 | * Try to reacquire byte range locks that were released when session |
464 | * to server was lost | ||
465 | */ | ||
464 | static int cifs_relock_file(struct cifsFileInfo *cifsFile) | 466 | static int cifs_relock_file(struct cifsFileInfo *cifsFile) |
465 | { | 467 | { |
466 | int rc = 0; | 468 | int rc = 0; |
467 | 469 | ||
468 | /* BB list all locks open on this file and relock */ | 470 | /* BB list all locks open on this file and relock */ |
469 | 471 | ||
470 | return rc; | 472 | return rc; |
471 | } | 473 | } |
472 | 474 | ||
473 | static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush) | 475 | static int |
476 | cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) | ||
474 | { | 477 | { |
475 | int rc = -EACCES; | 478 | int rc = -EACCES; |
476 | unsigned int xid; | 479 | unsigned int xid; |
477 | __u32 oplock; | 480 | __u32 oplock; |
478 | struct cifs_sb_info *cifs_sb; | 481 | struct cifs_sb_info *cifs_sb; |
479 | struct cifs_tcon *tcon; | 482 | struct cifs_tcon *tcon; |
480 | struct cifsInodeInfo *pCifsInode; | 483 | struct TCP_Server_Info *server; |
484 | struct cifsInodeInfo *cinode; | ||
481 | struct inode *inode; | 485 | struct inode *inode; |
482 | char *full_path = NULL; | 486 | char *full_path = NULL; |
483 | int desiredAccess; | 487 | int desired_access; |
484 | int disposition = FILE_OPEN; | 488 | int disposition = FILE_OPEN; |
485 | int create_options = CREATE_NOT_DIR; | 489 | int create_options = CREATE_NOT_DIR; |
486 | __u16 netfid; | 490 | struct cifs_fid fid; |
487 | 491 | ||
488 | xid = get_xid(); | 492 | xid = get_xid(); |
489 | mutex_lock(&pCifsFile->fh_mutex); | 493 | mutex_lock(&cfile->fh_mutex); |
490 | if (!pCifsFile->invalidHandle) { | 494 | if (!cfile->invalidHandle) { |
491 | mutex_unlock(&pCifsFile->fh_mutex); | 495 | mutex_unlock(&cfile->fh_mutex); |
492 | rc = 0; | 496 | rc = 0; |
493 | free_xid(xid); | 497 | free_xid(xid); |
494 | return rc; | 498 | return rc; |
495 | } | 499 | } |
496 | 500 | ||
497 | inode = pCifsFile->dentry->d_inode; | 501 | inode = cfile->dentry->d_inode; |
498 | cifs_sb = CIFS_SB(inode->i_sb); | 502 | cifs_sb = CIFS_SB(inode->i_sb); |
499 | tcon = tlink_tcon(pCifsFile->tlink); | 503 | tcon = tlink_tcon(cfile->tlink); |
504 | server = tcon->ses->server; | ||
500 | 505 | ||
501 | /* can not grab rename sem here because various ops, including | 506 | /* |
502 | those that already have the rename sem can end up causing writepage | 507 | * Can not grab rename sem here because various ops, including those |
503 | to get called and if the server was down that means we end up here, | 508 | * that already have the rename sem can end up causing writepage to get |
504 | and we can never tell if the caller already has the rename_sem */ | 509 | * called and if the server was down that means we end up here, and we |
505 | full_path = build_path_from_dentry(pCifsFile->dentry); | 510 | * can never tell if the caller already has the rename_sem. |
511 | */ | ||
512 | full_path = build_path_from_dentry(cfile->dentry); | ||
506 | if (full_path == NULL) { | 513 | if (full_path == NULL) { |
507 | rc = -ENOMEM; | 514 | rc = -ENOMEM; |
508 | mutex_unlock(&pCifsFile->fh_mutex); | 515 | mutex_unlock(&cfile->fh_mutex); |
509 | free_xid(xid); | 516 | free_xid(xid); |
510 | return rc; | 517 | return rc; |
511 | } | 518 | } |
512 | 519 | ||
513 | cFYI(1, "inode = 0x%p file flags 0x%x for %s", | 520 | cFYI(1, "inode = 0x%p file flags 0x%x for %s", inode, cfile->f_flags, |
514 | inode, pCifsFile->f_flags, full_path); | 521 | full_path); |
515 | 522 | ||
516 | if (tcon->ses->server->oplocks) | 523 | if (tcon->ses->server->oplocks) |
517 | oplock = REQ_OPLOCK; | 524 | oplock = REQ_OPLOCK; |
@@ -525,69 +532,69 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush) | |||
525 | * O_CREAT, O_EXCL and O_TRUNC already had their effect on the | 532 | * O_CREAT, O_EXCL and O_TRUNC already had their effect on the |
526 | * original open. Must mask them off for a reopen. | 533 | * original open. Must mask them off for a reopen. |
527 | */ | 534 | */ |
528 | unsigned int oflags = pCifsFile->f_flags & | 535 | unsigned int oflags = cfile->f_flags & |
529 | ~(O_CREAT | O_EXCL | O_TRUNC); | 536 | ~(O_CREAT | O_EXCL | O_TRUNC); |
530 | 537 | ||
531 | rc = cifs_posix_open(full_path, NULL, inode->i_sb, | 538 | rc = cifs_posix_open(full_path, NULL, inode->i_sb, |
532 | cifs_sb->mnt_file_mode /* ignored */, | 539 | cifs_sb->mnt_file_mode /* ignored */, |
533 | oflags, &oplock, &netfid, xid); | 540 | oflags, &oplock, &fid.netfid, xid); |
534 | if (rc == 0) { | 541 | if (rc == 0) { |
535 | cFYI(1, "posix reopen succeeded"); | 542 | cFYI(1, "posix reopen succeeded"); |
536 | goto reopen_success; | 543 | goto reopen_success; |
537 | } | 544 | } |
538 | /* fallthrough to retry open the old way on errors, especially | 545 | /* |
539 | in the reconnect path it is important to retry hard */ | 546 | * fallthrough to retry open the old way on errors, especially |
547 | * in the reconnect path it is important to retry hard | ||
548 | */ | ||
540 | } | 549 | } |
541 | 550 | ||
542 | desiredAccess = cifs_convert_flags(pCifsFile->f_flags); | 551 | desired_access = cifs_convert_flags(cfile->f_flags); |
543 | 552 | ||
544 | if (backup_cred(cifs_sb)) | 553 | if (backup_cred(cifs_sb)) |
545 | create_options |= CREATE_OPEN_BACKUP_INTENT; | 554 | create_options |= CREATE_OPEN_BACKUP_INTENT; |
546 | 555 | ||
547 | /* Can not refresh inode by passing in file_info buf to be returned | 556 | /* |
548 | by SMBOpen and then calling get_inode_info with returned buf | 557 | * Can not refresh inode by passing in file_info buf to be returned by |
549 | since file might have write behind data that needs to be flushed | 558 | * CIFSSMBOpen and then calling get_inode_info with returned buf since |
550 | and server version of file size can be stale. If we knew for sure | 559 | * file might have write behind data that needs to be flushed and server |
551 | that inode was not dirty locally we could do this */ | 560 | * version of file size can be stale. If we knew for sure that inode was |
552 | 561 | * not dirty locally we could do this. | |
553 | rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess, | 562 | */ |
554 | create_options, &netfid, &oplock, NULL, | 563 | rc = server->ops->open(xid, tcon, full_path, disposition, |
555 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 564 | desired_access, create_options, &fid, &oplock, |
556 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 565 | NULL, cifs_sb); |
557 | if (rc) { | 566 | if (rc) { |
558 | mutex_unlock(&pCifsFile->fh_mutex); | 567 | mutex_unlock(&cfile->fh_mutex); |
559 | cFYI(1, "cifs_open returned 0x%x", rc); | 568 | cFYI(1, "cifs_reopen returned 0x%x", rc); |
560 | cFYI(1, "oplock: %d", oplock); | 569 | cFYI(1, "oplock: %d", oplock); |
561 | goto reopen_error_exit; | 570 | goto reopen_error_exit; |
562 | } | 571 | } |
563 | 572 | ||
564 | reopen_success: | 573 | reopen_success: |
565 | pCifsFile->fid.netfid = netfid; | 574 | cfile->invalidHandle = false; |
566 | pCifsFile->invalidHandle = false; | 575 | mutex_unlock(&cfile->fh_mutex); |
567 | mutex_unlock(&pCifsFile->fh_mutex); | 576 | cinode = CIFS_I(inode); |
568 | pCifsInode = CIFS_I(inode); | ||
569 | 577 | ||
570 | if (can_flush) { | 578 | if (can_flush) { |
571 | rc = filemap_write_and_wait(inode->i_mapping); | 579 | rc = filemap_write_and_wait(inode->i_mapping); |
572 | mapping_set_error(inode->i_mapping, rc); | 580 | mapping_set_error(inode->i_mapping, rc); |
573 | 581 | ||
574 | if (tcon->unix_ext) | 582 | if (tcon->unix_ext) |
575 | rc = cifs_get_inode_info_unix(&inode, | 583 | rc = cifs_get_inode_info_unix(&inode, full_path, |
576 | full_path, inode->i_sb, xid); | 584 | inode->i_sb, xid); |
577 | else | 585 | else |
578 | rc = cifs_get_inode_info(&inode, | 586 | rc = cifs_get_inode_info(&inode, full_path, NULL, |
579 | full_path, NULL, inode->i_sb, | 587 | inode->i_sb, xid, NULL); |
580 | xid, NULL); | 588 | } |
581 | } /* else we are writing out data to server already | 589 | /* |
582 | and could deadlock if we tried to flush data, and | 590 | * Else we are writing out data to server already and could deadlock if |
583 | since we do not know if we have data that would | 591 | * we tried to flush data, and since we do not know if we have data that |
584 | invalidate the current end of file on the server | 592 | * would invalidate the current end of file on the server we can not go |
585 | we can not go to the server to get the new inod | 593 | * to the server to get the new inode info. |
586 | info */ | 594 | */ |
587 | 595 | ||
588 | cifs_set_oplock_level(pCifsInode, oplock); | 596 | server->ops->set_fid(cfile, &fid, oplock); |
589 | 597 | cifs_relock_file(cfile); | |
590 | cifs_relock_file(pCifsFile); | ||
591 | 598 | ||
592 | reopen_error_exit: | 599 | reopen_error_exit: |
593 | kfree(full_path); | 600 | kfree(full_path); |