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:
Jeff Layton 2009-07-09 20:02:50 -04:00 committed by Steve French
parent 654cf14ac0
commit 3bbeeb3c93
3 changed files with 77 additions and 1 deletions

View File

@ -220,6 +220,10 @@ struct cifs_unix_set_info_args {
dev_t device; 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, extern int CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *pTcon,
char *fileName, char *fileName,
const struct cifs_unix_set_info_args *args, const struct cifs_unix_set_info_args *args,

View File

@ -5115,6 +5115,69 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
data_offset->Type = cpu_to_le32(UNIX_SOCKET); 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 int
CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
const struct cifs_unix_set_info_args *args, const struct cifs_unix_set_info_args *args,

View File

@ -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 cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsTconInfo *pTcon = cifs_sb->tcon; struct cifsTconInfo *pTcon = cifs_sb->tcon;
struct cifs_unix_set_info_args *args = NULL; struct cifs_unix_set_info_args *args = NULL;
struct cifsFileInfo *open_file;
cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x",
direntry->d_name.name, attrs->ia_valid)); 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->ctime = NO_CHANGE_64;
args->device = 0; 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->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
}
if (!rc) if (!rc)
rc = inode_setattr(inode, attrs); rc = inode_setattr(inode, attrs);