CIFS: Move query inode info code to ops struct
Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org> Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:
parent
2503a0dba9
commit
1208ef1f76
@ -163,6 +163,7 @@ struct cifsFileInfo;
|
|||||||
struct cifs_ses;
|
struct cifs_ses;
|
||||||
struct cifs_tcon;
|
struct cifs_tcon;
|
||||||
struct dfs_info3_param;
|
struct dfs_info3_param;
|
||||||
|
struct cifs_fattr;
|
||||||
|
|
||||||
struct smb_version_operations {
|
struct smb_version_operations {
|
||||||
int (*send_cancel)(struct TCP_Server_Info *, void *,
|
int (*send_cancel)(struct TCP_Server_Info *, void *,
|
||||||
@ -218,6 +219,14 @@ struct smb_version_operations {
|
|||||||
/* check if a path is accessible or not */
|
/* check if a path is accessible or not */
|
||||||
int (*is_path_accessible)(const unsigned int, struct cifs_tcon *,
|
int (*is_path_accessible)(const unsigned int, struct cifs_tcon *,
|
||||||
struct cifs_sb_info *, const char *);
|
struct cifs_sb_info *, const char *);
|
||||||
|
/* query path data from the server */
|
||||||
|
int (*query_path_info)(const unsigned int, struct cifs_tcon *,
|
||||||
|
struct cifs_sb_info *, const char *,
|
||||||
|
FILE_ALL_INFO *, bool *);
|
||||||
|
/* get server index number */
|
||||||
|
int (*get_srv_inum)(const unsigned int, struct cifs_tcon *,
|
||||||
|
struct cifs_sb_info *, const char *,
|
||||||
|
u64 *uniqueid, FILE_ALL_INFO *);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smb_version_values {
|
struct smb_version_values {
|
||||||
|
@ -138,11 +138,9 @@ extern struct inode *cifs_iget(struct super_block *sb,
|
|||||||
struct cifs_fattr *fattr);
|
struct cifs_fattr *fattr);
|
||||||
|
|
||||||
extern int cifs_get_file_info(struct file *filp);
|
extern int cifs_get_file_info(struct file *filp);
|
||||||
extern int cifs_get_inode_info(struct inode **pinode,
|
extern int cifs_get_inode_info(struct inode **inode, const char *full_path,
|
||||||
const unsigned char *search_path,
|
FILE_ALL_INFO *data, struct super_block *sb,
|
||||||
FILE_ALL_INFO *pfile_info,
|
int xid, const __u16 *fid);
|
||||||
struct super_block *sb, unsigned int xid,
|
|
||||||
const __u16 *pfid);
|
|
||||||
extern int cifs_get_file_info_unix(struct file *filp);
|
extern int cifs_get_file_info_unix(struct file *filp);
|
||||||
extern int cifs_get_inode_info_unix(struct inode **pinode,
|
extern int cifs_get_inode_info_unix(struct inode **pinode,
|
||||||
const unsigned char *search_path,
|
const unsigned char *search_path,
|
||||||
@ -376,9 +374,9 @@ extern int CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
|
|||||||
unsigned int *nbytes, struct kvec *iov, const int nvec,
|
unsigned int *nbytes, struct kvec *iov, const int nvec,
|
||||||
const int long_op);
|
const int long_op);
|
||||||
extern int CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const unsigned char *searchName, __u64 *inode_number,
|
const char *search_name, __u64 *inode_number,
|
||||||
const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage,
|
||||||
int remap_special_chars);
|
int remap);
|
||||||
|
|
||||||
extern int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const __u16 netfid, const __u8 lock_type,
|
const __u16 netfid, const __u8 lock_type,
|
||||||
|
@ -4559,8 +4559,7 @@ CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
|
|
||||||
int
|
int
|
||||||
CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
|
CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const unsigned char *searchName,
|
const char *search_name, __u64 *inode_number,
|
||||||
__u64 *inode_number,
|
|
||||||
const struct nls_table *nls_codepage, int remap)
|
const struct nls_table *nls_codepage, int remap)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@ -4569,7 +4568,7 @@ CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
int name_len, bytes_returned;
|
int name_len, bytes_returned;
|
||||||
__u16 params, byte_count;
|
__u16 params, byte_count;
|
||||||
|
|
||||||
cFYI(1, "In GetSrvInodeNum for %s", searchName);
|
cFYI(1, "In GetSrvInodeNum for %s", search_name);
|
||||||
if (tcon == NULL)
|
if (tcon == NULL)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
@ -4582,14 +4581,14 @@ GetInodeNumberRetry:
|
|||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUTF16((__le16 *) pSMB->FileName,
|
cifsConvertToUTF16((__le16 *) pSMB->FileName,
|
||||||
searchName, PATH_MAX, nls_codepage,
|
search_name, PATH_MAX, nls_codepage,
|
||||||
remap);
|
remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
} else { /* BB improve the check for buffer overruns BB */
|
} else { /* BB improve the check for buffer overruns BB */
|
||||||
name_len = strnlen(searchName, PATH_MAX);
|
name_len = strnlen(search_name, PATH_MAX);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
strncpy(pSMB->FileName, searchName, name_len);
|
strncpy(pSMB->FileName, search_name, name_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
|
params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
|
||||||
|
@ -600,61 +600,54 @@ cgfi_exit:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cifs_get_inode_info(struct inode **pinode,
|
int
|
||||||
const unsigned char *full_path, FILE_ALL_INFO *pfindData,
|
cifs_get_inode_info(struct inode **inode, const char *full_path,
|
||||||
struct super_block *sb, unsigned int xid, const __u16 *pfid)
|
FILE_ALL_INFO *data, struct super_block *sb, int xid,
|
||||||
|
const __u16 *fid)
|
||||||
{
|
{
|
||||||
int rc = 0, tmprc;
|
int rc = 0, tmprc;
|
||||||
struct cifs_tcon *pTcon;
|
struct cifs_tcon *tcon;
|
||||||
|
struct TCP_Server_Info *server;
|
||||||
struct tcon_link *tlink;
|
struct tcon_link *tlink;
|
||||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
bool adjustTZ = false;
|
bool adjust_tz = false;
|
||||||
struct cifs_fattr fattr;
|
struct cifs_fattr fattr;
|
||||||
|
|
||||||
tlink = cifs_sb_tlink(cifs_sb);
|
tlink = cifs_sb_tlink(cifs_sb);
|
||||||
if (IS_ERR(tlink))
|
if (IS_ERR(tlink))
|
||||||
return PTR_ERR(tlink);
|
return PTR_ERR(tlink);
|
||||||
pTcon = tlink_tcon(tlink);
|
tcon = tlink_tcon(tlink);
|
||||||
|
server = tcon->ses->server;
|
||||||
|
|
||||||
cFYI(1, "Getting info on %s", full_path);
|
cFYI(1, "Getting info on %s", full_path);
|
||||||
|
|
||||||
if ((pfindData == NULL) && (*pinode != NULL)) {
|
if ((data == NULL) && (*inode != NULL)) {
|
||||||
if (CIFS_I(*pinode)->clientCanCacheRead) {
|
if (CIFS_I(*inode)->clientCanCacheRead) {
|
||||||
cFYI(1, "No need to revalidate cached inode sizes");
|
cFYI(1, "No need to revalidate cached inode sizes");
|
||||||
goto cgii_exit;
|
goto cgii_exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if file info not passed in then get it from server */
|
/* if inode info is not passed, get it from server */
|
||||||
if (pfindData == NULL) {
|
if (data == NULL) {
|
||||||
|
if (!server->ops->query_path_info) {
|
||||||
|
rc = -ENOSYS;
|
||||||
|
goto cgii_exit;
|
||||||
|
}
|
||||||
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto cgii_exit;
|
goto cgii_exit;
|
||||||
}
|
}
|
||||||
pfindData = (FILE_ALL_INFO *)buf;
|
data = (FILE_ALL_INFO *)buf;
|
||||||
|
rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
|
||||||
/* could do find first instead but this returns more info */
|
data, &adjust_tz);
|
||||||
rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData,
|
|
||||||
0 /* not legacy */,
|
|
||||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
/* BB optimize code so we do not make the above call
|
|
||||||
when server claims no NT SMB support and the above call
|
|
||||||
failed at least once - set flag in tcon or mount */
|
|
||||||
if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
|
|
||||||
rc = SMBQueryInformation(xid, pTcon, full_path,
|
|
||||||
pfindData, cifs_sb->local_nls,
|
|
||||||
cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
adjustTZ = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData,
|
cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *)data, cifs_sb,
|
||||||
cifs_sb, adjustTZ);
|
adjust_tz);
|
||||||
} else if (rc == -EREMOTE) {
|
} else if (rc == -EREMOTE) {
|
||||||
cifs_create_dfs_fattr(&fattr, sb);
|
cifs_create_dfs_fattr(&fattr, sb);
|
||||||
rc = 0;
|
rc = 0;
|
||||||
@ -668,28 +661,17 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||||||
* Is an i_ino of zero legal? Can we use that to check if the server
|
* Is an i_ino of zero legal? Can we use that to check if the server
|
||||||
* supports returning inode numbers? Are there other sanity checks we
|
* supports returning inode numbers? Are there other sanity checks we
|
||||||
* can use to ensure that the server is really filling in that field?
|
* can use to ensure that the server is really filling in that field?
|
||||||
*
|
|
||||||
* We can not use the IndexNumber field by default from Windows or
|
|
||||||
* Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
|
|
||||||
* CIFS spec claims that this value is unique within the scope of a
|
|
||||||
* share, and the windows docs hint that it's actually unique
|
|
||||||
* per-machine.
|
|
||||||
*
|
|
||||||
* There may be higher info levels that work but are there Windows
|
|
||||||
* server or network appliances for which IndexNumber field is not
|
|
||||||
* guaranteed unique?
|
|
||||||
*/
|
*/
|
||||||
if (*pinode == NULL) {
|
if (*inode == NULL) {
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||||
int rc1 = 0;
|
if (server->ops->get_srv_inum)
|
||||||
|
tmprc = server->ops->get_srv_inum(xid, tcon,
|
||||||
rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
|
cifs_sb, full_path, &fattr.cf_uniqueid,
|
||||||
full_path, &fattr.cf_uniqueid,
|
data);
|
||||||
cifs_sb->local_nls,
|
else
|
||||||
cifs_sb->mnt_cifs_flags &
|
tmprc = -ENOSYS;
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
if (tmprc || !fattr.cf_uniqueid) {
|
||||||
if (rc1 || !fattr.cf_uniqueid) {
|
cFYI(1, "GetSrvInodeNum rc %d", tmprc);
|
||||||
cFYI(1, "GetSrvInodeNum rc %d", rc1);
|
|
||||||
fattr.cf_uniqueid = iunique(sb, ROOT_I);
|
fattr.cf_uniqueid = iunique(sb, ROOT_I);
|
||||||
cifs_autodisable_serverino(cifs_sb);
|
cifs_autodisable_serverino(cifs_sb);
|
||||||
}
|
}
|
||||||
@ -697,7 +679,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||||||
fattr.cf_uniqueid = iunique(sb, ROOT_I);
|
fattr.cf_uniqueid = iunique(sb, ROOT_I);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid;
|
fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* query for SFU type info if supported and needed */
|
/* query for SFU type info if supported and needed */
|
||||||
@ -711,8 +693,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||||||
#ifdef CONFIG_CIFS_ACL
|
#ifdef CONFIG_CIFS_ACL
|
||||||
/* fill in 0777 bits from ACL */
|
/* fill in 0777 bits from ACL */
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
|
||||||
rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path,
|
rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
|
||||||
pfid);
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cFYI(1, "%s: Getting ACL failed with error: %d",
|
cFYI(1, "%s: Getting ACL failed with error: %d",
|
||||||
__func__, rc);
|
__func__, rc);
|
||||||
@ -732,12 +713,12 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||||||
cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
|
cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*pinode) {
|
if (!*inode) {
|
||||||
*pinode = cifs_iget(sb, &fattr);
|
*inode = cifs_iget(sb, &fattr);
|
||||||
if (!*pinode)
|
if (!*inode)
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
} else {
|
} else {
|
||||||
cifs_fattr_to_inode(*pinode, &fattr);
|
cifs_fattr_to_inode(*inode, &fattr);
|
||||||
}
|
}
|
||||||
|
|
||||||
cgii_exit:
|
cgii_exit:
|
||||||
|
@ -441,6 +441,54 @@ cifs_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
struct cifs_sb_info *cifs_sb, const char *full_path,
|
||||||
|
FILE_ALL_INFO *data, bool *adjustTZ)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* could do find first instead but this returns more info */
|
||||||
|
rc = CIFSSMBQPathInfo(xid, tcon, full_path, data, 0 /* not legacy */,
|
||||||
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
/*
|
||||||
|
* BB optimize code so we do not make the above call when server claims
|
||||||
|
* no NT SMB support and the above call failed at least once - set flag
|
||||||
|
* in tcon or mount.
|
||||||
|
*/
|
||||||
|
if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
|
||||||
|
rc = SMBQueryInformation(xid, tcon, full_path, data,
|
||||||
|
cifs_sb->local_nls,
|
||||||
|
cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
*adjustTZ = true;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cifs_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
struct cifs_sb_info *cifs_sb, const char *full_path,
|
||||||
|
u64 *uniqueid, FILE_ALL_INFO *data)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We can not use the IndexNumber field by default from Windows or
|
||||||
|
* Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
|
||||||
|
* CIFS spec claims that this value is unique within the scope of a
|
||||||
|
* share, and the windows docs hint that it's actually unique
|
||||||
|
* per-machine.
|
||||||
|
*
|
||||||
|
* There may be higher info levels that work but are there Windows
|
||||||
|
* server or network appliances for which IndexNumber field is not
|
||||||
|
* guaranteed unique?
|
||||||
|
*/
|
||||||
|
return CIFSGetSrvInodeNumber(xid, tcon, full_path, uniqueid,
|
||||||
|
cifs_sb->local_nls,
|
||||||
|
cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
}
|
||||||
|
|
||||||
struct smb_version_operations smb1_operations = {
|
struct smb_version_operations smb1_operations = {
|
||||||
.send_cancel = send_nt_cancel,
|
.send_cancel = send_nt_cancel,
|
||||||
.compare_fids = cifs_compare_fids,
|
.compare_fids = cifs_compare_fids,
|
||||||
@ -468,6 +516,8 @@ struct smb_version_operations smb1_operations = {
|
|||||||
.get_dfs_refer = CIFSGetDFSRefer,
|
.get_dfs_refer = CIFSGetDFSRefer,
|
||||||
.qfs_tcon = cifs_qfs_tcon,
|
.qfs_tcon = cifs_qfs_tcon,
|
||||||
.is_path_accessible = cifs_is_path_accessible,
|
.is_path_accessible = cifs_is_path_accessible,
|
||||||
|
.query_path_info = cifs_query_path_info,
|
||||||
|
.get_srv_inum = cifs_get_srv_inum,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smb_version_values smb1_values = {
|
struct smb_version_values smb1_values = {
|
||||||
|
Loading…
Reference in New Issue
Block a user