[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>
This commit is contained in:
parent
50c2f75388
commit
2d785a50a8
5 changed files with 103 additions and 11 deletions
|
@ -1,7 +1,9 @@
|
|||
Version 1.50
|
||||
------------
|
||||
Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is
|
||||
done with "serverino" mount option).
|
||||
done with "serverino" mount option). Add support for POSIX Unlink
|
||||
(helps with certain sharing violation cases when server such as
|
||||
Samba supports newer POSIX CIFS Protocol Extensions).
|
||||
|
||||
Version 1.49
|
||||
------------
|
||||
|
|
|
@ -2155,6 +2155,12 @@ typedef struct {
|
|||
/* struct following varies based on requested level */
|
||||
} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
|
||||
|
||||
#define SMB_POSIX_UNLINK_FILE_TARGET 0
|
||||
#define SMB_POSIX_UNLINK_DIRECTORY_TARGET 1
|
||||
|
||||
struct unlink_psx_rq { /* level 0x20a SetPathInfo */
|
||||
__le16 type;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct file_internal_info {
|
||||
__u64 UniqueId; /* inode number */
|
||||
|
|
|
@ -196,7 +196,10 @@ extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
|
|||
extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
|
||||
const char *name, const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
|
||||
extern int CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon,
|
||||
const char *name, __u16 type,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
|
||||
const char *name,
|
||||
const struct nls_table *nls_codepage,
|
||||
|
|
|
@ -788,6 +788,82 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
|
|||
return rc;
|
||||
}
|
||||
|
||||
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 @@ CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
|
|||
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 @@ CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
|
|||
(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)
|
||||
|
|
|
@ -620,9 +620,21 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
|||
FreeXid(xid);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if ((pTcon->ses->capabilities & CAP_UNIX) &&
|
||||
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
|
||||
rc = CIFSPOSIXDelFile(xid, pTcon, full_path,
|
||||
SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
cFYI(1, ("posix del rc %d", rc));
|
||||
if ((rc == 0) || (rc == -ENOENT))
|
||||
goto psx_del_no_retry;
|
||||
}
|
||||
|
||||
rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
|
||||
psx_del_no_retry:
|
||||
if (!rc) {
|
||||
if (direntry->d_inode)
|
||||
drop_nlink(direntry->d_inode);
|
||||
|
|
Loading…
Reference in a new issue