cifs: add and use CIFSSMBUnixSetFileInfo for setattr calls
cifs: add and use CIFSSMBUnixSetFileInfo for setattr calls When there's an open filehandle, SET_FILE_INFO is apparently preferred over SET_PATH_INFO. Add a new variant that sets a FILE_UNIX_INFO_BASIC infolevel via SET_FILE_INFO and switch cifs_setattr_unix to use the new call when there's an open filehandle available. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
654cf14ac0
commit
3bbeeb3c93
|
@ -220,6 +220,10 @@ struct cifs_unix_set_info_args {
|
|||
dev_t device;
|
||||
};
|
||||
|
||||
extern int CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
|
||||
const struct cifs_unix_set_info_args *args,
|
||||
u16 fid, u32 pid_of_opener);
|
||||
|
||||
extern int CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *pTcon,
|
||||
char *fileName,
|
||||
const struct cifs_unix_set_info_args *args,
|
||||
|
|
|
@ -5115,6 +5115,69 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
|
|||
data_offset->Type = cpu_to_le32(UNIX_SOCKET);
|
||||
}
|
||||
|
||||
int
|
||||
CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
|
||||
const struct cifs_unix_set_info_args *args,
|
||||
u16 fid, u32 pid_of_opener)
|
||||
{
|
||||
struct smb_com_transaction2_sfi_req *pSMB = NULL;
|
||||
FILE_UNIX_BASIC_INFO *data_offset;
|
||||
int rc = 0;
|
||||
u16 params, param_offset, offset, byte_count, count;
|
||||
|
||||
cFYI(1, ("Set Unix Info (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 = (FILE_UNIX_BASIC_INFO *)
|
||||
((char *)(&pSMB->hdr.Protocol) + offset);
|
||||
count = sizeof(FILE_UNIX_BASIC_INFO);
|
||||
|
||||
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_UNIX_BASIC);
|
||||
pSMB->Reserved4 = 0;
|
||||
pSMB->hdr.smb_buf_length += byte_count;
|
||||
pSMB->ByteCount = cpu_to_le16(byte_count);
|
||||
|
||||
cifs_fill_unix_set_info(data_offset, args);
|
||||
|
||||
rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
|
||||
if (rc)
|
||||
cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
|
||||
|
||||
/* Note: On -EAGAIN error only caller can retry on handle based calls
|
||||
since file handle passed in no longer valid */
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
|
||||
const struct cifs_unix_set_info_args *args,
|
||||
|
|
|
@ -1790,6 +1790,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
|||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifsTconInfo *pTcon = cifs_sb->tcon;
|
||||
struct cifs_unix_set_info_args *args = NULL;
|
||||
struct cifsFileInfo *open_file;
|
||||
|
||||
cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x",
|
||||
direntry->d_name.name, attrs->ia_valid));
|
||||
|
@ -1876,10 +1877,18 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
|||
args->ctime = NO_CHANGE_64;
|
||||
|
||||
args->device = 0;
|
||||
rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
|
||||
open_file = find_writable_file(cifsInode);
|
||||
if (open_file) {
|
||||
u16 nfid = open_file->netfid;
|
||||
u32 npid = open_file->pid;
|
||||
rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
|
||||
atomic_dec(&open_file->wrtPending);
|
||||
} else {
|
||||
rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
}
|
||||
|
||||
if (!rc)
|
||||
rc = inode_setattr(inode, attrs);
|
||||
|
|
Loading…
Reference in New Issue