cifs: add a CIFSSMBQFileInfo function
...to get inode attributes via filehandle instead of by path. In some places, we need to revalidate an inode on an open filehandle, but we can't necessarily guarantee that the dentry associated with it will still be valid. When we have an open filehandle already, it makes more sense to do a filehandle based operation anyway. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
Родитель
df2cf170c8
Коммит
bcd5357f43
|
@ -142,6 +142,8 @@ extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
|
|||
extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
|
||||
const __u16 search_handle);
|
||||
|
||||
extern int CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
|
||||
u16 netfid, FILE_ALL_INFO *pFindData);
|
||||
extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
|
||||
const unsigned char *searchName,
|
||||
FILE_ALL_INFO *findData,
|
||||
|
|
|
@ -3230,8 +3230,72 @@ QInfRetry:
|
|||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
|
||||
u16 netfid, FILE_ALL_INFO *pFindData)
|
||||
{
|
||||
struct smb_t2_qfi_req *pSMB = NULL;
|
||||
struct smb_t2_qfi_rsp *pSMBr = NULL;
|
||||
int rc = 0;
|
||||
int bytes_returned;
|
||||
__u16 params, byte_count;
|
||||
|
||||
QFileInfoRetry:
|
||||
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
|
||||
(void **) &pSMBr);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
params = 2 /* level */ + 2 /* fid */;
|
||||
pSMB->t2.TotalDataCount = 0;
|
||||
pSMB->t2.MaxParameterCount = cpu_to_le16(4);
|
||||
/* BB find exact max data count below from sess structure BB */
|
||||
pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
|
||||
pSMB->t2.MaxSetupCount = 0;
|
||||
pSMB->t2.Reserved = 0;
|
||||
pSMB->t2.Flags = 0;
|
||||
pSMB->t2.Timeout = 0;
|
||||
pSMB->t2.Reserved2 = 0;
|
||||
pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
|
||||
Fid) - 4);
|
||||
pSMB->t2.DataCount = 0;
|
||||
pSMB->t2.DataOffset = 0;
|
||||
pSMB->t2.SetupCount = 1;
|
||||
pSMB->t2.Reserved3 = 0;
|
||||
pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
|
||||
byte_count = params + 1 /* pad */ ;
|
||||
pSMB->t2.TotalParameterCount = cpu_to_le16(params);
|
||||
pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
|
||||
pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
|
||||
pSMB->Pad = 0;
|
||||
pSMB->Fid = netfid;
|
||||
pSMB->hdr.smb_buf_length += byte_count;
|
||||
|
||||
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
|
||||
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
||||
if (rc) {
|
||||
cFYI(1, ("Send error in QPathInfo = %d", rc));
|
||||
} else { /* decode response */
|
||||
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
|
||||
|
||||
if (rc) /* BB add auto retry on EOPNOTSUPP? */
|
||||
rc = -EIO;
|
||||
else if (pSMBr->ByteCount < 40)
|
||||
rc = -EIO; /* bad smb */
|
||||
else if (pFindData) {
|
||||
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
|
||||
memcpy((char *) pFindData,
|
||||
(char *) &pSMBr->hdr.Protocol +
|
||||
data_offset, sizeof(FILE_ALL_INFO));
|
||||
} else
|
||||
rc = -ENOMEM;
|
||||
}
|
||||
cifs_buf_release(pSMB);
|
||||
if (rc == -EAGAIN)
|
||||
goto QFileInfoRetry;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
|
||||
|
|
Загрузка…
Ссылка в новой задаче