cifs: add function to set file disposition
authorJeff Layton <jlayton@redhat.com>
Tue, 23 Sep 2008 15:48:35 +0000 (11:48 -0400)
committerSteve French <sfrench@us.ibm.com>
Tue, 23 Sep 2008 17:39:28 +0000 (17:39 +0000)
cifs: add function to set file disposition

The proper way to set the delete on close bit on an already existing
file is to use SET_FILE_INFO with an infolevel of
SMB_FILE_DISPOSITION_INFO. Add a function to do that and have the
silly-rename code use it.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>

fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/inode.c

index a729d08..014f26c 100644 (file)
@@ -179,6 +179,8 @@ extern int CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
 extern int CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
                        const FILE_BASIC_INFO *data, __u16 fid,
                        __u32 pid_of_opener);
+extern int CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
+                       bool delete_file, __u16 fid, __u32 pid_of_opener);
 #if 0
 extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon,
                        char *fileName, __u16 dos_attributes,
index 994de7c..7b36584 100644 (file)
@@ -4876,6 +4876,61 @@ CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
        return rc;
 }
 
+int
+CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
+                         bool delete_file, __u16 fid, __u32 pid_of_opener)
+{
+       struct smb_com_transaction2_sfi_req *pSMB  = NULL;
+       char *data_offset;
+       int rc = 0;
+       __u16 params, param_offset, offset, byte_count, count;
+
+       cFYI(1, ("Set File Disposition (via SetFileInfo)"));
+       rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
+
+       if (rc)
+               return rc;
+
+       pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+       pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
+
+       params = 6;
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+       pSMB->Flags = 0;
+       pSMB->Timeout = 0;
+       pSMB->Reserved2 = 0;
+       param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+       offset = param_offset + params;
+
+       data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+
+       count = 1;
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+       /* BB find max SMB PDU from sess */
+       pSMB->MaxDataCount = cpu_to_le16(1000);
+       pSMB->SetupCount = 1;
+       pSMB->Reserved3 = 0;
+       pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+       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->ParameterOffset = cpu_to_le16(param_offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
+       pSMB->Fid = fid;
+       pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
+       pSMB->Reserved4 = 0;
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+       *data_offset = delete_file ? 1 : 0;
+       rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
+       if (rc)
+               cFYI(1, ("Send error in SetFileDisposition = %d", rc));
+
+       return rc;
+}
 
 int
 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
index 660aac8..954b670 100644 (file)
@@ -778,8 +778,7 @@ cifs_rename_pending_delete(char *full_path, struct inode *inode, int xid)
        FILE_BASIC_INFO *info_buf;
 
        rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
-                        DELETE|FILE_WRITE_ATTRIBUTES,
-                        CREATE_NOT_DIR|CREATE_DELETE_ON_CLOSE,
+                        DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
                         &netfid, &oplock, NULL, cifs_sb->local_nls,
                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
        if (rc != 0)
@@ -807,6 +806,12 @@ cifs_rename_pending_delete(char *full_path, struct inode *inode, int xid)
        rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
                                   cifs_sb->mnt_cifs_flags &
                                            CIFS_MOUNT_MAP_SPECIAL_CHR);
+       if (rc != 0)
+               goto out_close;
+
+       /* set DELETE_ON_CLOSE */
+       rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid, current->tgid);
+
 out_close:
        CIFSSMBClose(xid, tcon, netfid);
 out: