diff options
author | Steve French <sfrench@us.ibm.com> | 2007-07-15 01:48:57 +0000 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2007-07-15 01:48:57 +0000 |
commit | 2d785a50a8aa404c19f56d2c22445e48e418112b (patch) | |
tree | 260f7a1bf95126a8681d170e15337ff0ffad7e17 /fs/cifs/cifssmb.c | |
parent | 50c2f75388727018c3c357454a247072915a9e3f (diff) | |
download | linux-2d785a50a8aa404c19f56d2c22445e48e418112b.tar.gz linux-2d785a50a8aa404c19f56d2c22445e48e418112b.tar.bz2 linux-2d785a50a8aa404c19f56d2c22445e48e418112b.zip |
[CIFS] Add support for new POSIX unlink
In the cleanup phase of the dbench test, we were noticing sharing
violation followed by failed directory removals when dbench
did not close the test files before the cleanup phase started.
Using the new POSIX unlink, which Samba has supported for a few
months, avoids this.
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 85 |
1 files changed, 77 insertions, 8 deletions
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) } int +CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName, + __u16 type, const struct nls_table *nls_codepage, int remap) +{ + TRANSACTION2_SPI_REQ *pSMB = NULL; + TRANSACTION2_SPI_RSP *pSMBr = NULL; + struct unlink_psx_rq *pRqD; + int name_len; + int rc = 0; + int bytes_returned = 0; + __u16 params, param_offset, offset, byte_count; + + cFYI(1, ("In POSIX delete")); +PsxDelete: + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, + (void **) &pSMBr); + if (rc) + return rc; + + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { + name_len = + cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, + PATH_MAX, nls_codepage, remap); + name_len++; /* trailing null */ + name_len *= 2; + } else { /* BB add path length overrun check */ + name_len = strnlen(fileName, PATH_MAX); + name_len++; /* trailing null */ + strncpy(pSMB->FileName, fileName, name_len); + } + + params = 6 + name_len; + pSMB->MaxParameterCount = cpu_to_le16(2); + pSMB->MaxDataCount = 0; /* BB double check this with jra */ + 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; + + /* Setup pointer to Request Data (inode type) */ + pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset); + pRqD->type = cpu_to_le16(type); + 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); + byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq); + + pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq)); + pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq)); + pSMB->ParameterCount = cpu_to_le16(params); + pSMB->TotalParameterCount = pSMB->ParameterCount; + pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK); + pSMB->Reserved4 = 0; + pSMB->hdr.smb_buf_length += byte_count; + pSMB->ByteCount = cpu_to_le16(byte_count); + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned, 0); + if (rc) { + cFYI(1, ("Posix delete returned %d", rc)); + } + cifs_buf_release(pSMB); + + cifs_stats_inc(&tcon->num_deletes); + + if (rc == -EAGAIN) + goto PsxDelete; + + return rc; +} + +int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName, const struct nls_table *nls_codepage, int remap) { @@ -933,7 +1009,6 @@ CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags, int name_len; int rc = 0; int bytes_returned = 0; - char *data_offset; __u16 params, param_offset, offset, byte_count, count; OPEN_PSX_REQ * pdata; OPEN_PSX_RSP * psx_rsp; @@ -969,7 +1044,6 @@ PsxCreat: param_offset = offsetof(struct smb_com_transaction2_spi_req, InformationLevel) - 4; offset = param_offset + params; - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset); pdata->Level = SMB_QUERY_FILE_UNIX_BASIC; pdata->Permissions = cpu_to_le64(mode); @@ -1671,7 +1745,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, { struct smb_com_transaction2_sfi_req *pSMB = NULL; struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; - char *data_offset; struct cifs_posix_lock *parm_data; int rc = 0; int timeout = 0; @@ -1698,8 +1771,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; offset = param_offset + params; - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; - count = sizeof(struct cifs_posix_lock); pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ @@ -2120,9 +2191,7 @@ createSymLinkRetry: (struct smb_hdr *) pSMBr, &bytes_returned, 0); cifs_stats_inc(&tcon->num_symlinks); if (rc) { - cFYI(1, - ("Send error in SetPathInfo (create symlink) = %d", - rc)); + cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc)); } if (pSMB) |