diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 93 |
1 files changed, 37 insertions, 56 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index af902864ac0..df071fb2567 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -600,61 +600,54 @@ cgfi_exit: return rc; } -int cifs_get_inode_info(struct inode **pinode, - const unsigned char *full_path, FILE_ALL_INFO *pfindData, - struct super_block *sb, unsigned int xid, const __u16 *pfid) +int +cifs_get_inode_info(struct inode **inode, const char *full_path, + FILE_ALL_INFO *data, struct super_block *sb, int xid, + const __u16 *fid) { int rc = 0, tmprc; - struct cifs_tcon *pTcon; + struct cifs_tcon *tcon; + struct TCP_Server_Info *server; struct tcon_link *tlink; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); char *buf = NULL; - bool adjustTZ = false; + bool adjust_tz = false; struct cifs_fattr fattr; tlink = cifs_sb_tlink(cifs_sb); if (IS_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); - if ((pfindData == NULL) && (*pinode != NULL)) { - if (CIFS_I(*pinode)->clientCanCacheRead) { + if ((data == NULL) && (*inode != NULL)) { + if (CIFS_I(*inode)->clientCanCacheRead) { cFYI(1, "No need to revalidate cached inode sizes"); goto cgii_exit; } } - /* if file info not passed in then get it from server */ - if (pfindData == NULL) { + /* if inode info is not passed, get it from server */ + if (data == NULL) { + if (!server->ops->query_path_info) { + rc = -ENOSYS; + goto cgii_exit; + } buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); if (buf == NULL) { rc = -ENOMEM; goto cgii_exit; } - pfindData = (FILE_ALL_INFO *)buf; - - /* could do find first instead but this returns more info */ - 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; - } + data = (FILE_ALL_INFO *)buf; + rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path, + data, &adjust_tz); } if (!rc) { - cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData, - cifs_sb, adjustTZ); + cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *)data, cifs_sb, + adjust_tz); } else if (rc == -EREMOTE) { cifs_create_dfs_fattr(&fattr, sb); 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 * supports returning inode numbers? Are there other sanity checks we * 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) { - int rc1 = 0; - - rc1 = CIFSGetSrvInodeNumber(xid, pTcon, - full_path, &fattr.cf_uniqueid, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc1 || !fattr.cf_uniqueid) { - cFYI(1, "GetSrvInodeNum rc %d", rc1); + if (server->ops->get_srv_inum) + tmprc = server->ops->get_srv_inum(xid, tcon, + cifs_sb, full_path, &fattr.cf_uniqueid, + data); + else + tmprc = -ENOSYS; + if (tmprc || !fattr.cf_uniqueid) { + cFYI(1, "GetSrvInodeNum rc %d", tmprc); fattr.cf_uniqueid = iunique(sb, ROOT_I); cifs_autodisable_serverino(cifs_sb); } @@ -697,7 +679,7 @@ int cifs_get_inode_info(struct inode **pinode, fattr.cf_uniqueid = iunique(sb, ROOT_I); } } else { - fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid; + fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid; } /* 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 /* fill in 0777 bits from ACL */ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { - rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, - pfid); + rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid); if (rc) { cFYI(1, "%s: Getting ACL failed with error: %d", __func__, rc); @@ -732,12 +713,12 @@ int cifs_get_inode_info(struct inode **pinode, cFYI(1, "CIFSCheckMFSymlink: %d", tmprc); } - if (!*pinode) { - *pinode = cifs_iget(sb, &fattr); - if (!*pinode) + if (!*inode) { + *inode = cifs_iget(sb, &fattr); + if (!*inode) rc = -ENOMEM; } else { - cifs_fattr_to_inode(*pinode, &fattr); + cifs_fattr_to_inode(*inode, &fattr); } cgii_exit: |