diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 501 |
1 files changed, 347 insertions, 154 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 53cce8cc2224..9b018c8334fa 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #include "fscache.h" | 32 | #include "fscache.h" |
33 | 33 | ||
34 | 34 | ||
35 | static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | 35 | static void cifs_set_ops(struct inode *inode) |
36 | { | 36 | { |
37 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 37 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
38 | 38 | ||
@@ -44,15 +44,19 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | |||
44 | inode->i_fop = &cifs_file_direct_nobrl_ops; | 44 | inode->i_fop = &cifs_file_direct_nobrl_ops; |
45 | else | 45 | else |
46 | inode->i_fop = &cifs_file_direct_ops; | 46 | inode->i_fop = &cifs_file_direct_ops; |
47 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) { | ||
48 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
49 | inode->i_fop = &cifs_file_strict_nobrl_ops; | ||
50 | else | ||
51 | inode->i_fop = &cifs_file_strict_ops; | ||
47 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | 52 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) |
48 | inode->i_fop = &cifs_file_nobrl_ops; | 53 | inode->i_fop = &cifs_file_nobrl_ops; |
49 | else { /* not direct, send byte range locks */ | 54 | else { /* not direct, send byte range locks */ |
50 | inode->i_fop = &cifs_file_ops; | 55 | inode->i_fop = &cifs_file_ops; |
51 | } | 56 | } |
52 | 57 | ||
53 | |||
54 | /* check if server can support readpages */ | 58 | /* check if server can support readpages */ |
55 | if (cifs_sb->tcon->ses->server->maxBuf < | 59 | if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf < |
56 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) | 60 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) |
57 | inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | 61 | inode->i_data.a_ops = &cifs_addr_ops_smallbuf; |
58 | else | 62 | else |
@@ -60,7 +64,7 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | |||
60 | break; | 64 | break; |
61 | case S_IFDIR: | 65 | case S_IFDIR: |
62 | #ifdef CONFIG_CIFS_DFS_UPCALL | 66 | #ifdef CONFIG_CIFS_DFS_UPCALL |
63 | if (is_dfs_referral) { | 67 | if (IS_AUTOMOUNT(inode)) { |
64 | inode->i_op = &cifs_dfs_referral_inode_operations; | 68 | inode->i_op = &cifs_dfs_referral_inode_operations; |
65 | } else { | 69 | } else { |
66 | #else /* NO DFS support, treat as a directory */ | 70 | #else /* NO DFS support, treat as a directory */ |
@@ -167,7 +171,9 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | |||
167 | } | 171 | } |
168 | spin_unlock(&inode->i_lock); | 172 | spin_unlock(&inode->i_lock); |
169 | 173 | ||
170 | cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL); | 174 | if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL) |
175 | inode->i_flags |= S_AUTOMOUNT; | ||
176 | cifs_set_ops(inode); | ||
171 | } | 177 | } |
172 | 178 | ||
173 | void | 179 | void |
@@ -288,8 +294,8 @@ int cifs_get_file_info_unix(struct file *filp) | |||
288 | struct cifs_fattr fattr; | 294 | struct cifs_fattr fattr; |
289 | struct inode *inode = filp->f_path.dentry->d_inode; | 295 | struct inode *inode = filp->f_path.dentry->d_inode; |
290 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 296 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
291 | struct cifsTconInfo *tcon = cifs_sb->tcon; | ||
292 | struct cifsFileInfo *cfile = filp->private_data; | 297 | struct cifsFileInfo *cfile = filp->private_data; |
298 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | ||
293 | 299 | ||
294 | xid = GetXid(); | 300 | xid = GetXid(); |
295 | rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); | 301 | rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); |
@@ -312,16 +318,22 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
312 | int rc; | 318 | int rc; |
313 | FILE_UNIX_BASIC_INFO find_data; | 319 | FILE_UNIX_BASIC_INFO find_data; |
314 | struct cifs_fattr fattr; | 320 | struct cifs_fattr fattr; |
315 | struct cifsTconInfo *tcon; | 321 | struct cifs_tcon *tcon; |
322 | struct tcon_link *tlink; | ||
316 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 323 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
317 | 324 | ||
318 | tcon = cifs_sb->tcon; | ||
319 | cFYI(1, "Getting info on %s", full_path); | 325 | cFYI(1, "Getting info on %s", full_path); |
320 | 326 | ||
327 | tlink = cifs_sb_tlink(cifs_sb); | ||
328 | if (IS_ERR(tlink)) | ||
329 | return PTR_ERR(tlink); | ||
330 | tcon = tlink_tcon(tlink); | ||
331 | |||
321 | /* could have done a find first instead but this returns more info */ | 332 | /* could have done a find first instead but this returns more info */ |
322 | rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, | 333 | rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, |
323 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 334 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
324 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 335 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
336 | cifs_put_tlink(tlink); | ||
325 | 337 | ||
326 | if (!rc) { | 338 | if (!rc) { |
327 | cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); | 339 | cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); |
@@ -332,6 +344,13 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
332 | return rc; | 344 | return rc; |
333 | } | 345 | } |
334 | 346 | ||
347 | /* check for Minshall+French symlinks */ | ||
348 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { | ||
349 | int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid); | ||
350 | if (tmprc) | ||
351 | cFYI(1, "CIFSCheckMFSymlink: %d", tmprc); | ||
352 | } | ||
353 | |||
335 | if (*pinode == NULL) { | 354 | if (*pinode == NULL) { |
336 | /* get new inode */ | 355 | /* get new inode */ |
337 | cifs_fill_uniqueid(sb, &fattr); | 356 | cifs_fill_uniqueid(sb, &fattr); |
@@ -353,7 +372,9 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
353 | int rc; | 372 | int rc; |
354 | int oplock = 0; | 373 | int oplock = 0; |
355 | __u16 netfid; | 374 | __u16 netfid; |
356 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 375 | struct tcon_link *tlink; |
376 | struct cifs_tcon *tcon; | ||
377 | struct cifs_io_parms io_parms; | ||
357 | char buf[24]; | 378 | char buf[24]; |
358 | unsigned int bytes_read; | 379 | unsigned int bytes_read; |
359 | char *pbuf; | 380 | char *pbuf; |
@@ -372,7 +393,12 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
372 | return -EINVAL; /* EOPNOTSUPP? */ | 393 | return -EINVAL; /* EOPNOTSUPP? */ |
373 | } | 394 | } |
374 | 395 | ||
375 | rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ, | 396 | tlink = cifs_sb_tlink(cifs_sb); |
397 | if (IS_ERR(tlink)) | ||
398 | return PTR_ERR(tlink); | ||
399 | tcon = tlink_tcon(tlink); | ||
400 | |||
401 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ, | ||
376 | CREATE_NOT_DIR, &netfid, &oplock, NULL, | 402 | CREATE_NOT_DIR, &netfid, &oplock, NULL, |
377 | cifs_sb->local_nls, | 403 | cifs_sb->local_nls, |
378 | cifs_sb->mnt_cifs_flags & | 404 | cifs_sb->mnt_cifs_flags & |
@@ -380,9 +406,13 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
380 | if (rc == 0) { | 406 | if (rc == 0) { |
381 | int buf_type = CIFS_NO_BUFFER; | 407 | int buf_type = CIFS_NO_BUFFER; |
382 | /* Read header */ | 408 | /* Read header */ |
383 | rc = CIFSSMBRead(xid, pTcon, netfid, | 409 | io_parms.netfid = netfid; |
384 | 24 /* length */, 0 /* offset */, | 410 | io_parms.pid = current->tgid; |
385 | &bytes_read, &pbuf, &buf_type); | 411 | io_parms.tcon = tcon; |
412 | io_parms.offset = 0; | ||
413 | io_parms.length = 24; | ||
414 | rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, | ||
415 | &buf_type); | ||
386 | if ((rc == 0) && (bytes_read >= 8)) { | 416 | if ((rc == 0) && (bytes_read >= 8)) { |
387 | if (memcmp("IntxBLK", pbuf, 8) == 0) { | 417 | if (memcmp("IntxBLK", pbuf, 8) == 0) { |
388 | cFYI(1, "Block device"); | 418 | cFYI(1, "Block device"); |
@@ -422,8 +452,9 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
422 | fattr->cf_dtype = DT_REG; | 452 | fattr->cf_dtype = DT_REG; |
423 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | 453 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ |
424 | } | 454 | } |
425 | CIFSSMBClose(xid, pTcon, netfid); | 455 | CIFSSMBClose(xid, tcon, netfid); |
426 | } | 456 | } |
457 | cifs_put_tlink(tlink); | ||
427 | return rc; | 458 | return rc; |
428 | } | 459 | } |
429 | 460 | ||
@@ -441,11 +472,19 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, | |||
441 | ssize_t rc; | 472 | ssize_t rc; |
442 | char ea_value[4]; | 473 | char ea_value[4]; |
443 | __u32 mode; | 474 | __u32 mode; |
475 | struct tcon_link *tlink; | ||
476 | struct cifs_tcon *tcon; | ||
477 | |||
478 | tlink = cifs_sb_tlink(cifs_sb); | ||
479 | if (IS_ERR(tlink)) | ||
480 | return PTR_ERR(tlink); | ||
481 | tcon = tlink_tcon(tlink); | ||
444 | 482 | ||
445 | rc = CIFSSMBQAllEAs(xid, cifs_sb->tcon, path, "SETFILEBITS", | 483 | rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS", |
446 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, | 484 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, |
447 | cifs_sb->mnt_cifs_flags & | 485 | cifs_sb->mnt_cifs_flags & |
448 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 486 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
487 | cifs_put_tlink(tlink); | ||
449 | if (rc < 0) | 488 | if (rc < 0) |
450 | return (int)rc; | 489 | return (int)rc; |
451 | else if (rc > 3) { | 490 | else if (rc > 3) { |
@@ -468,6 +507,8 @@ static void | |||
468 | cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, | 507 | cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, |
469 | struct cifs_sb_info *cifs_sb, bool adjust_tz) | 508 | struct cifs_sb_info *cifs_sb, bool adjust_tz) |
470 | { | 509 | { |
510 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); | ||
511 | |||
471 | memset(fattr, 0, sizeof(*fattr)); | 512 | memset(fattr, 0, sizeof(*fattr)); |
472 | fattr->cf_cifsattrs = le32_to_cpu(info->Attributes); | 513 | fattr->cf_cifsattrs = le32_to_cpu(info->Attributes); |
473 | if (info->DeletePending) | 514 | if (info->DeletePending) |
@@ -482,12 +523,13 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, | |||
482 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); | 523 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); |
483 | 524 | ||
484 | if (adjust_tz) { | 525 | if (adjust_tz) { |
485 | fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; | 526 | fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj; |
486 | fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; | 527 | fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj; |
487 | } | 528 | } |
488 | 529 | ||
489 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); | 530 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); |
490 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); | 531 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); |
532 | fattr->cf_createtime = le64_to_cpu(info->CreationTime); | ||
491 | 533 | ||
492 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { | 534 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { |
493 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; | 535 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; |
@@ -515,8 +557,8 @@ int cifs_get_file_info(struct file *filp) | |||
515 | struct cifs_fattr fattr; | 557 | struct cifs_fattr fattr; |
516 | struct inode *inode = filp->f_path.dentry->d_inode; | 558 | struct inode *inode = filp->f_path.dentry->d_inode; |
517 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 559 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
518 | struct cifsTconInfo *tcon = cifs_sb->tcon; | ||
519 | struct cifsFileInfo *cfile = filp->private_data; | 560 | struct cifsFileInfo *cfile = filp->private_data; |
561 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | ||
520 | 562 | ||
521 | xid = GetXid(); | 563 | xid = GetXid(); |
522 | rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); | 564 | rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); |
@@ -553,27 +595,34 @@ int cifs_get_inode_info(struct inode **pinode, | |||
553 | struct super_block *sb, int xid, const __u16 *pfid) | 595 | struct super_block *sb, int xid, const __u16 *pfid) |
554 | { | 596 | { |
555 | int rc = 0, tmprc; | 597 | int rc = 0, tmprc; |
556 | struct cifsTconInfo *pTcon; | 598 | struct cifs_tcon *pTcon; |
599 | struct tcon_link *tlink; | ||
557 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 600 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
558 | char *buf = NULL; | 601 | char *buf = NULL; |
559 | bool adjustTZ = false; | 602 | bool adjustTZ = false; |
560 | struct cifs_fattr fattr; | 603 | struct cifs_fattr fattr; |
561 | 604 | ||
562 | pTcon = cifs_sb->tcon; | 605 | tlink = cifs_sb_tlink(cifs_sb); |
606 | if (IS_ERR(tlink)) | ||
607 | return PTR_ERR(tlink); | ||
608 | pTcon = tlink_tcon(tlink); | ||
609 | |||
563 | cFYI(1, "Getting info on %s", full_path); | 610 | cFYI(1, "Getting info on %s", full_path); |
564 | 611 | ||
565 | if ((pfindData == NULL) && (*pinode != NULL)) { | 612 | if ((pfindData == NULL) && (*pinode != NULL)) { |
566 | if (CIFS_I(*pinode)->clientCanCacheRead) { | 613 | if (CIFS_I(*pinode)->clientCanCacheRead) { |
567 | cFYI(1, "No need to revalidate cached inode sizes"); | 614 | cFYI(1, "No need to revalidate cached inode sizes"); |
568 | return rc; | 615 | goto cgii_exit; |
569 | } | 616 | } |
570 | } | 617 | } |
571 | 618 | ||
572 | /* if file info not passed in then get it from server */ | 619 | /* if file info not passed in then get it from server */ |
573 | if (pfindData == NULL) { | 620 | if (pfindData == NULL) { |
574 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | 621 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
575 | if (buf == NULL) | 622 | if (buf == NULL) { |
576 | return -ENOMEM; | 623 | rc = -ENOMEM; |
624 | goto cgii_exit; | ||
625 | } | ||
577 | pfindData = (FILE_ALL_INFO *)buf; | 626 | pfindData = (FILE_ALL_INFO *)buf; |
578 | 627 | ||
579 | /* could do find first instead but this returns more info */ | 628 | /* could do find first instead but this returns more info */ |
@@ -649,18 +698,30 @@ int cifs_get_inode_info(struct inode **pinode, | |||
649 | cFYI(1, "cifs_sfu_type failed: %d", tmprc); | 698 | cFYI(1, "cifs_sfu_type failed: %d", tmprc); |
650 | } | 699 | } |
651 | 700 | ||
652 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 701 | #ifdef CONFIG_CIFS_ACL |
653 | /* fill in 0777 bits from ACL */ | 702 | /* fill in 0777 bits from ACL */ |
654 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 703 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
655 | cFYI(1, "Getting mode bits from ACL"); | 704 | rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, |
656 | cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); | 705 | pfid); |
706 | if (rc) { | ||
707 | cFYI(1, "%s: Getting ACL failed with error: %d", | ||
708 | __func__, rc); | ||
709 | goto cgii_exit; | ||
710 | } | ||
657 | } | 711 | } |
658 | #endif | 712 | #endif /* CONFIG_CIFS_ACL */ |
659 | 713 | ||
660 | /* fill in remaining high mode bits e.g. SUID, VTX */ | 714 | /* fill in remaining high mode bits e.g. SUID, VTX */ |
661 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) | 715 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) |
662 | cifs_sfu_mode(&fattr, full_path, cifs_sb, xid); | 716 | cifs_sfu_mode(&fattr, full_path, cifs_sb, xid); |
663 | 717 | ||
718 | /* check for Minshall+French symlinks */ | ||
719 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { | ||
720 | tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid); | ||
721 | if (tmprc) | ||
722 | cFYI(1, "CIFSCheckMFSymlink: %d", tmprc); | ||
723 | } | ||
724 | |||
664 | if (!*pinode) { | 725 | if (!*pinode) { |
665 | *pinode = cifs_iget(sb, &fattr); | 726 | *pinode = cifs_iget(sb, &fattr); |
666 | if (!*pinode) | 727 | if (!*pinode) |
@@ -671,6 +732,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
671 | 732 | ||
672 | cgii_exit: | 733 | cgii_exit: |
673 | kfree(buf); | 734 | kfree(buf); |
735 | cifs_put_tlink(tlink); | ||
674 | return rc; | 736 | return rc; |
675 | } | 737 | } |
676 | 738 | ||
@@ -678,9 +740,10 @@ static const struct inode_operations cifs_ipc_inode_ops = { | |||
678 | .lookup = cifs_lookup, | 740 | .lookup = cifs_lookup, |
679 | }; | 741 | }; |
680 | 742 | ||
681 | char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) | 743 | char *cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, |
744 | struct cifs_tcon *tcon) | ||
682 | { | 745 | { |
683 | int pplen = cifs_sb->prepathlen; | 746 | int pplen = vol->prepath ? strlen(vol->prepath) : 0; |
684 | int dfsplen; | 747 | int dfsplen; |
685 | char *full_path = NULL; | 748 | char *full_path = NULL; |
686 | 749 | ||
@@ -692,8 +755,8 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) | |||
692 | return full_path; | 755 | return full_path; |
693 | } | 756 | } |
694 | 757 | ||
695 | if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS)) | 758 | if (tcon->Flags & SMB_SHARE_IS_IN_DFS) |
696 | dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1); | 759 | dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1); |
697 | else | 760 | else |
698 | dfsplen = 0; | 761 | dfsplen = 0; |
699 | 762 | ||
@@ -702,7 +765,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) | |||
702 | return full_path; | 765 | return full_path; |
703 | 766 | ||
704 | if (dfsplen) { | 767 | if (dfsplen) { |
705 | strncpy(full_path, cifs_sb->tcon->treeName, dfsplen); | 768 | strncpy(full_path, tcon->treeName, dfsplen); |
706 | /* switch slash direction in prepath depending on whether | 769 | /* switch slash direction in prepath depending on whether |
707 | * windows or posix style path names | 770 | * windows or posix style path names |
708 | */ | 771 | */ |
@@ -714,7 +777,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) | |||
714 | } | 777 | } |
715 | } | 778 | } |
716 | } | 779 | } |
717 | strncpy(full_path + dfsplen, cifs_sb->prepath, pplen); | 780 | strncpy(full_path + dfsplen, vol->prepath, pplen); |
718 | full_path[dfsplen + pplen] = 0; /* add trailing null */ | 781 | full_path[dfsplen + pplen] = 0; /* add trailing null */ |
719 | return full_path; | 782 | return full_path; |
720 | } | 783 | } |
@@ -728,6 +791,10 @@ cifs_find_inode(struct inode *inode, void *opaque) | |||
728 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) | 791 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) |
729 | return 0; | 792 | return 0; |
730 | 793 | ||
794 | /* use createtime like an i_generation field */ | ||
795 | if (CIFS_I(inode)->createtime != fattr->cf_createtime) | ||
796 | return 0; | ||
797 | |||
731 | /* don't match inode of different type */ | 798 | /* don't match inode of different type */ |
732 | if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT)) | 799 | if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT)) |
733 | return 0; | 800 | return 0; |
@@ -745,6 +812,7 @@ cifs_init_inode(struct inode *inode, void *opaque) | |||
745 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | 812 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; |
746 | 813 | ||
747 | CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; | 814 | CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; |
815 | CIFS_I(inode)->createtime = fattr->cf_createtime; | ||
748 | return 0; | 816 | return 0; |
749 | } | 817 | } |
750 | 818 | ||
@@ -758,14 +826,14 @@ inode_has_hashed_dentries(struct inode *inode) | |||
758 | { | 826 | { |
759 | struct dentry *dentry; | 827 | struct dentry *dentry; |
760 | 828 | ||
761 | spin_lock(&dcache_lock); | 829 | spin_lock(&inode->i_lock); |
762 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { | 830 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { |
763 | if (!d_unhashed(dentry) || IS_ROOT(dentry)) { | 831 | if (!d_unhashed(dentry) || IS_ROOT(dentry)) { |
764 | spin_unlock(&dcache_lock); | 832 | spin_unlock(&inode->i_lock); |
765 | return true; | 833 | return true; |
766 | } | 834 | } |
767 | } | 835 | } |
768 | spin_unlock(&dcache_lock); | 836 | spin_unlock(&inode->i_lock); |
769 | return false; | 837 | return false; |
770 | } | 838 | } |
771 | 839 | ||
@@ -815,35 +883,31 @@ retry_iget5_locked: | |||
815 | } | 883 | } |
816 | 884 | ||
817 | /* gets root inode */ | 885 | /* gets root inode */ |
818 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | 886 | struct inode *cifs_root_iget(struct super_block *sb) |
819 | { | 887 | { |
820 | int xid; | 888 | int xid; |
821 | struct cifs_sb_info *cifs_sb; | 889 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
822 | struct inode *inode = NULL; | 890 | struct inode *inode = NULL; |
823 | long rc; | 891 | long rc; |
824 | char *full_path; | 892 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); |
825 | |||
826 | cifs_sb = CIFS_SB(sb); | ||
827 | full_path = cifs_build_path_to_root(cifs_sb); | ||
828 | if (full_path == NULL) | ||
829 | return ERR_PTR(-ENOMEM); | ||
830 | 893 | ||
831 | xid = GetXid(); | 894 | xid = GetXid(); |
832 | if (cifs_sb->tcon->unix_ext) | 895 | if (tcon->unix_ext) |
833 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); | 896 | rc = cifs_get_inode_info_unix(&inode, "", sb, xid); |
834 | else | 897 | else |
835 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, | 898 | rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL); |
836 | xid, NULL); | ||
837 | 899 | ||
838 | if (!inode) | 900 | if (!inode) { |
839 | return ERR_PTR(rc); | 901 | inode = ERR_PTR(rc); |
902 | goto out; | ||
903 | } | ||
840 | 904 | ||
841 | #ifdef CONFIG_CIFS_FSCACHE | 905 | #ifdef CONFIG_CIFS_FSCACHE |
842 | /* populate tcon->resource_id */ | 906 | /* populate tcon->resource_id */ |
843 | cifs_sb->tcon->resource_id = CIFS_I(inode)->uniqueid; | 907 | tcon->resource_id = CIFS_I(inode)->uniqueid; |
844 | #endif | 908 | #endif |
845 | 909 | ||
846 | if (rc && cifs_sb->tcon->ipc) { | 910 | if (rc && tcon->ipc) { |
847 | cFYI(1, "ipc connection - fake read inode"); | 911 | cFYI(1, "ipc connection - fake read inode"); |
848 | inode->i_mode |= S_IFDIR; | 912 | inode->i_mode |= S_IFDIR; |
849 | inode->i_nlink = 2; | 913 | inode->i_nlink = 2; |
@@ -852,14 +916,11 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
852 | inode->i_uid = cifs_sb->mnt_uid; | 916 | inode->i_uid = cifs_sb->mnt_uid; |
853 | inode->i_gid = cifs_sb->mnt_gid; | 917 | inode->i_gid = cifs_sb->mnt_gid; |
854 | } else if (rc) { | 918 | } else if (rc) { |
855 | kfree(full_path); | ||
856 | _FreeXid(xid); | ||
857 | iget_failed(inode); | 919 | iget_failed(inode); |
858 | return ERR_PTR(rc); | 920 | inode = ERR_PTR(rc); |
859 | } | 921 | } |
860 | 922 | ||
861 | 923 | out: | |
862 | kfree(full_path); | ||
863 | /* can not call macro FreeXid here since in a void func | 924 | /* can not call macro FreeXid here since in a void func |
864 | * TODO: This is no longer true | 925 | * TODO: This is no longer true |
865 | */ | 926 | */ |
@@ -879,7 +940,8 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, | |||
879 | struct cifsFileInfo *open_file; | 940 | struct cifsFileInfo *open_file; |
880 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 941 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
881 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 942 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
882 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 943 | struct tcon_link *tlink = NULL; |
944 | struct cifs_tcon *pTcon; | ||
883 | FILE_BASIC_INFO info_buf; | 945 | FILE_BASIC_INFO info_buf; |
884 | 946 | ||
885 | if (attrs == NULL) | 947 | if (attrs == NULL) |
@@ -918,13 +980,22 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, | |||
918 | /* | 980 | /* |
919 | * If the file is already open for write, just use that fileid | 981 | * If the file is already open for write, just use that fileid |
920 | */ | 982 | */ |
921 | open_file = find_writable_file(cifsInode); | 983 | open_file = find_writable_file(cifsInode, true); |
922 | if (open_file) { | 984 | if (open_file) { |
923 | netfid = open_file->netfid; | 985 | netfid = open_file->netfid; |
924 | netpid = open_file->pid; | 986 | netpid = open_file->pid; |
987 | pTcon = tlink_tcon(open_file->tlink); | ||
925 | goto set_via_filehandle; | 988 | goto set_via_filehandle; |
926 | } | 989 | } |
927 | 990 | ||
991 | tlink = cifs_sb_tlink(cifs_sb); | ||
992 | if (IS_ERR(tlink)) { | ||
993 | rc = PTR_ERR(tlink); | ||
994 | tlink = NULL; | ||
995 | goto out; | ||
996 | } | ||
997 | pTcon = tlink_tcon(tlink); | ||
998 | |||
928 | /* | 999 | /* |
929 | * NT4 apparently returns success on this call, but it doesn't | 1000 | * NT4 apparently returns success on this call, but it doesn't |
930 | * really work. | 1001 | * really work. |
@@ -968,6 +1039,8 @@ set_via_filehandle: | |||
968 | else | 1039 | else |
969 | cifsFileInfo_put(open_file); | 1040 | cifsFileInfo_put(open_file); |
970 | out: | 1041 | out: |
1042 | if (tlink != NULL) | ||
1043 | cifs_put_tlink(tlink); | ||
971 | return rc; | 1044 | return rc; |
972 | } | 1045 | } |
973 | 1046 | ||
@@ -985,10 +1058,16 @@ cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid) | |||
985 | struct inode *inode = dentry->d_inode; | 1058 | struct inode *inode = dentry->d_inode; |
986 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1059 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
987 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1060 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
988 | struct cifsTconInfo *tcon = cifs_sb->tcon; | 1061 | struct tcon_link *tlink; |
1062 | struct cifs_tcon *tcon; | ||
989 | __u32 dosattr, origattr; | 1063 | __u32 dosattr, origattr; |
990 | FILE_BASIC_INFO *info_buf = NULL; | 1064 | FILE_BASIC_INFO *info_buf = NULL; |
991 | 1065 | ||
1066 | tlink = cifs_sb_tlink(cifs_sb); | ||
1067 | if (IS_ERR(tlink)) | ||
1068 | return PTR_ERR(tlink); | ||
1069 | tcon = tlink_tcon(tlink); | ||
1070 | |||
992 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | 1071 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, |
993 | DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, | 1072 | DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, |
994 | &netfid, &oplock, NULL, cifs_sb->local_nls, | 1073 | &netfid, &oplock, NULL, cifs_sb->local_nls, |
@@ -1057,6 +1136,7 @@ out_close: | |||
1057 | CIFSSMBClose(xid, tcon, netfid); | 1136 | CIFSSMBClose(xid, tcon, netfid); |
1058 | out: | 1137 | out: |
1059 | kfree(info_buf); | 1138 | kfree(info_buf); |
1139 | cifs_put_tlink(tlink); | ||
1060 | return rc; | 1140 | return rc; |
1061 | 1141 | ||
1062 | /* | 1142 | /* |
@@ -1096,12 +1176,18 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
1096 | struct cifsInodeInfo *cifs_inode; | 1176 | struct cifsInodeInfo *cifs_inode; |
1097 | struct super_block *sb = dir->i_sb; | 1177 | struct super_block *sb = dir->i_sb; |
1098 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 1178 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
1099 | struct cifsTconInfo *tcon = cifs_sb->tcon; | 1179 | struct tcon_link *tlink; |
1180 | struct cifs_tcon *tcon; | ||
1100 | struct iattr *attrs = NULL; | 1181 | struct iattr *attrs = NULL; |
1101 | __u32 dosattr = 0, origattr = 0; | 1182 | __u32 dosattr = 0, origattr = 0; |
1102 | 1183 | ||
1103 | cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry); | 1184 | cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry); |
1104 | 1185 | ||
1186 | tlink = cifs_sb_tlink(cifs_sb); | ||
1187 | if (IS_ERR(tlink)) | ||
1188 | return PTR_ERR(tlink); | ||
1189 | tcon = tlink_tcon(tlink); | ||
1190 | |||
1105 | xid = GetXid(); | 1191 | xid = GetXid(); |
1106 | 1192 | ||
1107 | /* Unlink can be called from rename so we can not take the | 1193 | /* Unlink can be called from rename so we can not take the |
@@ -1109,8 +1195,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
1109 | full_path = build_path_from_dentry(dentry); | 1195 | full_path = build_path_from_dentry(dentry); |
1110 | if (full_path == NULL) { | 1196 | if (full_path == NULL) { |
1111 | rc = -ENOMEM; | 1197 | rc = -ENOMEM; |
1112 | FreeXid(xid); | 1198 | goto unlink_out; |
1113 | return rc; | ||
1114 | } | 1199 | } |
1115 | 1200 | ||
1116 | if ((tcon->ses->capabilities & CAP_UNIX) && | 1201 | if ((tcon->ses->capabilities & CAP_UNIX) && |
@@ -1176,10 +1261,11 @@ out_reval: | |||
1176 | dir->i_ctime = dir->i_mtime = current_fs_time(sb); | 1261 | dir->i_ctime = dir->i_mtime = current_fs_time(sb); |
1177 | cifs_inode = CIFS_I(dir); | 1262 | cifs_inode = CIFS_I(dir); |
1178 | CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ | 1263 | CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ |
1179 | 1264 | unlink_out: | |
1180 | kfree(full_path); | 1265 | kfree(full_path); |
1181 | kfree(attrs); | 1266 | kfree(attrs); |
1182 | FreeXid(xid); | 1267 | FreeXid(xid); |
1268 | cifs_put_tlink(tlink); | ||
1183 | return rc; | 1269 | return rc; |
1184 | } | 1270 | } |
1185 | 1271 | ||
@@ -1188,23 +1274,26 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1188 | int rc = 0, tmprc; | 1274 | int rc = 0, tmprc; |
1189 | int xid; | 1275 | int xid; |
1190 | struct cifs_sb_info *cifs_sb; | 1276 | struct cifs_sb_info *cifs_sb; |
1191 | struct cifsTconInfo *pTcon; | 1277 | struct tcon_link *tlink; |
1278 | struct cifs_tcon *pTcon; | ||
1192 | char *full_path = NULL; | 1279 | char *full_path = NULL; |
1193 | struct inode *newinode = NULL; | 1280 | struct inode *newinode = NULL; |
1194 | struct cifs_fattr fattr; | 1281 | struct cifs_fattr fattr; |
1195 | 1282 | ||
1196 | cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode); | 1283 | cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode); |
1197 | 1284 | ||
1198 | xid = GetXid(); | ||
1199 | |||
1200 | cifs_sb = CIFS_SB(inode->i_sb); | 1285 | cifs_sb = CIFS_SB(inode->i_sb); |
1201 | pTcon = cifs_sb->tcon; | 1286 | tlink = cifs_sb_tlink(cifs_sb); |
1287 | if (IS_ERR(tlink)) | ||
1288 | return PTR_ERR(tlink); | ||
1289 | pTcon = tlink_tcon(tlink); | ||
1290 | |||
1291 | xid = GetXid(); | ||
1202 | 1292 | ||
1203 | full_path = build_path_from_dentry(direntry); | 1293 | full_path = build_path_from_dentry(direntry); |
1204 | if (full_path == NULL) { | 1294 | if (full_path == NULL) { |
1205 | rc = -ENOMEM; | 1295 | rc = -ENOMEM; |
1206 | FreeXid(xid); | 1296 | goto mkdir_out; |
1207 | return rc; | ||
1208 | } | 1297 | } |
1209 | 1298 | ||
1210 | if ((pTcon->ses->capabilities & CAP_UNIX) && | 1299 | if ((pTcon->ses->capabilities & CAP_UNIX) && |
@@ -1239,10 +1328,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1239 | /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need | 1328 | /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need |
1240 | to set uid/gid */ | 1329 | to set uid/gid */ |
1241 | inc_nlink(inode); | 1330 | inc_nlink(inode); |
1242 | if (pTcon->nocase) | ||
1243 | direntry->d_op = &cifs_ci_dentry_ops; | ||
1244 | else | ||
1245 | direntry->d_op = &cifs_dentry_ops; | ||
1246 | 1331 | ||
1247 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); | 1332 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); |
1248 | cifs_fill_uniqueid(inode->i_sb, &fattr); | 1333 | cifs_fill_uniqueid(inode->i_sb, &fattr); |
@@ -1283,10 +1368,6 @@ mkdir_get_info: | |||
1283 | rc = cifs_get_inode_info(&newinode, full_path, NULL, | 1368 | rc = cifs_get_inode_info(&newinode, full_path, NULL, |
1284 | inode->i_sb, xid, NULL); | 1369 | inode->i_sb, xid, NULL); |
1285 | 1370 | ||
1286 | if (pTcon->nocase) | ||
1287 | direntry->d_op = &cifs_ci_dentry_ops; | ||
1288 | else | ||
1289 | direntry->d_op = &cifs_dentry_ops; | ||
1290 | d_instantiate(direntry, newinode); | 1371 | d_instantiate(direntry, newinode); |
1291 | /* setting nlink not necessary except in cases where we | 1372 | /* setting nlink not necessary except in cases where we |
1292 | * failed to get it from the server or was set bogus */ | 1373 | * failed to get it from the server or was set bogus */ |
@@ -1362,6 +1443,7 @@ mkdir_get_info: | |||
1362 | mkdir_out: | 1443 | mkdir_out: |
1363 | kfree(full_path); | 1444 | kfree(full_path); |
1364 | FreeXid(xid); | 1445 | FreeXid(xid); |
1446 | cifs_put_tlink(tlink); | ||
1365 | return rc; | 1447 | return rc; |
1366 | } | 1448 | } |
1367 | 1449 | ||
@@ -1370,7 +1452,8 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1370 | int rc = 0; | 1452 | int rc = 0; |
1371 | int xid; | 1453 | int xid; |
1372 | struct cifs_sb_info *cifs_sb; | 1454 | struct cifs_sb_info *cifs_sb; |
1373 | struct cifsTconInfo *pTcon; | 1455 | struct tcon_link *tlink; |
1456 | struct cifs_tcon *pTcon; | ||
1374 | char *full_path = NULL; | 1457 | char *full_path = NULL; |
1375 | struct cifsInodeInfo *cifsInode; | 1458 | struct cifsInodeInfo *cifsInode; |
1376 | 1459 | ||
@@ -1378,18 +1461,23 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1378 | 1461 | ||
1379 | xid = GetXid(); | 1462 | xid = GetXid(); |
1380 | 1463 | ||
1381 | cifs_sb = CIFS_SB(inode->i_sb); | ||
1382 | pTcon = cifs_sb->tcon; | ||
1383 | |||
1384 | full_path = build_path_from_dentry(direntry); | 1464 | full_path = build_path_from_dentry(direntry); |
1385 | if (full_path == NULL) { | 1465 | if (full_path == NULL) { |
1386 | rc = -ENOMEM; | 1466 | rc = -ENOMEM; |
1387 | FreeXid(xid); | 1467 | goto rmdir_exit; |
1388 | return rc; | ||
1389 | } | 1468 | } |
1390 | 1469 | ||
1470 | cifs_sb = CIFS_SB(inode->i_sb); | ||
1471 | tlink = cifs_sb_tlink(cifs_sb); | ||
1472 | if (IS_ERR(tlink)) { | ||
1473 | rc = PTR_ERR(tlink); | ||
1474 | goto rmdir_exit; | ||
1475 | } | ||
1476 | pTcon = tlink_tcon(tlink); | ||
1477 | |||
1391 | rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, | 1478 | rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, |
1392 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1479 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
1480 | cifs_put_tlink(tlink); | ||
1393 | 1481 | ||
1394 | if (!rc) { | 1482 | if (!rc) { |
1395 | drop_nlink(inode); | 1483 | drop_nlink(inode); |
@@ -1410,6 +1498,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1410 | direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = | 1498 | direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = |
1411 | current_fs_time(inode->i_sb); | 1499 | current_fs_time(inode->i_sb); |
1412 | 1500 | ||
1501 | rmdir_exit: | ||
1413 | kfree(full_path); | 1502 | kfree(full_path); |
1414 | FreeXid(xid); | 1503 | FreeXid(xid); |
1415 | return rc; | 1504 | return rc; |
@@ -1420,10 +1509,16 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, | |||
1420 | struct dentry *to_dentry, const char *toPath) | 1509 | struct dentry *to_dentry, const char *toPath) |
1421 | { | 1510 | { |
1422 | struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb); | 1511 | struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb); |
1423 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 1512 | struct tcon_link *tlink; |
1513 | struct cifs_tcon *pTcon; | ||
1424 | __u16 srcfid; | 1514 | __u16 srcfid; |
1425 | int oplock, rc; | 1515 | int oplock, rc; |
1426 | 1516 | ||
1517 | tlink = cifs_sb_tlink(cifs_sb); | ||
1518 | if (IS_ERR(tlink)) | ||
1519 | return PTR_ERR(tlink); | ||
1520 | pTcon = tlink_tcon(tlink); | ||
1521 | |||
1427 | /* try path-based rename first */ | 1522 | /* try path-based rename first */ |
1428 | rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls, | 1523 | rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls, |
1429 | cifs_sb->mnt_cifs_flags & | 1524 | cifs_sb->mnt_cifs_flags & |
@@ -1435,11 +1530,11 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, | |||
1435 | * rename by filehandle to various Windows servers. | 1530 | * rename by filehandle to various Windows servers. |
1436 | */ | 1531 | */ |
1437 | if (rc == 0 || rc != -ETXTBSY) | 1532 | if (rc == 0 || rc != -ETXTBSY) |
1438 | return rc; | 1533 | goto do_rename_exit; |
1439 | 1534 | ||
1440 | /* open-file renames don't work across directories */ | 1535 | /* open-file renames don't work across directories */ |
1441 | if (to_dentry->d_parent != from_dentry->d_parent) | 1536 | if (to_dentry->d_parent != from_dentry->d_parent) |
1442 | return rc; | 1537 | goto do_rename_exit; |
1443 | 1538 | ||
1444 | /* open the file to be renamed -- we need DELETE perms */ | 1539 | /* open the file to be renamed -- we need DELETE perms */ |
1445 | rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, | 1540 | rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, |
@@ -1455,7 +1550,8 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, | |||
1455 | 1550 | ||
1456 | CIFSSMBClose(xid, pTcon, srcfid); | 1551 | CIFSSMBClose(xid, pTcon, srcfid); |
1457 | } | 1552 | } |
1458 | 1553 | do_rename_exit: | |
1554 | cifs_put_tlink(tlink); | ||
1459 | return rc; | 1555 | return rc; |
1460 | } | 1556 | } |
1461 | 1557 | ||
@@ -1465,13 +1561,17 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
1465 | char *fromName = NULL; | 1561 | char *fromName = NULL; |
1466 | char *toName = NULL; | 1562 | char *toName = NULL; |
1467 | struct cifs_sb_info *cifs_sb; | 1563 | struct cifs_sb_info *cifs_sb; |
1468 | struct cifsTconInfo *tcon; | 1564 | struct tcon_link *tlink; |
1565 | struct cifs_tcon *tcon; | ||
1469 | FILE_UNIX_BASIC_INFO *info_buf_source = NULL; | 1566 | FILE_UNIX_BASIC_INFO *info_buf_source = NULL; |
1470 | FILE_UNIX_BASIC_INFO *info_buf_target; | 1567 | FILE_UNIX_BASIC_INFO *info_buf_target; |
1471 | int xid, rc, tmprc; | 1568 | int xid, rc, tmprc; |
1472 | 1569 | ||
1473 | cifs_sb = CIFS_SB(source_dir->i_sb); | 1570 | cifs_sb = CIFS_SB(source_dir->i_sb); |
1474 | tcon = cifs_sb->tcon; | 1571 | tlink = cifs_sb_tlink(cifs_sb); |
1572 | if (IS_ERR(tlink)) | ||
1573 | return PTR_ERR(tlink); | ||
1574 | tcon = tlink_tcon(tlink); | ||
1475 | 1575 | ||
1476 | xid = GetXid(); | 1576 | xid = GetXid(); |
1477 | 1577 | ||
@@ -1547,6 +1647,7 @@ cifs_rename_exit: | |||
1547 | kfree(fromName); | 1647 | kfree(fromName); |
1548 | kfree(toName); | 1648 | kfree(toName); |
1549 | FreeXid(xid); | 1649 | FreeXid(xid); |
1650 | cifs_put_tlink(tlink); | ||
1550 | return rc; | 1651 | return rc; |
1551 | } | 1652 | } |
1552 | 1653 | ||
@@ -1554,6 +1655,7 @@ static bool | |||
1554 | cifs_inode_needs_reval(struct inode *inode) | 1655 | cifs_inode_needs_reval(struct inode *inode) |
1555 | { | 1656 | { |
1556 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | 1657 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
1658 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1557 | 1659 | ||
1558 | if (cifs_i->clientCanCacheRead) | 1660 | if (cifs_i->clientCanCacheRead) |
1559 | return false; | 1661 | return false; |
@@ -1564,111 +1666,170 @@ cifs_inode_needs_reval(struct inode *inode) | |||
1564 | if (cifs_i->time == 0) | 1666 | if (cifs_i->time == 0) |
1565 | return true; | 1667 | return true; |
1566 | 1668 | ||
1567 | /* FIXME: the actimeo should be tunable */ | 1669 | if (!time_in_range(jiffies, cifs_i->time, |
1568 | if (time_after_eq(jiffies, cifs_i->time + HZ)) | 1670 | cifs_i->time + cifs_sb->actimeo)) |
1569 | return true; | 1671 | return true; |
1570 | 1672 | ||
1571 | /* hardlinked files w/ noserverino get "special" treatment */ | 1673 | /* hardlinked files w/ noserverino get "special" treatment */ |
1572 | if (!(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) && | 1674 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) && |
1573 | S_ISREG(inode->i_mode) && inode->i_nlink != 1) | 1675 | S_ISREG(inode->i_mode) && inode->i_nlink != 1) |
1574 | return true; | 1676 | return true; |
1575 | 1677 | ||
1576 | return false; | 1678 | return false; |
1577 | } | 1679 | } |
1578 | 1680 | ||
1579 | /* check invalid_mapping flag and zap the cache if it's set */ | 1681 | /* |
1580 | static void | 1682 | * Zap the cache. Called when invalid_mapping flag is set. |
1683 | */ | ||
1684 | int | ||
1581 | cifs_invalidate_mapping(struct inode *inode) | 1685 | cifs_invalidate_mapping(struct inode *inode) |
1582 | { | 1686 | { |
1583 | int rc; | 1687 | int rc = 0; |
1584 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | 1688 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
1585 | 1689 | ||
1586 | cifs_i->invalid_mapping = false; | 1690 | cifs_i->invalid_mapping = false; |
1587 | 1691 | ||
1588 | /* write back any cached data */ | ||
1589 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { | 1692 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { |
1590 | rc = filemap_write_and_wait(inode->i_mapping); | 1693 | rc = invalidate_inode_pages2(inode->i_mapping); |
1591 | if (rc) | 1694 | if (rc) { |
1592 | cifs_i->write_behind_rc = rc; | 1695 | cERROR(1, "%s: could not invalidate inode %p", __func__, |
1696 | inode); | ||
1697 | cifs_i->invalid_mapping = true; | ||
1698 | } | ||
1593 | } | 1699 | } |
1594 | invalidate_remote_inode(inode); | 1700 | |
1595 | cifs_fscache_reset_inode_cookie(inode); | 1701 | cifs_fscache_reset_inode_cookie(inode); |
1702 | return rc; | ||
1596 | } | 1703 | } |
1597 | 1704 | ||
1598 | int cifs_revalidate_file(struct file *filp) | 1705 | int cifs_revalidate_file_attr(struct file *filp) |
1599 | { | 1706 | { |
1600 | int rc = 0; | 1707 | int rc = 0; |
1601 | struct inode *inode = filp->f_path.dentry->d_inode; | 1708 | struct inode *inode = filp->f_path.dentry->d_inode; |
1709 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; | ||
1602 | 1710 | ||
1603 | if (!cifs_inode_needs_reval(inode)) | 1711 | if (!cifs_inode_needs_reval(inode)) |
1604 | goto check_inval; | 1712 | return rc; |
1605 | 1713 | ||
1606 | if (CIFS_SB(inode->i_sb)->tcon->unix_ext) | 1714 | if (tlink_tcon(cfile->tlink)->unix_ext) |
1607 | rc = cifs_get_file_info_unix(filp); | 1715 | rc = cifs_get_file_info_unix(filp); |
1608 | else | 1716 | else |
1609 | rc = cifs_get_file_info(filp); | 1717 | rc = cifs_get_file_info(filp); |
1610 | 1718 | ||
1611 | check_inval: | ||
1612 | if (CIFS_I(inode)->invalid_mapping) | ||
1613 | cifs_invalidate_mapping(inode); | ||
1614 | |||
1615 | return rc; | 1719 | return rc; |
1616 | } | 1720 | } |
1617 | 1721 | ||
1618 | /* revalidate a dentry's inode attributes */ | 1722 | int cifs_revalidate_dentry_attr(struct dentry *dentry) |
1619 | int cifs_revalidate_dentry(struct dentry *dentry) | ||
1620 | { | 1723 | { |
1621 | int xid; | 1724 | int xid; |
1622 | int rc = 0; | 1725 | int rc = 0; |
1623 | char *full_path = NULL; | ||
1624 | struct inode *inode = dentry->d_inode; | 1726 | struct inode *inode = dentry->d_inode; |
1625 | struct super_block *sb = dentry->d_sb; | 1727 | struct super_block *sb = dentry->d_sb; |
1728 | char *full_path = NULL; | ||
1626 | 1729 | ||
1627 | if (inode == NULL) | 1730 | if (inode == NULL) |
1628 | return -ENOENT; | 1731 | return -ENOENT; |
1629 | 1732 | ||
1630 | xid = GetXid(); | ||
1631 | |||
1632 | if (!cifs_inode_needs_reval(inode)) | 1733 | if (!cifs_inode_needs_reval(inode)) |
1633 | goto check_inval; | 1734 | return rc; |
1735 | |||
1736 | xid = GetXid(); | ||
1634 | 1737 | ||
1635 | /* can not safely grab the rename sem here if rename calls revalidate | 1738 | /* can not safely grab the rename sem here if rename calls revalidate |
1636 | since that would deadlock */ | 1739 | since that would deadlock */ |
1637 | full_path = build_path_from_dentry(dentry); | 1740 | full_path = build_path_from_dentry(dentry); |
1638 | if (full_path == NULL) { | 1741 | if (full_path == NULL) { |
1639 | rc = -ENOMEM; | 1742 | rc = -ENOMEM; |
1640 | goto check_inval; | 1743 | goto out; |
1641 | } | 1744 | } |
1642 | 1745 | ||
1643 | cFYI(1, "Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " | 1746 | cFYI(1, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time " |
1644 | "jiffies %ld", full_path, inode, inode->i_count.counter, | 1747 | "%ld jiffies %ld", full_path, inode, inode->i_count.counter, |
1645 | dentry, dentry->d_time, jiffies); | 1748 | dentry, dentry->d_time, jiffies); |
1646 | 1749 | ||
1647 | if (CIFS_SB(sb)->tcon->unix_ext) | 1750 | if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) |
1648 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); | 1751 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); |
1649 | else | 1752 | else |
1650 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, | 1753 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
1651 | xid, NULL); | 1754 | xid, NULL); |
1652 | 1755 | ||
1653 | check_inval: | 1756 | out: |
1654 | if (CIFS_I(inode)->invalid_mapping) | ||
1655 | cifs_invalidate_mapping(inode); | ||
1656 | |||
1657 | kfree(full_path); | 1757 | kfree(full_path); |
1658 | FreeXid(xid); | 1758 | FreeXid(xid); |
1659 | return rc; | 1759 | return rc; |
1660 | } | 1760 | } |
1661 | 1761 | ||
1762 | int cifs_revalidate_file(struct file *filp) | ||
1763 | { | ||
1764 | int rc; | ||
1765 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
1766 | |||
1767 | rc = cifs_revalidate_file_attr(filp); | ||
1768 | if (rc) | ||
1769 | return rc; | ||
1770 | |||
1771 | if (CIFS_I(inode)->invalid_mapping) | ||
1772 | rc = cifs_invalidate_mapping(inode); | ||
1773 | return rc; | ||
1774 | } | ||
1775 | |||
1776 | /* revalidate a dentry's inode attributes */ | ||
1777 | int cifs_revalidate_dentry(struct dentry *dentry) | ||
1778 | { | ||
1779 | int rc; | ||
1780 | struct inode *inode = dentry->d_inode; | ||
1781 | |||
1782 | rc = cifs_revalidate_dentry_attr(dentry); | ||
1783 | if (rc) | ||
1784 | return rc; | ||
1785 | |||
1786 | if (CIFS_I(inode)->invalid_mapping) | ||
1787 | rc = cifs_invalidate_mapping(inode); | ||
1788 | return rc; | ||
1789 | } | ||
1790 | |||
1662 | int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | 1791 | int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, |
1663 | struct kstat *stat) | 1792 | struct kstat *stat) |
1664 | { | 1793 | { |
1665 | int err = cifs_revalidate_dentry(dentry); | 1794 | struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); |
1666 | if (!err) { | 1795 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); |
1667 | generic_fillattr(dentry->d_inode, stat); | 1796 | struct inode *inode = dentry->d_inode; |
1668 | stat->blksize = CIFS_MAX_MSGSIZE; | 1797 | int rc; |
1669 | stat->ino = CIFS_I(dentry->d_inode)->uniqueid; | 1798 | |
1799 | /* | ||
1800 | * We need to be sure that all dirty pages are written and the server | ||
1801 | * has actual ctime, mtime and file length. | ||
1802 | */ | ||
1803 | if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping && | ||
1804 | inode->i_mapping->nrpages != 0) { | ||
1805 | rc = filemap_fdatawait(inode->i_mapping); | ||
1806 | if (rc) { | ||
1807 | mapping_set_error(inode->i_mapping, rc); | ||
1808 | return rc; | ||
1809 | } | ||
1810 | } | ||
1811 | |||
1812 | rc = cifs_revalidate_dentry_attr(dentry); | ||
1813 | if (rc) | ||
1814 | return rc; | ||
1815 | |||
1816 | generic_fillattr(inode, stat); | ||
1817 | stat->blksize = CIFS_MAX_MSGSIZE; | ||
1818 | stat->ino = CIFS_I(inode)->uniqueid; | ||
1819 | |||
1820 | /* | ||
1821 | * If on a multiuser mount without unix extensions, and the admin hasn't | ||
1822 | * overridden them, set the ownership to the fsuid/fsgid of the current | ||
1823 | * process. | ||
1824 | */ | ||
1825 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) && | ||
1826 | !tcon->unix_ext) { | ||
1827 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) | ||
1828 | stat->uid = current_fsuid(); | ||
1829 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) | ||
1830 | stat->gid = current_fsgid(); | ||
1670 | } | 1831 | } |
1671 | return err; | 1832 | return rc; |
1672 | } | 1833 | } |
1673 | 1834 | ||
1674 | static int cifs_truncate_page(struct address_space *mapping, loff_t from) | 1835 | static int cifs_truncate_page(struct address_space *mapping, loff_t from) |
@@ -1708,7 +1869,9 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1708 | struct cifsFileInfo *open_file; | 1869 | struct cifsFileInfo *open_file; |
1709 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1870 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
1710 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1871 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1711 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 1872 | struct tcon_link *tlink = NULL; |
1873 | struct cifs_tcon *pTcon = NULL; | ||
1874 | struct cifs_io_parms io_parms; | ||
1712 | 1875 | ||
1713 | /* | 1876 | /* |
1714 | * To avoid spurious oplock breaks from server, in the case of | 1877 | * To avoid spurious oplock breaks from server, in the case of |
@@ -1719,24 +1882,38 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1719 | * writebehind data than the SMB timeout for the SetPathInfo | 1882 | * writebehind data than the SMB timeout for the SetPathInfo |
1720 | * request would allow | 1883 | * request would allow |
1721 | */ | 1884 | */ |
1722 | open_file = find_writable_file(cifsInode); | 1885 | open_file = find_writable_file(cifsInode, true); |
1723 | if (open_file) { | 1886 | if (open_file) { |
1724 | __u16 nfid = open_file->netfid; | 1887 | __u16 nfid = open_file->netfid; |
1725 | __u32 npid = open_file->pid; | 1888 | __u32 npid = open_file->pid; |
1889 | pTcon = tlink_tcon(open_file->tlink); | ||
1726 | rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid, | 1890 | rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid, |
1727 | npid, false); | 1891 | npid, false); |
1728 | cifsFileInfo_put(open_file); | 1892 | cifsFileInfo_put(open_file); |
1729 | cFYI(1, "SetFSize for attrs rc = %d", rc); | 1893 | cFYI(1, "SetFSize for attrs rc = %d", rc); |
1730 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 1894 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
1731 | unsigned int bytes_written; | 1895 | unsigned int bytes_written; |
1732 | rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size, | 1896 | |
1733 | &bytes_written, NULL, NULL, 1); | 1897 | io_parms.netfid = nfid; |
1898 | io_parms.pid = npid; | ||
1899 | io_parms.tcon = pTcon; | ||
1900 | io_parms.offset = 0; | ||
1901 | io_parms.length = attrs->ia_size; | ||
1902 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, | ||
1903 | NULL, NULL, 1); | ||
1734 | cFYI(1, "Wrt seteof rc %d", rc); | 1904 | cFYI(1, "Wrt seteof rc %d", rc); |
1735 | } | 1905 | } |
1736 | } else | 1906 | } else |
1737 | rc = -EINVAL; | 1907 | rc = -EINVAL; |
1738 | 1908 | ||
1739 | if (rc != 0) { | 1909 | if (rc != 0) { |
1910 | if (pTcon == NULL) { | ||
1911 | tlink = cifs_sb_tlink(cifs_sb); | ||
1912 | if (IS_ERR(tlink)) | ||
1913 | return PTR_ERR(tlink); | ||
1914 | pTcon = tlink_tcon(tlink); | ||
1915 | } | ||
1916 | |||
1740 | /* Set file size by pathname rather than by handle | 1917 | /* Set file size by pathname rather than by handle |
1741 | either because no valid, writeable file handle for | 1918 | either because no valid, writeable file handle for |
1742 | it was found or because there was an error setting | 1919 | it was found or because there was an error setting |
@@ -1758,14 +1935,21 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1758 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1935 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1759 | if (rc == 0) { | 1936 | if (rc == 0) { |
1760 | unsigned int bytes_written; | 1937 | unsigned int bytes_written; |
1761 | rc = CIFSSMBWrite(xid, pTcon, netfid, 0, | 1938 | |
1762 | attrs->ia_size, | 1939 | io_parms.netfid = netfid; |
1763 | &bytes_written, NULL, | 1940 | io_parms.pid = current->tgid; |
1764 | NULL, 1); | 1941 | io_parms.tcon = pTcon; |
1942 | io_parms.offset = 0; | ||
1943 | io_parms.length = attrs->ia_size; | ||
1944 | rc = CIFSSMBWrite(xid, &io_parms, | ||
1945 | &bytes_written, | ||
1946 | NULL, NULL, 1); | ||
1765 | cFYI(1, "wrt seteof rc %d", rc); | 1947 | cFYI(1, "wrt seteof rc %d", rc); |
1766 | CIFSSMBClose(xid, pTcon, netfid); | 1948 | CIFSSMBClose(xid, pTcon, netfid); |
1767 | } | 1949 | } |
1768 | } | 1950 | } |
1951 | if (tlink) | ||
1952 | cifs_put_tlink(tlink); | ||
1769 | } | 1953 | } |
1770 | 1954 | ||
1771 | if (rc == 0) { | 1955 | if (rc == 0) { |
@@ -1786,7 +1970,8 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1786 | struct inode *inode = direntry->d_inode; | 1970 | struct inode *inode = direntry->d_inode; |
1787 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1971 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
1788 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1972 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1789 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 1973 | struct tcon_link *tlink; |
1974 | struct cifs_tcon *pTcon; | ||
1790 | struct cifs_unix_set_info_args *args = NULL; | 1975 | struct cifs_unix_set_info_args *args = NULL; |
1791 | struct cifsFileInfo *open_file; | 1976 | struct cifsFileInfo *open_file; |
1792 | 1977 | ||
@@ -1820,10 +2005,8 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1820 | * the flush returns error? | 2005 | * the flush returns error? |
1821 | */ | 2006 | */ |
1822 | rc = filemap_write_and_wait(inode->i_mapping); | 2007 | rc = filemap_write_and_wait(inode->i_mapping); |
1823 | if (rc != 0) { | 2008 | mapping_set_error(inode->i_mapping, rc); |
1824 | cifsInode->write_behind_rc = rc; | 2009 | rc = 0; |
1825 | rc = 0; | ||
1826 | } | ||
1827 | 2010 | ||
1828 | if (attrs->ia_valid & ATTR_SIZE) { | 2011 | if (attrs->ia_valid & ATTR_SIZE) { |
1829 | rc = cifs_set_file_size(inode, attrs, xid, full_path); | 2012 | rc = cifs_set_file_size(inode, attrs, xid, full_path); |
@@ -1873,17 +2056,25 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1873 | args->ctime = NO_CHANGE_64; | 2056 | args->ctime = NO_CHANGE_64; |
1874 | 2057 | ||
1875 | args->device = 0; | 2058 | args->device = 0; |
1876 | open_file = find_writable_file(cifsInode); | 2059 | open_file = find_writable_file(cifsInode, true); |
1877 | if (open_file) { | 2060 | if (open_file) { |
1878 | u16 nfid = open_file->netfid; | 2061 | u16 nfid = open_file->netfid; |
1879 | u32 npid = open_file->pid; | 2062 | u32 npid = open_file->pid; |
2063 | pTcon = tlink_tcon(open_file->tlink); | ||
1880 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); | 2064 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); |
1881 | cifsFileInfo_put(open_file); | 2065 | cifsFileInfo_put(open_file); |
1882 | } else { | 2066 | } else { |
2067 | tlink = cifs_sb_tlink(cifs_sb); | ||
2068 | if (IS_ERR(tlink)) { | ||
2069 | rc = PTR_ERR(tlink); | ||
2070 | goto out; | ||
2071 | } | ||
2072 | pTcon = tlink_tcon(tlink); | ||
1883 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, | 2073 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, |
1884 | cifs_sb->local_nls, | 2074 | cifs_sb->local_nls, |
1885 | cifs_sb->mnt_cifs_flags & | 2075 | cifs_sb->mnt_cifs_flags & |
1886 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 2076 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
2077 | cifs_put_tlink(tlink); | ||
1887 | } | 2078 | } |
1888 | 2079 | ||
1889 | if (rc) | 2080 | if (rc) |
@@ -1956,10 +2147,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
1956 | * the flush returns error? | 2147 | * the flush returns error? |
1957 | */ | 2148 | */ |
1958 | rc = filemap_write_and_wait(inode->i_mapping); | 2149 | rc = filemap_write_and_wait(inode->i_mapping); |
1959 | if (rc != 0) { | 2150 | mapping_set_error(inode->i_mapping, rc); |
1960 | cifsInode->write_behind_rc = rc; | 2151 | rc = 0; |
1961 | rc = 0; | ||
1962 | } | ||
1963 | 2152 | ||
1964 | if (attrs->ia_valid & ATTR_SIZE) { | 2153 | if (attrs->ia_valid & ATTR_SIZE) { |
1965 | rc = cifs_set_file_size(inode, attrs, xid, full_path); | 2154 | rc = cifs_set_file_size(inode, attrs, xid, full_path); |
@@ -1988,11 +2177,16 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
1988 | 2177 | ||
1989 | if (attrs->ia_valid & ATTR_MODE) { | 2178 | if (attrs->ia_valid & ATTR_MODE) { |
1990 | rc = 0; | 2179 | rc = 0; |
1991 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 2180 | #ifdef CONFIG_CIFS_ACL |
1992 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) | 2181 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
1993 | rc = mode_to_acl(inode, full_path, mode); | 2182 | rc = mode_to_cifs_acl(inode, full_path, mode); |
1994 | else | 2183 | if (rc) { |
1995 | #endif | 2184 | cFYI(1, "%s: Setting ACL failed with error: %d", |
2185 | __func__, rc); | ||
2186 | goto cifs_setattr_exit; | ||
2187 | } | ||
2188 | } else | ||
2189 | #endif /* CONFIG_CIFS_ACL */ | ||
1996 | if (((mode & S_IWUGO) == 0) && | 2190 | if (((mode & S_IWUGO) == 0) && |
1997 | (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { | 2191 | (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { |
1998 | 2192 | ||
@@ -2051,7 +2245,6 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
2051 | 2245 | ||
2052 | setattr_copy(inode, attrs); | 2246 | setattr_copy(inode, attrs); |
2053 | mark_inode_dirty(inode); | 2247 | mark_inode_dirty(inode); |
2054 | return 0; | ||
2055 | 2248 | ||
2056 | cifs_setattr_exit: | 2249 | cifs_setattr_exit: |
2057 | kfree(full_path); | 2250 | kfree(full_path); |
@@ -2064,7 +2257,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
2064 | { | 2257 | { |
2065 | struct inode *inode = direntry->d_inode; | 2258 | struct inode *inode = direntry->d_inode; |
2066 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 2259 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
2067 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 2260 | struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb); |
2068 | 2261 | ||
2069 | if (pTcon->unix_ext) | 2262 | if (pTcon->unix_ext) |
2070 | return cifs_setattr_unix(direntry, attrs); | 2263 | return cifs_setattr_unix(direntry, attrs); |