diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 548 |
1 files changed, 236 insertions, 312 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index b1a4a65eaa08..bc673c8c1e6b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -29,6 +29,162 @@ | |||
29 | #include "cifs_debug.h" | 29 | #include "cifs_debug.h" |
30 | #include "cifs_fs_sb.h" | 30 | #include "cifs_fs_sb.h" |
31 | 31 | ||
32 | |||
33 | static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | ||
34 | { | ||
35 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
36 | |||
37 | switch (inode->i_mode & S_IFMT) { | ||
38 | case S_IFREG: | ||
39 | inode->i_op = &cifs_file_inode_ops; | ||
40 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { | ||
41 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
42 | inode->i_fop = &cifs_file_direct_nobrl_ops; | ||
43 | else | ||
44 | inode->i_fop = &cifs_file_direct_ops; | ||
45 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
46 | inode->i_fop = &cifs_file_nobrl_ops; | ||
47 | else { /* not direct, send byte range locks */ | ||
48 | inode->i_fop = &cifs_file_ops; | ||
49 | } | ||
50 | |||
51 | |||
52 | /* check if server can support readpages */ | ||
53 | if (cifs_sb->tcon->ses->server->maxBuf < | ||
54 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) | ||
55 | inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | ||
56 | else | ||
57 | inode->i_data.a_ops = &cifs_addr_ops; | ||
58 | break; | ||
59 | case S_IFDIR: | ||
60 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
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 | } | ||
70 | break; | ||
71 | case S_IFLNK: | ||
72 | inode->i_op = &cifs_symlink_inode_ops; | ||
73 | break; | ||
74 | default: | ||
75 | init_special_inode(inode, inode->i_mode, inode->i_rdev); | ||
76 | break; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | static void cifs_unix_info_to_inode(struct inode *inode, | ||
81 | FILE_UNIX_BASIC_INFO *info, int force_uid_gid) | ||
82 | { | ||
83 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
84 | struct cifsInodeInfo *cifsInfo = CIFS_I(inode); | ||
85 | __u64 num_of_bytes = le64_to_cpu(info->NumOfBytes); | ||
86 | __u64 end_of_file = le64_to_cpu(info->EndOfFile); | ||
87 | |||
88 | inode->i_atime = cifs_NTtimeToUnix(le64_to_cpu(info->LastAccessTime)); | ||
89 | inode->i_mtime = | ||
90 | cifs_NTtimeToUnix(le64_to_cpu(info->LastModificationTime)); | ||
91 | inode->i_ctime = cifs_NTtimeToUnix(le64_to_cpu(info->LastStatusChange)); | ||
92 | inode->i_mode = le64_to_cpu(info->Permissions); | ||
93 | |||
94 | /* | ||
95 | * Since we set the inode type below we need to mask off | ||
96 | * to avoid strange results if bits set above. | ||
97 | */ | ||
98 | inode->i_mode &= ~S_IFMT; | ||
99 | switch (le32_to_cpu(info->Type)) { | ||
100 | case UNIX_FILE: | ||
101 | inode->i_mode |= S_IFREG; | ||
102 | break; | ||
103 | case UNIX_SYMLINK: | ||
104 | inode->i_mode |= S_IFLNK; | ||
105 | break; | ||
106 | case UNIX_DIR: | ||
107 | inode->i_mode |= S_IFDIR; | ||
108 | break; | ||
109 | case UNIX_CHARDEV: | ||
110 | inode->i_mode |= S_IFCHR; | ||
111 | inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), | ||
112 | le64_to_cpu(info->DevMinor) & MINORMASK); | ||
113 | break; | ||
114 | case UNIX_BLOCKDEV: | ||
115 | inode->i_mode |= S_IFBLK; | ||
116 | inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), | ||
117 | le64_to_cpu(info->DevMinor) & MINORMASK); | ||
118 | break; | ||
119 | case UNIX_FIFO: | ||
120 | inode->i_mode |= S_IFIFO; | ||
121 | break; | ||
122 | case UNIX_SOCKET: | ||
123 | inode->i_mode |= S_IFSOCK; | ||
124 | break; | ||
125 | default: | ||
126 | /* safest to call it a file if we do not know */ | ||
127 | inode->i_mode |= S_IFREG; | ||
128 | cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); | ||
129 | break; | ||
130 | } | ||
131 | |||
132 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) && | ||
133 | !force_uid_gid) | ||
134 | inode->i_uid = cifs_sb->mnt_uid; | ||
135 | else | ||
136 | inode->i_uid = le64_to_cpu(info->Uid); | ||
137 | |||
138 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) && | ||
139 | !force_uid_gid) | ||
140 | inode->i_gid = cifs_sb->mnt_gid; | ||
141 | else | ||
142 | inode->i_gid = le64_to_cpu(info->Gid); | ||
143 | |||
144 | inode->i_nlink = le64_to_cpu(info->Nlinks); | ||
145 | |||
146 | spin_lock(&inode->i_lock); | ||
147 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | ||
148 | /* | ||
149 | * We can not safely change the file size here if the client | ||
150 | * is writing to it due to potential races. | ||
151 | */ | ||
152 | i_size_write(inode, end_of_file); | ||
153 | |||
154 | /* | ||
155 | * i_blocks is not related to (i_size / i_blksize), | ||
156 | * but instead 512 byte (2**9) size is required for | ||
157 | * calculating num blocks. | ||
158 | */ | ||
159 | inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
160 | } | ||
161 | spin_unlock(&inode->i_lock); | ||
162 | } | ||
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 | |||
32 | int cifs_get_inode_info_unix(struct inode **pinode, | 188 | int cifs_get_inode_info_unix(struct inode **pinode, |
33 | const unsigned char *search_path, struct super_block *sb, int xid) | 189 | const unsigned char *search_path, struct super_block *sb, int xid) |
34 | { | 190 | { |
@@ -37,52 +193,43 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
37 | struct cifsTconInfo *pTcon; | 193 | struct cifsTconInfo *pTcon; |
38 | struct inode *inode; | 194 | struct inode *inode; |
39 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 195 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
40 | char *tmp_path; | 196 | const unsigned char *full_path; |
197 | bool is_dfs_referral = false; | ||
41 | 198 | ||
42 | pTcon = cifs_sb->tcon; | 199 | pTcon = cifs_sb->tcon; |
43 | 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: | ||
44 | /* 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 */ |
45 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, | 206 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData, |
46 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 207 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
47 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 208 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
48 | /* dump_mem("\nUnixQPathInfo return data", &findData, | 209 | /* dump_mem("\nUnixQPathInfo return data", &findData, |
49 | sizeof(findData)); */ | 210 | sizeof(findData)); */ |
50 | if (rc) { | 211 | if (rc) { |
51 | if (rc == -EREMOTE) { | 212 | if (rc == -EREMOTE && !is_dfs_referral) { |
52 | tmp_path = | 213 | is_dfs_referral = true; |
53 | kmalloc(strnlen(pTcon->treeName, | 214 | if (full_path != search_path) { |
54 | MAX_TREE_SIZE + 1) + | 215 | kfree(full_path); |
55 | strnlen(search_path, MAX_PATHCONF) + 1, | 216 | full_path = search_path; |
56 | GFP_KERNEL); | 217 | } |
57 | if (tmp_path == NULL) | 218 | goto try_again_CIFSSMBUnixQPathInfo; |
58 | return -ENOMEM; | ||
59 | |||
60 | /* have to skip first of the double backslash of | ||
61 | UNC name */ | ||
62 | strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); | ||
63 | strncat(tmp_path, search_path, MAX_PATHCONF); | ||
64 | rc = connect_to_dfs_path(xid, pTcon->ses, | ||
65 | /* treename + */ tmp_path, | ||
66 | cifs_sb->local_nls, | ||
67 | cifs_sb->mnt_cifs_flags & | ||
68 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
69 | kfree(tmp_path); | ||
70 | |||
71 | /* BB fix up inode etc. */ | ||
72 | } else if (rc) { | ||
73 | return rc; | ||
74 | } | 219 | } |
220 | goto cgiiu_exit; | ||
75 | } else { | 221 | } else { |
76 | struct cifsInodeInfo *cifsInfo; | 222 | struct cifsInodeInfo *cifsInfo; |
77 | __u32 type = le32_to_cpu(findData.Type); | ||
78 | __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); | 223 | __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); |
79 | __u64 end_of_file = le64_to_cpu(findData.EndOfFile); | 224 | __u64 end_of_file = le64_to_cpu(findData.EndOfFile); |
80 | 225 | ||
81 | /* get new inode */ | 226 | /* get new inode */ |
82 | if (*pinode == NULL) { | 227 | if (*pinode == NULL) { |
83 | *pinode = new_inode(sb); | 228 | *pinode = new_inode(sb); |
84 | if (*pinode == NULL) | 229 | if (*pinode == NULL) { |
85 | return -ENOMEM; | 230 | rc = -ENOMEM; |
231 | goto cgiiu_exit; | ||
232 | } | ||
86 | /* Is an i_ino of zero legal? */ | 233 | /* Is an i_ino of zero legal? */ |
87 | /* Are there sanity checks we can use to ensure that | 234 | /* Are there sanity checks we can use to ensure that |
88 | the server is really filling in that field? */ | 235 | the server is really filling in that field? */ |
@@ -105,113 +252,20 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
105 | /* this is ok to set on every inode revalidate */ | 252 | /* this is ok to set on every inode revalidate */ |
106 | atomic_set(&cifsInfo->inUse, 1); | 253 | atomic_set(&cifsInfo->inUse, 1); |
107 | 254 | ||
108 | inode->i_atime = | 255 | cifs_unix_info_to_inode(inode, &findData, 0); |
109 | cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime)); | ||
110 | inode->i_mtime = | ||
111 | cifs_NTtimeToUnix(le64_to_cpu | ||
112 | (findData.LastModificationTime)); | ||
113 | inode->i_ctime = | ||
114 | cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange)); | ||
115 | inode->i_mode = le64_to_cpu(findData.Permissions); | ||
116 | /* since we set the inode type below we need to mask off | ||
117 | to avoid strange results if bits set above */ | ||
118 | inode->i_mode &= ~S_IFMT; | ||
119 | if (type == UNIX_FILE) { | ||
120 | inode->i_mode |= S_IFREG; | ||
121 | } else if (type == UNIX_SYMLINK) { | ||
122 | inode->i_mode |= S_IFLNK; | ||
123 | } else if (type == UNIX_DIR) { | ||
124 | inode->i_mode |= S_IFDIR; | ||
125 | } else if (type == UNIX_CHARDEV) { | ||
126 | inode->i_mode |= S_IFCHR; | ||
127 | inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor), | ||
128 | le64_to_cpu(findData.DevMinor) & MINORMASK); | ||
129 | } else if (type == UNIX_BLOCKDEV) { | ||
130 | inode->i_mode |= S_IFBLK; | ||
131 | inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor), | ||
132 | le64_to_cpu(findData.DevMinor) & MINORMASK); | ||
133 | } else if (type == UNIX_FIFO) { | ||
134 | inode->i_mode |= S_IFIFO; | ||
135 | } else if (type == UNIX_SOCKET) { | ||
136 | inode->i_mode |= S_IFSOCK; | ||
137 | } else { | ||
138 | /* safest to call it a file if we do not know */ | ||
139 | inode->i_mode |= S_IFREG; | ||
140 | cFYI(1, ("unknown type %d", type)); | ||
141 | } | ||
142 | |||
143 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) | ||
144 | inode->i_uid = cifs_sb->mnt_uid; | ||
145 | else | ||
146 | inode->i_uid = le64_to_cpu(findData.Uid); | ||
147 | |||
148 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) | ||
149 | inode->i_gid = cifs_sb->mnt_gid; | ||
150 | else | ||
151 | inode->i_gid = le64_to_cpu(findData.Gid); | ||
152 | |||
153 | inode->i_nlink = le64_to_cpu(findData.Nlinks); | ||
154 | 256 | ||
155 | spin_lock(&inode->i_lock); | ||
156 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | ||
157 | /* can not safely change the file size here if the | ||
158 | client is writing to it due to potential races */ | ||
159 | i_size_write(inode, end_of_file); | ||
160 | |||
161 | /* blksize needs to be multiple of two. So safer to default to | ||
162 | blksize and blkbits set in superblock so 2**blkbits and blksize | ||
163 | will match rather than setting to: | ||
164 | (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ | ||
165 | |||
166 | /* This seems incredibly stupid but it turns out that i_blocks | ||
167 | is not related to (i_size / i_blksize), instead 512 byte size | ||
168 | is required for calculating num blocks */ | ||
169 | |||
170 | /* 512 bytes (2**9) is the fake blocksize that must be used */ | ||
171 | /* for this calculation */ | ||
172 | inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
173 | } | ||
174 | spin_unlock(&inode->i_lock); | ||
175 | 257 | ||
176 | if (num_of_bytes < end_of_file) | 258 | if (num_of_bytes < end_of_file) |
177 | cFYI(1, ("allocation size less than end of file")); | 259 | cFYI(1, ("allocation size less than end of file")); |
178 | cFYI(1, ("Size %ld and blocks %llu", | 260 | cFYI(1, ("Size %ld and blocks %llu", |
179 | (unsigned long) inode->i_size, | 261 | (unsigned long) inode->i_size, |
180 | (unsigned long long)inode->i_blocks)); | 262 | (unsigned long long)inode->i_blocks)); |
181 | if (S_ISREG(inode->i_mode)) { | 263 | |
182 | cFYI(1, ("File inode")); | 264 | cifs_set_ops(inode, is_dfs_referral); |
183 | inode->i_op = &cifs_file_inode_ops; | ||
184 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { | ||
185 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
186 | inode->i_fop = | ||
187 | &cifs_file_direct_nobrl_ops; | ||
188 | else | ||
189 | inode->i_fop = &cifs_file_direct_ops; | ||
190 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
191 | inode->i_fop = &cifs_file_nobrl_ops; | ||
192 | else /* not direct, send byte range locks */ | ||
193 | inode->i_fop = &cifs_file_ops; | ||
194 | |||
195 | /* check if server can support readpages */ | ||
196 | if (pTcon->ses->server->maxBuf < | ||
197 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) | ||
198 | inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | ||
199 | else | ||
200 | inode->i_data.a_ops = &cifs_addr_ops; | ||
201 | } else if (S_ISDIR(inode->i_mode)) { | ||
202 | cFYI(1, ("Directory inode")); | ||
203 | inode->i_op = &cifs_dir_inode_ops; | ||
204 | inode->i_fop = &cifs_dir_ops; | ||
205 | } else if (S_ISLNK(inode->i_mode)) { | ||
206 | cFYI(1, ("Symbolic Link inode")); | ||
207 | inode->i_op = &cifs_symlink_inode_ops; | ||
208 | /* tmp_inode->i_fop = */ /* do not need to set to anything */ | ||
209 | } else { | ||
210 | cFYI(1, ("Init special inode")); | ||
211 | init_special_inode(inode, inode->i_mode, | ||
212 | inode->i_rdev); | ||
213 | } | ||
214 | } | 265 | } |
266 | cgiiu_exit: | ||
267 | if (full_path != search_path) | ||
268 | kfree(full_path); | ||
215 | return rc; | 269 | return rc; |
216 | } | 270 | } |
217 | 271 | ||
@@ -320,15 +374,16 @@ static int get_sfu_mode(struct inode *inode, | |||
320 | 374 | ||
321 | int cifs_get_inode_info(struct inode **pinode, | 375 | int cifs_get_inode_info(struct inode **pinode, |
322 | const unsigned char *search_path, FILE_ALL_INFO *pfindData, | 376 | const unsigned char *search_path, FILE_ALL_INFO *pfindData, |
323 | struct super_block *sb, int xid) | 377 | struct super_block *sb, int xid, const __u16 *pfid) |
324 | { | 378 | { |
325 | int rc = 0; | 379 | int rc = 0; |
326 | struct cifsTconInfo *pTcon; | 380 | struct cifsTconInfo *pTcon; |
327 | struct inode *inode; | 381 | struct inode *inode; |
328 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 382 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
329 | char *tmp_path; | 383 | const unsigned char *full_path = NULL; |
330 | char *buf = NULL; | 384 | char *buf = NULL; |
331 | int adjustTZ = FALSE; | 385 | int adjustTZ = FALSE; |
386 | bool is_dfs_referral = false; | ||
332 | 387 | ||
333 | pTcon = cifs_sb->tcon; | 388 | pTcon = cifs_sb->tcon; |
334 | cFYI(1, ("Getting info on %s", search_path)); | 389 | cFYI(1, ("Getting info on %s", search_path)); |
@@ -346,8 +401,12 @@ int cifs_get_inode_info(struct inode **pinode, | |||
346 | if (buf == NULL) | 401 | if (buf == NULL) |
347 | return -ENOMEM; | 402 | return -ENOMEM; |
348 | pfindData = (FILE_ALL_INFO *)buf; | 403 | pfindData = (FILE_ALL_INFO *)buf; |
404 | |||
405 | full_path = cifs_get_search_path(pTcon, search_path); | ||
406 | |||
407 | try_again_CIFSSMBQPathInfo: | ||
349 | /* could do find first instead but this returns more info */ | 408 | /* could do find first instead but this returns more info */ |
350 | rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, | 409 | rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, |
351 | 0 /* not legacy */, | 410 | 0 /* not legacy */, |
352 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 411 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
353 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 412 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
@@ -355,7 +414,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
355 | when server claims no NT SMB support and the above call | 414 | when server claims no NT SMB support and the above call |
356 | failed at least once - set flag in tcon or mount */ | 415 | failed at least once - set flag in tcon or mount */ |
357 | if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { | 416 | if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { |
358 | rc = SMBQueryInformation(xid, pTcon, search_path, | 417 | rc = SMBQueryInformation(xid, pTcon, full_path, |
359 | pfindData, cifs_sb->local_nls, | 418 | pfindData, cifs_sb->local_nls, |
360 | cifs_sb->mnt_cifs_flags & | 419 | cifs_sb->mnt_cifs_flags & |
361 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 420 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
@@ -364,31 +423,15 @@ int cifs_get_inode_info(struct inode **pinode, | |||
364 | } | 423 | } |
365 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ | 424 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ |
366 | if (rc) { | 425 | if (rc) { |
367 | if (rc == -EREMOTE) { | 426 | if (rc == -EREMOTE && !is_dfs_referral) { |
368 | tmp_path = | 427 | is_dfs_referral = true; |
369 | kmalloc(strnlen | 428 | if (full_path != search_path) { |
370 | (pTcon->treeName, | 429 | kfree(full_path); |
371 | MAX_TREE_SIZE + 1) + | 430 | full_path = search_path; |
372 | strnlen(search_path, MAX_PATHCONF) + 1, | ||
373 | GFP_KERNEL); | ||
374 | if (tmp_path == NULL) { | ||
375 | kfree(buf); | ||
376 | return -ENOMEM; | ||
377 | } | 431 | } |
378 | 432 | goto try_again_CIFSSMBQPathInfo; | |
379 | strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); | ||
380 | strncat(tmp_path, search_path, MAX_PATHCONF); | ||
381 | rc = connect_to_dfs_path(xid, pTcon->ses, | ||
382 | /* treename + */ tmp_path, | ||
383 | cifs_sb->local_nls, | ||
384 | cifs_sb->mnt_cifs_flags & | ||
385 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
386 | kfree(tmp_path); | ||
387 | /* BB fix up inode etc. */ | ||
388 | } else if (rc) { | ||
389 | kfree(buf); | ||
390 | return rc; | ||
391 | } | 433 | } |
434 | goto cgii_exit; | ||
392 | } else { | 435 | } else { |
393 | struct cifsInodeInfo *cifsInfo; | 436 | struct cifsInodeInfo *cifsInfo; |
394 | __u32 attr = le32_to_cpu(pfindData->Attributes); | 437 | __u32 attr = le32_to_cpu(pfindData->Attributes); |
@@ -397,8 +440,8 @@ int cifs_get_inode_info(struct inode **pinode, | |||
397 | if (*pinode == NULL) { | 440 | if (*pinode == NULL) { |
398 | *pinode = new_inode(sb); | 441 | *pinode = new_inode(sb); |
399 | if (*pinode == NULL) { | 442 | if (*pinode == NULL) { |
400 | kfree(buf); | 443 | rc = -ENOMEM; |
401 | return -ENOMEM; | 444 | goto cgii_exit; |
402 | } | 445 | } |
403 | /* Is an i_ino of zero legal? Can we use that to check | 446 | /* Is an i_ino of zero legal? Can we use that to check |
404 | if the server supports returning inode numbers? Are | 447 | if the server supports returning inode numbers? Are |
@@ -490,9 +533,9 @@ int cifs_get_inode_info(struct inode **pinode, | |||
490 | if (decode_sfu_inode(inode, | 533 | if (decode_sfu_inode(inode, |
491 | le64_to_cpu(pfindData->EndOfFile), | 534 | le64_to_cpu(pfindData->EndOfFile), |
492 | search_path, | 535 | search_path, |
493 | cifs_sb, xid)) { | 536 | cifs_sb, xid)) |
494 | cFYI(1, ("Unrecognized sfu inode type")); | 537 | cFYI(1, ("Unrecognized sfu inode type")); |
495 | } | 538 | |
496 | cFYI(1, ("sfu mode 0%o", inode->i_mode)); | 539 | cFYI(1, ("sfu mode 0%o", inode->i_mode)); |
497 | } else { | 540 | } else { |
498 | inode->i_mode |= S_IFREG; | 541 | inode->i_mode |= S_IFREG; |
@@ -532,7 +575,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
532 | /* fill in 0777 bits from ACL */ | 575 | /* fill in 0777 bits from ACL */ |
533 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 576 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
534 | cFYI(1, ("Getting mode bits from ACL")); | 577 | cFYI(1, ("Getting mode bits from ACL")); |
535 | acl_to_uid_mode(inode, search_path); | 578 | acl_to_uid_mode(inode, search_path, pfid); |
536 | } | 579 | } |
537 | #endif | 580 | #endif |
538 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | 581 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
@@ -546,37 +589,11 @@ int cifs_get_inode_info(struct inode **pinode, | |||
546 | atomic_set(&cifsInfo->inUse, 1); | 589 | atomic_set(&cifsInfo->inUse, 1); |
547 | } | 590 | } |
548 | 591 | ||
549 | if (S_ISREG(inode->i_mode)) { | 592 | cifs_set_ops(inode, is_dfs_referral); |
550 | cFYI(1, ("File inode")); | ||
551 | inode->i_op = &cifs_file_inode_ops; | ||
552 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { | ||
553 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
554 | inode->i_fop = | ||
555 | &cifs_file_direct_nobrl_ops; | ||
556 | else | ||
557 | inode->i_fop = &cifs_file_direct_ops; | ||
558 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
559 | inode->i_fop = &cifs_file_nobrl_ops; | ||
560 | else /* not direct, send byte range locks */ | ||
561 | inode->i_fop = &cifs_file_ops; | ||
562 | |||
563 | if (pTcon->ses->server->maxBuf < | ||
564 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) | ||
565 | inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | ||
566 | else | ||
567 | inode->i_data.a_ops = &cifs_addr_ops; | ||
568 | } else if (S_ISDIR(inode->i_mode)) { | ||
569 | cFYI(1, ("Directory inode")); | ||
570 | inode->i_op = &cifs_dir_inode_ops; | ||
571 | inode->i_fop = &cifs_dir_ops; | ||
572 | } else if (S_ISLNK(inode->i_mode)) { | ||
573 | cFYI(1, ("Symbolic Link inode")); | ||
574 | inode->i_op = &cifs_symlink_inode_ops; | ||
575 | } else { | ||
576 | init_special_inode(inode, inode->i_mode, | ||
577 | inode->i_rdev); | ||
578 | } | ||
579 | } | 593 | } |
594 | cgii_exit: | ||
595 | if (full_path != search_path) | ||
596 | kfree(full_path); | ||
580 | kfree(buf); | 597 | kfree(buf); |
581 | return rc; | 598 | return rc; |
582 | } | 599 | } |
@@ -605,7 +622,8 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino) | |||
605 | if (cifs_sb->tcon->unix_ext) | 622 | if (cifs_sb->tcon->unix_ext) |
606 | rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid); | 623 | rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid); |
607 | else | 624 | else |
608 | rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid); | 625 | rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid, |
626 | NULL); | ||
609 | if (rc && cifs_sb->tcon->ipc) { | 627 | if (rc && cifs_sb->tcon->ipc) { |
610 | cFYI(1, ("ipc connection - fake read inode")); | 628 | cFYI(1, ("ipc connection - fake read inode")); |
611 | inode->i_mode |= S_IFDIR; | 629 | inode->i_mode |= S_IFDIR; |
@@ -792,17 +810,12 @@ psx_del_no_retry: | |||
792 | } | 810 | } |
793 | 811 | ||
794 | static void posix_fill_in_inode(struct inode *tmp_inode, | 812 | static void posix_fill_in_inode(struct inode *tmp_inode, |
795 | FILE_UNIX_BASIC_INFO *pData, int *pobject_type, int isNewInode) | 813 | FILE_UNIX_BASIC_INFO *pData, int isNewInode) |
796 | { | 814 | { |
815 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
797 | loff_t local_size; | 816 | loff_t local_size; |
798 | struct timespec local_mtime; | 817 | struct timespec local_mtime; |
799 | 818 | ||
800 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
801 | struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); | ||
802 | |||
803 | __u32 type = le32_to_cpu(pData->Type); | ||
804 | __u64 num_of_bytes = le64_to_cpu(pData->NumOfBytes); | ||
805 | __u64 end_of_file = le64_to_cpu(pData->EndOfFile); | ||
806 | cifsInfo->time = jiffies; | 819 | cifsInfo->time = jiffies; |
807 | atomic_inc(&cifsInfo->inUse); | 820 | atomic_inc(&cifsInfo->inUse); |
808 | 821 | ||
@@ -810,115 +823,27 @@ static void posix_fill_in_inode(struct inode *tmp_inode, | |||
810 | local_mtime = tmp_inode->i_mtime; | 823 | local_mtime = tmp_inode->i_mtime; |
811 | local_size = tmp_inode->i_size; | 824 | local_size = tmp_inode->i_size; |
812 | 825 | ||
813 | tmp_inode->i_atime = | 826 | cifs_unix_info_to_inode(tmp_inode, pData, 1); |
814 | cifs_NTtimeToUnix(le64_to_cpu(pData->LastAccessTime)); | 827 | cifs_set_ops(tmp_inode, false); |
815 | tmp_inode->i_mtime = | ||
816 | cifs_NTtimeToUnix(le64_to_cpu(pData->LastModificationTime)); | ||
817 | tmp_inode->i_ctime = | ||
818 | cifs_NTtimeToUnix(le64_to_cpu(pData->LastStatusChange)); | ||
819 | |||
820 | tmp_inode->i_mode = le64_to_cpu(pData->Permissions); | ||
821 | /* since we set the inode type below we need to mask off type | ||
822 | to avoid strange results if bits above were corrupt */ | ||
823 | tmp_inode->i_mode &= ~S_IFMT; | ||
824 | if (type == UNIX_FILE) { | ||
825 | *pobject_type = DT_REG; | ||
826 | tmp_inode->i_mode |= S_IFREG; | ||
827 | } else if (type == UNIX_SYMLINK) { | ||
828 | *pobject_type = DT_LNK; | ||
829 | tmp_inode->i_mode |= S_IFLNK; | ||
830 | } else if (type == UNIX_DIR) { | ||
831 | *pobject_type = DT_DIR; | ||
832 | tmp_inode->i_mode |= S_IFDIR; | ||
833 | } else if (type == UNIX_CHARDEV) { | ||
834 | *pobject_type = DT_CHR; | ||
835 | tmp_inode->i_mode |= S_IFCHR; | ||
836 | tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor), | ||
837 | le64_to_cpu(pData->DevMinor) & MINORMASK); | ||
838 | } else if (type == UNIX_BLOCKDEV) { | ||
839 | *pobject_type = DT_BLK; | ||
840 | tmp_inode->i_mode |= S_IFBLK; | ||
841 | tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor), | ||
842 | le64_to_cpu(pData->DevMinor) & MINORMASK); | ||
843 | } else if (type == UNIX_FIFO) { | ||
844 | *pobject_type = DT_FIFO; | ||
845 | tmp_inode->i_mode |= S_IFIFO; | ||
846 | } else if (type == UNIX_SOCKET) { | ||
847 | *pobject_type = DT_SOCK; | ||
848 | tmp_inode->i_mode |= S_IFSOCK; | ||
849 | } else { | ||
850 | /* safest to just call it a file */ | ||
851 | *pobject_type = DT_REG; | ||
852 | tmp_inode->i_mode |= S_IFREG; | ||
853 | cFYI(1, ("unknown inode type %d", type)); | ||
854 | } | ||
855 | |||
856 | #ifdef CONFIG_CIFS_DEBUG2 | ||
857 | cFYI(1, ("object type: %d", type)); | ||
858 | #endif | ||
859 | tmp_inode->i_uid = le64_to_cpu(pData->Uid); | ||
860 | tmp_inode->i_gid = le64_to_cpu(pData->Gid); | ||
861 | tmp_inode->i_nlink = le64_to_cpu(pData->Nlinks); | ||
862 | |||
863 | spin_lock(&tmp_inode->i_lock); | ||
864 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | ||
865 | /* can not safely change the file size here if the | ||
866 | client is writing to it due to potential races */ | ||
867 | i_size_write(tmp_inode, end_of_file); | ||
868 | |||
869 | /* 512 bytes (2**9) is the fake blocksize that must be used */ | ||
870 | /* for this calculation, not the real blocksize */ | ||
871 | tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
872 | } | ||
873 | spin_unlock(&tmp_inode->i_lock); | ||
874 | |||
875 | if (S_ISREG(tmp_inode->i_mode)) { | ||
876 | cFYI(1, ("File inode")); | ||
877 | tmp_inode->i_op = &cifs_file_inode_ops; | ||
878 | |||
879 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { | ||
880 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
881 | tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; | ||
882 | else | ||
883 | tmp_inode->i_fop = &cifs_file_direct_ops; | ||
884 | 828 | ||
885 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | 829 | if (!S_ISREG(tmp_inode->i_mode)) |
886 | tmp_inode->i_fop = &cifs_file_nobrl_ops; | 830 | return; |
887 | else | ||
888 | tmp_inode->i_fop = &cifs_file_ops; | ||
889 | 831 | ||
890 | if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && | 832 | /* |
891 | (cifs_sb->tcon->ses->server->maxBuf < | 833 | * No sense invalidating pages for new inode |
892 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) | 834 | * since we we have not started caching |
893 | tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | 835 | * readahead file data yet. |
894 | else | 836 | */ |
895 | tmp_inode->i_data.a_ops = &cifs_addr_ops; | 837 | if (isNewInode) |
896 | 838 | return; | |
897 | if (isNewInode) | ||
898 | return; /* No sense invalidating pages for new inode | ||
899 | since we we have not started caching | ||
900 | readahead file data yet */ | ||
901 | 839 | ||
902 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | 840 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && |
903 | (local_size == tmp_inode->i_size)) { | 841 | (local_size == tmp_inode->i_size)) { |
904 | cFYI(1, ("inode exists but unchanged")); | 842 | cFYI(1, ("inode exists but unchanged")); |
905 | } else { | ||
906 | /* file may have changed on server */ | ||
907 | cFYI(1, ("invalidate inode, readdir detected change")); | ||
908 | invalidate_remote_inode(tmp_inode); | ||
909 | } | ||
910 | } else if (S_ISDIR(tmp_inode->i_mode)) { | ||
911 | cFYI(1, ("Directory inode")); | ||
912 | tmp_inode->i_op = &cifs_dir_inode_ops; | ||
913 | tmp_inode->i_fop = &cifs_dir_ops; | ||
914 | } else if (S_ISLNK(tmp_inode->i_mode)) { | ||
915 | cFYI(1, ("Symbolic Link inode")); | ||
916 | tmp_inode->i_op = &cifs_symlink_inode_ops; | ||
917 | /* tmp_inode->i_fop = *//* do not need to set to anything */ | ||
918 | } else { | 843 | } else { |
919 | cFYI(1, ("Special inode")); | 844 | /* file may have changed on server */ |
920 | init_special_inode(tmp_inode, tmp_inode->i_mode, | 845 | cFYI(1, ("invalidate inode, readdir detected change")); |
921 | tmp_inode->i_rdev); | 846 | invalidate_remote_inode(tmp_inode); |
922 | } | 847 | } |
923 | } | 848 | } |
924 | 849 | ||
@@ -968,7 +893,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
968 | cFYI(1, ("posix mkdir returned 0x%x", rc)); | 893 | cFYI(1, ("posix mkdir returned 0x%x", rc)); |
969 | d_drop(direntry); | 894 | d_drop(direntry); |
970 | } else { | 895 | } else { |
971 | int obj_type; | ||
972 | if (pInfo->Type == cpu_to_le32(-1)) { | 896 | if (pInfo->Type == cpu_to_le32(-1)) { |
973 | /* no return info, go query for it */ | 897 | /* no return info, go query for it */ |
974 | kfree(pInfo); | 898 | kfree(pInfo); |
@@ -1004,7 +928,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1004 | /* we already checked in POSIXCreate whether | 928 | /* we already checked in POSIXCreate whether |
1005 | frame was long enough */ | 929 | frame was long enough */ |
1006 | posix_fill_in_inode(direntry->d_inode, | 930 | posix_fill_in_inode(direntry->d_inode, |
1007 | pInfo, &obj_type, 1 /* NewInode */); | 931 | pInfo, 1 /* NewInode */); |
1008 | #ifdef CONFIG_CIFS_DEBUG2 | 932 | #ifdef CONFIG_CIFS_DEBUG2 |
1009 | cFYI(1, ("instantiated dentry %p %s to inode %p", | 933 | cFYI(1, ("instantiated dentry %p %s to inode %p", |
1010 | direntry, direntry->d_name.name, newinode)); | 934 | direntry, direntry->d_name.name, newinode)); |
@@ -1032,7 +956,7 @@ mkdir_get_info: | |||
1032 | inode->i_sb, xid); | 956 | inode->i_sb, xid); |
1033 | else | 957 | else |
1034 | rc = cifs_get_inode_info(&newinode, full_path, NULL, | 958 | rc = cifs_get_inode_info(&newinode, full_path, NULL, |
1035 | inode->i_sb, xid); | 959 | inode->i_sb, xid, NULL); |
1036 | 960 | ||
1037 | if (pTcon->nocase) | 961 | if (pTcon->nocase) |
1038 | direntry->d_op = &cifs_ci_dentry_ops; | 962 | direntry->d_op = &cifs_ci_dentry_ops; |
@@ -1214,9 +1138,8 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry, | |||
1214 | } /* if we can not get memory just leave rc as EEXIST */ | 1138 | } /* if we can not get memory just leave rc as EEXIST */ |
1215 | } | 1139 | } |
1216 | 1140 | ||
1217 | if (rc) { | 1141 | if (rc) |
1218 | cFYI(1, ("rename rc %d", rc)); | 1142 | cFYI(1, ("rename rc %d", rc)); |
1219 | } | ||
1220 | 1143 | ||
1221 | if ((rc == -EIO) || (rc == -EEXIST)) { | 1144 | if ((rc == -EIO) || (rc == -EEXIST)) { |
1222 | int oplock = FALSE; | 1145 | int oplock = FALSE; |
@@ -1315,7 +1238,7 @@ int cifs_revalidate(struct dentry *direntry) | |||
1315 | } | 1238 | } |
1316 | } else { | 1239 | } else { |
1317 | rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL, | 1240 | rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL, |
1318 | direntry->d_sb, xid); | 1241 | direntry->d_sb, xid, NULL); |
1319 | if (rc) { | 1242 | if (rc) { |
1320 | cFYI(1, ("error on getting revalidate info %d", rc)); | 1243 | cFYI(1, ("error on getting revalidate info %d", rc)); |
1321 | /* if (rc != -ENOENT) | 1244 | /* if (rc != -ENOENT) |
@@ -1504,11 +1427,10 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1504 | } | 1427 | } |
1505 | cifsInode = CIFS_I(direntry->d_inode); | 1428 | cifsInode = CIFS_I(direntry->d_inode); |
1506 | 1429 | ||
1507 | /* BB check if we need to refresh inode from server now ? BB */ | 1430 | if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { |
1508 | |||
1509 | if (attrs->ia_valid & ATTR_SIZE) { | ||
1510 | /* | 1431 | /* |
1511 | Flush data before changing file size on server. If the | 1432 | Flush data before changing file size or changing the last |
1433 | write time of the file on the server. If the | ||
1512 | flush returns error, store it to report later and continue. | 1434 | flush returns error, store it to report later and continue. |
1513 | BB: This should be smarter. Why bother flushing pages that | 1435 | BB: This should be smarter. Why bother flushing pages that |
1514 | will be truncated anyway? Also, should we error out here if | 1436 | will be truncated anyway? Also, should we error out here if |
@@ -1519,7 +1441,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1519 | CIFS_I(direntry->d_inode)->write_behind_rc = rc; | 1441 | CIFS_I(direntry->d_inode)->write_behind_rc = rc; |
1520 | rc = 0; | 1442 | rc = 0; |
1521 | } | 1443 | } |
1444 | } | ||
1522 | 1445 | ||
1446 | if (attrs->ia_valid & ATTR_SIZE) { | ||
1523 | /* To avoid spurious oplock breaks from server, in the case of | 1447 | /* To avoid spurious oplock breaks from server, in the case of |
1524 | inodes that we already have open, avoid doing path based | 1448 | inodes that we already have open, avoid doing path based |
1525 | setting of file size if we can do it by handle. | 1449 | setting of file size if we can do it by handle. |