ChangeSet 1.2191, 2005/03/21 20:09:44-06:00, [EMAIL PROTECTED](none)
[CIFS] add new retry on failure to legacy servers such as NT4 of delete
of readonly files.
Signed-off-by: Steve French ([EMAIL PROTECTED])
cifspdu.h | 19 ++++++++++++++
cifsproto.h | 7 ++---
cifssmb.c | 81 ++++++++++++++++++++----------------------------------------
inode.c | 30 ++++++++++++++++++++--
misc.c | 10 +++++--
5 files changed, 85 insertions(+), 62 deletions(-)
diff -Nru a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
--- a/fs/cifs/cifspdu.h 2005-03-30 12:08:35 -08:00
+++ b/fs/cifs/cifspdu.h 2005-03-30 12:08:35 -08:00
@@ -36,6 +36,7 @@
#define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored
*/
#define SMB_COM_DELETE 0x06 /* trivial response */
#define SMB_COM_RENAME 0x07 /* trivial response */
+#define SMB_COM_SETATTR 0x09 /* trivial response */
#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */
#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename
ignrd*/
#define SMB_COM_READ_ANDX 0x2E
@@ -864,6 +865,24 @@
struct smb_hdr hdr; /* wct = 0 */
__u16 ByteCount; /* bct = 0 */
} CREATE_DIRECTORY_RSP;
+
+typedef struct smb_com_setattr_req {
+ struct smb_hdr hdr; /* wct = 8 */
+ __le16 attr;
+ __le16 time_low;
+ __le16 time_high;
+ __le16 reserved[5]; /* must be zero */
+ __u16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char fileName[1];
+} SETATTR_REQ;
+
+typedef struct smb_com_setattr_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+} SETATTR_RSP;
+
+/* empty wct response to setattr */
/***************************************************/
/* NT Transact structure defintions follow */
diff -Nru a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
--- a/fs/cifs/cifsproto.h 2005-03-30 12:08:35 -08:00
+++ b/fs/cifs/cifsproto.h 2005-03-30 12:08:35 -08:00
@@ -137,10 +137,11 @@
const struct nls_table *nls_codepage);
extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
const FILE_BASIC_INFO * data, __u16 fid);
-extern int CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon,
- char *fileName, FILE_BASIC_INFO * data,
+#if 0
+extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon,
+ char *fileName, __u16 dos_attributes,
const struct nls_table *nls_codepage);
-
+#endif /* possibly unneeded function */
extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
const char *fileName, __u64 size,int
setAllocationSizeFlag,
const struct nls_table *nls_codepage);
diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
--- a/fs/cifs/cifssmb.c 2005-03-30 12:08:35 -08:00
+++ b/fs/cifs/cifssmb.c 2005-03-30 12:08:35 -08:00
@@ -3526,85 +3526,58 @@
return rc;
}
+/* Can not be used to set time stamps yet (due to old DOS time format) */
+/* Can be used to set attributes */
+#if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
+ handling it anyway and NT4 was what we thought it would be needed for
+ Do not delete it until we prove whether needed for Win9x though */
int
-CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
- FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
+CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
+ __u16 dos_attrs, const struct nls_table *nls_codepage)
{
- TRANSACTION2_SPI_REQ *pSMB = NULL;
- TRANSACTION2_SPI_RSP *pSMBr = NULL;
- FILE_INFO_STANDARD *pfinfo;
- int name_len;
+ SETATTR_REQ *pSMB = NULL;
+ SETATTR_RSP *pSMBr = NULL;
int rc = 0;
- int bytes_returned = 0;
- char *data_offset;
- __u16 params, param_offset, count, offset, byte_count;
+ int bytes_returned;
+ int name_len;
- cFYI(1, ("In SetTimesLegacy"));
+ cFYI(1, ("In SetAttrLegacy"));
-SetTimesRetryLegacy:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+SetAttrLgcyRetry:
+ rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
- /* find define for this maxpathcomponent */
- , nls_codepage);
- name_len++; /* trailing null */
+ cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName,
+ PATH_MAX, nls_codepage);
+ name_len++; /* trailing null */
name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB
*/
+ } else { /* BB improve the check for buffer overruns BB
*/
name_len = strnlen(fileName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, fileName, name_len);
+ name_len++; /* trailing null */
+ strncpy(pSMB->fileName, fileName, name_len);
}
-/* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info
- in parent function, from the better and ususal FILE_BASIC_INFO */
- params = 6 + name_len;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU
from sess structure BB */
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_spi_req,
- InformationLevel) - 4;
- offset = param_offset + params;
- data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
- pfinfo = (FILE_INFO_STANDARD *)data_offset;
- /* BB add conversion for FILE_BASIC_INFO data struct to
- FILE_INFO_STANDARD finfo struct */
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
- count = sizeof(FILE_INFO_STANDARD);
- byte_count = 3 /* pad */ + params + count;
-
- pSMB->DataCount = cpu_to_le16(count);
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
- pSMB->Reserved4 = 0;
- pSMB->hdr.smb_buf_length += byte_count;
- pSMB->ByteCount = cpu_to_le16(byte_count);
+ pSMB->attr = cpu_to_le16(dos_attrs);
+ pSMB->BufferFormat = 0x04;
+ pSMB->hdr.smb_buf_length += name_len + 1;
+ pSMB->ByteCount = cpu_to_le16(name_len + 1);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("SetPathInfo (times legacy) returned %d", rc));
+ cFYI(1, ("Error in LegacySetAttr = %d", rc));
}
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
- goto SetTimesRetryLegacy;
+ goto SetAttrLgcyRetry;
return rc;
}
+#endif /* temporarily unneeded SetAttr legacy function */
int
CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c
--- a/fs/cifs/inode.c 2005-03-30 12:08:34 -08:00
+++ b/fs/cifs/inode.c 2005-03-30 12:08:34 -08:00
@@ -417,14 +417,40 @@
}
} else if (rc == -EACCES) {
/* try only if r/o attribute set in local lookup data? */
- pinfo_buf = (FILE_BASIC_INFO
*)kmalloc(sizeof(FILE_BASIC_INFO),GFP_KERNEL);
+ pinfo_buf = (FILE_BASIC_INFO *)kmalloc(sizeof(FILE_BASIC_INFO),
+ GFP_KERNEL);
if(pinfo_buf) {
memset(pinfo_buf,0,sizeof(FILE_BASIC_INFO));
/* ATTRS set to normal clears r/o bit */
pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
rc = CIFSSMBSetTimes(xid, pTcon, full_path, pinfo_buf,
cifs_sb->local_nls);
- kfree(pinfo_buf);
+ if(rc == -EOPNOTSUPP) {
+ int oplock = FALSE;
+ __u16 netfid;
+ /* rc = CIFSSMBSetAttrLegacy(xid, pTcon, full_path,
+ (__u16)ATTR_NORMAL,
+ cifs_sb->local_nls);
+ For some strange reason it seems that NT4 eats the
+ old setattr call without actually setting the attributes
+ so on to the third attempted workaround ... */
+
+ /* BB could scan to see if we already have it open */
+ /* and pass in pid of opener to function */
+ rc = CIFSSMBOpen(xid, pTcon, full_path,
+ FILE_OPEN,
+ FILE_WRITE_ATTRIBUTES,
+ CREATE_NOT_DIR, &netfid,
+ &oplock, NULL,
+ cifs_sb->local_nls);
+ if(rc==0) {
+ rc = CIFSSMBSetFileTimes(xid, pTcon,
+ pinfo_buf, netfid);
+ CIFSSMBClose(xid, pTcon, netfid);
+ }
+ }
+ kfree(pinfo_buf);
+
}
if(rc==0) {
rc = CIFSSMBDelFile(xid, pTcon, full_path,
cifs_sb->local_nls);
diff -Nru a/fs/cifs/misc.c b/fs/cifs/misc.c
--- a/fs/cifs/misc.c 2005-03-30 12:08:35 -08:00
+++ b/fs/cifs/misc.c 2005-03-30 12:08:35 -08:00
@@ -353,10 +353,14 @@
if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
(len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
- cERROR(1, ("Length less than 2 + sizeof smb_hdr "));
- if (((unsigned int)length >= sizeof (struct smb_hdr) -
1)
- && (smb->Status.CifsError != 0))
+ if (((unsigned int)length >=
+ sizeof (struct smb_hdr) - 1)
+ && (smb->Status.CifsError != 0)) {
+ smb->WordCount = 0;
return 0; /* some error cases do not
return wct and bcc */
+ } else {
+ cERROR(1, ("Length less than smb header size"));
+ }
}
if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html