提交 1208ef1f 编写于 作者: P Pavel Shilovsky

CIFS: Move query inode info code to ops struct

Signed-off-by: NPavel Shilovsky <pshilovsky@samba.org>
Signed-off-by: NSteve French <smfrench@gmail.com>
上级 2503a0db
...@@ -163,6 +163,7 @@ struct cifsFileInfo; ...@@ -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 { ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 @@ CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -4582,14 +4581,14 @@ CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
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 @@ int cifs_get_file_info(struct file *filp) ...@@ -600,61 +600,54 @@ int cifs_get_file_info(struct file *filp)
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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 = { ...@@ -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 = {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册