Loading fs/cifs/inode.c +71 −62 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ #include "cifs_fs_sb.h" static void cifs_set_ops(struct inode *inode) static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) { struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); Loading @@ -57,8 +57,12 @@ static void cifs_set_ops(struct inode *inode) inode->i_data.a_ops = &cifs_addr_ops; break; case S_IFDIR: if (is_dfs_referral) { inode->i_op = &cifs_dfs_referral_inode_operations; } else { inode->i_op = &cifs_dir_inode_ops; inode->i_fop = &cifs_dir_ops; } break; case S_IFLNK: inode->i_op = &cifs_symlink_inode_ops; Loading Loading @@ -153,6 +157,30 @@ static void cifs_unix_info_to_inode(struct inode *inode, spin_unlock(&inode->i_lock); } static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon, const char *search_path) { int tree_len; int path_len; char *tmp_path; if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS)) return search_path; /* use full path name for working with DFS */ tree_len = strnlen(pTcon->treeName, MAX_TREE_SIZE + 1); path_len = strnlen(search_path, MAX_PATHCONF); tmp_path = kmalloc(tree_len+path_len+1, GFP_KERNEL); if (tmp_path == NULL) return search_path; strncpy(tmp_path, pTcon->treeName, tree_len); strncpy(tmp_path+tree_len, search_path, path_len); tmp_path[tree_len+path_len] = 0; return tmp_path; } int cifs_get_inode_info_unix(struct inode **pinode, const unsigned char *search_path, struct super_block *sb, int xid) { Loading @@ -161,41 +189,28 @@ int cifs_get_inode_info_unix(struct inode **pinode, struct cifsTconInfo *pTcon; struct inode *inode; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); char *tmp_path; const unsigned char *full_path; bool is_dfs_referral = false; pTcon = cifs_sb->tcon; cFYI(1, ("Getting info on %s", search_path)); full_path = cifs_get_search_path(pTcon, search_path); try_again_CIFSSMBUnixQPathInfo: /* could have done a find first instead but this returns more info */ rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); /* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */ if (rc) { if (rc == -EREMOTE) { tmp_path = kmalloc(strnlen(pTcon->treeName, MAX_TREE_SIZE + 1) + strnlen(search_path, MAX_PATHCONF) + 1, GFP_KERNEL); if (tmp_path == NULL) return -ENOMEM; /* have to skip first of the double backslash of UNC name */ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); strncat(tmp_path, search_path, MAX_PATHCONF); rc = connect_to_dfs_path(xid, pTcon->ses, /* treename + */ tmp_path, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); kfree(tmp_path); /* BB fix up inode etc. */ } else if (rc) { return rc; if (rc == -EREMOTE && !is_dfs_referral) { is_dfs_referral = true; full_path = search_path; goto try_again_CIFSSMBUnixQPathInfo; } goto cgiiu_exit; } else { struct cifsInodeInfo *cifsInfo; __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); Loading @@ -204,8 +219,10 @@ int cifs_get_inode_info_unix(struct inode **pinode, /* get new inode */ if (*pinode == NULL) { *pinode = new_inode(sb); if (*pinode == NULL) return -ENOMEM; if (*pinode == NULL) { rc = -ENOMEM; goto cgiiu_exit; } /* Is an i_ino of zero legal? */ /* Are there sanity checks we can use to ensure that the server is really filling in that field? */ Loading Loading @@ -237,8 +254,11 @@ int cifs_get_inode_info_unix(struct inode **pinode, (unsigned long) inode->i_size, (unsigned long long)inode->i_blocks)); cifs_set_ops(inode); cifs_set_ops(inode, is_dfs_referral); } cgiiu_exit: if (full_path != search_path) kfree(full_path); return rc; } Loading Loading @@ -353,9 +373,10 @@ int cifs_get_inode_info(struct inode **pinode, struct cifsTconInfo *pTcon; struct inode *inode; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); char *tmp_path; const unsigned char *full_path = NULL; char *buf = NULL; int adjustTZ = FALSE; bool is_dfs_referral = false; pTcon = cifs_sb->tcon; cFYI(1, ("Getting info on %s", search_path)); Loading @@ -373,8 +394,12 @@ int cifs_get_inode_info(struct inode **pinode, if (buf == NULL) return -ENOMEM; pfindData = (FILE_ALL_INFO *)buf; full_path = cifs_get_search_path(pTcon, search_path); try_again_CIFSSMBQPathInfo: /* could do find first instead but this returns more info */ rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, 0 /* not legacy */, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); Loading @@ -382,7 +407,7 @@ int cifs_get_inode_info(struct inode **pinode, 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, search_path, rc = SMBQueryInformation(xid, pTcon, full_path, pfindData, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); Loading @@ -391,31 +416,12 @@ int cifs_get_inode_info(struct inode **pinode, } /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ if (rc) { if (rc == -EREMOTE) { tmp_path = kmalloc(strnlen (pTcon->treeName, MAX_TREE_SIZE + 1) + strnlen(search_path, MAX_PATHCONF) + 1, GFP_KERNEL); if (tmp_path == NULL) { kfree(buf); return -ENOMEM; } strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); strncat(tmp_path, search_path, MAX_PATHCONF); rc = connect_to_dfs_path(xid, pTcon->ses, /* treename + */ tmp_path, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); kfree(tmp_path); /* BB fix up inode etc. */ } else if (rc) { kfree(buf); return rc; if (rc == -EREMOTE && !is_dfs_referral) { is_dfs_referral = true; full_path = search_path; goto try_again_CIFSSMBQPathInfo; } goto cgii_exit; } else { struct cifsInodeInfo *cifsInfo; __u32 attr = le32_to_cpu(pfindData->Attributes); Loading @@ -424,8 +430,8 @@ int cifs_get_inode_info(struct inode **pinode, if (*pinode == NULL) { *pinode = new_inode(sb); if (*pinode == NULL) { kfree(buf); return -ENOMEM; rc = -ENOMEM; goto cgii_exit; } /* Is an i_ino of zero legal? Can we use that to check if the server supports returning inode numbers? Are Loading Loading @@ -573,8 +579,11 @@ int cifs_get_inode_info(struct inode **pinode, atomic_set(&cifsInfo->inUse, 1); } cifs_set_ops(inode); cifs_set_ops(inode, is_dfs_referral); } cgii_exit: if (full_path != search_path) kfree(full_path); kfree(buf); return rc; } Loading Loading @@ -804,7 +813,7 @@ static void posix_fill_in_inode(struct inode *tmp_inode, local_size = tmp_inode->i_size; cifs_unix_info_to_inode(tmp_inode, pData, 1); cifs_set_ops(tmp_inode); cifs_set_ops(tmp_inode, false); if (!S_ISREG(tmp_inode->i_mode)) return; Loading Loading
fs/cifs/inode.c +71 −62 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ #include "cifs_fs_sb.h" static void cifs_set_ops(struct inode *inode) static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) { struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); Loading @@ -57,8 +57,12 @@ static void cifs_set_ops(struct inode *inode) inode->i_data.a_ops = &cifs_addr_ops; break; case S_IFDIR: if (is_dfs_referral) { inode->i_op = &cifs_dfs_referral_inode_operations; } else { inode->i_op = &cifs_dir_inode_ops; inode->i_fop = &cifs_dir_ops; } break; case S_IFLNK: inode->i_op = &cifs_symlink_inode_ops; Loading Loading @@ -153,6 +157,30 @@ static void cifs_unix_info_to_inode(struct inode *inode, spin_unlock(&inode->i_lock); } static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon, const char *search_path) { int tree_len; int path_len; char *tmp_path; if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS)) return search_path; /* use full path name for working with DFS */ tree_len = strnlen(pTcon->treeName, MAX_TREE_SIZE + 1); path_len = strnlen(search_path, MAX_PATHCONF); tmp_path = kmalloc(tree_len+path_len+1, GFP_KERNEL); if (tmp_path == NULL) return search_path; strncpy(tmp_path, pTcon->treeName, tree_len); strncpy(tmp_path+tree_len, search_path, path_len); tmp_path[tree_len+path_len] = 0; return tmp_path; } int cifs_get_inode_info_unix(struct inode **pinode, const unsigned char *search_path, struct super_block *sb, int xid) { Loading @@ -161,41 +189,28 @@ int cifs_get_inode_info_unix(struct inode **pinode, struct cifsTconInfo *pTcon; struct inode *inode; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); char *tmp_path; const unsigned char *full_path; bool is_dfs_referral = false; pTcon = cifs_sb->tcon; cFYI(1, ("Getting info on %s", search_path)); full_path = cifs_get_search_path(pTcon, search_path); try_again_CIFSSMBUnixQPathInfo: /* could have done a find first instead but this returns more info */ rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); /* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */ if (rc) { if (rc == -EREMOTE) { tmp_path = kmalloc(strnlen(pTcon->treeName, MAX_TREE_SIZE + 1) + strnlen(search_path, MAX_PATHCONF) + 1, GFP_KERNEL); if (tmp_path == NULL) return -ENOMEM; /* have to skip first of the double backslash of UNC name */ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); strncat(tmp_path, search_path, MAX_PATHCONF); rc = connect_to_dfs_path(xid, pTcon->ses, /* treename + */ tmp_path, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); kfree(tmp_path); /* BB fix up inode etc. */ } else if (rc) { return rc; if (rc == -EREMOTE && !is_dfs_referral) { is_dfs_referral = true; full_path = search_path; goto try_again_CIFSSMBUnixQPathInfo; } goto cgiiu_exit; } else { struct cifsInodeInfo *cifsInfo; __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); Loading @@ -204,8 +219,10 @@ int cifs_get_inode_info_unix(struct inode **pinode, /* get new inode */ if (*pinode == NULL) { *pinode = new_inode(sb); if (*pinode == NULL) return -ENOMEM; if (*pinode == NULL) { rc = -ENOMEM; goto cgiiu_exit; } /* Is an i_ino of zero legal? */ /* Are there sanity checks we can use to ensure that the server is really filling in that field? */ Loading Loading @@ -237,8 +254,11 @@ int cifs_get_inode_info_unix(struct inode **pinode, (unsigned long) inode->i_size, (unsigned long long)inode->i_blocks)); cifs_set_ops(inode); cifs_set_ops(inode, is_dfs_referral); } cgiiu_exit: if (full_path != search_path) kfree(full_path); return rc; } Loading Loading @@ -353,9 +373,10 @@ int cifs_get_inode_info(struct inode **pinode, struct cifsTconInfo *pTcon; struct inode *inode; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); char *tmp_path; const unsigned char *full_path = NULL; char *buf = NULL; int adjustTZ = FALSE; bool is_dfs_referral = false; pTcon = cifs_sb->tcon; cFYI(1, ("Getting info on %s", search_path)); Loading @@ -373,8 +394,12 @@ int cifs_get_inode_info(struct inode **pinode, if (buf == NULL) return -ENOMEM; pfindData = (FILE_ALL_INFO *)buf; full_path = cifs_get_search_path(pTcon, search_path); try_again_CIFSSMBQPathInfo: /* could do find first instead but this returns more info */ rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, 0 /* not legacy */, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); Loading @@ -382,7 +407,7 @@ int cifs_get_inode_info(struct inode **pinode, 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, search_path, rc = SMBQueryInformation(xid, pTcon, full_path, pfindData, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); Loading @@ -391,31 +416,12 @@ int cifs_get_inode_info(struct inode **pinode, } /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ if (rc) { if (rc == -EREMOTE) { tmp_path = kmalloc(strnlen (pTcon->treeName, MAX_TREE_SIZE + 1) + strnlen(search_path, MAX_PATHCONF) + 1, GFP_KERNEL); if (tmp_path == NULL) { kfree(buf); return -ENOMEM; } strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); strncat(tmp_path, search_path, MAX_PATHCONF); rc = connect_to_dfs_path(xid, pTcon->ses, /* treename + */ tmp_path, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); kfree(tmp_path); /* BB fix up inode etc. */ } else if (rc) { kfree(buf); return rc; if (rc == -EREMOTE && !is_dfs_referral) { is_dfs_referral = true; full_path = search_path; goto try_again_CIFSSMBQPathInfo; } goto cgii_exit; } else { struct cifsInodeInfo *cifsInfo; __u32 attr = le32_to_cpu(pfindData->Attributes); Loading @@ -424,8 +430,8 @@ int cifs_get_inode_info(struct inode **pinode, if (*pinode == NULL) { *pinode = new_inode(sb); if (*pinode == NULL) { kfree(buf); return -ENOMEM; rc = -ENOMEM; goto cgii_exit; } /* Is an i_ino of zero legal? Can we use that to check if the server supports returning inode numbers? Are Loading Loading @@ -573,8 +579,11 @@ int cifs_get_inode_info(struct inode **pinode, atomic_set(&cifsInfo->inUse, 1); } cifs_set_ops(inode); cifs_set_ops(inode, is_dfs_referral); } cgii_exit: if (full_path != search_path) kfree(full_path); kfree(buf); return rc; } Loading Loading @@ -804,7 +813,7 @@ static void posix_fill_in_inode(struct inode *tmp_inode, local_size = tmp_inode->i_size; cifs_unix_info_to_inode(tmp_inode, pData, 1); cifs_set_ops(tmp_inode); cifs_set_ops(tmp_inode, false); if (!S_ISREG(tmp_inode->i_mode)) return; Loading