diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 907 |
1 files changed, 440 insertions, 467 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 8e8bb49112ff..afdff79651f1 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -124,10 +124,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | |||
124 | { | 124 | { |
125 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | 125 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
126 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 126 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
127 | unsigned long oldtime = cifs_i->time; | ||
128 | 127 | ||
129 | cifs_revalidate_cache(inode, fattr); | 128 | cifs_revalidate_cache(inode, fattr); |
130 | 129 | ||
130 | spin_lock(&inode->i_lock); | ||
131 | inode->i_atime = fattr->cf_atime; | 131 | inode->i_atime = fattr->cf_atime; |
132 | inode->i_mtime = fattr->cf_mtime; | 132 | inode->i_mtime = fattr->cf_mtime; |
133 | inode->i_ctime = fattr->cf_ctime; | 133 | inode->i_ctime = fattr->cf_ctime; |
@@ -148,9 +148,6 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | |||
148 | else | 148 | else |
149 | cifs_i->time = jiffies; | 149 | cifs_i->time = jiffies; |
150 | 150 | ||
151 | cFYI(1, "inode 0x%p old_time=%ld new_time=%ld", inode, | ||
152 | oldtime, cifs_i->time); | ||
153 | |||
154 | cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; | 151 | cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; |
155 | 152 | ||
156 | cifs_i->server_eof = fattr->cf_eof; | 153 | cifs_i->server_eof = fattr->cf_eof; |
@@ -158,7 +155,6 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | |||
158 | * Can't safely change the file size here if the client is writing to | 155 | * Can't safely change the file size here if the client is writing to |
159 | * it due to potential races. | 156 | * it due to potential races. |
160 | */ | 157 | */ |
161 | spin_lock(&inode->i_lock); | ||
162 | if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { | 158 | if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { |
163 | i_size_write(inode, fattr->cf_eof); | 159 | i_size_write(inode, fattr->cf_eof); |
164 | 160 | ||
@@ -286,10 +282,11 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) | |||
286 | fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; | 282 | fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; |
287 | } | 283 | } |
288 | 284 | ||
289 | int cifs_get_file_info_unix(struct file *filp) | 285 | static int |
286 | cifs_get_file_info_unix(struct file *filp) | ||
290 | { | 287 | { |
291 | int rc; | 288 | int rc; |
292 | int xid; | 289 | unsigned int xid; |
293 | FILE_UNIX_BASIC_INFO find_data; | 290 | FILE_UNIX_BASIC_INFO find_data; |
294 | struct cifs_fattr fattr; | 291 | struct cifs_fattr fattr; |
295 | struct inode *inode = filp->f_path.dentry->d_inode; | 292 | struct inode *inode = filp->f_path.dentry->d_inode; |
@@ -297,8 +294,8 @@ int cifs_get_file_info_unix(struct file *filp) | |||
297 | struct cifsFileInfo *cfile = filp->private_data; | 294 | struct cifsFileInfo *cfile = filp->private_data; |
298 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | 295 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
299 | 296 | ||
300 | xid = GetXid(); | 297 | xid = get_xid(); |
301 | rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); | 298 | rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data); |
302 | if (!rc) { | 299 | if (!rc) { |
303 | cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); | 300 | cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); |
304 | } else if (rc == -EREMOTE) { | 301 | } else if (rc == -EREMOTE) { |
@@ -307,13 +304,13 @@ int cifs_get_file_info_unix(struct file *filp) | |||
307 | } | 304 | } |
308 | 305 | ||
309 | cifs_fattr_to_inode(inode, &fattr); | 306 | cifs_fattr_to_inode(inode, &fattr); |
310 | FreeXid(xid); | 307 | free_xid(xid); |
311 | return rc; | 308 | return rc; |
312 | } | 309 | } |
313 | 310 | ||
314 | int cifs_get_inode_info_unix(struct inode **pinode, | 311 | int cifs_get_inode_info_unix(struct inode **pinode, |
315 | const unsigned char *full_path, | 312 | const unsigned char *full_path, |
316 | struct super_block *sb, int xid) | 313 | struct super_block *sb, unsigned int xid) |
317 | { | 314 | { |
318 | int rc; | 315 | int rc; |
319 | FILE_UNIX_BASIC_INFO find_data; | 316 | FILE_UNIX_BASIC_INFO find_data; |
@@ -367,7 +364,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
367 | 364 | ||
368 | static int | 365 | static int |
369 | cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | 366 | cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, |
370 | struct cifs_sb_info *cifs_sb, int xid) | 367 | struct cifs_sb_info *cifs_sb, unsigned int xid) |
371 | { | 368 | { |
372 | int rc; | 369 | int rc; |
373 | int oplock = 0; | 370 | int oplock = 0; |
@@ -466,7 +463,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
466 | * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ? | 463 | * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ? |
467 | */ | 464 | */ |
468 | static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, | 465 | static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, |
469 | struct cifs_sb_info *cifs_sb, int xid) | 466 | struct cifs_sb_info *cifs_sb, unsigned int xid) |
470 | { | 467 | { |
471 | #ifdef CONFIG_CIFS_XATTR | 468 | #ifdef CONFIG_CIFS_XATTR |
472 | ssize_t rc; | 469 | ssize_t rc; |
@@ -554,19 +551,24 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, | |||
554 | fattr->cf_gid = cifs_sb->mnt_gid; | 551 | fattr->cf_gid = cifs_sb->mnt_gid; |
555 | } | 552 | } |
556 | 553 | ||
557 | int cifs_get_file_info(struct file *filp) | 554 | static int |
555 | cifs_get_file_info(struct file *filp) | ||
558 | { | 556 | { |
559 | int rc; | 557 | int rc; |
560 | int xid; | 558 | unsigned int xid; |
561 | FILE_ALL_INFO find_data; | 559 | FILE_ALL_INFO find_data; |
562 | struct cifs_fattr fattr; | 560 | struct cifs_fattr fattr; |
563 | struct inode *inode = filp->f_path.dentry->d_inode; | 561 | struct inode *inode = filp->f_path.dentry->d_inode; |
564 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 562 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
565 | struct cifsFileInfo *cfile = filp->private_data; | 563 | struct cifsFileInfo *cfile = filp->private_data; |
566 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | 564 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
565 | struct TCP_Server_Info *server = tcon->ses->server; | ||
566 | |||
567 | if (!server->ops->query_file_info) | ||
568 | return -ENOSYS; | ||
567 | 569 | ||
568 | xid = GetXid(); | 570 | xid = get_xid(); |
569 | rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); | 571 | rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data); |
570 | switch (rc) { | 572 | switch (rc) { |
571 | case 0: | 573 | case 0: |
572 | cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false); | 574 | cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false); |
@@ -596,71 +598,96 @@ int cifs_get_file_info(struct file *filp) | |||
596 | fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; | 598 | fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; |
597 | cifs_fattr_to_inode(inode, &fattr); | 599 | cifs_fattr_to_inode(inode, &fattr); |
598 | cgfi_exit: | 600 | cgfi_exit: |
599 | FreeXid(xid); | 601 | free_xid(xid); |
600 | return rc; | 602 | return rc; |
601 | } | 603 | } |
602 | 604 | ||
603 | int cifs_get_inode_info(struct inode **pinode, | 605 | int |
604 | const unsigned char *full_path, FILE_ALL_INFO *pfindData, | 606 | cifs_get_inode_info(struct inode **inode, const char *full_path, |
605 | struct super_block *sb, int xid, const __u16 *pfid) | 607 | FILE_ALL_INFO *data, struct super_block *sb, int xid, |
608 | const __u16 *fid) | ||
606 | { | 609 | { |
607 | int rc = 0, tmprc; | 610 | bool validinum = false; |
608 | struct cifs_tcon *pTcon; | 611 | __u16 srchflgs; |
612 | int rc = 0, tmprc = ENOSYS; | ||
613 | struct cifs_tcon *tcon; | ||
614 | struct TCP_Server_Info *server; | ||
609 | struct tcon_link *tlink; | 615 | struct tcon_link *tlink; |
610 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 616 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
611 | char *buf = NULL; | 617 | char *buf = NULL; |
612 | bool adjustTZ = false; | 618 | bool adjust_tz = false; |
613 | struct cifs_fattr fattr; | 619 | struct cifs_fattr fattr; |
620 | struct cifs_search_info *srchinf = NULL; | ||
614 | 621 | ||
615 | tlink = cifs_sb_tlink(cifs_sb); | 622 | tlink = cifs_sb_tlink(cifs_sb); |
616 | if (IS_ERR(tlink)) | 623 | if (IS_ERR(tlink)) |
617 | return PTR_ERR(tlink); | 624 | return PTR_ERR(tlink); |
618 | pTcon = tlink_tcon(tlink); | 625 | tcon = tlink_tcon(tlink); |
626 | server = tcon->ses->server; | ||
619 | 627 | ||
620 | cFYI(1, "Getting info on %s", full_path); | 628 | cFYI(1, "Getting info on %s", full_path); |
621 | 629 | ||
622 | if ((pfindData == NULL) && (*pinode != NULL)) { | 630 | if ((data == NULL) && (*inode != NULL)) { |
623 | if (CIFS_I(*pinode)->clientCanCacheRead) { | 631 | if (CIFS_I(*inode)->clientCanCacheRead) { |
624 | cFYI(1, "No need to revalidate cached inode sizes"); | 632 | cFYI(1, "No need to revalidate cached inode sizes"); |
625 | goto cgii_exit; | 633 | goto cgii_exit; |
626 | } | 634 | } |
627 | } | 635 | } |
628 | 636 | ||
629 | /* if file info not passed in then get it from server */ | 637 | /* if inode info is not passed, get it from server */ |
630 | if (pfindData == NULL) { | 638 | if (data == NULL) { |
639 | if (!server->ops->query_path_info) { | ||
640 | rc = -ENOSYS; | ||
641 | goto cgii_exit; | ||
642 | } | ||
631 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | 643 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
632 | if (buf == NULL) { | 644 | if (buf == NULL) { |
633 | rc = -ENOMEM; | 645 | rc = -ENOMEM; |
634 | goto cgii_exit; | 646 | goto cgii_exit; |
635 | } | 647 | } |
636 | pfindData = (FILE_ALL_INFO *)buf; | 648 | data = (FILE_ALL_INFO *)buf; |
637 | 649 | rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path, | |
638 | /* could do find first instead but this returns more info */ | 650 | data, &adjust_tz); |
639 | rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, | ||
640 | 0 /* not legacy */, | ||
641 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
642 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
643 | /* BB optimize code so we do not make the above call | ||
644 | when server claims no NT SMB support and the above call | ||
645 | failed at least once - set flag in tcon or mount */ | ||
646 | if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { | ||
647 | rc = SMBQueryInformation(xid, pTcon, full_path, | ||
648 | pfindData, cifs_sb->local_nls, | ||
649 | cifs_sb->mnt_cifs_flags & | ||
650 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
651 | adjustTZ = true; | ||
652 | } | ||
653 | } | 651 | } |
654 | 652 | ||
655 | if (!rc) { | 653 | if (!rc) { |
656 | cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData, | 654 | cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *)data, cifs_sb, |
657 | cifs_sb, adjustTZ); | 655 | adjust_tz); |
658 | } else if (rc == -EREMOTE) { | 656 | } else if (rc == -EREMOTE) { |
659 | cifs_create_dfs_fattr(&fattr, sb); | 657 | cifs_create_dfs_fattr(&fattr, sb); |
660 | rc = 0; | 658 | rc = 0; |
661 | } else { | 659 | } else if (rc == -EACCES && backup_cred(cifs_sb)) { |
660 | srchinf = kzalloc(sizeof(struct cifs_search_info), | ||
661 | GFP_KERNEL); | ||
662 | if (srchinf == NULL) { | ||
663 | rc = -ENOMEM; | ||
664 | goto cgii_exit; | ||
665 | } | ||
666 | |||
667 | srchinf->endOfSearch = false; | ||
668 | srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO; | ||
669 | |||
670 | srchflgs = CIFS_SEARCH_CLOSE_ALWAYS | | ||
671 | CIFS_SEARCH_CLOSE_AT_END | | ||
672 | CIFS_SEARCH_BACKUP_SEARCH; | ||
673 | |||
674 | rc = CIFSFindFirst(xid, tcon, full_path, | ||
675 | cifs_sb, NULL, srchflgs, srchinf, false); | ||
676 | if (!rc) { | ||
677 | data = | ||
678 | (FILE_ALL_INFO *)srchinf->srch_entries_start; | ||
679 | |||
680 | cifs_dir_info_to_fattr(&fattr, | ||
681 | (FILE_DIRECTORY_INFO *)data, cifs_sb); | ||
682 | fattr.cf_uniqueid = le64_to_cpu( | ||
683 | ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId); | ||
684 | validinum = true; | ||
685 | |||
686 | cifs_buf_release(srchinf->ntwrk_buf_start); | ||
687 | } | ||
688 | kfree(srchinf); | ||
689 | } else | ||
662 | goto cgii_exit; | 690 | goto cgii_exit; |
663 | } | ||
664 | 691 | ||
665 | /* | 692 | /* |
666 | * If an inode wasn't passed in, then get the inode number | 693 | * If an inode wasn't passed in, then get the inode number |
@@ -668,37 +695,24 @@ int cifs_get_inode_info(struct inode **pinode, | |||
668 | * Is an i_ino of zero legal? Can we use that to check if the server | 695 | * Is an i_ino of zero legal? Can we use that to check if the server |
669 | * supports returning inode numbers? Are there other sanity checks we | 696 | * supports returning inode numbers? Are there other sanity checks we |
670 | * can use to ensure that the server is really filling in that field? | 697 | * can use to ensure that the server is really filling in that field? |
671 | * | ||
672 | * We can not use the IndexNumber field by default from Windows or | ||
673 | * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA | ||
674 | * CIFS spec claims that this value is unique within the scope of a | ||
675 | * share, and the windows docs hint that it's actually unique | ||
676 | * per-machine. | ||
677 | * | ||
678 | * There may be higher info levels that work but are there Windows | ||
679 | * server or network appliances for which IndexNumber field is not | ||
680 | * guaranteed unique? | ||
681 | */ | 698 | */ |
682 | if (*pinode == NULL) { | 699 | if (*inode == NULL) { |
683 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 700 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
684 | int rc1 = 0; | 701 | if (validinum == false) { |
685 | 702 | if (server->ops->get_srv_inum) | |
686 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, | 703 | tmprc = server->ops->get_srv_inum(xid, |
687 | full_path, &fattr.cf_uniqueid, | 704 | tcon, cifs_sb, full_path, |
688 | cifs_sb->local_nls, | 705 | &fattr.cf_uniqueid, data); |
689 | cifs_sb->mnt_cifs_flags & | 706 | if (tmprc) { |
690 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 707 | cFYI(1, "GetSrvInodeNum rc %d", tmprc); |
691 | if (rc1 || !fattr.cf_uniqueid) { | 708 | fattr.cf_uniqueid = iunique(sb, ROOT_I); |
692 | cFYI(1, "GetSrvInodeNum rc %d", rc1); | 709 | cifs_autodisable_serverino(cifs_sb); |
693 | fattr.cf_uniqueid = iunique(sb, ROOT_I); | 710 | } |
694 | cifs_autodisable_serverino(cifs_sb); | ||
695 | } | 711 | } |
696 | } else { | 712 | } else |
697 | fattr.cf_uniqueid = iunique(sb, ROOT_I); | 713 | fattr.cf_uniqueid = iunique(sb, ROOT_I); |
698 | } | 714 | } else |
699 | } else { | 715 | fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid; |
700 | fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid; | ||
701 | } | ||
702 | 716 | ||
703 | /* query for SFU type info if supported and needed */ | 717 | /* query for SFU type info if supported and needed */ |
704 | if (fattr.cf_cifsattrs & ATTR_SYSTEM && | 718 | if (fattr.cf_cifsattrs & ATTR_SYSTEM && |
@@ -711,8 +725,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
711 | #ifdef CONFIG_CIFS_ACL | 725 | #ifdef CONFIG_CIFS_ACL |
712 | /* fill in 0777 bits from ACL */ | 726 | /* fill in 0777 bits from ACL */ |
713 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 727 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
714 | rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, | 728 | rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid); |
715 | pfid); | ||
716 | if (rc) { | 729 | if (rc) { |
717 | cFYI(1, "%s: Getting ACL failed with error: %d", | 730 | cFYI(1, "%s: Getting ACL failed with error: %d", |
718 | __func__, rc); | 731 | __func__, rc); |
@@ -732,12 +745,12 @@ int cifs_get_inode_info(struct inode **pinode, | |||
732 | cFYI(1, "CIFSCheckMFSymlink: %d", tmprc); | 745 | cFYI(1, "CIFSCheckMFSymlink: %d", tmprc); |
733 | } | 746 | } |
734 | 747 | ||
735 | if (!*pinode) { | 748 | if (!*inode) { |
736 | *pinode = cifs_iget(sb, &fattr); | 749 | *inode = cifs_iget(sb, &fattr); |
737 | if (!*pinode) | 750 | if (!*inode) |
738 | rc = -ENOMEM; | 751 | rc = -ENOMEM; |
739 | } else { | 752 | } else { |
740 | cifs_fattr_to_inode(*pinode, &fattr); | 753 | cifs_fattr_to_inode(*inode, &fattr); |
741 | } | 754 | } |
742 | 755 | ||
743 | cgii_exit: | 756 | cgii_exit: |
@@ -750,38 +763,6 @@ static const struct inode_operations cifs_ipc_inode_ops = { | |||
750 | .lookup = cifs_lookup, | 763 | .lookup = cifs_lookup, |
751 | }; | 764 | }; |
752 | 765 | ||
753 | char *cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, | ||
754 | struct cifs_tcon *tcon) | ||
755 | { | ||
756 | int pplen = vol->prepath ? strlen(vol->prepath) : 0; | ||
757 | int dfsplen; | ||
758 | char *full_path = NULL; | ||
759 | |||
760 | /* if no prefix path, simply set path to the root of share to "" */ | ||
761 | if (pplen == 0) { | ||
762 | full_path = kmalloc(1, GFP_KERNEL); | ||
763 | if (full_path) | ||
764 | full_path[0] = 0; | ||
765 | return full_path; | ||
766 | } | ||
767 | |||
768 | if (tcon->Flags & SMB_SHARE_IS_IN_DFS) | ||
769 | dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1); | ||
770 | else | ||
771 | dfsplen = 0; | ||
772 | |||
773 | full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL); | ||
774 | if (full_path == NULL) | ||
775 | return full_path; | ||
776 | |||
777 | if (dfsplen) | ||
778 | strncpy(full_path, tcon->treeName, dfsplen); | ||
779 | strncpy(full_path + dfsplen, vol->prepath, pplen); | ||
780 | convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb)); | ||
781 | full_path[dfsplen + pplen] = 0; /* add trailing null */ | ||
782 | return full_path; | ||
783 | } | ||
784 | |||
785 | static int | 766 | static int |
786 | cifs_find_inode(struct inode *inode, void *opaque) | 767 | cifs_find_inode(struct inode *inode, void *opaque) |
787 | { | 768 | { |
@@ -886,13 +867,13 @@ retry_iget5_locked: | |||
886 | /* gets root inode */ | 867 | /* gets root inode */ |
887 | struct inode *cifs_root_iget(struct super_block *sb) | 868 | struct inode *cifs_root_iget(struct super_block *sb) |
888 | { | 869 | { |
889 | int xid; | 870 | unsigned int xid; |
890 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 871 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
891 | struct inode *inode = NULL; | 872 | struct inode *inode = NULL; |
892 | long rc; | 873 | long rc; |
893 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); | 874 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); |
894 | 875 | ||
895 | xid = GetXid(); | 876 | xid = get_xid(); |
896 | if (tcon->unix_ext) | 877 | if (tcon->unix_ext) |
897 | rc = cifs_get_inode_info_unix(&inode, "", sb, xid); | 878 | rc = cifs_get_inode_info_unix(&inode, "", sb, xid); |
898 | else | 879 | else |
@@ -910,44 +891,43 @@ struct inode *cifs_root_iget(struct super_block *sb) | |||
910 | 891 | ||
911 | if (rc && tcon->ipc) { | 892 | if (rc && tcon->ipc) { |
912 | cFYI(1, "ipc connection - fake read inode"); | 893 | cFYI(1, "ipc connection - fake read inode"); |
894 | spin_lock(&inode->i_lock); | ||
913 | inode->i_mode |= S_IFDIR; | 895 | inode->i_mode |= S_IFDIR; |
914 | set_nlink(inode, 2); | 896 | set_nlink(inode, 2); |
915 | inode->i_op = &cifs_ipc_inode_ops; | 897 | inode->i_op = &cifs_ipc_inode_ops; |
916 | inode->i_fop = &simple_dir_operations; | 898 | inode->i_fop = &simple_dir_operations; |
917 | inode->i_uid = cifs_sb->mnt_uid; | 899 | inode->i_uid = cifs_sb->mnt_uid; |
918 | inode->i_gid = cifs_sb->mnt_gid; | 900 | inode->i_gid = cifs_sb->mnt_gid; |
901 | spin_unlock(&inode->i_lock); | ||
919 | } else if (rc) { | 902 | } else if (rc) { |
920 | iget_failed(inode); | 903 | iget_failed(inode); |
921 | inode = ERR_PTR(rc); | 904 | inode = ERR_PTR(rc); |
922 | } | 905 | } |
923 | 906 | ||
924 | out: | 907 | out: |
925 | /* can not call macro FreeXid here since in a void func | 908 | /* can not call macro free_xid here since in a void func |
926 | * TODO: This is no longer true | 909 | * TODO: This is no longer true |
927 | */ | 910 | */ |
928 | _FreeXid(xid); | 911 | _free_xid(xid); |
929 | return inode; | 912 | return inode; |
930 | } | 913 | } |
931 | 914 | ||
932 | static int | 915 | int |
933 | cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, | 916 | cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid, |
934 | char *full_path, __u32 dosattr) | 917 | char *full_path, __u32 dosattr) |
935 | { | 918 | { |
936 | int rc; | ||
937 | int oplock = 0; | ||
938 | __u16 netfid; | ||
939 | __u32 netpid; | ||
940 | bool set_time = false; | 919 | bool set_time = false; |
941 | struct cifsFileInfo *open_file; | ||
942 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | ||
943 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 920 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
944 | struct tcon_link *tlink = NULL; | 921 | struct TCP_Server_Info *server; |
945 | struct cifs_tcon *pTcon; | ||
946 | FILE_BASIC_INFO info_buf; | 922 | FILE_BASIC_INFO info_buf; |
947 | 923 | ||
948 | if (attrs == NULL) | 924 | if (attrs == NULL) |
949 | return -EINVAL; | 925 | return -EINVAL; |
950 | 926 | ||
927 | server = cifs_sb_master_tcon(cifs_sb)->ses->server; | ||
928 | if (!server->ops->set_file_info) | ||
929 | return -ENOSYS; | ||
930 | |||
951 | if (attrs->ia_valid & ATTR_ATIME) { | 931 | if (attrs->ia_valid & ATTR_ATIME) { |
952 | set_time = true; | 932 | set_time = true; |
953 | info_buf.LastAccessTime = | 933 | info_buf.LastAccessTime = |
@@ -978,80 +958,17 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, | |||
978 | info_buf.CreationTime = 0; /* don't change */ | 958 | info_buf.CreationTime = 0; /* don't change */ |
979 | info_buf.Attributes = cpu_to_le32(dosattr); | 959 | info_buf.Attributes = cpu_to_le32(dosattr); |
980 | 960 | ||
981 | /* | 961 | return server->ops->set_file_info(inode, full_path, &info_buf, xid); |
982 | * If the file is already open for write, just use that fileid | ||
983 | */ | ||
984 | open_file = find_writable_file(cifsInode, true); | ||
985 | if (open_file) { | ||
986 | netfid = open_file->netfid; | ||
987 | netpid = open_file->pid; | ||
988 | pTcon = tlink_tcon(open_file->tlink); | ||
989 | goto set_via_filehandle; | ||
990 | } | ||
991 | |||
992 | tlink = cifs_sb_tlink(cifs_sb); | ||
993 | if (IS_ERR(tlink)) { | ||
994 | rc = PTR_ERR(tlink); | ||
995 | tlink = NULL; | ||
996 | goto out; | ||
997 | } | ||
998 | pTcon = tlink_tcon(tlink); | ||
999 | |||
1000 | /* | ||
1001 | * NT4 apparently returns success on this call, but it doesn't | ||
1002 | * really work. | ||
1003 | */ | ||
1004 | if (!(pTcon->ses->flags & CIFS_SES_NT4)) { | ||
1005 | rc = CIFSSMBSetPathInfo(xid, pTcon, full_path, | ||
1006 | &info_buf, cifs_sb->local_nls, | ||
1007 | cifs_sb->mnt_cifs_flags & | ||
1008 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1009 | if (rc == 0) { | ||
1010 | cifsInode->cifsAttrs = dosattr; | ||
1011 | goto out; | ||
1012 | } else if (rc != -EOPNOTSUPP && rc != -EINVAL) | ||
1013 | goto out; | ||
1014 | } | ||
1015 | |||
1016 | cFYI(1, "calling SetFileInfo since SetPathInfo for " | ||
1017 | "times not supported by this server"); | ||
1018 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, | ||
1019 | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, | ||
1020 | CREATE_NOT_DIR, &netfid, &oplock, | ||
1021 | NULL, cifs_sb->local_nls, | ||
1022 | cifs_sb->mnt_cifs_flags & | ||
1023 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1024 | |||
1025 | if (rc != 0) { | ||
1026 | if (rc == -EIO) | ||
1027 | rc = -EINVAL; | ||
1028 | goto out; | ||
1029 | } | ||
1030 | |||
1031 | netpid = current->tgid; | ||
1032 | |||
1033 | set_via_filehandle: | ||
1034 | rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid); | ||
1035 | if (!rc) | ||
1036 | cifsInode->cifsAttrs = dosattr; | ||
1037 | |||
1038 | if (open_file == NULL) | ||
1039 | CIFSSMBClose(xid, pTcon, netfid); | ||
1040 | else | ||
1041 | cifsFileInfo_put(open_file); | ||
1042 | out: | ||
1043 | if (tlink != NULL) | ||
1044 | cifs_put_tlink(tlink); | ||
1045 | return rc; | ||
1046 | } | 962 | } |
1047 | 963 | ||
1048 | /* | 964 | /* |
1049 | * open the given file (if it isn't already), set the DELETE_ON_CLOSE bit | 965 | * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit |
1050 | * and rename it to a random name that hopefully won't conflict with | 966 | * and rename it to a random name that hopefully won't conflict with |
1051 | * anything else. | 967 | * anything else. |
1052 | */ | 968 | */ |
1053 | static int | 969 | int |
1054 | cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid) | 970 | cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, |
971 | const unsigned int xid) | ||
1055 | { | 972 | { |
1056 | int oplock = 0; | 973 | int oplock = 0; |
1057 | int rc; | 974 | int rc; |
@@ -1160,6 +1077,15 @@ undo_setattr: | |||
1160 | goto out_close; | 1077 | goto out_close; |
1161 | } | 1078 | } |
1162 | 1079 | ||
1080 | /* copied from fs/nfs/dir.c with small changes */ | ||
1081 | static void | ||
1082 | cifs_drop_nlink(struct inode *inode) | ||
1083 | { | ||
1084 | spin_lock(&inode->i_lock); | ||
1085 | if (inode->i_nlink > 0) | ||
1086 | drop_nlink(inode); | ||
1087 | spin_unlock(&inode->i_lock); | ||
1088 | } | ||
1163 | 1089 | ||
1164 | /* | 1090 | /* |
1165 | * If dentry->d_inode is null (usually meaning the cached dentry | 1091 | * If dentry->d_inode is null (usually meaning the cached dentry |
@@ -1171,7 +1097,7 @@ undo_setattr: | |||
1171 | int cifs_unlink(struct inode *dir, struct dentry *dentry) | 1097 | int cifs_unlink(struct inode *dir, struct dentry *dentry) |
1172 | { | 1098 | { |
1173 | int rc = 0; | 1099 | int rc = 0; |
1174 | int xid; | 1100 | unsigned int xid; |
1175 | char *full_path = NULL; | 1101 | char *full_path = NULL; |
1176 | struct inode *inode = dentry->d_inode; | 1102 | struct inode *inode = dentry->d_inode; |
1177 | struct cifsInodeInfo *cifs_inode; | 1103 | struct cifsInodeInfo *cifs_inode; |
@@ -1179,6 +1105,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
1179 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 1105 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
1180 | struct tcon_link *tlink; | 1106 | struct tcon_link *tlink; |
1181 | struct cifs_tcon *tcon; | 1107 | struct cifs_tcon *tcon; |
1108 | struct TCP_Server_Info *server; | ||
1182 | struct iattr *attrs = NULL; | 1109 | struct iattr *attrs = NULL; |
1183 | __u32 dosattr = 0, origattr = 0; | 1110 | __u32 dosattr = 0, origattr = 0; |
1184 | 1111 | ||
@@ -1188,8 +1115,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
1188 | if (IS_ERR(tlink)) | 1115 | if (IS_ERR(tlink)) |
1189 | return PTR_ERR(tlink); | 1116 | return PTR_ERR(tlink); |
1190 | tcon = tlink_tcon(tlink); | 1117 | tcon = tlink_tcon(tlink); |
1118 | server = tcon->ses->server; | ||
1191 | 1119 | ||
1192 | xid = GetXid(); | 1120 | xid = get_xid(); |
1193 | 1121 | ||
1194 | /* Unlink can be called from rename so we can not take the | 1122 | /* Unlink can be called from rename so we can not take the |
1195 | * sb->s_vfs_rename_mutex here */ | 1123 | * sb->s_vfs_rename_mutex here */ |
@@ -1199,9 +1127,8 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
1199 | goto unlink_out; | 1127 | goto unlink_out; |
1200 | } | 1128 | } |
1201 | 1129 | ||
1202 | if ((tcon->ses->capabilities & CAP_UNIX) && | 1130 | if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
1203 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & | 1131 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
1204 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | ||
1205 | rc = CIFSPOSIXDelFile(xid, tcon, full_path, | 1132 | rc = CIFSPOSIXDelFile(xid, tcon, full_path, |
1206 | SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls, | 1133 | SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls, |
1207 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1134 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
@@ -1211,19 +1138,28 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
1211 | } | 1138 | } |
1212 | 1139 | ||
1213 | retry_std_delete: | 1140 | retry_std_delete: |
1214 | rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls, | 1141 | if (!server->ops->unlink) { |
1215 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1142 | rc = -ENOSYS; |
1143 | goto psx_del_no_retry; | ||
1144 | } | ||
1145 | |||
1146 | rc = server->ops->unlink(xid, tcon, full_path, cifs_sb); | ||
1216 | 1147 | ||
1217 | psx_del_no_retry: | 1148 | psx_del_no_retry: |
1218 | if (!rc) { | 1149 | if (!rc) { |
1219 | if (inode) | 1150 | if (inode) |
1220 | drop_nlink(inode); | 1151 | cifs_drop_nlink(inode); |
1221 | } else if (rc == -ENOENT) { | 1152 | } else if (rc == -ENOENT) { |
1222 | d_drop(dentry); | 1153 | d_drop(dentry); |
1223 | } else if (rc == -ETXTBSY) { | 1154 | } else if (rc == -ETXTBSY) { |
1224 | rc = cifs_rename_pending_delete(full_path, dentry, xid); | 1155 | if (server->ops->rename_pending_delete) { |
1225 | if (rc == 0) | 1156 | rc = server->ops->rename_pending_delete(full_path, |
1226 | drop_nlink(inode); | 1157 | dentry, xid); |
1158 | if (rc == 0) | ||
1159 | cifs_drop_nlink(inode); | ||
1160 | } | ||
1161 | if (rc == -ETXTBSY) | ||
1162 | rc = -EBUSY; | ||
1227 | } else if ((rc == -EACCES) && (dosattr == 0) && inode) { | 1163 | } else if ((rc == -EACCES) && (dosattr == 0) && inode) { |
1228 | attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); | 1164 | attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); |
1229 | if (attrs == NULL) { | 1165 | if (attrs == NULL) { |
@@ -1265,21 +1201,156 @@ out_reval: | |||
1265 | unlink_out: | 1201 | unlink_out: |
1266 | kfree(full_path); | 1202 | kfree(full_path); |
1267 | kfree(attrs); | 1203 | kfree(attrs); |
1268 | FreeXid(xid); | 1204 | free_xid(xid); |
1269 | cifs_put_tlink(tlink); | 1205 | cifs_put_tlink(tlink); |
1270 | return rc; | 1206 | return rc; |
1271 | } | 1207 | } |
1272 | 1208 | ||
1209 | static int | ||
1210 | cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, | ||
1211 | const char *full_path, struct cifs_sb_info *cifs_sb, | ||
1212 | struct cifs_tcon *tcon, const unsigned int xid) | ||
1213 | { | ||
1214 | int rc = 0; | ||
1215 | struct inode *inode = NULL; | ||
1216 | |||
1217 | if (tcon->unix_ext) | ||
1218 | rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb, | ||
1219 | xid); | ||
1220 | else | ||
1221 | rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb, | ||
1222 | xid, NULL); | ||
1223 | |||
1224 | if (rc) | ||
1225 | return rc; | ||
1226 | |||
1227 | /* | ||
1228 | * setting nlink not necessary except in cases where we failed to get it | ||
1229 | * from the server or was set bogus. Also, since this is a brand new | ||
1230 | * inode, no need to grab the i_lock before setting the i_nlink. | ||
1231 | */ | ||
1232 | if (inode->i_nlink < 2) | ||
1233 | set_nlink(inode, 2); | ||
1234 | mode &= ~current_umask(); | ||
1235 | /* must turn on setgid bit if parent dir has it */ | ||
1236 | if (parent->i_mode & S_ISGID) | ||
1237 | mode |= S_ISGID; | ||
1238 | |||
1239 | if (tcon->unix_ext) { | ||
1240 | struct cifs_unix_set_info_args args = { | ||
1241 | .mode = mode, | ||
1242 | .ctime = NO_CHANGE_64, | ||
1243 | .atime = NO_CHANGE_64, | ||
1244 | .mtime = NO_CHANGE_64, | ||
1245 | .device = 0, | ||
1246 | }; | ||
1247 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | ||
1248 | args.uid = (__u64)current_fsuid(); | ||
1249 | if (parent->i_mode & S_ISGID) | ||
1250 | args.gid = (__u64)parent->i_gid; | ||
1251 | else | ||
1252 | args.gid = (__u64)current_fsgid(); | ||
1253 | } else { | ||
1254 | args.uid = NO_CHANGE_64; | ||
1255 | args.gid = NO_CHANGE_64; | ||
1256 | } | ||
1257 | CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, | ||
1258 | cifs_sb->local_nls, | ||
1259 | cifs_sb->mnt_cifs_flags & | ||
1260 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1261 | } else { | ||
1262 | struct TCP_Server_Info *server = tcon->ses->server; | ||
1263 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && | ||
1264 | (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo) | ||
1265 | server->ops->mkdir_setinfo(inode, full_path, cifs_sb, | ||
1266 | tcon, xid); | ||
1267 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) | ||
1268 | inode->i_mode = (mode | S_IFDIR); | ||
1269 | |||
1270 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | ||
1271 | inode->i_uid = current_fsuid(); | ||
1272 | if (inode->i_mode & S_ISGID) | ||
1273 | inode->i_gid = parent->i_gid; | ||
1274 | else | ||
1275 | inode->i_gid = current_fsgid(); | ||
1276 | } | ||
1277 | } | ||
1278 | d_instantiate(dentry, inode); | ||
1279 | return rc; | ||
1280 | } | ||
1281 | |||
1282 | static int | ||
1283 | cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode, | ||
1284 | const char *full_path, struct cifs_sb_info *cifs_sb, | ||
1285 | struct cifs_tcon *tcon, const unsigned int xid) | ||
1286 | { | ||
1287 | int rc = 0; | ||
1288 | u32 oplock = 0; | ||
1289 | FILE_UNIX_BASIC_INFO *info = NULL; | ||
1290 | struct inode *newinode = NULL; | ||
1291 | struct cifs_fattr fattr; | ||
1292 | |||
1293 | info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); | ||
1294 | if (info == NULL) { | ||
1295 | rc = -ENOMEM; | ||
1296 | goto posix_mkdir_out; | ||
1297 | } | ||
1298 | |||
1299 | mode &= ~current_umask(); | ||
1300 | rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode, | ||
1301 | NULL /* netfid */, info, &oplock, full_path, | ||
1302 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
1303 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1304 | if (rc == -EOPNOTSUPP) | ||
1305 | goto posix_mkdir_out; | ||
1306 | else if (rc) { | ||
1307 | cFYI(1, "posix mkdir returned 0x%x", rc); | ||
1308 | d_drop(dentry); | ||
1309 | goto posix_mkdir_out; | ||
1310 | } | ||
1311 | |||
1312 | if (info->Type == cpu_to_le32(-1)) | ||
1313 | /* no return info, go query for it */ | ||
1314 | goto posix_mkdir_get_info; | ||
1315 | /* | ||
1316 | * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if | ||
1317 | * need to set uid/gid. | ||
1318 | */ | ||
1319 | |||
1320 | cifs_unix_basic_to_fattr(&fattr, info, cifs_sb); | ||
1321 | cifs_fill_uniqueid(inode->i_sb, &fattr); | ||
1322 | newinode = cifs_iget(inode->i_sb, &fattr); | ||
1323 | if (!newinode) | ||
1324 | goto posix_mkdir_get_info; | ||
1325 | |||
1326 | d_instantiate(dentry, newinode); | ||
1327 | |||
1328 | #ifdef CONFIG_CIFS_DEBUG2 | ||
1329 | cFYI(1, "instantiated dentry %p %s to inode %p", dentry, | ||
1330 | dentry->d_name.name, newinode); | ||
1331 | |||
1332 | if (newinode->i_nlink != 2) | ||
1333 | cFYI(1, "unexpected number of links %d", newinode->i_nlink); | ||
1334 | #endif | ||
1335 | |||
1336 | posix_mkdir_out: | ||
1337 | kfree(info); | ||
1338 | return rc; | ||
1339 | posix_mkdir_get_info: | ||
1340 | rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon, | ||
1341 | xid); | ||
1342 | goto posix_mkdir_out; | ||
1343 | } | ||
1344 | |||
1273 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) | 1345 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) |
1274 | { | 1346 | { |
1275 | int rc = 0, tmprc; | 1347 | int rc = 0; |
1276 | int xid; | 1348 | unsigned int xid; |
1277 | struct cifs_sb_info *cifs_sb; | 1349 | struct cifs_sb_info *cifs_sb; |
1278 | struct tcon_link *tlink; | 1350 | struct tcon_link *tlink; |
1279 | struct cifs_tcon *pTcon; | 1351 | struct cifs_tcon *tcon; |
1280 | char *full_path = NULL; | 1352 | struct TCP_Server_Info *server; |
1281 | struct inode *newinode = NULL; | 1353 | char *full_path; |
1282 | struct cifs_fattr fattr; | ||
1283 | 1354 | ||
1284 | cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode); | 1355 | cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode); |
1285 | 1356 | ||
@@ -1287,9 +1358,9 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) | |||
1287 | tlink = cifs_sb_tlink(cifs_sb); | 1358 | tlink = cifs_sb_tlink(cifs_sb); |
1288 | if (IS_ERR(tlink)) | 1359 | if (IS_ERR(tlink)) |
1289 | return PTR_ERR(tlink); | 1360 | return PTR_ERR(tlink); |
1290 | pTcon = tlink_tcon(tlink); | 1361 | tcon = tlink_tcon(tlink); |
1291 | 1362 | ||
1292 | xid = GetXid(); | 1363 | xid = get_xid(); |
1293 | 1364 | ||
1294 | full_path = build_path_from_dentry(direntry); | 1365 | full_path = build_path_from_dentry(direntry); |
1295 | if (full_path == NULL) { | 1366 | if (full_path == NULL) { |
@@ -1297,148 +1368,31 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) | |||
1297 | goto mkdir_out; | 1368 | goto mkdir_out; |
1298 | } | 1369 | } |
1299 | 1370 | ||
1300 | if ((pTcon->ses->capabilities & CAP_UNIX) && | 1371 | if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
1301 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & | 1372 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
1302 | le64_to_cpu(pTcon->fsUnixInfo.Capability))) { | 1373 | rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb, |
1303 | u32 oplock = 0; | 1374 | tcon, xid); |
1304 | FILE_UNIX_BASIC_INFO *pInfo = | 1375 | if (rc != -EOPNOTSUPP) |
1305 | kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); | ||
1306 | if (pInfo == NULL) { | ||
1307 | rc = -ENOMEM; | ||
1308 | goto mkdir_out; | 1376 | goto mkdir_out; |
1309 | } | 1377 | } |
1310 | |||
1311 | mode &= ~current_umask(); | ||
1312 | rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, | ||
1313 | mode, NULL /* netfid */, pInfo, &oplock, | ||
1314 | full_path, cifs_sb->local_nls, | ||
1315 | cifs_sb->mnt_cifs_flags & | ||
1316 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1317 | if (rc == -EOPNOTSUPP) { | ||
1318 | kfree(pInfo); | ||
1319 | goto mkdir_retry_old; | ||
1320 | } else if (rc) { | ||
1321 | cFYI(1, "posix mkdir returned 0x%x", rc); | ||
1322 | d_drop(direntry); | ||
1323 | } else { | ||
1324 | if (pInfo->Type == cpu_to_le32(-1)) { | ||
1325 | /* no return info, go query for it */ | ||
1326 | kfree(pInfo); | ||
1327 | goto mkdir_get_info; | ||
1328 | } | ||
1329 | /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need | ||
1330 | to set uid/gid */ | ||
1331 | |||
1332 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); | ||
1333 | cifs_fill_uniqueid(inode->i_sb, &fattr); | ||
1334 | newinode = cifs_iget(inode->i_sb, &fattr); | ||
1335 | if (!newinode) { | ||
1336 | kfree(pInfo); | ||
1337 | goto mkdir_get_info; | ||
1338 | } | ||
1339 | |||
1340 | d_instantiate(direntry, newinode); | ||
1341 | 1378 | ||
1342 | #ifdef CONFIG_CIFS_DEBUG2 | 1379 | server = tcon->ses->server; |
1343 | cFYI(1, "instantiated dentry %p %s to inode %p", | ||
1344 | direntry, direntry->d_name.name, newinode); | ||
1345 | 1380 | ||
1346 | if (newinode->i_nlink != 2) | 1381 | if (!server->ops->mkdir) { |
1347 | cFYI(1, "unexpected number of links %d", | 1382 | rc = -ENOSYS; |
1348 | newinode->i_nlink); | ||
1349 | #endif | ||
1350 | } | ||
1351 | kfree(pInfo); | ||
1352 | goto mkdir_out; | 1383 | goto mkdir_out; |
1353 | } | 1384 | } |
1354 | mkdir_retry_old: | 1385 | |
1355 | /* BB add setting the equivalent of mode via CreateX w/ACLs */ | 1386 | /* BB add setting the equivalent of mode via CreateX w/ACLs */ |
1356 | rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, | 1387 | rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb); |
1357 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1358 | if (rc) { | 1388 | if (rc) { |
1359 | cFYI(1, "cifs_mkdir returned 0x%x", rc); | 1389 | cFYI(1, "cifs_mkdir returned 0x%x", rc); |
1360 | d_drop(direntry); | 1390 | d_drop(direntry); |
1361 | } else { | 1391 | goto mkdir_out; |
1362 | mkdir_get_info: | ||
1363 | if (pTcon->unix_ext) | ||
1364 | rc = cifs_get_inode_info_unix(&newinode, full_path, | ||
1365 | inode->i_sb, xid); | ||
1366 | else | ||
1367 | rc = cifs_get_inode_info(&newinode, full_path, NULL, | ||
1368 | inode->i_sb, xid, NULL); | ||
1369 | |||
1370 | d_instantiate(direntry, newinode); | ||
1371 | /* setting nlink not necessary except in cases where we | ||
1372 | * failed to get it from the server or was set bogus */ | ||
1373 | if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) | ||
1374 | set_nlink(direntry->d_inode, 2); | ||
1375 | |||
1376 | mode &= ~current_umask(); | ||
1377 | /* must turn on setgid bit if parent dir has it */ | ||
1378 | if (inode->i_mode & S_ISGID) | ||
1379 | mode |= S_ISGID; | ||
1380 | |||
1381 | if (pTcon->unix_ext) { | ||
1382 | struct cifs_unix_set_info_args args = { | ||
1383 | .mode = mode, | ||
1384 | .ctime = NO_CHANGE_64, | ||
1385 | .atime = NO_CHANGE_64, | ||
1386 | .mtime = NO_CHANGE_64, | ||
1387 | .device = 0, | ||
1388 | }; | ||
1389 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | ||
1390 | args.uid = (__u64)current_fsuid(); | ||
1391 | if (inode->i_mode & S_ISGID) | ||
1392 | args.gid = (__u64)inode->i_gid; | ||
1393 | else | ||
1394 | args.gid = (__u64)current_fsgid(); | ||
1395 | } else { | ||
1396 | args.uid = NO_CHANGE_64; | ||
1397 | args.gid = NO_CHANGE_64; | ||
1398 | } | ||
1399 | CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, | ||
1400 | cifs_sb->local_nls, | ||
1401 | cifs_sb->mnt_cifs_flags & | ||
1402 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1403 | } else { | ||
1404 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && | ||
1405 | (mode & S_IWUGO) == 0) { | ||
1406 | FILE_BASIC_INFO pInfo; | ||
1407 | struct cifsInodeInfo *cifsInode; | ||
1408 | u32 dosattrs; | ||
1409 | |||
1410 | memset(&pInfo, 0, sizeof(pInfo)); | ||
1411 | cifsInode = CIFS_I(newinode); | ||
1412 | dosattrs = cifsInode->cifsAttrs|ATTR_READONLY; | ||
1413 | pInfo.Attributes = cpu_to_le32(dosattrs); | ||
1414 | tmprc = CIFSSMBSetPathInfo(xid, pTcon, | ||
1415 | full_path, &pInfo, | ||
1416 | cifs_sb->local_nls, | ||
1417 | cifs_sb->mnt_cifs_flags & | ||
1418 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1419 | if (tmprc == 0) | ||
1420 | cifsInode->cifsAttrs = dosattrs; | ||
1421 | } | ||
1422 | if (direntry->d_inode) { | ||
1423 | if (cifs_sb->mnt_cifs_flags & | ||
1424 | CIFS_MOUNT_DYNPERM) | ||
1425 | direntry->d_inode->i_mode = | ||
1426 | (mode | S_IFDIR); | ||
1427 | |||
1428 | if (cifs_sb->mnt_cifs_flags & | ||
1429 | CIFS_MOUNT_SET_UID) { | ||
1430 | direntry->d_inode->i_uid = | ||
1431 | current_fsuid(); | ||
1432 | if (inode->i_mode & S_ISGID) | ||
1433 | direntry->d_inode->i_gid = | ||
1434 | inode->i_gid; | ||
1435 | else | ||
1436 | direntry->d_inode->i_gid = | ||
1437 | current_fsgid(); | ||
1438 | } | ||
1439 | } | ||
1440 | } | ||
1441 | } | 1392 | } |
1393 | |||
1394 | rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon, | ||
1395 | xid); | ||
1442 | mkdir_out: | 1396 | mkdir_out: |
1443 | /* | 1397 | /* |
1444 | * Force revalidate to get parent dir info when needed since cached | 1398 | * Force revalidate to get parent dir info when needed since cached |
@@ -1446,7 +1400,7 @@ mkdir_out: | |||
1446 | */ | 1400 | */ |
1447 | CIFS_I(inode)->time = 0; | 1401 | CIFS_I(inode)->time = 0; |
1448 | kfree(full_path); | 1402 | kfree(full_path); |
1449 | FreeXid(xid); | 1403 | free_xid(xid); |
1450 | cifs_put_tlink(tlink); | 1404 | cifs_put_tlink(tlink); |
1451 | return rc; | 1405 | return rc; |
1452 | } | 1406 | } |
@@ -1454,16 +1408,17 @@ mkdir_out: | |||
1454 | int cifs_rmdir(struct inode *inode, struct dentry *direntry) | 1408 | int cifs_rmdir(struct inode *inode, struct dentry *direntry) |
1455 | { | 1409 | { |
1456 | int rc = 0; | 1410 | int rc = 0; |
1457 | int xid; | 1411 | unsigned int xid; |
1458 | struct cifs_sb_info *cifs_sb; | 1412 | struct cifs_sb_info *cifs_sb; |
1459 | struct tcon_link *tlink; | 1413 | struct tcon_link *tlink; |
1460 | struct cifs_tcon *pTcon; | 1414 | struct cifs_tcon *tcon; |
1415 | struct TCP_Server_Info *server; | ||
1461 | char *full_path = NULL; | 1416 | char *full_path = NULL; |
1462 | struct cifsInodeInfo *cifsInode; | 1417 | struct cifsInodeInfo *cifsInode; |
1463 | 1418 | ||
1464 | cFYI(1, "cifs_rmdir, inode = 0x%p", inode); | 1419 | cFYI(1, "cifs_rmdir, inode = 0x%p", inode); |
1465 | 1420 | ||
1466 | xid = GetXid(); | 1421 | xid = get_xid(); |
1467 | 1422 | ||
1468 | full_path = build_path_from_dentry(direntry); | 1423 | full_path = build_path_from_dentry(direntry); |
1469 | if (full_path == NULL) { | 1424 | if (full_path == NULL) { |
@@ -1477,10 +1432,16 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1477 | rc = PTR_ERR(tlink); | 1432 | rc = PTR_ERR(tlink); |
1478 | goto rmdir_exit; | 1433 | goto rmdir_exit; |
1479 | } | 1434 | } |
1480 | pTcon = tlink_tcon(tlink); | 1435 | tcon = tlink_tcon(tlink); |
1436 | server = tcon->ses->server; | ||
1481 | 1437 | ||
1482 | rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, | 1438 | if (!server->ops->rmdir) { |
1483 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1439 | rc = -ENOSYS; |
1440 | cifs_put_tlink(tlink); | ||
1441 | goto rmdir_exit; | ||
1442 | } | ||
1443 | |||
1444 | rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb); | ||
1484 | cifs_put_tlink(tlink); | 1445 | cifs_put_tlink(tlink); |
1485 | 1446 | ||
1486 | if (!rc) { | 1447 | if (!rc) { |
@@ -1506,33 +1467,37 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1506 | 1467 | ||
1507 | rmdir_exit: | 1468 | rmdir_exit: |
1508 | kfree(full_path); | 1469 | kfree(full_path); |
1509 | FreeXid(xid); | 1470 | free_xid(xid); |
1510 | return rc; | 1471 | return rc; |
1511 | } | 1472 | } |
1512 | 1473 | ||
1513 | static int | 1474 | static int |
1514 | cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, | 1475 | cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, |
1515 | struct dentry *to_dentry, const char *toPath) | 1476 | const char *from_path, struct dentry *to_dentry, |
1477 | const char *to_path) | ||
1516 | { | 1478 | { |
1517 | struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb); | 1479 | struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb); |
1518 | struct tcon_link *tlink; | 1480 | struct tcon_link *tlink; |
1519 | struct cifs_tcon *pTcon; | 1481 | struct cifs_tcon *tcon; |
1482 | struct TCP_Server_Info *server; | ||
1520 | __u16 srcfid; | 1483 | __u16 srcfid; |
1521 | int oplock, rc; | 1484 | int oplock, rc; |
1522 | 1485 | ||
1523 | tlink = cifs_sb_tlink(cifs_sb); | 1486 | tlink = cifs_sb_tlink(cifs_sb); |
1524 | if (IS_ERR(tlink)) | 1487 | if (IS_ERR(tlink)) |
1525 | return PTR_ERR(tlink); | 1488 | return PTR_ERR(tlink); |
1526 | pTcon = tlink_tcon(tlink); | 1489 | tcon = tlink_tcon(tlink); |
1490 | server = tcon->ses->server; | ||
1491 | |||
1492 | if (!server->ops->rename) | ||
1493 | return -ENOSYS; | ||
1527 | 1494 | ||
1528 | /* try path-based rename first */ | 1495 | /* try path-based rename first */ |
1529 | rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls, | 1496 | rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb); |
1530 | cifs_sb->mnt_cifs_flags & | ||
1531 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1532 | 1497 | ||
1533 | /* | 1498 | /* |
1534 | * don't bother with rename by filehandle unless file is busy and | 1499 | * Don't bother with rename by filehandle unless file is busy and |
1535 | * source Note that cross directory moves do not work with | 1500 | * source. Note that cross directory moves do not work with |
1536 | * rename by filehandle to various Windows servers. | 1501 | * rename by filehandle to various Windows servers. |
1537 | */ | 1502 | */ |
1538 | if (rc == 0 || rc != -ETXTBSY) | 1503 | if (rc == 0 || rc != -ETXTBSY) |
@@ -1543,35 +1508,35 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, | |||
1543 | goto do_rename_exit; | 1508 | goto do_rename_exit; |
1544 | 1509 | ||
1545 | /* open the file to be renamed -- we need DELETE perms */ | 1510 | /* open the file to be renamed -- we need DELETE perms */ |
1546 | rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, | 1511 | rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE, |
1547 | CREATE_NOT_DIR, &srcfid, &oplock, NULL, | 1512 | CREATE_NOT_DIR, &srcfid, &oplock, NULL, |
1548 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1513 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
1549 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1514 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1550 | |||
1551 | if (rc == 0) { | 1515 | if (rc == 0) { |
1552 | rc = CIFSSMBRenameOpenFile(xid, pTcon, srcfid, | 1516 | rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid, |
1553 | (const char *) to_dentry->d_name.name, | 1517 | (const char *) to_dentry->d_name.name, |
1554 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1518 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
1555 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1519 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1556 | 1520 | CIFSSMBClose(xid, tcon, srcfid); | |
1557 | CIFSSMBClose(xid, pTcon, srcfid); | ||
1558 | } | 1521 | } |
1559 | do_rename_exit: | 1522 | do_rename_exit: |
1560 | cifs_put_tlink(tlink); | 1523 | cifs_put_tlink(tlink); |
1561 | return rc; | 1524 | return rc; |
1562 | } | 1525 | } |
1563 | 1526 | ||
1564 | int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | 1527 | int |
1565 | struct inode *target_dir, struct dentry *target_dentry) | 1528 | cifs_rename(struct inode *source_dir, struct dentry *source_dentry, |
1529 | struct inode *target_dir, struct dentry *target_dentry) | ||
1566 | { | 1530 | { |
1567 | char *fromName = NULL; | 1531 | char *from_name = NULL; |
1568 | char *toName = NULL; | 1532 | char *to_name = NULL; |
1569 | struct cifs_sb_info *cifs_sb; | 1533 | struct cifs_sb_info *cifs_sb; |
1570 | struct tcon_link *tlink; | 1534 | struct tcon_link *tlink; |
1571 | struct cifs_tcon *tcon; | 1535 | struct cifs_tcon *tcon; |
1572 | FILE_UNIX_BASIC_INFO *info_buf_source = NULL; | 1536 | FILE_UNIX_BASIC_INFO *info_buf_source = NULL; |
1573 | FILE_UNIX_BASIC_INFO *info_buf_target; | 1537 | FILE_UNIX_BASIC_INFO *info_buf_target; |
1574 | int xid, rc, tmprc; | 1538 | unsigned int xid; |
1539 | int rc, tmprc; | ||
1575 | 1540 | ||
1576 | cifs_sb = CIFS_SB(source_dir->i_sb); | 1541 | cifs_sb = CIFS_SB(source_dir->i_sb); |
1577 | tlink = cifs_sb_tlink(cifs_sb); | 1542 | tlink = cifs_sb_tlink(cifs_sb); |
@@ -1579,31 +1544,31 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
1579 | return PTR_ERR(tlink); | 1544 | return PTR_ERR(tlink); |
1580 | tcon = tlink_tcon(tlink); | 1545 | tcon = tlink_tcon(tlink); |
1581 | 1546 | ||
1582 | xid = GetXid(); | 1547 | xid = get_xid(); |
1583 | 1548 | ||
1584 | /* | 1549 | /* |
1585 | * we already have the rename sem so we do not need to | 1550 | * we already have the rename sem so we do not need to |
1586 | * grab it again here to protect the path integrity | 1551 | * grab it again here to protect the path integrity |
1587 | */ | 1552 | */ |
1588 | fromName = build_path_from_dentry(source_dentry); | 1553 | from_name = build_path_from_dentry(source_dentry); |
1589 | if (fromName == NULL) { | 1554 | if (from_name == NULL) { |
1590 | rc = -ENOMEM; | 1555 | rc = -ENOMEM; |
1591 | goto cifs_rename_exit; | 1556 | goto cifs_rename_exit; |
1592 | } | 1557 | } |
1593 | 1558 | ||
1594 | toName = build_path_from_dentry(target_dentry); | 1559 | to_name = build_path_from_dentry(target_dentry); |
1595 | if (toName == NULL) { | 1560 | if (to_name == NULL) { |
1596 | rc = -ENOMEM; | 1561 | rc = -ENOMEM; |
1597 | goto cifs_rename_exit; | 1562 | goto cifs_rename_exit; |
1598 | } | 1563 | } |
1599 | 1564 | ||
1600 | rc = cifs_do_rename(xid, source_dentry, fromName, | 1565 | rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry, |
1601 | target_dentry, toName); | 1566 | to_name); |
1602 | 1567 | ||
1603 | if (rc == -EEXIST && tcon->unix_ext) { | 1568 | if (rc == -EEXIST && tcon->unix_ext) { |
1604 | /* | 1569 | /* |
1605 | * Are src and dst hardlinks of same inode? We can | 1570 | * Are src and dst hardlinks of same inode? We can only tell |
1606 | * only tell with unix extensions enabled | 1571 | * with unix extensions enabled. |
1607 | */ | 1572 | */ |
1608 | info_buf_source = | 1573 | info_buf_source = |
1609 | kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), | 1574 | kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), |
@@ -1614,19 +1579,19 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
1614 | } | 1579 | } |
1615 | 1580 | ||
1616 | info_buf_target = info_buf_source + 1; | 1581 | info_buf_target = info_buf_source + 1; |
1617 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName, | 1582 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name, |
1618 | info_buf_source, | 1583 | info_buf_source, |
1619 | cifs_sb->local_nls, | 1584 | cifs_sb->local_nls, |
1620 | cifs_sb->mnt_cifs_flags & | 1585 | cifs_sb->mnt_cifs_flags & |
1621 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1586 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1622 | if (tmprc != 0) | 1587 | if (tmprc != 0) |
1623 | goto unlink_target; | 1588 | goto unlink_target; |
1624 | 1589 | ||
1625 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, toName, | 1590 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name, |
1626 | info_buf_target, | 1591 | info_buf_target, |
1627 | cifs_sb->local_nls, | 1592 | cifs_sb->local_nls, |
1628 | cifs_sb->mnt_cifs_flags & | 1593 | cifs_sb->mnt_cifs_flags & |
1629 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1594 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1630 | 1595 | ||
1631 | if (tmprc == 0 && (info_buf_source->UniqueId == | 1596 | if (tmprc == 0 && (info_buf_source->UniqueId == |
1632 | info_buf_target->UniqueId)) { | 1597 | info_buf_target->UniqueId)) { |
@@ -1634,8 +1599,11 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
1634 | rc = 0; | 1599 | rc = 0; |
1635 | goto cifs_rename_exit; | 1600 | goto cifs_rename_exit; |
1636 | } | 1601 | } |
1637 | } /* else ... BB we could add the same check for Windows by | 1602 | } |
1638 | checking the UniqueId via FILE_INTERNAL_INFO */ | 1603 | /* |
1604 | * else ... BB we could add the same check for Windows by | ||
1605 | * checking the UniqueId via FILE_INTERNAL_INFO | ||
1606 | */ | ||
1639 | 1607 | ||
1640 | unlink_target: | 1608 | unlink_target: |
1641 | /* Try unlinking the target dentry if it's not negative */ | 1609 | /* Try unlinking the target dentry if it's not negative */ |
@@ -1643,16 +1611,15 @@ unlink_target: | |||
1643 | tmprc = cifs_unlink(target_dir, target_dentry); | 1611 | tmprc = cifs_unlink(target_dir, target_dentry); |
1644 | if (tmprc) | 1612 | if (tmprc) |
1645 | goto cifs_rename_exit; | 1613 | goto cifs_rename_exit; |
1646 | 1614 | rc = cifs_do_rename(xid, source_dentry, from_name, | |
1647 | rc = cifs_do_rename(xid, source_dentry, fromName, | 1615 | target_dentry, to_name); |
1648 | target_dentry, toName); | ||
1649 | } | 1616 | } |
1650 | 1617 | ||
1651 | cifs_rename_exit: | 1618 | cifs_rename_exit: |
1652 | kfree(info_buf_source); | 1619 | kfree(info_buf_source); |
1653 | kfree(fromName); | 1620 | kfree(from_name); |
1654 | kfree(toName); | 1621 | kfree(to_name); |
1655 | FreeXid(xid); | 1622 | free_xid(xid); |
1656 | cifs_put_tlink(tlink); | 1623 | cifs_put_tlink(tlink); |
1657 | return rc; | 1624 | return rc; |
1658 | } | 1625 | } |
@@ -1727,7 +1694,7 @@ int cifs_revalidate_file_attr(struct file *filp) | |||
1727 | 1694 | ||
1728 | int cifs_revalidate_dentry_attr(struct dentry *dentry) | 1695 | int cifs_revalidate_dentry_attr(struct dentry *dentry) |
1729 | { | 1696 | { |
1730 | int xid; | 1697 | unsigned int xid; |
1731 | int rc = 0; | 1698 | int rc = 0; |
1732 | struct inode *inode = dentry->d_inode; | 1699 | struct inode *inode = dentry->d_inode; |
1733 | struct super_block *sb = dentry->d_sb; | 1700 | struct super_block *sb = dentry->d_sb; |
@@ -1739,7 +1706,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry) | |||
1739 | if (!cifs_inode_needs_reval(inode)) | 1706 | if (!cifs_inode_needs_reval(inode)) |
1740 | return rc; | 1707 | return rc; |
1741 | 1708 | ||
1742 | xid = GetXid(); | 1709 | xid = get_xid(); |
1743 | 1710 | ||
1744 | /* can not safely grab the rename sem here if rename calls revalidate | 1711 | /* can not safely grab the rename sem here if rename calls revalidate |
1745 | since that would deadlock */ | 1712 | since that would deadlock */ |
@@ -1761,7 +1728,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry) | |||
1761 | 1728 | ||
1762 | out: | 1729 | out: |
1763 | kfree(full_path); | 1730 | kfree(full_path); |
1764 | FreeXid(xid); | 1731 | free_xid(xid); |
1765 | return rc; | 1732 | return rc; |
1766 | } | 1733 | } |
1767 | 1734 | ||
@@ -1869,14 +1836,15 @@ static void cifs_setsize(struct inode *inode, loff_t offset) | |||
1869 | 1836 | ||
1870 | static int | 1837 | static int |
1871 | cifs_set_file_size(struct inode *inode, struct iattr *attrs, | 1838 | cifs_set_file_size(struct inode *inode, struct iattr *attrs, |
1872 | int xid, char *full_path) | 1839 | unsigned int xid, char *full_path) |
1873 | { | 1840 | { |
1874 | int rc; | 1841 | int rc; |
1875 | struct cifsFileInfo *open_file; | 1842 | struct cifsFileInfo *open_file; |
1876 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1843 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
1877 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1844 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1878 | struct tcon_link *tlink = NULL; | 1845 | struct tcon_link *tlink = NULL; |
1879 | struct cifs_tcon *pTcon = NULL; | 1846 | struct cifs_tcon *tcon = NULL; |
1847 | struct TCP_Server_Info *server; | ||
1880 | struct cifs_io_parms io_parms; | 1848 | struct cifs_io_parms io_parms; |
1881 | 1849 | ||
1882 | /* | 1850 | /* |
@@ -1890,19 +1858,21 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1890 | */ | 1858 | */ |
1891 | open_file = find_writable_file(cifsInode, true); | 1859 | open_file = find_writable_file(cifsInode, true); |
1892 | if (open_file) { | 1860 | if (open_file) { |
1893 | __u16 nfid = open_file->netfid; | 1861 | tcon = tlink_tcon(open_file->tlink); |
1894 | __u32 npid = open_file->pid; | 1862 | server = tcon->ses->server; |
1895 | pTcon = tlink_tcon(open_file->tlink); | 1863 | if (server->ops->set_file_size) |
1896 | rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid, | 1864 | rc = server->ops->set_file_size(xid, tcon, open_file, |
1897 | npid, false); | 1865 | attrs->ia_size, false); |
1866 | else | ||
1867 | rc = -ENOSYS; | ||
1898 | cifsFileInfo_put(open_file); | 1868 | cifsFileInfo_put(open_file); |
1899 | cFYI(1, "SetFSize for attrs rc = %d", rc); | 1869 | cFYI(1, "SetFSize for attrs rc = %d", rc); |
1900 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 1870 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
1901 | unsigned int bytes_written; | 1871 | unsigned int bytes_written; |
1902 | 1872 | ||
1903 | io_parms.netfid = nfid; | 1873 | io_parms.netfid = open_file->fid.netfid; |
1904 | io_parms.pid = npid; | 1874 | io_parms.pid = open_file->pid; |
1905 | io_parms.tcon = pTcon; | 1875 | io_parms.tcon = tcon; |
1906 | io_parms.offset = 0; | 1876 | io_parms.offset = 0; |
1907 | io_parms.length = attrs->ia_size; | 1877 | io_parms.length = attrs->ia_size; |
1908 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, | 1878 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, |
@@ -1912,52 +1882,55 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1912 | } else | 1882 | } else |
1913 | rc = -EINVAL; | 1883 | rc = -EINVAL; |
1914 | 1884 | ||
1915 | if (rc != 0) { | 1885 | if (!rc) |
1916 | if (pTcon == NULL) { | 1886 | goto set_size_out; |
1917 | tlink = cifs_sb_tlink(cifs_sb); | 1887 | |
1918 | if (IS_ERR(tlink)) | 1888 | if (tcon == NULL) { |
1919 | return PTR_ERR(tlink); | 1889 | tlink = cifs_sb_tlink(cifs_sb); |
1920 | pTcon = tlink_tcon(tlink); | 1890 | if (IS_ERR(tlink)) |
1921 | } | 1891 | return PTR_ERR(tlink); |
1892 | tcon = tlink_tcon(tlink); | ||
1893 | server = tcon->ses->server; | ||
1894 | } | ||
1922 | 1895 | ||
1923 | /* Set file size by pathname rather than by handle | 1896 | /* |
1924 | either because no valid, writeable file handle for | 1897 | * Set file size by pathname rather than by handle either because no |
1925 | it was found or because there was an error setting | 1898 | * valid, writeable file handle for it was found or because there was |
1926 | it by handle */ | 1899 | * an error setting it by handle. |
1927 | rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, | 1900 | */ |
1928 | false, cifs_sb->local_nls, | 1901 | if (server->ops->set_path_size) |
1902 | rc = server->ops->set_path_size(xid, tcon, full_path, | ||
1903 | attrs->ia_size, cifs_sb, false); | ||
1904 | else | ||
1905 | rc = -ENOSYS; | ||
1906 | cFYI(1, "SetEOF by path (setattrs) rc = %d", rc); | ||
1907 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | ||
1908 | __u16 netfid; | ||
1909 | int oplock = 0; | ||
1910 | |||
1911 | rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN, | ||
1912 | GENERIC_WRITE, CREATE_NOT_DIR, &netfid, | ||
1913 | &oplock, NULL, cifs_sb->local_nls, | ||
1929 | cifs_sb->mnt_cifs_flags & | 1914 | cifs_sb->mnt_cifs_flags & |
1930 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1915 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1931 | cFYI(1, "SetEOF by path (setattrs) rc = %d", rc); | 1916 | if (rc == 0) { |
1932 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 1917 | unsigned int bytes_written; |
1933 | __u16 netfid; | 1918 | |
1934 | int oplock = 0; | 1919 | io_parms.netfid = netfid; |
1935 | 1920 | io_parms.pid = current->tgid; | |
1936 | rc = SMBLegacyOpen(xid, pTcon, full_path, | 1921 | io_parms.tcon = tcon; |
1937 | FILE_OPEN, GENERIC_WRITE, | 1922 | io_parms.offset = 0; |
1938 | CREATE_NOT_DIR, &netfid, &oplock, NULL, | 1923 | io_parms.length = attrs->ia_size; |
1939 | cifs_sb->local_nls, | 1924 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL, |
1940 | cifs_sb->mnt_cifs_flags & | 1925 | NULL, 1); |
1941 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1926 | cFYI(1, "wrt seteof rc %d", rc); |
1942 | if (rc == 0) { | 1927 | CIFSSMBClose(xid, tcon, netfid); |
1943 | unsigned int bytes_written; | ||
1944 | |||
1945 | io_parms.netfid = netfid; | ||
1946 | io_parms.pid = current->tgid; | ||
1947 | io_parms.tcon = pTcon; | ||
1948 | io_parms.offset = 0; | ||
1949 | io_parms.length = attrs->ia_size; | ||
1950 | rc = CIFSSMBWrite(xid, &io_parms, | ||
1951 | &bytes_written, | ||
1952 | NULL, NULL, 1); | ||
1953 | cFYI(1, "wrt seteof rc %d", rc); | ||
1954 | CIFSSMBClose(xid, pTcon, netfid); | ||
1955 | } | ||
1956 | } | 1928 | } |
1957 | if (tlink) | ||
1958 | cifs_put_tlink(tlink); | ||
1959 | } | 1929 | } |
1930 | if (tlink) | ||
1931 | cifs_put_tlink(tlink); | ||
1960 | 1932 | ||
1933 | set_size_out: | ||
1961 | if (rc == 0) { | 1934 | if (rc == 0) { |
1962 | cifsInode->server_eof = attrs->ia_size; | 1935 | cifsInode->server_eof = attrs->ia_size; |
1963 | cifs_setsize(inode, attrs->ia_size); | 1936 | cifs_setsize(inode, attrs->ia_size); |
@@ -1971,7 +1944,7 @@ static int | |||
1971 | cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | 1944 | cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) |
1972 | { | 1945 | { |
1973 | int rc; | 1946 | int rc; |
1974 | int xid; | 1947 | unsigned int xid; |
1975 | char *full_path = NULL; | 1948 | char *full_path = NULL; |
1976 | struct inode *inode = direntry->d_inode; | 1949 | struct inode *inode = direntry->d_inode; |
1977 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1950 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
@@ -1984,7 +1957,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1984 | cFYI(1, "setattr_unix on file %s attrs->ia_valid=0x%x", | 1957 | cFYI(1, "setattr_unix on file %s attrs->ia_valid=0x%x", |
1985 | direntry->d_name.name, attrs->ia_valid); | 1958 | direntry->d_name.name, attrs->ia_valid); |
1986 | 1959 | ||
1987 | xid = GetXid(); | 1960 | xid = get_xid(); |
1988 | 1961 | ||
1989 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) | 1962 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) |
1990 | attrs->ia_valid |= ATTR_FORCE; | 1963 | attrs->ia_valid |= ATTR_FORCE; |
@@ -2064,7 +2037,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
2064 | args->device = 0; | 2037 | args->device = 0; |
2065 | open_file = find_writable_file(cifsInode, true); | 2038 | open_file = find_writable_file(cifsInode, true); |
2066 | if (open_file) { | 2039 | if (open_file) { |
2067 | u16 nfid = open_file->netfid; | 2040 | u16 nfid = open_file->fid.netfid; |
2068 | u32 npid = open_file->pid; | 2041 | u32 npid = open_file->pid; |
2069 | pTcon = tlink_tcon(open_file->tlink); | 2042 | pTcon = tlink_tcon(open_file->tlink); |
2070 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); | 2043 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); |
@@ -2104,14 +2077,14 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
2104 | out: | 2077 | out: |
2105 | kfree(args); | 2078 | kfree(args); |
2106 | kfree(full_path); | 2079 | kfree(full_path); |
2107 | FreeXid(xid); | 2080 | free_xid(xid); |
2108 | return rc; | 2081 | return rc; |
2109 | } | 2082 | } |
2110 | 2083 | ||
2111 | static int | 2084 | static int |
2112 | cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | 2085 | cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) |
2113 | { | 2086 | { |
2114 | int xid; | 2087 | unsigned int xid; |
2115 | uid_t uid = NO_CHANGE_32; | 2088 | uid_t uid = NO_CHANGE_32; |
2116 | gid_t gid = NO_CHANGE_32; | 2089 | gid_t gid = NO_CHANGE_32; |
2117 | struct inode *inode = direntry->d_inode; | 2090 | struct inode *inode = direntry->d_inode; |
@@ -2122,7 +2095,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
2122 | __u32 dosattr = 0; | 2095 | __u32 dosattr = 0; |
2123 | __u64 mode = NO_CHANGE_64; | 2096 | __u64 mode = NO_CHANGE_64; |
2124 | 2097 | ||
2125 | xid = GetXid(); | 2098 | xid = get_xid(); |
2126 | 2099 | ||
2127 | cFYI(1, "setattr on file %s attrs->iavalid 0x%x", | 2100 | cFYI(1, "setattr on file %s attrs->iavalid 0x%x", |
2128 | direntry->d_name.name, attrs->ia_valid); | 2101 | direntry->d_name.name, attrs->ia_valid); |
@@ -2132,14 +2105,14 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
2132 | 2105 | ||
2133 | rc = inode_change_ok(inode, attrs); | 2106 | rc = inode_change_ok(inode, attrs); |
2134 | if (rc < 0) { | 2107 | if (rc < 0) { |
2135 | FreeXid(xid); | 2108 | free_xid(xid); |
2136 | return rc; | 2109 | return rc; |
2137 | } | 2110 | } |
2138 | 2111 | ||
2139 | full_path = build_path_from_dentry(direntry); | 2112 | full_path = build_path_from_dentry(direntry); |
2140 | if (full_path == NULL) { | 2113 | if (full_path == NULL) { |
2141 | rc = -ENOMEM; | 2114 | rc = -ENOMEM; |
2142 | FreeXid(xid); | 2115 | free_xid(xid); |
2143 | return rc; | 2116 | return rc; |
2144 | } | 2117 | } |
2145 | 2118 | ||
@@ -2265,7 +2238,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
2265 | 2238 | ||
2266 | cifs_setattr_exit: | 2239 | cifs_setattr_exit: |
2267 | kfree(full_path); | 2240 | kfree(full_path); |
2268 | FreeXid(xid); | 2241 | free_xid(xid); |
2269 | return rc; | 2242 | return rc; |
2270 | } | 2243 | } |
2271 | 2244 | ||