aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2005-09-20 23:49:16 -0400
committerSteve French <sfrench@us.ibm.com>2005-09-20 23:49:16 -0400
commite30dcf3a1905b4d2154f95db5fdfdf69691b4f0e (patch)
tree13fb11eff9f5bbbfae6eeefaf8f6a56c76885347 /fs
parent3e87d80391c84eefceb4bda94a6363661dba4f71 (diff)
[CIFS] Add support for legacy servers part eight. Write fixes for Windows
ME, and do not set ctime unless explicitly requested with atime and/or mtime (it gets thrown away by most servers anyway as there is no way to set this via posix). Signed-off-by: Steve French (sfrench@us.ibm.com)
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/CHANGES2
-rw-r--r--fs/cifs/cifsfs.c2
-rw-r--r--fs/cifs/cifssmb.c15
-rw-r--r--fs/cifs/inode.c78
4 files changed, 66 insertions, 31 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 8b55e56cf1fe..47ae68b51847 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -2,6 +2,8 @@ Version 1.37
2------------ 2------------
3Fix readdir caching when unlink removes file in current search buffer, 3Fix readdir caching when unlink removes file in current search buffer,
4and this is followed by a rewind search to just before the deleted entry. 4and this is followed by a rewind search to just before the deleted entry.
5Do not attempt to set ctime unless atime and/or mtime change requested
6(most servers throw it away anyway).
5 7
6Version 1.36 8Version 1.36
7------------ 9------------
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 43fb2aafa528..f738c8b19e3b 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -256,7 +256,7 @@ cifs_alloc_inode(struct super_block *sb)
256 cifs_inode->clientCanCacheAll = FALSE; 256 cifs_inode->clientCanCacheAll = FALSE;
257 cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE; 257 cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE;
258 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ 258 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
259 259 cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;
260 INIT_LIST_HEAD(&cifs_inode->openFileList); 260 INIT_LIST_HEAD(&cifs_inode->openFileList);
261 return &cifs_inode->vfs_inode; 261 return &cifs_inode->vfs_inode;
262} 262}
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 575b2281518d..f72a61df3c68 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1072,7 +1072,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1072 if (bytes_sent > count) 1072 if (bytes_sent > count)
1073 bytes_sent = count; 1073 bytes_sent = count;
1074 pSMB->DataOffset = 1074 pSMB->DataOffset =
1075 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); 1075 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1076 if(buf) 1076 if(buf)
1077 memcpy(pSMB->Data,buf,bytes_sent); 1077 memcpy(pSMB->Data,buf,bytes_sent);
1078 else if(ubuf) { 1078 else if(ubuf) {
@@ -1080,20 +1080,23 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1080 cifs_buf_release(pSMB); 1080 cifs_buf_release(pSMB);
1081 return -EFAULT; 1081 return -EFAULT;
1082 } 1082 }
1083 } else { 1083 } else if (count != 0) {
1084 /* No buffer */ 1084 /* No buffer */
1085 cifs_buf_release(pSMB); 1085 cifs_buf_release(pSMB);
1086 return -EINVAL; 1086 return -EINVAL;
1087 } /* else setting file size with write of zero bytes */
1088 if(wct == 14)
1089 byte_count = bytes_sent + 1; /* pad */
1090 else /* wct == 12 */ {
1091 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1087 } 1092 }
1088
1089 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
1090 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); 1093 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1091 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); 1094 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1092 pSMB->hdr.smb_buf_length += bytes_sent+1; 1095 pSMB->hdr.smb_buf_length += byte_count;
1093 1096
1094 if(wct == 14) 1097 if(wct == 14)
1095 pSMB->ByteCount = cpu_to_le16(byte_count); 1098 pSMB->ByteCount = cpu_to_le16(byte_count);
1096 else { /* old style write has byte count 4 bytes earlier */ 1099 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1097 struct smb_com_writex_req * pSMBW = 1100 struct smb_com_writex_req * pSMBW =
1098 (struct smb_com_writex_req *)pSMB; 1101 (struct smb_com_writex_req *)pSMB;
1099 pSMBW->ByteCount = cpu_to_le16(byte_count); 1102 pSMBW->ByteCount = cpu_to_le16(byte_count);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 6e82e1ae03b4..ca3af4eafcb2 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);
1220cifs_setattr_exit:
1191 kfree(full_path); 1221 kfree(full_path);
1192 FreeXid(xid); 1222 FreeXid(xid);
1193 return rc; 1223 return rc;