|
@@ -607,7 +607,9 @@ 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;
|
|
|
+ bool validinum = false;
|
|
|
+ __u16 srchflgs;
|
|
|
+ int rc = 0, tmprc = ENOSYS;
|
|
|
struct cifs_tcon *tcon;
|
|
|
struct TCP_Server_Info *server;
|
|
|
struct tcon_link *tlink;
|
|
@@ -615,6 +617,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
|
|
|
char *buf = NULL;
|
|
|
bool adjust_tz = false;
|
|
|
struct cifs_fattr fattr;
|
|
|
+ struct cifs_search_info *srchinf = NULL;
|
|
|
|
|
|
tlink = cifs_sb_tlink(cifs_sb);
|
|
|
if (IS_ERR(tlink))
|
|
@@ -653,9 +656,38 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
|
|
|
} else if (rc == -EREMOTE) {
|
|
|
cifs_create_dfs_fattr(&fattr, sb);
|
|
|
rc = 0;
|
|
|
- } else {
|
|
|
+ } else if (rc == -EACCES && backup_cred(cifs_sb)) {
|
|
|
+ srchinf = kzalloc(sizeof(struct cifs_search_info),
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (srchinf == NULL) {
|
|
|
+ rc = -ENOMEM;
|
|
|
+ goto cgii_exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ srchinf->endOfSearch = false;
|
|
|
+ srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
|
|
|
+
|
|
|
+ srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
|
|
|
+ CIFS_SEARCH_CLOSE_AT_END |
|
|
|
+ CIFS_SEARCH_BACKUP_SEARCH;
|
|
|
+
|
|
|
+ rc = CIFSFindFirst(xid, tcon, full_path,
|
|
|
+ cifs_sb, NULL, srchflgs, srchinf, false);
|
|
|
+ if (!rc) {
|
|
|
+ data =
|
|
|
+ (FILE_ALL_INFO *)srchinf->srch_entries_start;
|
|
|
+
|
|
|
+ cifs_dir_info_to_fattr(&fattr,
|
|
|
+ (FILE_DIRECTORY_INFO *)data, cifs_sb);
|
|
|
+ fattr.cf_uniqueid = le64_to_cpu(
|
|
|
+ ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
|
|
|
+ validinum = true;
|
|
|
+
|
|
|
+ cifs_buf_release(srchinf->ntwrk_buf_start);
|
|
|
+ }
|
|
|
+ kfree(srchinf);
|
|
|
+ } else
|
|
|
goto cgii_exit;
|
|
|
- }
|
|
|
|
|
|
/*
|
|
|
* If an inode wasn't passed in, then get the inode number
|
|
@@ -666,23 +698,21 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
|
|
|
*/
|
|
|
if (*inode == NULL) {
|
|
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
|
|
- 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);
|
|
|
+ if (validinum == false) {
|
|
|
+ if (server->ops->get_srv_inum)
|
|
|
+ tmprc = server->ops->get_srv_inum(xid,
|
|
|
+ tcon, cifs_sb, full_path,
|
|
|
+ &fattr.cf_uniqueid, data);
|
|
|
+ if (tmprc) {
|
|
|
+ cFYI(1, "GetSrvInodeNum rc %d", tmprc);
|
|
|
+ fattr.cf_uniqueid = iunique(sb, ROOT_I);
|
|
|
+ cifs_autodisable_serverino(cifs_sb);
|
|
|
+ }
|
|
|
}
|
|
|
- } else {
|
|
|
+ } else
|
|
|
fattr.cf_uniqueid = iunique(sb, ROOT_I);
|
|
|
- }
|
|
|
- } else {
|
|
|
+ } else
|
|
|
fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
|
|
|
- }
|
|
|
|
|
|
/* query for SFU type info if supported and needed */
|
|
|
if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
|