aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/CHANGES4
-rw-r--r--fs/cifs/cifspdu.h6
-rw-r--r--fs/cifs/cifsproto.h5
-rw-r--r--fs/cifs/cifssmb.c85
-rw-r--r--fs/cifs/inode.c14
5 files changed, 103 insertions, 11 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index f92e0ee661ae..6d84ca2beead 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,7 +1,9 @@
1Version 1.50 1Version 1.50
2------------ 2------------
3Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is 3Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is
4done with "serverino" mount option). 4done with "serverino" mount option). Add support for POSIX Unlink
5(helps with certain sharing violation cases when server such as
6Samba supports newer POSIX CIFS Protocol Extensions).
5 7
6Version 1.49 8Version 1.49
7------------ 9------------
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 9044d9886f0d..6a2056e58ceb 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -2155,6 +2155,12 @@ typedef struct {
2155 /* struct following varies based on requested level */ 2155 /* struct following varies based on requested level */
2156} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */ 2156} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
2157 2157
2158#define SMB_POSIX_UNLINK_FILE_TARGET 0
2159#define SMB_POSIX_UNLINK_DIRECTORY_TARGET 1
2160
2161struct unlink_psx_rq { /* level 0x20a SetPathInfo */
2162 __le16 type;
2163} __attribute__((packed));
2158 2164
2159struct file_internal_info { 2165struct file_internal_info {
2160 __u64 UniqueId; /* inode number */ 2166 __u64 UniqueId; /* inode number */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 3a76c72f3c89..04a69dafedba 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -196,7 +196,10 @@ extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
196extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, 196extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
197 const char *name, const struct nls_table *nls_codepage, 197 const char *name, const struct nls_table *nls_codepage,
198 int remap_special_chars); 198 int remap_special_chars);
199 199extern int CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon,
200 const char *name, __u16 type,
201 const struct nls_table *nls_codepage,
202 int remap_special_chars);
200extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, 203extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
201 const char *name, 204 const char *name,
202 const struct nls_table *nls_codepage, 205 const struct nls_table *nls_codepage,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 3ab78b776977..b339f5f128da 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -789,6 +789,82 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
789} 789}
790 790
791int 791int
792CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
793 __u16 type, const struct nls_table *nls_codepage, int remap)
794{
795 TRANSACTION2_SPI_REQ *pSMB = NULL;
796 TRANSACTION2_SPI_RSP *pSMBr = NULL;
797 struct unlink_psx_rq *pRqD;
798 int name_len;
799 int rc = 0;
800 int bytes_returned = 0;
801 __u16 params, param_offset, offset, byte_count;
802
803 cFYI(1, ("In POSIX delete"));
804PsxDelete:
805 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
806 (void **) &pSMBr);
807 if (rc)
808 return rc;
809
810 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
811 name_len =
812 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
813 PATH_MAX, nls_codepage, remap);
814 name_len++; /* trailing null */
815 name_len *= 2;
816 } else { /* BB add path length overrun check */
817 name_len = strnlen(fileName, PATH_MAX);
818 name_len++; /* trailing null */
819 strncpy(pSMB->FileName, fileName, name_len);
820 }
821
822 params = 6 + name_len;
823 pSMB->MaxParameterCount = cpu_to_le16(2);
824 pSMB->MaxDataCount = 0; /* BB double check this with jra */
825 pSMB->MaxSetupCount = 0;
826 pSMB->Reserved = 0;
827 pSMB->Flags = 0;
828 pSMB->Timeout = 0;
829 pSMB->Reserved2 = 0;
830 param_offset = offsetof(struct smb_com_transaction2_spi_req,
831 InformationLevel) - 4;
832 offset = param_offset + params;
833
834 /* Setup pointer to Request Data (inode type) */
835 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
836 pRqD->type = cpu_to_le16(type);
837 pSMB->ParameterOffset = cpu_to_le16(param_offset);
838 pSMB->DataOffset = cpu_to_le16(offset);
839 pSMB->SetupCount = 1;
840 pSMB->Reserved3 = 0;
841 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
842 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
843
844 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
845 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
846 pSMB->ParameterCount = cpu_to_le16(params);
847 pSMB->TotalParameterCount = pSMB->ParameterCount;
848 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
849 pSMB->Reserved4 = 0;
850 pSMB->hdr.smb_buf_length += byte_count;
851 pSMB->ByteCount = cpu_to_le16(byte_count);
852 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
853 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
854 if (rc) {
855 cFYI(1, ("Posix delete returned %d", rc));
856 }
857 cifs_buf_release(pSMB);
858
859 cifs_stats_inc(&tcon->num_deletes);
860
861 if (rc == -EAGAIN)
862 goto PsxDelete;
863
864 return rc;
865}
866
867int
792CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName, 868CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
793 const struct nls_table *nls_codepage, int remap) 869 const struct nls_table *nls_codepage, int remap)
794{ 870{
@@ -933,7 +1009,6 @@ CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
933 int name_len; 1009 int name_len;
934 int rc = 0; 1010 int rc = 0;
935 int bytes_returned = 0; 1011 int bytes_returned = 0;
936 char *data_offset;
937 __u16 params, param_offset, offset, byte_count, count; 1012 __u16 params, param_offset, offset, byte_count, count;
938 OPEN_PSX_REQ * pdata; 1013 OPEN_PSX_REQ * pdata;
939 OPEN_PSX_RSP * psx_rsp; 1014 OPEN_PSX_RSP * psx_rsp;
@@ -969,7 +1044,6 @@ PsxCreat:
969 param_offset = offsetof(struct smb_com_transaction2_spi_req, 1044 param_offset = offsetof(struct smb_com_transaction2_spi_req,
970 InformationLevel) - 4; 1045 InformationLevel) - 4;
971 offset = param_offset + params; 1046 offset = param_offset + params;
972 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
973 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset); 1047 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
974 pdata->Level = SMB_QUERY_FILE_UNIX_BASIC; 1048 pdata->Level = SMB_QUERY_FILE_UNIX_BASIC;
975 pdata->Permissions = cpu_to_le64(mode); 1049 pdata->Permissions = cpu_to_le64(mode);
@@ -1671,7 +1745,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1671{ 1745{
1672 struct smb_com_transaction2_sfi_req *pSMB = NULL; 1746 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1673 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; 1747 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1674 char *data_offset;
1675 struct cifs_posix_lock *parm_data; 1748 struct cifs_posix_lock *parm_data;
1676 int rc = 0; 1749 int rc = 0;
1677 int timeout = 0; 1750 int timeout = 0;
@@ -1698,8 +1771,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1698 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; 1771 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1699 offset = param_offset + params; 1772 offset = param_offset + params;
1700 1773
1701 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1702
1703 count = sizeof(struct cifs_posix_lock); 1774 count = sizeof(struct cifs_posix_lock);
1704 pSMB->MaxParameterCount = cpu_to_le16(2); 1775 pSMB->MaxParameterCount = cpu_to_le16(2);
1705 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ 1776 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
@@ -2120,9 +2191,7 @@ createSymLinkRetry:
2120 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 2191 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2121 cifs_stats_inc(&tcon->num_symlinks); 2192 cifs_stats_inc(&tcon->num_symlinks);
2122 if (rc) { 2193 if (rc) {
2123 cFYI(1, 2194 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2124 ("Send error in SetPathInfo (create symlink) = %d",
2125 rc));
2126 } 2195 }
2127 2196
2128 if (pSMB) 2197 if (pSMB)
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index a1ca55650505..cfa5b360d12e 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -620,9 +620,21 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
620 FreeXid(xid); 620 FreeXid(xid);
621 return -ENOMEM; 621 return -ENOMEM;
622 } 622 }
623 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls, 623
624 if ((pTcon->ses->capabilities & CAP_UNIX) &&
625 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
626 le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
627 rc = CIFSPOSIXDelFile(xid, pTcon, full_path,
628 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
624 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 629 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
630 cFYI(1, ("posix del rc %d", rc));
631 if ((rc == 0) || (rc == -ENOENT))
632 goto psx_del_no_retry;
633 }
625 634
635 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
636 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
637psx_del_no_retry:
626 if (!rc) { 638 if (!rc) {
627 if (direntry->d_inode) 639 if (direntry->d_inode)
628 drop_nlink(direntry->d_inode); 640 drop_nlink(direntry->d_inode);