diff options
-rw-r--r-- | fs/cifs/cifsglob.h | 3 | ||||
-rw-r--r-- | fs/cifs/inode.c | 79 | ||||
-rw-r--r-- | fs/cifs/smb1ops.c | 79 |
3 files changed, 88 insertions, 73 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 803c21218633..dff35830601f 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -258,6 +258,9 @@ struct smb_version_operations { | |||
258 | /* set size by file handle */ | 258 | /* set size by file handle */ |
259 | int (*set_file_size)(const unsigned int, struct cifs_tcon *, | 259 | int (*set_file_size)(const unsigned int, struct cifs_tcon *, |
260 | struct cifsFileInfo *, __u64, bool); | 260 | struct cifsFileInfo *, __u64, bool); |
261 | /* set attributes */ | ||
262 | int (*set_file_info)(struct inode *, const char *, FILE_BASIC_INFO *, | ||
263 | const unsigned int); | ||
261 | /* build a full path to the root of the mount */ | 264 | /* build a full path to the root of the mount */ |
262 | char * (*build_path_to_root)(struct smb_vol *, struct cifs_sb_info *, | 265 | char * (*build_path_to_root)(struct smb_vol *, struct cifs_sb_info *, |
263 | struct cifs_tcon *); | 266 | struct cifs_tcon *); |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 85e1b0a405a8..e74e1bceb416 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -886,21 +886,18 @@ int | |||
886 | cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid, | 886 | cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid, |
887 | char *full_path, __u32 dosattr) | 887 | char *full_path, __u32 dosattr) |
888 | { | 888 | { |
889 | int rc; | ||
890 | int oplock = 0; | ||
891 | __u16 netfid; | ||
892 | __u32 netpid; | ||
893 | bool set_time = false; | 889 | bool set_time = false; |
894 | struct cifsFileInfo *open_file; | ||
895 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | ||
896 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 890 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
897 | struct tcon_link *tlink = NULL; | 891 | struct TCP_Server_Info *server; |
898 | struct cifs_tcon *pTcon; | ||
899 | FILE_BASIC_INFO info_buf; | 892 | FILE_BASIC_INFO info_buf; |
900 | 893 | ||
901 | if (attrs == NULL) | 894 | if (attrs == NULL) |
902 | return -EINVAL; | 895 | return -EINVAL; |
903 | 896 | ||
897 | server = cifs_sb_master_tcon(cifs_sb)->ses->server; | ||
898 | if (!server->ops->set_file_info) | ||
899 | return -ENOSYS; | ||
900 | |||
904 | if (attrs->ia_valid & ATTR_ATIME) { | 901 | if (attrs->ia_valid & ATTR_ATIME) { |
905 | set_time = true; | 902 | set_time = true; |
906 | info_buf.LastAccessTime = | 903 | info_buf.LastAccessTime = |
@@ -931,71 +928,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid, | |||
931 | info_buf.CreationTime = 0; /* don't change */ | 928 | info_buf.CreationTime = 0; /* don't change */ |
932 | info_buf.Attributes = cpu_to_le32(dosattr); | 929 | info_buf.Attributes = cpu_to_le32(dosattr); |
933 | 930 | ||
934 | /* | 931 | return server->ops->set_file_info(inode, full_path, &info_buf, xid); |
935 | * If the file is already open for write, just use that fileid | ||
936 | */ | ||
937 | open_file = find_writable_file(cifsInode, true); | ||
938 | if (open_file) { | ||
939 | netfid = open_file->fid.netfid; | ||
940 | netpid = open_file->pid; | ||
941 | pTcon = tlink_tcon(open_file->tlink); | ||
942 | goto set_via_filehandle; | ||
943 | } | ||
944 | |||
945 | tlink = cifs_sb_tlink(cifs_sb); | ||
946 | if (IS_ERR(tlink)) { | ||
947 | rc = PTR_ERR(tlink); | ||
948 | tlink = NULL; | ||
949 | goto out; | ||
950 | } | ||
951 | pTcon = tlink_tcon(tlink); | ||
952 | |||
953 | /* | ||
954 | * NT4 apparently returns success on this call, but it doesn't | ||
955 | * really work. | ||
956 | */ | ||
957 | if (!(pTcon->ses->flags & CIFS_SES_NT4)) { | ||
958 | rc = CIFSSMBSetPathInfo(xid, pTcon, full_path, | ||
959 | &info_buf, cifs_sb->local_nls, | ||
960 | cifs_sb->mnt_cifs_flags & | ||
961 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
962 | if (rc == 0) { | ||
963 | cifsInode->cifsAttrs = dosattr; | ||
964 | goto out; | ||
965 | } else if (rc != -EOPNOTSUPP && rc != -EINVAL) | ||
966 | goto out; | ||
967 | } | ||
968 | |||
969 | cFYI(1, "calling SetFileInfo since SetPathInfo for " | ||
970 | "times not supported by this server"); | ||
971 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, | ||
972 | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, | ||
973 | CREATE_NOT_DIR, &netfid, &oplock, | ||
974 | NULL, cifs_sb->local_nls, | ||
975 | cifs_sb->mnt_cifs_flags & | ||
976 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
977 | |||
978 | if (rc != 0) { | ||
979 | if (rc == -EIO) | ||
980 | rc = -EINVAL; | ||
981 | goto out; | ||
982 | } | ||
983 | |||
984 | netpid = current->tgid; | ||
985 | |||
986 | set_via_filehandle: | ||
987 | rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid); | ||
988 | if (!rc) | ||
989 | cifsInode->cifsAttrs = dosattr; | ||
990 | |||
991 | if (open_file == NULL) | ||
992 | CIFSSMBClose(xid, pTcon, netfid); | ||
993 | else | ||
994 | cifsFileInfo_put(open_file); | ||
995 | out: | ||
996 | if (tlink != NULL) | ||
997 | cifs_put_tlink(tlink); | ||
998 | return rc; | ||
999 | } | 932 | } |
1000 | 933 | ||
1001 | /* | 934 | /* |
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index b73d2750296d..ed311968437a 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c | |||
@@ -758,6 +758,84 @@ cifs_sync_write(const unsigned int xid, struct cifsFileInfo *cfile, | |||
758 | return CIFSSMBWrite2(xid, parms, written, iov, nr_segs); | 758 | return CIFSSMBWrite2(xid, parms, written, iov, nr_segs); |
759 | } | 759 | } |
760 | 760 | ||
761 | static int | ||
762 | smb_set_file_info(struct inode *inode, const char *full_path, | ||
763 | FILE_BASIC_INFO *buf, const unsigned int xid) | ||
764 | { | ||
765 | int oplock = 0; | ||
766 | int rc; | ||
767 | __u16 netfid; | ||
768 | __u32 netpid; | ||
769 | struct cifsFileInfo *open_file; | ||
770 | struct cifsInodeInfo *cinode = CIFS_I(inode); | ||
771 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
772 | struct tcon_link *tlink = NULL; | ||
773 | struct cifs_tcon *tcon; | ||
774 | FILE_BASIC_INFO info_buf; | ||
775 | |||
776 | /* if the file is already open for write, just use that fileid */ | ||
777 | open_file = find_writable_file(cinode, true); | ||
778 | if (open_file) { | ||
779 | netfid = open_file->fid.netfid; | ||
780 | netpid = open_file->pid; | ||
781 | tcon = tlink_tcon(open_file->tlink); | ||
782 | goto set_via_filehandle; | ||
783 | } | ||
784 | |||
785 | tlink = cifs_sb_tlink(cifs_sb); | ||
786 | if (IS_ERR(tlink)) { | ||
787 | rc = PTR_ERR(tlink); | ||
788 | tlink = NULL; | ||
789 | goto out; | ||
790 | } | ||
791 | tcon = tlink_tcon(tlink); | ||
792 | |||
793 | /* | ||
794 | * NT4 apparently returns success on this call, but it doesn't really | ||
795 | * work. | ||
796 | */ | ||
797 | if (!(tcon->ses->flags & CIFS_SES_NT4)) { | ||
798 | rc = CIFSSMBSetPathInfo(xid, tcon, full_path, buf, | ||
799 | cifs_sb->local_nls, | ||
800 | cifs_sb->mnt_cifs_flags & | ||
801 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
802 | if (rc == 0) { | ||
803 | cinode->cifsAttrs = le32_to_cpu(buf->Attributes); | ||
804 | goto out; | ||
805 | } else if (rc != -EOPNOTSUPP && rc != -EINVAL) | ||
806 | goto out; | ||
807 | } | ||
808 | |||
809 | cFYI(1, "calling SetFileInfo since SetPathInfo for times not supported " | ||
810 | "by this server"); | ||
811 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | ||
812 | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, | ||
813 | &netfid, &oplock, NULL, cifs_sb->local_nls, | ||
814 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
815 | |||
816 | if (rc != 0) { | ||
817 | if (rc == -EIO) | ||
818 | rc = -EINVAL; | ||
819 | goto out; | ||
820 | } | ||
821 | |||
822 | netpid = current->tgid; | ||
823 | |||
824 | set_via_filehandle: | ||
825 | rc = CIFSSMBSetFileInfo(xid, tcon, &info_buf, netfid, netpid); | ||
826 | if (!rc) | ||
827 | cinode->cifsAttrs = le32_to_cpu(buf->Attributes); | ||
828 | |||
829 | if (open_file == NULL) | ||
830 | CIFSSMBClose(xid, tcon, netfid); | ||
831 | else | ||
832 | cifsFileInfo_put(open_file); | ||
833 | out: | ||
834 | if (tlink != NULL) | ||
835 | cifs_put_tlink(tlink); | ||
836 | return rc; | ||
837 | } | ||
838 | |||
761 | struct smb_version_operations smb1_operations = { | 839 | struct smb_version_operations smb1_operations = { |
762 | .send_cancel = send_nt_cancel, | 840 | .send_cancel = send_nt_cancel, |
763 | .compare_fids = cifs_compare_fids, | 841 | .compare_fids = cifs_compare_fids, |
@@ -795,6 +873,7 @@ struct smb_version_operations smb1_operations = { | |||
795 | .get_srv_inum = cifs_get_srv_inum, | 873 | .get_srv_inum = cifs_get_srv_inum, |
796 | .set_path_size = CIFSSMBSetEOF, | 874 | .set_path_size = CIFSSMBSetEOF, |
797 | .set_file_size = CIFSSMBSetFileSize, | 875 | .set_file_size = CIFSSMBSetFileSize, |
876 | .set_file_info = smb_set_file_info, | ||
798 | .build_path_to_root = cifs_build_path_to_root, | 877 | .build_path_to_root = cifs_build_path_to_root, |
799 | .echo = CIFSSMBEcho, | 878 | .echo = CIFSSMBEcho, |
800 | .mkdir = CIFSSMBMkDir, | 879 | .mkdir = CIFSSMBMkDir, |