diff options
author | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-01-24 15:34:47 -0500 |
---|---|---|
committer | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-01-24 15:34:47 -0500 |
commit | 0a0fc0ddbe732779366ab6b1b879f62195e65967 (patch) | |
tree | 7b42490a676cf39ae0691b6859ecf7fd410f229b /fs/cifs/inode.c | |
parent | 4d5dbd0945d9e0833dd7964a3d6ee33157f7cc7a (diff) | |
parent | 3ee68c4af3fd7228c1be63254b9f884614f9ebb2 (diff) |
Merge with /home/shaggy/git/linus-clean/
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 268 |
1 files changed, 216 insertions, 52 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 923d071163b2..59359911f481 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -41,7 +41,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
41 | char *tmp_path; | 41 | char *tmp_path; |
42 | 42 | ||
43 | pTcon = cifs_sb->tcon; | 43 | pTcon = cifs_sb->tcon; |
44 | cFYI(1, (" Getting info on %s ", search_path)); | 44 | cFYI(1, ("Getting info on %s ", search_path)); |
45 | /* could have done a find first instead but this returns more info */ | 45 | /* could have done a find first instead but this returns more info */ |
46 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, | 46 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, |
47 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 47 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
@@ -97,9 +97,9 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
97 | inode = *pinode; | 97 | inode = *pinode; |
98 | cifsInfo = CIFS_I(inode); | 98 | cifsInfo = CIFS_I(inode); |
99 | 99 | ||
100 | cFYI(1, (" Old time %ld ", cifsInfo->time)); | 100 | cFYI(1, ("Old time %ld ", cifsInfo->time)); |
101 | cifsInfo->time = jiffies; | 101 | cifsInfo->time = jiffies; |
102 | cFYI(1, (" New time %ld ", cifsInfo->time)); | 102 | cFYI(1, ("New time %ld ", cifsInfo->time)); |
103 | /* this is ok to set on every inode revalidate */ | 103 | /* this is ok to set on every inode revalidate */ |
104 | atomic_set(&cifsInfo->inUse,1); | 104 | atomic_set(&cifsInfo->inUse,1); |
105 | 105 | ||
@@ -111,6 +111,9 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
111 | inode->i_ctime = | 111 | inode->i_ctime = |
112 | cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange)); | 112 | cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange)); |
113 | inode->i_mode = le64_to_cpu(findData.Permissions); | 113 | inode->i_mode = le64_to_cpu(findData.Permissions); |
114 | /* since we set the inode type below we need to mask off | ||
115 | to avoid strange results if bits set above */ | ||
116 | inode->i_mode &= ~S_IFMT; | ||
114 | if (type == UNIX_FILE) { | 117 | if (type == UNIX_FILE) { |
115 | inode->i_mode |= S_IFREG; | 118 | inode->i_mode |= S_IFREG; |
116 | } else if (type == UNIX_SYMLINK) { | 119 | } else if (type == UNIX_SYMLINK) { |
@@ -129,6 +132,10 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
129 | inode->i_mode |= S_IFIFO; | 132 | inode->i_mode |= S_IFIFO; |
130 | } else if (type == UNIX_SOCKET) { | 133 | } else if (type == UNIX_SOCKET) { |
131 | inode->i_mode |= S_IFSOCK; | 134 | inode->i_mode |= S_IFSOCK; |
135 | } else { | ||
136 | /* safest to call it a file if we do not know */ | ||
137 | inode->i_mode |= S_IFREG; | ||
138 | cFYI(1,("unknown type %d",type)); | ||
132 | } | 139 | } |
133 | inode->i_uid = le64_to_cpu(findData.Uid); | 140 | inode->i_uid = le64_to_cpu(findData.Uid); |
134 | inode->i_gid = le64_to_cpu(findData.Gid); | 141 | inode->i_gid = le64_to_cpu(findData.Gid); |
@@ -155,34 +162,39 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
155 | } | 162 | } |
156 | 163 | ||
157 | if (num_of_bytes < end_of_file) | 164 | if (num_of_bytes < end_of_file) |
158 | cFYI(1, ("allocation size less than end of file ")); | 165 | cFYI(1, ("allocation size less than end of file")); |
159 | cFYI(1, | 166 | cFYI(1, |
160 | ("Size %ld and blocks %ld", | 167 | ("Size %ld and blocks %ld", |
161 | (unsigned long) inode->i_size, inode->i_blocks)); | 168 | (unsigned long) inode->i_size, inode->i_blocks)); |
162 | if (S_ISREG(inode->i_mode)) { | 169 | if (S_ISREG(inode->i_mode)) { |
163 | cFYI(1, (" File inode ")); | 170 | cFYI(1, ("File inode")); |
164 | inode->i_op = &cifs_file_inode_ops; | 171 | inode->i_op = &cifs_file_inode_ops; |
165 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) | 172 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { |
166 | inode->i_fop = &cifs_file_direct_ops; | 173 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) |
167 | else | 174 | inode->i_fop = |
175 | &cifs_file_direct_nobrl_ops; | ||
176 | else | ||
177 | inode->i_fop = &cifs_file_direct_ops; | ||
178 | } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
179 | inode->i_fop = &cifs_file_nobrl_ops; | ||
180 | else /* not direct, send byte range locks */ | ||
168 | inode->i_fop = &cifs_file_ops; | 181 | inode->i_fop = &cifs_file_ops; |
169 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | 182 | |
170 | inode->i_fop->lock = NULL; | ||
171 | inode->i_data.a_ops = &cifs_addr_ops; | 183 | inode->i_data.a_ops = &cifs_addr_ops; |
172 | /* check if server can support readpages */ | 184 | /* check if server can support readpages */ |
173 | if(pTcon->ses->server->maxBuf < | 185 | if(pTcon->ses->server->maxBuf < |
174 | 4096 + MAX_CIFS_HDR_SIZE) | 186 | 4096 + MAX_CIFS_HDR_SIZE) |
175 | inode->i_data.a_ops->readpages = NULL; | 187 | inode->i_data.a_ops->readpages = NULL; |
176 | } else if (S_ISDIR(inode->i_mode)) { | 188 | } else if (S_ISDIR(inode->i_mode)) { |
177 | cFYI(1, (" Directory inode")); | 189 | cFYI(1, ("Directory inode")); |
178 | inode->i_op = &cifs_dir_inode_ops; | 190 | inode->i_op = &cifs_dir_inode_ops; |
179 | inode->i_fop = &cifs_dir_ops; | 191 | inode->i_fop = &cifs_dir_ops; |
180 | } else if (S_ISLNK(inode->i_mode)) { | 192 | } else if (S_ISLNK(inode->i_mode)) { |
181 | cFYI(1, (" Symbolic Link inode ")); | 193 | cFYI(1, ("Symbolic Link inode")); |
182 | inode->i_op = &cifs_symlink_inode_ops; | 194 | inode->i_op = &cifs_symlink_inode_ops; |
183 | /* tmp_inode->i_fop = */ /* do not need to set to anything */ | 195 | /* tmp_inode->i_fop = */ /* do not need to set to anything */ |
184 | } else { | 196 | } else { |
185 | cFYI(1, (" Init special inode ")); | 197 | cFYI(1, ("Init special inode")); |
186 | init_special_inode(inode, inode->i_mode, | 198 | init_special_inode(inode, inode->i_mode, |
187 | inode->i_rdev); | 199 | inode->i_rdev); |
188 | } | 200 | } |
@@ -190,6 +202,112 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
190 | return rc; | 202 | return rc; |
191 | } | 203 | } |
192 | 204 | ||
205 | static int decode_sfu_inode(struct inode * inode, __u64 size, | ||
206 | const unsigned char *path, | ||
207 | struct cifs_sb_info *cifs_sb, int xid) | ||
208 | { | ||
209 | int rc; | ||
210 | int oplock = FALSE; | ||
211 | __u16 netfid; | ||
212 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | ||
213 | char buf[24]; | ||
214 | unsigned int bytes_read; | ||
215 | char * pbuf; | ||
216 | |||
217 | pbuf = buf; | ||
218 | |||
219 | if(size == 0) { | ||
220 | inode->i_mode |= S_IFIFO; | ||
221 | return 0; | ||
222 | } else if (size < 8) { | ||
223 | return -EINVAL; /* EOPNOTSUPP? */ | ||
224 | } | ||
225 | |||
226 | rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ, | ||
227 | CREATE_NOT_DIR, &netfid, &oplock, NULL, | ||
228 | cifs_sb->local_nls, | ||
229 | cifs_sb->mnt_cifs_flags & | ||
230 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
231 | if (rc==0) { | ||
232 | int buf_type = CIFS_NO_BUFFER; | ||
233 | /* Read header */ | ||
234 | rc = CIFSSMBRead(xid, pTcon, | ||
235 | netfid, | ||
236 | 24 /* length */, 0 /* offset */, | ||
237 | &bytes_read, &pbuf, &buf_type); | ||
238 | if((rc == 0) && (bytes_read >= 8)) { | ||
239 | if(memcmp("IntxBLK", pbuf, 8) == 0) { | ||
240 | cFYI(1,("Block device")); | ||
241 | inode->i_mode |= S_IFBLK; | ||
242 | if(bytes_read == 24) { | ||
243 | /* we have enough to decode dev num */ | ||
244 | __u64 mjr; /* major */ | ||
245 | __u64 mnr; /* minor */ | ||
246 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | ||
247 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | ||
248 | inode->i_rdev = MKDEV(mjr, mnr); | ||
249 | } | ||
250 | } else if(memcmp("IntxCHR", pbuf, 8) == 0) { | ||
251 | cFYI(1,("Char device")); | ||
252 | inode->i_mode |= S_IFCHR; | ||
253 | if(bytes_read == 24) { | ||
254 | /* we have enough to decode dev num */ | ||
255 | __u64 mjr; /* major */ | ||
256 | __u64 mnr; /* minor */ | ||
257 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | ||
258 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | ||
259 | inode->i_rdev = MKDEV(mjr, mnr); | ||
260 | } | ||
261 | } else if(memcmp("IntxLNK", pbuf, 7) == 0) { | ||
262 | cFYI(1,("Symlink")); | ||
263 | inode->i_mode |= S_IFLNK; | ||
264 | } else { | ||
265 | inode->i_mode |= S_IFREG; /* file? */ | ||
266 | rc = -EOPNOTSUPP; | ||
267 | } | ||
268 | } else { | ||
269 | inode->i_mode |= S_IFREG; /* then it is a file */ | ||
270 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | ||
271 | } | ||
272 | CIFSSMBClose(xid, pTcon, netfid); | ||
273 | } | ||
274 | return rc; | ||
275 | |||
276 | } | ||
277 | |||
278 | #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ | ||
279 | |||
280 | static int get_sfu_uid_mode(struct inode * inode, | ||
281 | const unsigned char *path, | ||
282 | struct cifs_sb_info *cifs_sb, int xid) | ||
283 | { | ||
284 | #ifdef CONFIG_CIFS_XATTR | ||
285 | ssize_t rc; | ||
286 | char ea_value[4]; | ||
287 | __u32 mode; | ||
288 | |||
289 | rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", | ||
290 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, | ||
291 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
292 | if(rc < 0) | ||
293 | return (int)rc; | ||
294 | else if (rc > 3) { | ||
295 | mode = le32_to_cpu(*((__le32 *)ea_value)); | ||
296 | inode->i_mode &= ~SFBITS_MASK; | ||
297 | cFYI(1,("special bits 0%o org mode 0%o", mode, inode->i_mode)); | ||
298 | inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode; | ||
299 | cFYI(1,("special mode bits 0%o", mode)); | ||
300 | return 0; | ||
301 | } else { | ||
302 | return 0; | ||
303 | } | ||
304 | #else | ||
305 | return -EOPNOTSUPP; | ||
306 | #endif | ||
307 | |||
308 | |||
309 | } | ||
310 | |||
193 | int cifs_get_inode_info(struct inode **pinode, | 311 | int cifs_get_inode_info(struct inode **pinode, |
194 | const unsigned char *search_path, FILE_ALL_INFO *pfindData, | 312 | const unsigned char *search_path, FILE_ALL_INFO *pfindData, |
195 | struct super_block *sb, int xid) | 313 | struct super_block *sb, int xid) |
@@ -202,7 +320,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
202 | char *buf = NULL; | 320 | char *buf = NULL; |
203 | 321 | ||
204 | pTcon = cifs_sb->tcon; | 322 | pTcon = cifs_sb->tcon; |
205 | cFYI(1,("Getting info on %s ", search_path)); | 323 | cFYI(1,("Getting info on %s", search_path)); |
206 | 324 | ||
207 | if ((pfindData == NULL) && (*pinode != NULL)) { | 325 | if ((pfindData == NULL) && (*pinode != NULL)) { |
208 | if (CIFS_I(*pinode)->clientCanCacheRead) { | 326 | if (CIFS_I(*pinode)->clientCanCacheRead) { |
@@ -303,9 +421,9 @@ int cifs_get_inode_info(struct inode **pinode, | |||
303 | inode = *pinode; | 421 | inode = *pinode; |
304 | cifsInfo = CIFS_I(inode); | 422 | cifsInfo = CIFS_I(inode); |
305 | cifsInfo->cifsAttrs = attr; | 423 | cifsInfo->cifsAttrs = attr; |
306 | cFYI(1, (" Old time %ld ", cifsInfo->time)); | 424 | cFYI(1, ("Old time %ld ", cifsInfo->time)); |
307 | cifsInfo->time = jiffies; | 425 | cifsInfo->time = jiffies; |
308 | cFYI(1, (" New time %ld ", cifsInfo->time)); | 426 | cFYI(1, ("New time %ld ", cifsInfo->time)); |
309 | 427 | ||
310 | /* blksize needs to be multiple of two. So safer to default to | 428 | /* blksize needs to be multiple of two. So safer to default to |
311 | blksize and blkbits set in superblock so 2**blkbits and blksize | 429 | blksize and blkbits set in superblock so 2**blkbits and blksize |
@@ -319,13 +437,15 @@ int cifs_get_inode_info(struct inode **pinode, | |||
319 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); | 437 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); |
320 | inode->i_ctime = | 438 | inode->i_ctime = |
321 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); | 439 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); |
322 | cFYI(0, (" Attributes came in as 0x%x ", attr)); | 440 | cFYI(0, ("Attributes came in as 0x%x ", attr)); |
323 | 441 | ||
324 | /* set default mode. will override for dirs below */ | 442 | /* set default mode. will override for dirs below */ |
325 | if (atomic_read(&cifsInfo->inUse) == 0) | 443 | if (atomic_read(&cifsInfo->inUse) == 0) |
326 | /* new inode, can safely set these fields */ | 444 | /* new inode, can safely set these fields */ |
327 | inode->i_mode = cifs_sb->mnt_file_mode; | 445 | inode->i_mode = cifs_sb->mnt_file_mode; |
328 | 446 | else /* since we set the inode type below we need to mask off | |
447 | to avoid strange results if type changes and both get orred in */ | ||
448 | inode->i_mode &= ~S_IFMT; | ||
329 | /* if (attr & ATTR_REPARSE) */ | 449 | /* if (attr & ATTR_REPARSE) */ |
330 | /* We no longer handle these as symlinks because we could not | 450 | /* We no longer handle these as symlinks because we could not |
331 | follow them due to the absolute path with drive letter */ | 451 | follow them due to the absolute path with drive letter */ |
@@ -340,10 +460,16 @@ int cifs_get_inode_info(struct inode **pinode, | |||
340 | (pfindData->EndOfFile == 0)) { | 460 | (pfindData->EndOfFile == 0)) { |
341 | inode->i_mode = cifs_sb->mnt_file_mode; | 461 | inode->i_mode = cifs_sb->mnt_file_mode; |
342 | inode->i_mode |= S_IFIFO; | 462 | inode->i_mode |= S_IFIFO; |
343 | /* BB Finish for SFU style symlinks and devies */ | 463 | /* BB Finish for SFU style symlinks and devices */ |
344 | /* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && | 464 | } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && |
345 | (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */ | 465 | (cifsInfo->cifsAttrs & ATTR_SYSTEM)) { |
346 | 466 | if (decode_sfu_inode(inode, | |
467 | le64_to_cpu(pfindData->EndOfFile), | ||
468 | search_path, | ||
469 | cifs_sb, xid)) { | ||
470 | cFYI(1,("Unrecognized sfu inode type")); | ||
471 | } | ||
472 | cFYI(1,("sfu mode 0%o",inode->i_mode)); | ||
347 | } else { | 473 | } else { |
348 | inode->i_mode |= S_IFREG; | 474 | inode->i_mode |= S_IFREG; |
349 | /* treat the dos attribute of read-only as read-only | 475 | /* treat the dos attribute of read-only as read-only |
@@ -368,7 +494,10 @@ int cifs_get_inode_info(struct inode **pinode, | |||
368 | 494 | ||
369 | /* BB fill in uid and gid here? with help from winbind? | 495 | /* BB fill in uid and gid here? with help from winbind? |
370 | or retrieve from NTFS stream extended attribute */ | 496 | or retrieve from NTFS stream extended attribute */ |
371 | if (atomic_read(&cifsInfo->inUse) == 0) { | 497 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
498 | /* fill in uid, gid, mode from server ACL */ | ||
499 | get_sfu_uid_mode(inode, search_path, cifs_sb, xid); | ||
500 | } else if (atomic_read(&cifsInfo->inUse) == 0) { | ||
372 | inode->i_uid = cifs_sb->mnt_uid; | 501 | inode->i_uid = cifs_sb->mnt_uid; |
373 | inode->i_gid = cifs_sb->mnt_gid; | 502 | inode->i_gid = cifs_sb->mnt_gid; |
374 | /* set so we do not keep refreshing these fields with | 503 | /* set so we do not keep refreshing these fields with |
@@ -377,24 +506,29 @@ int cifs_get_inode_info(struct inode **pinode, | |||
377 | } | 506 | } |
378 | 507 | ||
379 | if (S_ISREG(inode->i_mode)) { | 508 | if (S_ISREG(inode->i_mode)) { |
380 | cFYI(1, (" File inode ")); | 509 | cFYI(1, ("File inode")); |
381 | inode->i_op = &cifs_file_inode_ops; | 510 | inode->i_op = &cifs_file_inode_ops; |
382 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) | 511 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { |
383 | inode->i_fop = &cifs_file_direct_ops; | 512 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) |
384 | else | 513 | inode->i_fop = |
514 | &cifs_file_direct_nobrl_ops; | ||
515 | else | ||
516 | inode->i_fop = &cifs_file_direct_ops; | ||
517 | } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
518 | inode->i_fop = &cifs_file_nobrl_ops; | ||
519 | else /* not direct, send byte range locks */ | ||
385 | inode->i_fop = &cifs_file_ops; | 520 | inode->i_fop = &cifs_file_ops; |
386 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | 521 | |
387 | inode->i_fop->lock = NULL; | ||
388 | inode->i_data.a_ops = &cifs_addr_ops; | 522 | inode->i_data.a_ops = &cifs_addr_ops; |
389 | if(pTcon->ses->server->maxBuf < | 523 | if(pTcon->ses->server->maxBuf < |
390 | 4096 + MAX_CIFS_HDR_SIZE) | 524 | 4096 + MAX_CIFS_HDR_SIZE) |
391 | inode->i_data.a_ops->readpages = NULL; | 525 | inode->i_data.a_ops->readpages = NULL; |
392 | } else if (S_ISDIR(inode->i_mode)) { | 526 | } else if (S_ISDIR(inode->i_mode)) { |
393 | cFYI(1, (" Directory inode ")); | 527 | cFYI(1, ("Directory inode")); |
394 | inode->i_op = &cifs_dir_inode_ops; | 528 | inode->i_op = &cifs_dir_inode_ops; |
395 | inode->i_fop = &cifs_dir_ops; | 529 | inode->i_fop = &cifs_dir_ops; |
396 | } else if (S_ISLNK(inode->i_mode)) { | 530 | } else if (S_ISLNK(inode->i_mode)) { |
397 | cFYI(1, (" Symbolic Link inode ")); | 531 | cFYI(1, ("Symbolic Link inode")); |
398 | inode->i_op = &cifs_symlink_inode_ops; | 532 | inode->i_op = &cifs_symlink_inode_ops; |
399 | } else { | 533 | } else { |
400 | init_special_inode(inode, inode->i_mode, | 534 | init_special_inode(inode, inode->i_mode, |
@@ -431,7 +565,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) | |||
431 | struct cifsInodeInfo *cifsInode; | 565 | struct cifsInodeInfo *cifsInode; |
432 | FILE_BASIC_INFO *pinfo_buf; | 566 | FILE_BASIC_INFO *pinfo_buf; |
433 | 567 | ||
434 | cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode)); | 568 | cFYI(1, ("cifs_unlink, inode = 0x%p with ", inode)); |
435 | 569 | ||
436 | xid = GetXid(); | 570 | xid = GetXid(); |
437 | 571 | ||
@@ -577,7 +711,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
577 | char *full_path = NULL; | 711 | char *full_path = NULL; |
578 | struct inode *newinode = NULL; | 712 | struct inode *newinode = NULL; |
579 | 713 | ||
580 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode)); | 714 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); |
581 | 715 | ||
582 | xid = GetXid(); | 716 | xid = GetXid(); |
583 | 717 | ||
@@ -617,8 +751,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
617 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 751 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { |
618 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, | 752 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, |
619 | mode, | 753 | mode, |
620 | (__u64)current->euid, | 754 | (__u64)current->fsuid, |
621 | (__u64)current->egid, | 755 | (__u64)current->fsgid, |
622 | 0 /* dev_t */, | 756 | 0 /* dev_t */, |
623 | cifs_sb->local_nls, | 757 | cifs_sb->local_nls, |
624 | cifs_sb->mnt_cifs_flags & | 758 | cifs_sb->mnt_cifs_flags & |
@@ -635,6 +769,17 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
635 | /* BB to be implemented via Windows secrty descriptors | 769 | /* BB to be implemented via Windows secrty descriptors |
636 | eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, | 770 | eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, |
637 | -1, -1, local_nls); */ | 771 | -1, -1, local_nls); */ |
772 | if(direntry->d_inode) { | ||
773 | direntry->d_inode->i_mode = mode; | ||
774 | direntry->d_inode->i_mode |= S_IFDIR; | ||
775 | if(cifs_sb->mnt_cifs_flags & | ||
776 | CIFS_MOUNT_SET_UID) { | ||
777 | direntry->d_inode->i_uid = | ||
778 | current->fsuid; | ||
779 | direntry->d_inode->i_gid = | ||
780 | current->fsgid; | ||
781 | } | ||
782 | } | ||
638 | } | 783 | } |
639 | } | 784 | } |
640 | kfree(full_path); | 785 | kfree(full_path); |
@@ -651,7 +796,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
651 | char *full_path = NULL; | 796 | char *full_path = NULL; |
652 | struct cifsInodeInfo *cifsInode; | 797 | struct cifsInodeInfo *cifsInode; |
653 | 798 | ||
654 | cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode)); | 799 | cFYI(1, ("cifs_rmdir, inode = 0x%p with ", inode)); |
655 | 800 | ||
656 | xid = GetXid(); | 801 | xid = GetXid(); |
657 | 802 | ||
@@ -896,9 +1041,9 @@ int cifs_revalidate(struct dentry *direntry) | |||
896 | } | 1041 | } |
897 | 1042 | ||
898 | /* can not grab this sem since kernel filesys locking documentation | 1043 | /* can not grab this sem since kernel filesys locking documentation |
899 | indicates i_sem may be taken by the kernel on lookup and rename | 1044 | indicates i_mutex may be taken by the kernel on lookup and rename |
900 | which could deadlock if we grab the i_sem here as well */ | 1045 | which could deadlock if we grab the i_mutex here as well */ |
901 | /* down(&direntry->d_inode->i_sem);*/ | 1046 | /* mutex_lock(&direntry->d_inode->i_mutex);*/ |
902 | /* need to write out dirty pages here */ | 1047 | /* need to write out dirty pages here */ |
903 | if (direntry->d_inode->i_mapping) { | 1048 | if (direntry->d_inode->i_mapping) { |
904 | /* do we need to lock inode until after invalidate completes | 1049 | /* do we need to lock inode until after invalidate completes |
@@ -906,17 +1051,23 @@ int cifs_revalidate(struct dentry *direntry) | |||
906 | filemap_fdatawrite(direntry->d_inode->i_mapping); | 1051 | filemap_fdatawrite(direntry->d_inode->i_mapping); |
907 | } | 1052 | } |
908 | if (invalidate_inode) { | 1053 | if (invalidate_inode) { |
909 | if (direntry->d_inode->i_mapping) | 1054 | /* shrink_dcache not necessary now that cifs dentry ops |
910 | filemap_fdatawait(direntry->d_inode->i_mapping); | 1055 | are exported for negative dentries */ |
911 | /* may eventually have to do this for open files too */ | 1056 | /* if(S_ISDIR(direntry->d_inode->i_mode)) |
912 | if (list_empty(&(cifsInode->openFileList))) { | 1057 | shrink_dcache_parent(direntry); */ |
913 | /* Has changed on server - flush read ahead pages */ | 1058 | if (S_ISREG(direntry->d_inode->i_mode)) { |
914 | cFYI(1, ("Invalidating read ahead data on " | 1059 | if (direntry->d_inode->i_mapping) |
915 | "closed file")); | 1060 | filemap_fdatawait(direntry->d_inode->i_mapping); |
916 | invalidate_remote_inode(direntry->d_inode); | 1061 | /* may eventually have to do this for open files too */ |
1062 | if (list_empty(&(cifsInode->openFileList))) { | ||
1063 | /* changed on server - flush read ahead pages */ | ||
1064 | cFYI(1, ("Invalidating read ahead data on " | ||
1065 | "closed file")); | ||
1066 | invalidate_remote_inode(direntry->d_inode); | ||
1067 | } | ||
917 | } | 1068 | } |
918 | } | 1069 | } |
919 | /* up(&direntry->d_inode->i_sem); */ | 1070 | /* mutex_unlock(&direntry->d_inode->i_mutex); */ |
920 | 1071 | ||
921 | kfree(full_path); | 1072 | kfree(full_path); |
922 | FreeXid(xid); | 1073 | FreeXid(xid); |
@@ -970,11 +1121,22 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
970 | 1121 | ||
971 | xid = GetXid(); | 1122 | xid = GetXid(); |
972 | 1123 | ||
973 | cFYI(1, (" In cifs_setattr, name = %s attrs->iavalid 0x%x ", | 1124 | cFYI(1, ("In cifs_setattr, name = %s attrs->iavalid 0x%x ", |
974 | direntry->d_name.name, attrs->ia_valid)); | 1125 | direntry->d_name.name, attrs->ia_valid)); |
1126 | |||
975 | cifs_sb = CIFS_SB(direntry->d_inode->i_sb); | 1127 | cifs_sb = CIFS_SB(direntry->d_inode->i_sb); |
976 | pTcon = cifs_sb->tcon; | 1128 | pTcon = cifs_sb->tcon; |
977 | 1129 | ||
1130 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { | ||
1131 | /* check if we have permission to change attrs */ | ||
1132 | rc = inode_change_ok(direntry->d_inode, attrs); | ||
1133 | if(rc < 0) { | ||
1134 | FreeXid(xid); | ||
1135 | return rc; | ||
1136 | } else | ||
1137 | rc = 0; | ||
1138 | } | ||
1139 | |||
978 | down(&direntry->d_sb->s_vfs_rename_sem); | 1140 | down(&direntry->d_sb->s_vfs_rename_sem); |
979 | full_path = build_path_from_dentry(direntry); | 1141 | full_path = build_path_from_dentry(direntry); |
980 | up(&direntry->d_sb->s_vfs_rename_sem); | 1142 | up(&direntry->d_sb->s_vfs_rename_sem); |
@@ -987,8 +1149,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
987 | /* BB check if we need to refresh inode from server now ? BB */ | 1149 | /* BB check if we need to refresh inode from server now ? BB */ |
988 | 1150 | ||
989 | /* need to flush data before changing file size on server */ | 1151 | /* need to flush data before changing file size on server */ |
990 | filemap_fdatawrite(direntry->d_inode->i_mapping); | 1152 | filemap_write_and_wait(direntry->d_inode->i_mapping); |
991 | filemap_fdatawait(direntry->d_inode->i_mapping); | ||
992 | 1153 | ||
993 | if (attrs->ia_valid & ATTR_SIZE) { | 1154 | if (attrs->ia_valid & ATTR_SIZE) { |
994 | /* To avoid spurious oplock breaks from server, in the case of | 1155 | /* To avoid spurious oplock breaks from server, in the case of |
@@ -1014,7 +1175,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1014 | 1 /* 45 seconds */); | 1175 | 1 /* 45 seconds */); |
1015 | cFYI(1,("Wrt seteof rc %d", rc)); | 1176 | cFYI(1,("Wrt seteof rc %d", rc)); |
1016 | } | 1177 | } |
1017 | } | 1178 | } else |
1179 | rc = -EINVAL; | ||
1180 | |||
1018 | if (rc != 0) { | 1181 | if (rc != 0) { |
1019 | /* Set file size by pathname rather than by handle | 1182 | /* Set file size by pathname rather than by handle |
1020 | either because no valid, writeable file handle for | 1183 | either because no valid, writeable file handle for |
@@ -1086,6 +1249,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1086 | cifs_sb->mnt_cifs_flags & | 1249 | cifs_sb->mnt_cifs_flags & |
1087 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1250 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1088 | else if (attrs->ia_valid & ATTR_MODE) { | 1251 | else if (attrs->ia_valid & ATTR_MODE) { |
1252 | rc = 0; | ||
1089 | if ((mode & S_IWUGO) == 0) /* not writeable */ { | 1253 | if ((mode & S_IWUGO) == 0) /* not writeable */ { |
1090 | if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) | 1254 | if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) |
1091 | time_buf.Attributes = | 1255 | time_buf.Attributes = |