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)
        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;
        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);
 {
        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;
        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 */
                         (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)
 
                FreeXid(xid);
                return -ENOMEM;
        }
-       rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
+
+       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);