diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 94 |
1 files changed, 66 insertions, 28 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index fb49aef1f2ec..5c497c529772 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -555,7 +555,10 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
555 | if (ptmp) { | 555 | if (ptmp) { |
556 | cFYI(1, ("closedir free smb buf in srch struct")); | 556 | cFYI(1, ("closedir free smb buf in srch struct")); |
557 | pCFileStruct->srch_inf.ntwrk_buf_start = NULL; | 557 | pCFileStruct->srch_inf.ntwrk_buf_start = NULL; |
558 | cifs_buf_release(ptmp); | 558 | if(pCFileStruct->srch_inf.smallBuf) |
559 | cifs_small_buf_release(ptmp); | ||
560 | else | ||
561 | cifs_buf_release(ptmp); | ||
559 | } | 562 | } |
560 | ptmp = pCFileStruct->search_resume_name; | 563 | ptmp = pCFileStruct->search_resume_name; |
561 | if (ptmp) { | 564 | if (ptmp) { |
@@ -574,13 +577,14 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
574 | int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | 577 | int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) |
575 | { | 578 | { |
576 | int rc, xid; | 579 | int rc, xid; |
577 | __u32 lockType = LOCKING_ANDX_LARGE_FILES; | ||
578 | __u32 numLock = 0; | 580 | __u32 numLock = 0; |
579 | __u32 numUnlock = 0; | 581 | __u32 numUnlock = 0; |
580 | __u64 length; | 582 | __u64 length; |
581 | int wait_flag = FALSE; | 583 | int wait_flag = FALSE; |
582 | struct cifs_sb_info *cifs_sb; | 584 | struct cifs_sb_info *cifs_sb; |
583 | struct cifsTconInfo *pTcon; | 585 | struct cifsTconInfo *pTcon; |
586 | __u16 netfid; | ||
587 | __u8 lockType = LOCKING_ANDX_LARGE_FILES; | ||
584 | 588 | ||
585 | length = 1 + pfLock->fl_end - pfLock->fl_start; | 589 | length = 1 + pfLock->fl_end - pfLock->fl_start; |
586 | rc = -EACCES; | 590 | rc = -EACCES; |
@@ -592,11 +596,11 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
592 | pfLock->fl_end)); | 596 | pfLock->fl_end)); |
593 | 597 | ||
594 | if (pfLock->fl_flags & FL_POSIX) | 598 | if (pfLock->fl_flags & FL_POSIX) |
595 | cFYI(1, ("Posix ")); | 599 | cFYI(1, ("Posix")); |
596 | if (pfLock->fl_flags & FL_FLOCK) | 600 | if (pfLock->fl_flags & FL_FLOCK) |
597 | cFYI(1, ("Flock ")); | 601 | cFYI(1, ("Flock")); |
598 | if (pfLock->fl_flags & FL_SLEEP) { | 602 | if (pfLock->fl_flags & FL_SLEEP) { |
599 | cFYI(1, ("Blocking lock ")); | 603 | cFYI(1, ("Blocking lock")); |
600 | wait_flag = TRUE; | 604 | wait_flag = TRUE; |
601 | } | 605 | } |
602 | if (pfLock->fl_flags & FL_ACCESS) | 606 | if (pfLock->fl_flags & FL_ACCESS) |
@@ -612,21 +616,23 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
612 | cFYI(1, ("F_WRLCK ")); | 616 | cFYI(1, ("F_WRLCK ")); |
613 | numLock = 1; | 617 | numLock = 1; |
614 | } else if (pfLock->fl_type == F_UNLCK) { | 618 | } else if (pfLock->fl_type == F_UNLCK) { |
615 | cFYI(1, ("F_UNLCK ")); | 619 | cFYI(1, ("F_UNLCK")); |
616 | numUnlock = 1; | 620 | numUnlock = 1; |
621 | /* Check if unlock includes more than | ||
622 | one lock range */ | ||
617 | } else if (pfLock->fl_type == F_RDLCK) { | 623 | } else if (pfLock->fl_type == F_RDLCK) { |
618 | cFYI(1, ("F_RDLCK ")); | 624 | cFYI(1, ("F_RDLCK")); |
619 | lockType |= LOCKING_ANDX_SHARED_LOCK; | 625 | lockType |= LOCKING_ANDX_SHARED_LOCK; |
620 | numLock = 1; | 626 | numLock = 1; |
621 | } else if (pfLock->fl_type == F_EXLCK) { | 627 | } else if (pfLock->fl_type == F_EXLCK) { |
622 | cFYI(1, ("F_EXLCK ")); | 628 | cFYI(1, ("F_EXLCK")); |
623 | numLock = 1; | 629 | numLock = 1; |
624 | } else if (pfLock->fl_type == F_SHLCK) { | 630 | } else if (pfLock->fl_type == F_SHLCK) { |
625 | cFYI(1, ("F_SHLCK ")); | 631 | cFYI(1, ("F_SHLCK")); |
626 | lockType |= LOCKING_ANDX_SHARED_LOCK; | 632 | lockType |= LOCKING_ANDX_SHARED_LOCK; |
627 | numLock = 1; | 633 | numLock = 1; |
628 | } else | 634 | } else |
629 | cFYI(1, ("Unknown type of lock ")); | 635 | cFYI(1, ("Unknown type of lock")); |
630 | 636 | ||
631 | cifs_sb = CIFS_SB(file->f_dentry->d_sb); | 637 | cifs_sb = CIFS_SB(file->f_dentry->d_sb); |
632 | pTcon = cifs_sb->tcon; | 638 | pTcon = cifs_sb->tcon; |
@@ -635,27 +641,41 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
635 | FreeXid(xid); | 641 | FreeXid(xid); |
636 | return -EBADF; | 642 | return -EBADF; |
637 | } | 643 | } |
644 | netfid = ((struct cifsFileInfo *)file->private_data)->netfid; | ||
645 | |||
638 | 646 | ||
647 | /* BB add code here to normalize offset and length to | ||
648 | account for negative length which we can not accept over the | ||
649 | wire */ | ||
639 | if (IS_GETLK(cmd)) { | 650 | if (IS_GETLK(cmd)) { |
640 | rc = CIFSSMBLock(xid, pTcon, | 651 | if(experimEnabled && |
641 | ((struct cifsFileInfo *)file-> | 652 | (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && |
642 | private_data)->netfid, | 653 | (CIFS_UNIX_FCNTL_CAP & |
643 | length, | 654 | le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { |
644 | pfLock->fl_start, 0, 1, lockType, | 655 | int posix_lock_type; |
645 | 0 /* wait flag */ ); | 656 | if(lockType & LOCKING_ANDX_SHARED_LOCK) |
657 | posix_lock_type = CIFS_RDLCK; | ||
658 | else | ||
659 | posix_lock_type = CIFS_WRLCK; | ||
660 | rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */, | ||
661 | length, pfLock->fl_start, | ||
662 | posix_lock_type, wait_flag); | ||
663 | FreeXid(xid); | ||
664 | return rc; | ||
665 | } | ||
666 | |||
667 | /* BB we could chain these into one lock request BB */ | ||
668 | rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, | ||
669 | 0, 1, lockType, 0 /* wait flag */ ); | ||
646 | if (rc == 0) { | 670 | if (rc == 0) { |
647 | rc = CIFSSMBLock(xid, pTcon, | 671 | rc = CIFSSMBLock(xid, pTcon, netfid, length, |
648 | ((struct cifsFileInfo *) file-> | ||
649 | private_data)->netfid, | ||
650 | length, | ||
651 | pfLock->fl_start, 1 /* numUnlock */ , | 672 | pfLock->fl_start, 1 /* numUnlock */ , |
652 | 0 /* numLock */ , lockType, | 673 | 0 /* numLock */ , lockType, |
653 | 0 /* wait flag */ ); | 674 | 0 /* wait flag */ ); |
654 | pfLock->fl_type = F_UNLCK; | 675 | pfLock->fl_type = F_UNLCK; |
655 | if (rc != 0) | 676 | if (rc != 0) |
656 | cERROR(1, ("Error unlocking previously locked " | 677 | cERROR(1, ("Error unlocking previously locked " |
657 | "range %d during test of lock ", | 678 | "range %d during test of lock", rc)); |
658 | rc)); | ||
659 | rc = 0; | 679 | rc = 0; |
660 | 680 | ||
661 | } else { | 681 | } else { |
@@ -667,12 +687,30 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
667 | FreeXid(xid); | 687 | FreeXid(xid); |
668 | return rc; | 688 | return rc; |
669 | } | 689 | } |
670 | 690 | if (experimEnabled && | |
671 | rc = CIFSSMBLock(xid, pTcon, | 691 | (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && |
672 | ((struct cifsFileInfo *) file->private_data)-> | 692 | (CIFS_UNIX_FCNTL_CAP & |
673 | netfid, length, | 693 | le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { |
674 | pfLock->fl_start, numUnlock, numLock, lockType, | 694 | int posix_lock_type; |
675 | wait_flag); | 695 | if(lockType & LOCKING_ANDX_SHARED_LOCK) |
696 | posix_lock_type = CIFS_RDLCK; | ||
697 | else | ||
698 | posix_lock_type = CIFS_WRLCK; | ||
699 | |||
700 | if(numUnlock == 1) | ||
701 | posix_lock_type = CIFS_UNLCK; | ||
702 | else if(numLock == 0) { | ||
703 | /* if no lock or unlock then nothing | ||
704 | to do since we do not know what it is */ | ||
705 | FreeXid(xid); | ||
706 | return -EOPNOTSUPP; | ||
707 | } | ||
708 | rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, | ||
709 | length, pfLock->fl_start, | ||
710 | posix_lock_type, wait_flag); | ||
711 | } else | ||
712 | rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, | ||
713 | numUnlock, numLock, lockType, wait_flag); | ||
676 | if (pfLock->fl_flags & FL_POSIX) | 714 | if (pfLock->fl_flags & FL_POSIX) |
677 | posix_lock_file_wait(file, pfLock); | 715 | posix_lock_file_wait(file, pfLock); |
678 | FreeXid(xid); | 716 | FreeXid(xid); |