diff options
| -rw-r--r-- | fs/cifs/cifs_dfs_ref.c | 18 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 4 | ||||
| -rw-r--r-- | fs/cifs/dns_resolve.c | 8 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 146 |
4 files changed, 95 insertions, 81 deletions
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 7f8838253410..a1a95b027136 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c | |||
| @@ -74,7 +74,7 @@ static char *cifs_get_share_name(const char *node_name) | |||
| 74 | pSep = memchr(UNC+2, '\\', len-2); | 74 | pSep = memchr(UNC+2, '\\', len-2); |
| 75 | if (!pSep) { | 75 | if (!pSep) { |
| 76 | cERROR(1, ("%s: no server name end in node name: %s", | 76 | cERROR(1, ("%s: no server name end in node name: %s", |
| 77 | __FUNCTION__, node_name)); | 77 | __func__, node_name)); |
| 78 | kfree(UNC); | 78 | kfree(UNC); |
| 79 | return NULL; | 79 | return NULL; |
| 80 | } | 80 | } |
| @@ -84,7 +84,7 @@ static char *cifs_get_share_name(const char *node_name) | |||
| 84 | pSep = memchr(UNC+(pSep-UNC), '\\', len-(pSep-UNC)); | 84 | pSep = memchr(UNC+(pSep-UNC), '\\', len-(pSep-UNC)); |
| 85 | if (!pSep) { | 85 | if (!pSep) { |
| 86 | cERROR(1, ("%s:2 cant find share name in node name: %s", | 86 | cERROR(1, ("%s:2 cant find share name in node name: %s", |
| 87 | __FUNCTION__, node_name)); | 87 | __func__, node_name)); |
| 88 | kfree(UNC); | 88 | kfree(UNC); |
| 89 | return NULL; | 89 | return NULL; |
| 90 | } | 90 | } |
| @@ -127,7 +127,7 @@ static char *compose_mount_options(const char *sb_mountdata, | |||
| 127 | rc = dns_resolve_server_name_to_ip(*devname, &srvIP); | 127 | rc = dns_resolve_server_name_to_ip(*devname, &srvIP); |
| 128 | if (rc != 0) { | 128 | if (rc != 0) { |
| 129 | cERROR(1, ("%s: Failed to resolve server part of %s to IP", | 129 | cERROR(1, ("%s: Failed to resolve server part of %s to IP", |
| 130 | __FUNCTION__, *devname)); | 130 | __func__, *devname)); |
| 131 | mountdata = ERR_PTR(rc); | 131 | mountdata = ERR_PTR(rc); |
| 132 | goto compose_mount_options_out; | 132 | goto compose_mount_options_out; |
| 133 | } | 133 | } |
| @@ -181,8 +181,8 @@ static char *compose_mount_options(const char *sb_mountdata, | |||
| 181 | } | 181 | } |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | /*cFYI(1,("%s: parent mountdata: %s", __FUNCTION__,sb_mountdata));*/ | 184 | /*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/ |
| 185 | /*cFYI(1, ("%s: submount mountdata: %s", __FUNCTION__, mountdata ));*/ | 185 | /*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/ |
| 186 | 186 | ||
| 187 | compose_mount_options_out: | 187 | compose_mount_options_out: |
| 188 | kfree(srvIP); | 188 | kfree(srvIP); |
| @@ -302,7 +302,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
| 302 | int rc = 0; | 302 | int rc = 0; |
| 303 | struct vfsmount *mnt = ERR_PTR(-ENOENT); | 303 | struct vfsmount *mnt = ERR_PTR(-ENOENT); |
| 304 | 304 | ||
| 305 | cFYI(1, ("in %s", __FUNCTION__)); | 305 | cFYI(1, ("in %s", __func__)); |
| 306 | BUG_ON(IS_ROOT(dentry)); | 306 | BUG_ON(IS_ROOT(dentry)); |
| 307 | 307 | ||
| 308 | xid = GetXid(); | 308 | xid = GetXid(); |
| @@ -336,7 +336,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
| 336 | len = strlen(referrals[i].node_name); | 336 | len = strlen(referrals[i].node_name); |
| 337 | if (len < 2) { | 337 | if (len < 2) { |
| 338 | cERROR(1, ("%s: Net Address path too short: %s", | 338 | cERROR(1, ("%s: Net Address path too short: %s", |
| 339 | __FUNCTION__, referrals[i].node_name)); | 339 | __func__, referrals[i].node_name)); |
| 340 | rc = -EINVAL; | 340 | rc = -EINVAL; |
| 341 | goto out_err; | 341 | goto out_err; |
| 342 | } | 342 | } |
| @@ -344,7 +344,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
| 344 | nd->path.dentry, | 344 | nd->path.dentry, |
| 345 | referrals[i].node_name); | 345 | referrals[i].node_name); |
| 346 | cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", | 346 | cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", |
| 347 | __FUNCTION__, | 347 | __func__, |
| 348 | referrals[i].node_name, mnt)); | 348 | referrals[i].node_name, mnt)); |
| 349 | 349 | ||
| 350 | /* complete mount procedure if we accured submount */ | 350 | /* complete mount procedure if we accured submount */ |
| @@ -365,7 +365,7 @@ out: | |||
| 365 | FreeXid(xid); | 365 | FreeXid(xid); |
| 366 | free_dfs_info_array(referrals, num_referrals); | 366 | free_dfs_info_array(referrals, num_referrals); |
| 367 | kfree(full_path); | 367 | kfree(full_path); |
| 368 | cFYI(1, ("leaving %s" , __FUNCTION__)); | 368 | cFYI(1, ("leaving %s" , __func__)); |
| 369 | return ERR_PTR(rc); | 369 | return ERR_PTR(rc); |
| 370 | out_err: | 370 | out_err: |
| 371 | path_put(&nd->path); | 371 | path_put(&nd->path); |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 0af63e6b426b..a0414bda587c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -39,8 +39,8 @@ extern int smb_send(struct socket *, struct smb_hdr *, | |||
| 39 | unsigned int /* length */ , struct sockaddr *); | 39 | unsigned int /* length */ , struct sockaddr *); |
| 40 | extern unsigned int _GetXid(void); | 40 | extern unsigned int _GetXid(void); |
| 41 | extern void _FreeXid(unsigned int); | 41 | extern void _FreeXid(unsigned int); |
| 42 | #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid)); | 42 | #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current->fsuid)); |
| 43 | #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));} | 43 | #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));} |
| 44 | extern char *build_path_from_dentry(struct dentry *); | 44 | extern char *build_path_from_dentry(struct dentry *); |
| 45 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); | 45 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); |
| 46 | /* extern void renew_parental_timestamps(struct dentry *direntry);*/ | 46 | /* extern void renew_parental_timestamps(struct dentry *direntry);*/ |
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index ef7f43824347..7cc86c418182 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c | |||
| @@ -77,14 +77,14 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) | |||
| 77 | /* search for server name delimiter */ | 77 | /* search for server name delimiter */ |
| 78 | len = strlen(unc); | 78 | len = strlen(unc); |
| 79 | if (len < 3) { | 79 | if (len < 3) { |
| 80 | cFYI(1, ("%s: unc is too short: %s", __FUNCTION__, unc)); | 80 | cFYI(1, ("%s: unc is too short: %s", __func__, unc)); |
| 81 | return -EINVAL; | 81 | return -EINVAL; |
| 82 | } | 82 | } |
| 83 | len -= 2; | 83 | len -= 2; |
| 84 | name = memchr(unc+2, '\\', len); | 84 | name = memchr(unc+2, '\\', len); |
| 85 | if (!name) { | 85 | if (!name) { |
| 86 | cFYI(1, ("%s: probably server name is whole unc: %s", | 86 | cFYI(1, ("%s: probably server name is whole unc: %s", |
| 87 | __FUNCTION__, unc)); | 87 | __func__, unc)); |
| 88 | } else { | 88 | } else { |
| 89 | len = (name - unc) - 2/* leading // */; | 89 | len = (name - unc) - 2/* leading // */; |
| 90 | } | 90 | } |
| @@ -104,7 +104,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) | |||
| 104 | if (*ip_addr) { | 104 | if (*ip_addr) { |
| 105 | memcpy(*ip_addr, rkey->payload.data, len); | 105 | memcpy(*ip_addr, rkey->payload.data, len); |
| 106 | (*ip_addr)[len] = '\0'; | 106 | (*ip_addr)[len] = '\0'; |
| 107 | cFYI(1, ("%s: resolved: %s to %s", __FUNCTION__, | 107 | cFYI(1, ("%s: resolved: %s to %s", __func__, |
| 108 | rkey->description, | 108 | rkey->description, |
| 109 | *ip_addr | 109 | *ip_addr |
| 110 | )); | 110 | )); |
| @@ -114,7 +114,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) | |||
| 114 | } | 114 | } |
| 115 | key_put(rkey); | 115 | key_put(rkey); |
| 116 | } else { | 116 | } else { |
| 117 | cERROR(1, ("%s: unable to resolve: %s", __FUNCTION__, name)); | 117 | cERROR(1, ("%s: unable to resolve: %s", __func__, name)); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | kfree(name); | 120 | kfree(name); |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 24eb4d392155..e57e5c46ad48 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | #include "cifs_fs_sb.h" | 30 | #include "cifs_fs_sb.h" |
| 31 | 31 | ||
| 32 | 32 | ||
| 33 | static void cifs_set_ops(struct inode *inode) | 33 | static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) |
| 34 | { | 34 | { |
| 35 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 35 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| 36 | 36 | ||
| @@ -57,8 +57,16 @@ static void cifs_set_ops(struct inode *inode) | |||
| 57 | inode->i_data.a_ops = &cifs_addr_ops; | 57 | inode->i_data.a_ops = &cifs_addr_ops; |
| 58 | break; | 58 | break; |
| 59 | case S_IFDIR: | 59 | case S_IFDIR: |
| 60 | inode->i_op = &cifs_dir_inode_ops; | 60 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| 61 | inode->i_fop = &cifs_dir_ops; | 61 | if (is_dfs_referral) { |
| 62 | inode->i_op = &cifs_dfs_referral_inode_operations; | ||
| 63 | } else { | ||
| 64 | #else /* NO DFS support, treat as a directory */ | ||
| 65 | { | ||
| 66 | #endif | ||
| 67 | inode->i_op = &cifs_dir_inode_ops; | ||
| 68 | inode->i_fop = &cifs_dir_ops; | ||
| 69 | } | ||
| 62 | break; | 70 | break; |
| 63 | case S_IFLNK: | 71 | case S_IFLNK: |
| 64 | inode->i_op = &cifs_symlink_inode_ops; | 72 | inode->i_op = &cifs_symlink_inode_ops; |
| @@ -153,6 +161,30 @@ static void cifs_unix_info_to_inode(struct inode *inode, | |||
| 153 | spin_unlock(&inode->i_lock); | 161 | spin_unlock(&inode->i_lock); |
| 154 | } | 162 | } |
| 155 | 163 | ||
| 164 | static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon, | ||
| 165 | const char *search_path) | ||
| 166 | { | ||
| 167 | int tree_len; | ||
| 168 | int path_len; | ||
| 169 | char *tmp_path; | ||
| 170 | |||
| 171 | if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS)) | ||
| 172 | return search_path; | ||
| 173 | |||
| 174 | /* use full path name for working with DFS */ | ||
| 175 | tree_len = strnlen(pTcon->treeName, MAX_TREE_SIZE + 1); | ||
| 176 | path_len = strnlen(search_path, MAX_PATHCONF); | ||
| 177 | |||
| 178 | tmp_path = kmalloc(tree_len+path_len+1, GFP_KERNEL); | ||
| 179 | if (tmp_path == NULL) | ||
| 180 | return search_path; | ||
| 181 | |||
| 182 | strncpy(tmp_path, pTcon->treeName, tree_len); | ||
| 183 | strncpy(tmp_path+tree_len, search_path, path_len); | ||
| 184 | tmp_path[tree_len+path_len] = 0; | ||
| 185 | return tmp_path; | ||
| 186 | } | ||
| 187 | |||
| 156 | int cifs_get_inode_info_unix(struct inode **pinode, | 188 | int cifs_get_inode_info_unix(struct inode **pinode, |
| 157 | const unsigned char *search_path, struct super_block *sb, int xid) | 189 | const unsigned char *search_path, struct super_block *sb, int xid) |
| 158 | { | 190 | { |
| @@ -161,41 +193,28 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
| 161 | struct cifsTconInfo *pTcon; | 193 | struct cifsTconInfo *pTcon; |
| 162 | struct inode *inode; | 194 | struct inode *inode; |
| 163 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 195 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 164 | char *tmp_path; | 196 | const unsigned char *full_path; |
| 197 | bool is_dfs_referral = false; | ||
| 165 | 198 | ||
| 166 | pTcon = cifs_sb->tcon; | 199 | pTcon = cifs_sb->tcon; |
| 167 | cFYI(1, ("Getting info on %s", search_path)); | 200 | cFYI(1, ("Getting info on %s", search_path)); |
| 201 | |||
| 202 | full_path = cifs_get_search_path(pTcon, search_path); | ||
| 203 | |||
| 204 | try_again_CIFSSMBUnixQPathInfo: | ||
| 168 | /* could have done a find first instead but this returns more info */ | 205 | /* could have done a find first instead but this returns more info */ |
| 169 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, | 206 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData, |
| 170 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 207 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
| 171 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 208 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 172 | /* dump_mem("\nUnixQPathInfo return data", &findData, | 209 | /* dump_mem("\nUnixQPathInfo return data", &findData, |
| 173 | sizeof(findData)); */ | 210 | sizeof(findData)); */ |
| 174 | if (rc) { | 211 | if (rc) { |
| 175 | if (rc == -EREMOTE) { | 212 | if (rc == -EREMOTE && !is_dfs_referral) { |
| 176 | tmp_path = | 213 | is_dfs_referral = true; |
| 177 | kmalloc(strnlen(pTcon->treeName, | 214 | full_path = search_path; |
| 178 | MAX_TREE_SIZE + 1) + | 215 | goto try_again_CIFSSMBUnixQPathInfo; |
| 179 | strnlen(search_path, MAX_PATHCONF) + 1, | ||
| 180 | GFP_KERNEL); | ||
| 181 | if (tmp_path == NULL) | ||
| 182 | return -ENOMEM; | ||
| 183 | |||
| 184 | /* have to skip first of the double backslash of | ||
| 185 | UNC name */ | ||
| 186 | strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); | ||
| 187 | strncat(tmp_path, search_path, MAX_PATHCONF); | ||
| 188 | rc = connect_to_dfs_path(xid, pTcon->ses, | ||
| 189 | /* treename + */ tmp_path, | ||
| 190 | cifs_sb->local_nls, | ||
| 191 | cifs_sb->mnt_cifs_flags & | ||
| 192 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 193 | kfree(tmp_path); | ||
| 194 | |||
| 195 | /* BB fix up inode etc. */ | ||
| 196 | } else if (rc) { | ||
| 197 | return rc; | ||
| 198 | } | 216 | } |
| 217 | goto cgiiu_exit; | ||
| 199 | } else { | 218 | } else { |
| 200 | struct cifsInodeInfo *cifsInfo; | 219 | struct cifsInodeInfo *cifsInfo; |
| 201 | __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); | 220 | __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); |
| @@ -204,8 +223,10 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
| 204 | /* get new inode */ | 223 | /* get new inode */ |
| 205 | if (*pinode == NULL) { | 224 | if (*pinode == NULL) { |
| 206 | *pinode = new_inode(sb); | 225 | *pinode = new_inode(sb); |
| 207 | if (*pinode == NULL) | 226 | if (*pinode == NULL) { |
| 208 | return -ENOMEM; | 227 | rc = -ENOMEM; |
| 228 | goto cgiiu_exit; | ||
| 229 | } | ||
| 209 | /* Is an i_ino of zero legal? */ | 230 | /* Is an i_ino of zero legal? */ |
| 210 | /* Are there sanity checks we can use to ensure that | 231 | /* Are there sanity checks we can use to ensure that |
| 211 | the server is really filling in that field? */ | 232 | the server is really filling in that field? */ |
| @@ -237,8 +258,11 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
| 237 | (unsigned long) inode->i_size, | 258 | (unsigned long) inode->i_size, |
| 238 | (unsigned long long)inode->i_blocks)); | 259 | (unsigned long long)inode->i_blocks)); |
| 239 | 260 | ||
| 240 | cifs_set_ops(inode); | 261 | cifs_set_ops(inode, is_dfs_referral); |
| 241 | } | 262 | } |
| 263 | cgiiu_exit: | ||
| 264 | if (full_path != search_path) | ||
| 265 | kfree(full_path); | ||
| 242 | return rc; | 266 | return rc; |
| 243 | } | 267 | } |
| 244 | 268 | ||
| @@ -353,9 +377,10 @@ int cifs_get_inode_info(struct inode **pinode, | |||
| 353 | struct cifsTconInfo *pTcon; | 377 | struct cifsTconInfo *pTcon; |
| 354 | struct inode *inode; | 378 | struct inode *inode; |
| 355 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 379 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 356 | char *tmp_path; | 380 | const unsigned char *full_path = NULL; |
| 357 | char *buf = NULL; | 381 | char *buf = NULL; |
| 358 | int adjustTZ = FALSE; | 382 | int adjustTZ = FALSE; |
| 383 | bool is_dfs_referral = false; | ||
| 359 | 384 | ||
| 360 | pTcon = cifs_sb->tcon; | 385 | pTcon = cifs_sb->tcon; |
| 361 | cFYI(1, ("Getting info on %s", search_path)); | 386 | cFYI(1, ("Getting info on %s", search_path)); |
| @@ -373,8 +398,12 @@ int cifs_get_inode_info(struct inode **pinode, | |||
| 373 | if (buf == NULL) | 398 | if (buf == NULL) |
| 374 | return -ENOMEM; | 399 | return -ENOMEM; |
| 375 | pfindData = (FILE_ALL_INFO *)buf; | 400 | pfindData = (FILE_ALL_INFO *)buf; |
| 401 | |||
| 402 | full_path = cifs_get_search_path(pTcon, search_path); | ||
| 403 | |||
| 404 | try_again_CIFSSMBQPathInfo: | ||
| 376 | /* could do find first instead but this returns more info */ | 405 | /* could do find first instead but this returns more info */ |
| 377 | rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, | 406 | rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, |
| 378 | 0 /* not legacy */, | 407 | 0 /* not legacy */, |
| 379 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 408 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
| 380 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 409 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| @@ -382,7 +411,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
| 382 | when server claims no NT SMB support and the above call | 411 | when server claims no NT SMB support and the above call |
| 383 | failed at least once - set flag in tcon or mount */ | 412 | failed at least once - set flag in tcon or mount */ |
| 384 | if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { | 413 | if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { |
| 385 | rc = SMBQueryInformation(xid, pTcon, search_path, | 414 | rc = SMBQueryInformation(xid, pTcon, full_path, |
| 386 | pfindData, cifs_sb->local_nls, | 415 | pfindData, cifs_sb->local_nls, |
| 387 | cifs_sb->mnt_cifs_flags & | 416 | cifs_sb->mnt_cifs_flags & |
| 388 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 417 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| @@ -391,31 +420,12 @@ int cifs_get_inode_info(struct inode **pinode, | |||
| 391 | } | 420 | } |
| 392 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ | 421 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ |
| 393 | if (rc) { | 422 | if (rc) { |
| 394 | if (rc == -EREMOTE) { | 423 | if (rc == -EREMOTE && !is_dfs_referral) { |
| 395 | tmp_path = | 424 | is_dfs_referral = true; |
| 396 | kmalloc(strnlen | 425 | full_path = search_path; |
| 397 | (pTcon->treeName, | 426 | goto try_again_CIFSSMBQPathInfo; |
| 398 | MAX_TREE_SIZE + 1) + | ||
| 399 | strnlen(search_path, MAX_PATHCONF) + 1, | ||
| 400 | GFP_KERNEL); | ||
| 401 | if (tmp_path == NULL) { | ||
| 402 | kfree(buf); | ||
| 403 | return -ENOMEM; | ||
| 404 | } | ||
| 405 | |||
| 406 | strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); | ||
| 407 | strncat(tmp_path, search_path, MAX_PATHCONF); | ||
| 408 | rc = connect_to_dfs_path(xid, pTcon->ses, | ||
| 409 | /* treename + */ tmp_path, | ||
| 410 | cifs_sb->local_nls, | ||
| 411 | cifs_sb->mnt_cifs_flags & | ||
| 412 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 413 | kfree(tmp_path); | ||
| 414 | /* BB fix up inode etc. */ | ||
| 415 | } else if (rc) { | ||
| 416 | kfree(buf); | ||
| 417 | return rc; | ||
| 418 | } | 427 | } |
| 428 | goto cgii_exit; | ||
| 419 | } else { | 429 | } else { |
| 420 | struct cifsInodeInfo *cifsInfo; | 430 | struct cifsInodeInfo *cifsInfo; |
| 421 | __u32 attr = le32_to_cpu(pfindData->Attributes); | 431 | __u32 attr = le32_to_cpu(pfindData->Attributes); |
| @@ -424,8 +434,8 @@ int cifs_get_inode_info(struct inode **pinode, | |||
| 424 | if (*pinode == NULL) { | 434 | if (*pinode == NULL) { |
| 425 | *pinode = new_inode(sb); | 435 | *pinode = new_inode(sb); |
| 426 | if (*pinode == NULL) { | 436 | if (*pinode == NULL) { |
| 427 | kfree(buf); | 437 | rc = -ENOMEM; |
| 428 | return -ENOMEM; | 438 | goto cgii_exit; |
| 429 | } | 439 | } |
| 430 | /* Is an i_ino of zero legal? Can we use that to check | 440 | /* Is an i_ino of zero legal? Can we use that to check |
| 431 | if the server supports returning inode numbers? Are | 441 | if the server supports returning inode numbers? Are |
| @@ -573,8 +583,11 @@ int cifs_get_inode_info(struct inode **pinode, | |||
| 573 | atomic_set(&cifsInfo->inUse, 1); | 583 | atomic_set(&cifsInfo->inUse, 1); |
| 574 | } | 584 | } |
| 575 | 585 | ||
| 576 | cifs_set_ops(inode); | 586 | cifs_set_ops(inode, is_dfs_referral); |
| 577 | } | 587 | } |
| 588 | cgii_exit: | ||
| 589 | if (full_path != search_path) | ||
| 590 | kfree(full_path); | ||
| 578 | kfree(buf); | 591 | kfree(buf); |
| 579 | return rc; | 592 | return rc; |
| 580 | } | 593 | } |
| @@ -804,7 +817,7 @@ static void posix_fill_in_inode(struct inode *tmp_inode, | |||
| 804 | local_size = tmp_inode->i_size; | 817 | local_size = tmp_inode->i_size; |
| 805 | 818 | ||
| 806 | cifs_unix_info_to_inode(tmp_inode, pData, 1); | 819 | cifs_unix_info_to_inode(tmp_inode, pData, 1); |
| 807 | cifs_set_ops(tmp_inode); | 820 | cifs_set_ops(tmp_inode, false); |
| 808 | 821 | ||
| 809 | if (!S_ISREG(tmp_inode->i_mode)) | 822 | if (!S_ISREG(tmp_inode->i_mode)) |
| 810 | return; | 823 | return; |
| @@ -1407,11 +1420,10 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
| 1407 | } | 1420 | } |
| 1408 | cifsInode = CIFS_I(direntry->d_inode); | 1421 | cifsInode = CIFS_I(direntry->d_inode); |
| 1409 | 1422 | ||
| 1410 | /* BB check if we need to refresh inode from server now ? BB */ | 1423 | if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { |
| 1411 | |||
| 1412 | if (attrs->ia_valid & ATTR_SIZE) { | ||
| 1413 | /* | 1424 | /* |
| 1414 | Flush data before changing file size on server. If the | 1425 | Flush data before changing file size or changing the last |
| 1426 | write time of the file on the server. If the | ||
| 1415 | flush returns error, store it to report later and continue. | 1427 | flush returns error, store it to report later and continue. |
| 1416 | BB: This should be smarter. Why bother flushing pages that | 1428 | BB: This should be smarter. Why bother flushing pages that |
| 1417 | will be truncated anyway? Also, should we error out here if | 1429 | will be truncated anyway? Also, should we error out here if |
| @@ -1422,7 +1434,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
| 1422 | CIFS_I(direntry->d_inode)->write_behind_rc = rc; | 1434 | CIFS_I(direntry->d_inode)->write_behind_rc = rc; |
| 1423 | rc = 0; | 1435 | rc = 0; |
| 1424 | } | 1436 | } |
| 1437 | } | ||
| 1425 | 1438 | ||
| 1439 | if (attrs->ia_valid & ATTR_SIZE) { | ||
| 1426 | /* To avoid spurious oplock breaks from server, in the case of | 1440 | /* To avoid spurious oplock breaks from server, in the case of |
| 1427 | inodes that we already have open, avoid doing path based | 1441 | inodes that we already have open, avoid doing path based |
| 1428 | setting of file size if we can do it by handle. | 1442 | setting of file size if we can do it by handle. |
