diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 78 |
1 files changed, 54 insertions, 24 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 6e82e1ae03b..ca3af4eafcb 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -1030,14 +1030,15 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1030 | /* now that we found one valid file | 1030 | /* now that we found one valid file |
1031 | handle no sense continuing to loop | 1031 | handle no sense continuing to loop |
1032 | trying others, so break here */ | 1032 | trying others, so break here */ |
1033 | /* if(rc == -EINVAL) { | 1033 | if(rc == -EINVAL) { |
1034 | int bytes_written; | 1034 | int bytes_written; |
1035 | rc = CIFSSMBWrite(xid, pTcon, | 1035 | rc = CIFSSMBWrite(xid, pTcon, |
1036 | nfid, 0, | 1036 | nfid, 0, |
1037 | attrs->ia_size, | 1037 | attrs->ia_size, |
1038 | &bytes_written, | 1038 | &bytes_written, NULL, |
1039 | NULL, NULL, long_op); | 1039 | NULL, 1 /* 45 sec */); |
1040 | } */ | 1040 | cFYI(1,("wrt seteof rc %d",rc)); |
1041 | } | ||
1041 | break; | 1042 | break; |
1042 | } | 1043 | } |
1043 | } | 1044 | } |
@@ -1055,14 +1056,30 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1055 | cifs_sb->local_nls, | 1056 | cifs_sb->local_nls, |
1056 | cifs_sb->mnt_cifs_flags & | 1057 | cifs_sb->mnt_cifs_flags & |
1057 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1058 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1058 | cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc)); | 1059 | cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc)); |
1059 | /* if(rc == -EINVAL) | 1060 | if(rc == -EINVAL) { |
1060 | old_style_set_eof_via_write(xid, pTcon, | 1061 | __u16 netfid; |
1061 | full_path, | 1062 | int oplock = FALSE; |
1062 | attrs->ia_size, | 1063 | |
1063 | cifs_sb->local_nls, | 1064 | rc = SMBLegacyOpen(xid, pTcon, full_path, |
1064 | cifs_sb->mnt_cifs_flags & | 1065 | FILE_OPEN, |
1065 | CIFS_MOUNT_MAP_SPECIAL_CHR);*/ | 1066 | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, |
1067 | CREATE_NOT_DIR, &netfid, &oplock, | ||
1068 | NULL, cifs_sb->local_nls, | ||
1069 | cifs_sb->mnt_cifs_flags & | ||
1070 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1071 | if (rc==0) { | ||
1072 | int bytes_written; | ||
1073 | rc = CIFSSMBWrite(xid, pTcon, | ||
1074 | netfid, 0, | ||
1075 | attrs->ia_size, | ||
1076 | &bytes_written, NULL, | ||
1077 | NULL, 1 /* 45 sec */); | ||
1078 | cFYI(1,("wrt seteof rc %d",rc)); | ||
1079 | CIFSSMBClose(xid, pTcon, netfid); | ||
1080 | } | ||
1081 | |||
1082 | } | ||
1066 | } | 1083 | } |
1067 | 1084 | ||
1068 | /* Server is ok setting allocation size implicitly - no need | 1085 | /* Server is ok setting allocation size implicitly - no need |
@@ -1075,24 +1092,22 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1075 | rc = vmtruncate(direntry->d_inode, attrs->ia_size); | 1092 | rc = vmtruncate(direntry->d_inode, attrs->ia_size); |
1076 | cifs_truncate_page(direntry->d_inode->i_mapping, | 1093 | cifs_truncate_page(direntry->d_inode->i_mapping, |
1077 | direntry->d_inode->i_size); | 1094 | direntry->d_inode->i_size); |
1078 | } | 1095 | } else |
1096 | goto cifs_setattr_exit; | ||
1079 | } | 1097 | } |
1080 | if (attrs->ia_valid & ATTR_UID) { | 1098 | if (attrs->ia_valid & ATTR_UID) { |
1081 | cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid)); | 1099 | cFYI(1, ("UID changed to %d", attrs->ia_uid)); |
1082 | uid = attrs->ia_uid; | 1100 | uid = attrs->ia_uid; |
1083 | /* entry->uid = cpu_to_le16(attr->ia_uid); */ | ||
1084 | } | 1101 | } |
1085 | if (attrs->ia_valid & ATTR_GID) { | 1102 | if (attrs->ia_valid & ATTR_GID) { |
1086 | cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid)); | 1103 | cFYI(1, ("GID changed to %d", attrs->ia_gid)); |
1087 | gid = attrs->ia_gid; | 1104 | gid = attrs->ia_gid; |
1088 | /* entry->gid = cpu_to_le16(attr->ia_gid); */ | ||
1089 | } | 1105 | } |
1090 | 1106 | ||
1091 | time_buf.Attributes = 0; | 1107 | time_buf.Attributes = 0; |
1092 | if (attrs->ia_valid & ATTR_MODE) { | 1108 | if (attrs->ia_valid & ATTR_MODE) { |
1093 | cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode)); | 1109 | cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode)); |
1094 | mode = attrs->ia_mode; | 1110 | mode = attrs->ia_mode; |
1095 | /* entry->mode = cpu_to_le16(attr->ia_mode); */ | ||
1096 | } | 1111 | } |
1097 | 1112 | ||
1098 | if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) | 1113 | if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) |
@@ -1132,18 +1147,24 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1132 | cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime)); | 1147 | cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime)); |
1133 | } else | 1148 | } else |
1134 | time_buf.LastWriteTime = 0; | 1149 | time_buf.LastWriteTime = 0; |
1135 | 1150 | /* Do not set ctime explicitly unless other time | |
1136 | if (attrs->ia_valid & ATTR_CTIME) { | 1151 | stamps are changed explicitly (i.e. by utime() |
1152 | since we would then have a mix of client and | ||
1153 | server times */ | ||
1154 | |||
1155 | if (set_time && (attrs->ia_valid & ATTR_CTIME)) { | ||
1137 | set_time = TRUE; | 1156 | set_time = TRUE; |
1138 | cFYI(1, (" CIFS - CTIME changed ")); /* BB probably no need */ | 1157 | /* Although Samba throws this field away |
1158 | it may be useful to Windows - but we do | ||
1159 | not want to set ctime unless some other | ||
1160 | timestamp is changing */ | ||
1161 | cFYI(1, ("CIFS - CTIME changed ")); | ||
1139 | time_buf.ChangeTime = | 1162 | time_buf.ChangeTime = |
1140 | cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); | 1163 | cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); |
1141 | } else | 1164 | } else |
1142 | time_buf.ChangeTime = 0; | 1165 | time_buf.ChangeTime = 0; |
1143 | 1166 | ||
1144 | if (set_time || time_buf.Attributes) { | 1167 | if (set_time || time_buf.Attributes) { |
1145 | /* BB what if setting one attribute fails (such as size) but | ||
1146 | time setting works? */ | ||
1147 | time_buf.CreationTime = 0; /* do not change */ | 1168 | time_buf.CreationTime = 0; /* do not change */ |
1148 | /* In the future we should experiment - try setting timestamps | 1169 | /* In the future we should experiment - try setting timestamps |
1149 | via Handle (SetFileInfo) instead of by path */ | 1170 | via Handle (SetFileInfo) instead of by path */ |
@@ -1182,12 +1203,21 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1182 | &time_buf, cifs_sb->local_nls); */ | 1203 | &time_buf, cifs_sb->local_nls); */ |
1183 | } | 1204 | } |
1184 | } | 1205 | } |
1206 | /* Even if error on time set, no sense failing the call if | ||
1207 | the server would set the time to a reasonable value anyway, | ||
1208 | and this check ensures that we are not being called from | ||
1209 | sys_utimes in which case we ought to fail the call back to | ||
1210 | the user when the server rejects the call */ | ||
1211 | if((rc) && (attrs->ia_valid && | ||
1212 | (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE))) | ||
1213 | rc = 0; | ||
1185 | } | 1214 | } |
1186 | 1215 | ||
1187 | /* do not need local check to inode_check_ok since the server does | 1216 | /* do not need local check to inode_check_ok since the server does |
1188 | that */ | 1217 | that */ |
1189 | if (!rc) | 1218 | if (!rc) |
1190 | rc = inode_setattr(direntry->d_inode, attrs); | 1219 | rc = inode_setattr(direntry->d_inode, attrs); |
1220 | cifs_setattr_exit: | ||
1191 | kfree(full_path); | 1221 | kfree(full_path); |
1192 | FreeXid(xid); | 1222 | FreeXid(xid); |
1193 | return rc; | 1223 | return rc; |