diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 397 |
1 files changed, 151 insertions, 246 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 55b616bb381e..a807397f444e 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -82,23 +82,34 @@ void | |||
82 | cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | 82 | cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) |
83 | { | 83 | { |
84 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | 84 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
85 | unsigned long now = jiffies; | 85 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
86 | unsigned long oldtime = cifs_i->time; | ||
86 | 87 | ||
87 | inode->i_atime = fattr->cf_atime; | 88 | inode->i_atime = fattr->cf_atime; |
88 | inode->i_mtime = fattr->cf_mtime; | 89 | inode->i_mtime = fattr->cf_mtime; |
89 | inode->i_ctime = fattr->cf_ctime; | 90 | inode->i_ctime = fattr->cf_ctime; |
90 | inode->i_mode = fattr->cf_mode; | ||
91 | inode->i_rdev = fattr->cf_rdev; | 91 | inode->i_rdev = fattr->cf_rdev; |
92 | inode->i_nlink = fattr->cf_nlink; | 92 | inode->i_nlink = fattr->cf_nlink; |
93 | inode->i_uid = fattr->cf_uid; | 93 | inode->i_uid = fattr->cf_uid; |
94 | inode->i_gid = fattr->cf_gid; | 94 | inode->i_gid = fattr->cf_gid; |
95 | 95 | ||
96 | /* if dynperm is set, don't clobber existing mode */ | ||
97 | if (inode->i_state & I_NEW || | ||
98 | !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) | ||
99 | inode->i_mode = fattr->cf_mode; | ||
100 | |||
96 | cifs_i->cifsAttrs = fattr->cf_cifsattrs; | 101 | cifs_i->cifsAttrs = fattr->cf_cifsattrs; |
97 | cifs_i->uniqueid = fattr->cf_uniqueid; | 102 | cifs_i->uniqueid = fattr->cf_uniqueid; |
98 | 103 | ||
104 | if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL) | ||
105 | cifs_i->time = 0; | ||
106 | else | ||
107 | cifs_i->time = jiffies; | ||
108 | |||
99 | cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode, | 109 | cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode, |
100 | cifs_i->time, now)); | 110 | oldtime, cifs_i->time)); |
101 | cifs_i->time = now; | 111 | |
112 | cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; | ||
102 | 113 | ||
103 | /* | 114 | /* |
104 | * Can't safely change the file size here if the client is writing to | 115 | * Can't safely change the file size here if the client is writing to |
@@ -219,49 +230,6 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) | |||
219 | fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; | 230 | fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; |
220 | } | 231 | } |
221 | 232 | ||
222 | /** | ||
223 | * cifs_new inode - create new inode, initialize, and hash it | ||
224 | * @sb - pointer to superblock | ||
225 | * @inum - if valid pointer and serverino is enabled, replace i_ino with val | ||
226 | * | ||
227 | * Create a new inode, initialize it for CIFS and hash it. Returns the new | ||
228 | * inode or NULL if one couldn't be allocated. | ||
229 | * | ||
230 | * If the share isn't mounted with "serverino" or inum is a NULL pointer then | ||
231 | * we'll just use the inode number assigned by new_inode(). Note that this can | ||
232 | * mean i_ino collisions since the i_ino assigned by new_inode is not | ||
233 | * guaranteed to be unique. | ||
234 | */ | ||
235 | struct inode * | ||
236 | cifs_new_inode(struct super_block *sb, __u64 *inum) | ||
237 | { | ||
238 | struct inode *inode; | ||
239 | |||
240 | inode = new_inode(sb); | ||
241 | if (inode == NULL) | ||
242 | return NULL; | ||
243 | |||
244 | /* | ||
245 | * BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we | ||
246 | * stop passing inum as ptr. Are there sanity checks we can use to | ||
247 | * ensure that the server is really filling in that field? Also, | ||
248 | * if serverino is disabled, perhaps we should be using iunique()? | ||
249 | */ | ||
250 | if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) | ||
251 | inode->i_ino = (unsigned long) *inum; | ||
252 | |||
253 | /* | ||
254 | * must set this here instead of cifs_alloc_inode since VFS will | ||
255 | * clobber i_flags | ||
256 | */ | ||
257 | if (sb->s_flags & MS_NOATIME) | ||
258 | inode->i_flags |= S_NOATIME | S_NOCMTIME; | ||
259 | |||
260 | insert_inode_hash(inode); | ||
261 | |||
262 | return inode; | ||
263 | } | ||
264 | |||
265 | int cifs_get_inode_info_unix(struct inode **pinode, | 233 | int cifs_get_inode_info_unix(struct inode **pinode, |
266 | const unsigned char *full_path, | 234 | const unsigned char *full_path, |
267 | struct super_block *sb, int xid) | 235 | struct super_block *sb, int xid) |
@@ -302,9 +270,9 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
302 | return rc; | 270 | return rc; |
303 | } | 271 | } |
304 | 272 | ||
305 | static int decode_sfu_inode(struct inode *inode, __u64 size, | 273 | static int |
306 | const unsigned char *path, | 274 | cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, |
307 | struct cifs_sb_info *cifs_sb, int xid) | 275 | struct cifs_sb_info *cifs_sb, int xid) |
308 | { | 276 | { |
309 | int rc; | 277 | int rc; |
310 | int oplock = 0; | 278 | int oplock = 0; |
@@ -316,10 +284,15 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, | |||
316 | 284 | ||
317 | pbuf = buf; | 285 | pbuf = buf; |
318 | 286 | ||
319 | if (size == 0) { | 287 | fattr->cf_mode &= ~S_IFMT; |
320 | inode->i_mode |= S_IFIFO; | 288 | |
289 | if (fattr->cf_eof == 0) { | ||
290 | fattr->cf_mode |= S_IFIFO; | ||
291 | fattr->cf_dtype = DT_FIFO; | ||
321 | return 0; | 292 | return 0; |
322 | } else if (size < 8) { | 293 | } else if (fattr->cf_eof < 8) { |
294 | fattr->cf_mode |= S_IFREG; | ||
295 | fattr->cf_dtype = DT_REG; | ||
323 | return -EINVAL; /* EOPNOTSUPP? */ | 296 | return -EINVAL; /* EOPNOTSUPP? */ |
324 | } | 297 | } |
325 | 298 | ||
@@ -331,42 +304,46 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, | |||
331 | if (rc == 0) { | 304 | if (rc == 0) { |
332 | int buf_type = CIFS_NO_BUFFER; | 305 | int buf_type = CIFS_NO_BUFFER; |
333 | /* Read header */ | 306 | /* Read header */ |
334 | rc = CIFSSMBRead(xid, pTcon, | 307 | rc = CIFSSMBRead(xid, pTcon, netfid, |
335 | netfid, | ||
336 | 24 /* length */, 0 /* offset */, | 308 | 24 /* length */, 0 /* offset */, |
337 | &bytes_read, &pbuf, &buf_type); | 309 | &bytes_read, &pbuf, &buf_type); |
338 | if ((rc == 0) && (bytes_read >= 8)) { | 310 | if ((rc == 0) && (bytes_read >= 8)) { |
339 | if (memcmp("IntxBLK", pbuf, 8) == 0) { | 311 | if (memcmp("IntxBLK", pbuf, 8) == 0) { |
340 | cFYI(1, ("Block device")); | 312 | cFYI(1, ("Block device")); |
341 | inode->i_mode |= S_IFBLK; | 313 | fattr->cf_mode |= S_IFBLK; |
314 | fattr->cf_dtype = DT_BLK; | ||
342 | if (bytes_read == 24) { | 315 | if (bytes_read == 24) { |
343 | /* we have enough to decode dev num */ | 316 | /* we have enough to decode dev num */ |
344 | __u64 mjr; /* major */ | 317 | __u64 mjr; /* major */ |
345 | __u64 mnr; /* minor */ | 318 | __u64 mnr; /* minor */ |
346 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | 319 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); |
347 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | 320 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); |
348 | inode->i_rdev = MKDEV(mjr, mnr); | 321 | fattr->cf_rdev = MKDEV(mjr, mnr); |
349 | } | 322 | } |
350 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { | 323 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { |
351 | cFYI(1, ("Char device")); | 324 | cFYI(1, ("Char device")); |
352 | inode->i_mode |= S_IFCHR; | 325 | fattr->cf_mode |= S_IFCHR; |
326 | fattr->cf_dtype = DT_CHR; | ||
353 | if (bytes_read == 24) { | 327 | if (bytes_read == 24) { |
354 | /* we have enough to decode dev num */ | 328 | /* we have enough to decode dev num */ |
355 | __u64 mjr; /* major */ | 329 | __u64 mjr; /* major */ |
356 | __u64 mnr; /* minor */ | 330 | __u64 mnr; /* minor */ |
357 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | 331 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); |
358 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | 332 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); |
359 | inode->i_rdev = MKDEV(mjr, mnr); | 333 | fattr->cf_rdev = MKDEV(mjr, mnr); |
360 | } | 334 | } |
361 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { | 335 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { |
362 | cFYI(1, ("Symlink")); | 336 | cFYI(1, ("Symlink")); |
363 | inode->i_mode |= S_IFLNK; | 337 | fattr->cf_mode |= S_IFLNK; |
338 | fattr->cf_dtype = DT_LNK; | ||
364 | } else { | 339 | } else { |
365 | inode->i_mode |= S_IFREG; /* file? */ | 340 | fattr->cf_mode |= S_IFREG; /* file? */ |
341 | fattr->cf_dtype = DT_REG; | ||
366 | rc = -EOPNOTSUPP; | 342 | rc = -EOPNOTSUPP; |
367 | } | 343 | } |
368 | } else { | 344 | } else { |
369 | inode->i_mode |= S_IFREG; /* then it is a file */ | 345 | fattr->cf_mode |= S_IFREG; /* then it is a file */ |
346 | fattr->cf_dtype = DT_REG; | ||
370 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | 347 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ |
371 | } | 348 | } |
372 | CIFSSMBClose(xid, pTcon, netfid); | 349 | CIFSSMBClose(xid, pTcon, netfid); |
@@ -376,9 +353,13 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, | |||
376 | 353 | ||
377 | #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ | 354 | #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ |
378 | 355 | ||
379 | static int get_sfu_mode(struct inode *inode, | 356 | /* |
380 | const unsigned char *path, | 357 | * Fetch mode bits as provided by SFU. |
381 | struct cifs_sb_info *cifs_sb, int xid) | 358 | * |
359 | * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ? | ||
360 | */ | ||
361 | static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, | ||
362 | struct cifs_sb_info *cifs_sb, int xid) | ||
382 | { | 363 | { |
383 | #ifdef CONFIG_CIFS_XATTR | 364 | #ifdef CONFIG_CIFS_XATTR |
384 | ssize_t rc; | 365 | ssize_t rc; |
@@ -386,68 +367,80 @@ static int get_sfu_mode(struct inode *inode, | |||
386 | __u32 mode; | 367 | __u32 mode; |
387 | 368 | ||
388 | rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", | 369 | rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", |
389 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, | 370 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, |
390 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 371 | cifs_sb->mnt_cifs_flags & |
372 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
391 | if (rc < 0) | 373 | if (rc < 0) |
392 | return (int)rc; | 374 | return (int)rc; |
393 | else if (rc > 3) { | 375 | else if (rc > 3) { |
394 | mode = le32_to_cpu(*((__le32 *)ea_value)); | 376 | mode = le32_to_cpu(*((__le32 *)ea_value)); |
395 | inode->i_mode &= ~SFBITS_MASK; | 377 | fattr->cf_mode &= ~SFBITS_MASK; |
396 | cFYI(1, ("special bits 0%o org mode 0%o", mode, inode->i_mode)); | 378 | cFYI(1, ("special bits 0%o org mode 0%o", mode, |
397 | inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode; | 379 | fattr->cf_mode)); |
380 | fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode; | ||
398 | cFYI(1, ("special mode bits 0%o", mode)); | 381 | cFYI(1, ("special mode bits 0%o", mode)); |
399 | return 0; | ||
400 | } else { | ||
401 | return 0; | ||
402 | } | 382 | } |
383 | |||
384 | return 0; | ||
403 | #else | 385 | #else |
404 | return -EOPNOTSUPP; | 386 | return -EOPNOTSUPP; |
405 | #endif | 387 | #endif |
406 | } | 388 | } |
407 | 389 | ||
408 | /* | 390 | /* Fill a cifs_fattr struct with info from FILE_ALL_INFO */ |
409 | * Needed to setup inode data for the directory which is the | 391 | void |
410 | * junction to the new submount (ie to setup the fake directory | 392 | cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, |
411 | * which represents a DFS referral) | 393 | struct cifs_sb_info *cifs_sb, bool adjust_tz) |
412 | */ | ||
413 | static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat, | ||
414 | struct super_block *sb) | ||
415 | { | 394 | { |
416 | memset(pfnd_dat, 0, sizeof(FILE_ALL_INFO)); | 395 | memset(fattr, 0, sizeof(*fattr)); |
417 | 396 | fattr->cf_cifsattrs = le32_to_cpu(info->Attributes); | |
418 | /* __le64 pfnd_dat->AllocationSize = cpu_to_le64(0); | 397 | if (info->DeletePending) |
419 | __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); | 398 | fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING; |
420 | __u8 pfnd_dat->DeletePending = 0; | 399 | |
421 | __u8 pfnd_data->Directory = 0; | 400 | if (info->LastAccessTime) |
422 | __le32 pfnd_dat->EASize = 0; | 401 | fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); |
423 | __u64 pfnd_dat->IndexNumber = 0; | 402 | else |
424 | __u64 pfnd_dat->IndexNumber1 = 0; */ | 403 | fattr->cf_atime = CURRENT_TIME; |
425 | pfnd_dat->CreationTime = | 404 | |
426 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 405 | fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); |
427 | pfnd_dat->LastAccessTime = | 406 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); |
428 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 407 | |
429 | pfnd_dat->LastWriteTime = | 408 | if (adjust_tz) { |
430 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 409 | fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; |
431 | pfnd_dat->ChangeTime = | 410 | fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; |
432 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 411 | } |
433 | pfnd_dat->Attributes = cpu_to_le32(ATTR_DIRECTORY); | 412 | |
434 | pfnd_dat->NumberOfLinks = cpu_to_le32(2); | 413 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); |
414 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); | ||
415 | |||
416 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { | ||
417 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; | ||
418 | fattr->cf_dtype = DT_DIR; | ||
419 | } else { | ||
420 | fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; | ||
421 | fattr->cf_dtype = DT_REG; | ||
422 | } | ||
423 | |||
424 | /* clear write bits if ATTR_READONLY is set */ | ||
425 | if (fattr->cf_cifsattrs & ATTR_READONLY) | ||
426 | fattr->cf_mode &= ~(S_IWUGO); | ||
427 | |||
428 | fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); | ||
429 | |||
430 | fattr->cf_uid = cifs_sb->mnt_uid; | ||
431 | fattr->cf_gid = cifs_sb->mnt_gid; | ||
435 | } | 432 | } |
436 | 433 | ||
437 | int cifs_get_inode_info(struct inode **pinode, | 434 | int cifs_get_inode_info(struct inode **pinode, |
438 | const unsigned char *full_path, FILE_ALL_INFO *pfindData, | 435 | const unsigned char *full_path, FILE_ALL_INFO *pfindData, |
439 | struct super_block *sb, int xid, const __u16 *pfid) | 436 | struct super_block *sb, int xid, const __u16 *pfid) |
440 | { | 437 | { |
441 | int rc = 0; | 438 | int rc = 0, tmprc; |
442 | __u32 attr; | ||
443 | struct cifsInodeInfo *cifsInfo; | ||
444 | struct cifsTconInfo *pTcon; | 439 | struct cifsTconInfo *pTcon; |
445 | struct inode *inode; | ||
446 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 440 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
447 | char *buf = NULL; | 441 | char *buf = NULL; |
448 | bool adjustTZ = false; | 442 | bool adjustTZ = false; |
449 | bool is_dfs_referral = false; | 443 | struct cifs_fattr fattr; |
450 | umode_t default_mode; | ||
451 | 444 | ||
452 | pTcon = cifs_sb->tcon; | 445 | pTcon = cifs_sb->tcon; |
453 | cFYI(1, ("Getting info on %s", full_path)); | 446 | cFYI(1, ("Getting info on %s", full_path)); |
@@ -482,163 +475,82 @@ int cifs_get_inode_info(struct inode **pinode, | |||
482 | adjustTZ = true; | 475 | adjustTZ = true; |
483 | } | 476 | } |
484 | } | 477 | } |
485 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ | 478 | |
486 | if (rc == -EREMOTE) { | 479 | if (!rc) { |
487 | is_dfs_referral = true; | 480 | cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData, |
488 | fill_fake_finddata(pfindData, sb); | 481 | cifs_sb, adjustTZ); |
482 | } else if (rc == -EREMOTE) { | ||
483 | cifs_create_dfs_fattr(&fattr, sb); | ||
489 | rc = 0; | 484 | rc = 0; |
490 | } else if (rc) | 485 | } else { |
491 | goto cgii_exit; | 486 | goto cgii_exit; |
487 | } | ||
492 | 488 | ||
493 | attr = le32_to_cpu(pfindData->Attributes); | 489 | /* |
494 | 490 | * If an inode wasn't passed in, then get the inode number | |
495 | /* get new inode */ | 491 | * |
492 | * Is an i_ino of zero legal? Can we use that to check if the server | ||
493 | * supports returning inode numbers? Are there other sanity checks we | ||
494 | * can use to ensure that the server is really filling in that field? | ||
495 | * | ||
496 | * We can not use the IndexNumber field by default from Windows or | ||
497 | * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA | ||
498 | * CIFS spec claims that this value is unique within the scope of a | ||
499 | * share, and the windows docs hint that it's actually unique | ||
500 | * per-machine. | ||
501 | * | ||
502 | * There may be higher info levels that work but are there Windows | ||
503 | * server or network appliances for which IndexNumber field is not | ||
504 | * guaranteed unique? | ||
505 | */ | ||
496 | if (*pinode == NULL) { | 506 | if (*pinode == NULL) { |
497 | __u64 inode_num; | ||
498 | __u64 *pinum = &inode_num; | ||
499 | |||
500 | /* Is an i_ino of zero legal? Can we use that to check | ||
501 | if the server supports returning inode numbers? Are | ||
502 | there other sanity checks we can use to ensure that | ||
503 | the server is really filling in that field? */ | ||
504 | |||
505 | /* We can not use the IndexNumber field by default from | ||
506 | Windows or Samba (in ALL_INFO buf) but we can request | ||
507 | it explicitly. It may not be unique presumably if | ||
508 | the server has multiple devices mounted under one share */ | ||
509 | |||
510 | /* There may be higher info levels that work but are | ||
511 | there Windows server or network appliances for which | ||
512 | IndexNumber field is not guaranteed unique? */ | ||
513 | |||
514 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 507 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
515 | int rc1 = 0; | 508 | int rc1 = 0; |
516 | 509 | ||
517 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, | 510 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, |
518 | full_path, pinum, | 511 | full_path, &fattr.cf_uniqueid, |
519 | cifs_sb->local_nls, | 512 | cifs_sb->local_nls, |
520 | cifs_sb->mnt_cifs_flags & | 513 | cifs_sb->mnt_cifs_flags & |
521 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 514 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
522 | if (rc1) { | 515 | if (rc1) { |
523 | cFYI(1, ("GetSrvInodeNum rc %d", rc1)); | ||
524 | pinum = NULL; | ||
525 | /* BB EOPNOSUPP disable SERVER_INUM? */ | 516 | /* BB EOPNOSUPP disable SERVER_INUM? */ |
517 | cFYI(1, ("GetSrvInodeNum rc %d", rc1)); | ||
518 | fattr.cf_uniqueid = iunique(sb, ROOT_I); | ||
526 | } | 519 | } |
527 | } else { | 520 | } else { |
528 | pinum = NULL; | 521 | fattr.cf_uniqueid = iunique(sb, ROOT_I); |
529 | } | 522 | } |
530 | |||
531 | *pinode = cifs_new_inode(sb, pinum); | ||
532 | if (*pinode == NULL) { | ||
533 | rc = -ENOMEM; | ||
534 | goto cgii_exit; | ||
535 | } | ||
536 | } | ||
537 | inode = *pinode; | ||
538 | cifsInfo = CIFS_I(inode); | ||
539 | cifsInfo->cifsAttrs = attr; | ||
540 | cifsInfo->delete_pending = pfindData->DeletePending ? true : false; | ||
541 | cFYI(1, ("Old time %ld", cifsInfo->time)); | ||
542 | cifsInfo->time = jiffies; | ||
543 | cFYI(1, ("New time %ld", cifsInfo->time)); | ||
544 | |||
545 | /* blksize needs to be multiple of two. So safer to default to | ||
546 | blksize and blkbits set in superblock so 2**blkbits and blksize | ||
547 | will match rather than setting to: | ||
548 | (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ | ||
549 | |||
550 | /* Linux can not store file creation time so ignore it */ | ||
551 | if (pfindData->LastAccessTime) | ||
552 | inode->i_atime = cifs_NTtimeToUnix(pfindData->LastAccessTime); | ||
553 | else /* do not need to use current_fs_time - time not stored */ | ||
554 | inode->i_atime = CURRENT_TIME; | ||
555 | inode->i_mtime = cifs_NTtimeToUnix(pfindData->LastWriteTime); | ||
556 | inode->i_ctime = cifs_NTtimeToUnix(pfindData->ChangeTime); | ||
557 | cFYI(DBG2, ("Attributes came in as 0x%x", attr)); | ||
558 | if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { | ||
559 | inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; | ||
560 | inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; | ||
561 | } | ||
562 | |||
563 | /* get default inode mode */ | ||
564 | if (attr & ATTR_DIRECTORY) | ||
565 | default_mode = cifs_sb->mnt_dir_mode; | ||
566 | else | ||
567 | default_mode = cifs_sb->mnt_file_mode; | ||
568 | |||
569 | /* set permission bits */ | ||
570 | if (atomic_read(&cifsInfo->inUse) == 0 || | ||
571 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) | ||
572 | inode->i_mode = default_mode; | ||
573 | else { | ||
574 | /* just reenable write bits if !ATTR_READONLY */ | ||
575 | if ((inode->i_mode & S_IWUGO) == 0 && | ||
576 | (attr & ATTR_READONLY) == 0) | ||
577 | inode->i_mode |= (S_IWUGO & default_mode); | ||
578 | |||
579 | inode->i_mode &= ~S_IFMT; | ||
580 | } | ||
581 | /* clear write bits if ATTR_READONLY is set */ | ||
582 | if (attr & ATTR_READONLY) | ||
583 | inode->i_mode &= ~S_IWUGO; | ||
584 | |||
585 | /* set inode type */ | ||
586 | if ((attr & ATTR_SYSTEM) && | ||
587 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { | ||
588 | /* no need to fix endianness on 0 */ | ||
589 | if (pfindData->EndOfFile == 0) | ||
590 | inode->i_mode |= S_IFIFO; | ||
591 | else if (decode_sfu_inode(inode, | ||
592 | le64_to_cpu(pfindData->EndOfFile), | ||
593 | full_path, cifs_sb, xid)) | ||
594 | cFYI(1, ("unknown SFU file type\n")); | ||
595 | } else { | 523 | } else { |
596 | if (attr & ATTR_DIRECTORY) | 524 | fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid; |
597 | inode->i_mode |= S_IFDIR; | ||
598 | else | ||
599 | inode->i_mode |= S_IFREG; | ||
600 | } | 525 | } |
601 | 526 | ||
602 | cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile); | 527 | /* query for SFU type info if supported and needed */ |
603 | spin_lock(&inode->i_lock); | 528 | if (fattr.cf_cifsattrs & ATTR_SYSTEM && |
604 | if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) { | 529 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
605 | /* can not safely shrink the file size here if the | 530 | tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid); |
606 | client is writing to it due to potential races */ | 531 | if (tmprc) |
607 | i_size_write(inode, cifsInfo->server_eof); | 532 | cFYI(1, ("cifs_sfu_type failed: %d", tmprc)); |
608 | |||
609 | /* 512 bytes (2**9) is the fake blocksize that must be | ||
610 | used for this calculation */ | ||
611 | inode->i_blocks = (512 - 1 + le64_to_cpu( | ||
612 | pfindData->AllocationSize)) >> 9; | ||
613 | } | 533 | } |
614 | spin_unlock(&inode->i_lock); | ||
615 | 534 | ||
616 | inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); | ||
617 | |||
618 | /* BB fill in uid and gid here? with help from winbind? | ||
619 | or retrieve from NTFS stream extended attribute */ | ||
620 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 535 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
621 | /* fill in 0777 bits from ACL */ | 536 | /* fill in 0777 bits from ACL */ |
622 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 537 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
623 | cFYI(1, ("Getting mode bits from ACL")); | 538 | cFYI(1, ("Getting mode bits from ACL")); |
624 | acl_to_uid_mode(cifs_sb, inode, full_path, pfid); | 539 | cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); |
625 | } | 540 | } |
626 | #endif | 541 | #endif |
627 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | ||
628 | /* fill in remaining high mode bits e.g. SUID, VTX */ | ||
629 | get_sfu_mode(inode, full_path, cifs_sb, xid); | ||
630 | } else if (atomic_read(&cifsInfo->inUse) == 0) { | ||
631 | inode->i_uid = cifs_sb->mnt_uid; | ||
632 | inode->i_gid = cifs_sb->mnt_gid; | ||
633 | /* set so we do not keep refreshing these fields with | ||
634 | bad data after user has changed them in memory */ | ||
635 | atomic_set(&cifsInfo->inUse, 1); | ||
636 | } | ||
637 | |||
638 | cifs_set_ops(inode, is_dfs_referral); | ||
639 | |||
640 | 542 | ||
543 | /* fill in remaining high mode bits e.g. SUID, VTX */ | ||
544 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) | ||
545 | cifs_sfu_mode(&fattr, full_path, cifs_sb, xid); | ||
641 | 546 | ||
547 | if (!*pinode) { | ||
548 | *pinode = cifs_iget(sb, &fattr); | ||
549 | if (!*pinode) | ||
550 | rc = -ENOMEM; | ||
551 | } else { | ||
552 | cifs_fattr_to_inode(*pinode, &fattr); | ||
553 | } | ||
642 | 554 | ||
643 | cgii_exit: | 555 | cgii_exit: |
644 | kfree(buf); | 556 | kfree(buf); |
@@ -753,21 +665,14 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
753 | return ERR_PTR(-ENOMEM); | 665 | return ERR_PTR(-ENOMEM); |
754 | 666 | ||
755 | xid = GetXid(); | 667 | xid = GetXid(); |
756 | if (cifs_sb->tcon->unix_ext) { | 668 | if (cifs_sb->tcon->unix_ext) |
757 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); | 669 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); |
758 | if (!inode) | 670 | else |
759 | return ERR_PTR(-ENOMEM); | 671 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
760 | } else { | ||
761 | inode = iget_locked(sb, ino); | ||
762 | if (!inode) | ||
763 | return ERR_PTR(-ENOMEM); | ||
764 | if (!(inode->i_state & I_NEW)) | ||
765 | return inode; | ||
766 | |||
767 | rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb, | ||
768 | xid, NULL); | 672 | xid, NULL); |
769 | unlock_new_inode(inode); | 673 | |
770 | } | 674 | if (!inode) |
675 | return ERR_PTR(-ENOMEM); | ||
771 | 676 | ||
772 | if (rc && cifs_sb->tcon->ipc) { | 677 | if (rc && cifs_sb->tcon->ipc) { |
773 | cFYI(1, ("ipc connection - fake read inode")); | 678 | cFYI(1, ("ipc connection - fake read inode")); |