aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/inode.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2005-10-21 11:39:12 -0400
committerSteve French <sfrench@us.ibm.com>2005-10-21 11:39:12 -0400
commitd6d3f5bc68be3c4ab84e6f1f9db92291da671504 (patch)
tree76946c62cc7d1a18203fba50ea87fd567387f637 /fs/cifs/inode.c
parentac9b9c667c2e1194e22ebe0a441ae1c37aaa9b90 (diff)
parent23e7dd7d95f6fdc167a6d6ddea79ced0af33bbff (diff)
Merge with /pub/scm/linux/kernel/git/sfrench/cifs-2.6.git/
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r--fs/cifs/inode.c150
1 files changed, 100 insertions, 50 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 8d336a900255..912d401600f6 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -166,7 +166,13 @@ int cifs_get_inode_info_unix(struct inode **pinode,
166 inode->i_fop = &cifs_file_direct_ops; 166 inode->i_fop = &cifs_file_direct_ops;
167 else 167 else
168 inode->i_fop = &cifs_file_ops; 168 inode->i_fop = &cifs_file_ops;
169 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
170 inode->i_fop->lock = NULL;
169 inode->i_data.a_ops = &cifs_addr_ops; 171 inode->i_data.a_ops = &cifs_addr_ops;
172 /* check if server can support readpages */
173 if(pTcon->ses->server->maxBuf <
174 4096 + MAX_CIFS_HDR_SIZE)
175 inode->i_data.a_ops->readpages = NULL;
170 } else if (S_ISDIR(inode->i_mode)) { 176 } else if (S_ISDIR(inode->i_mode)) {
171 cFYI(1, (" Directory inode")); 177 cFYI(1, (" Directory inode"));
172 inode->i_op = &cifs_dir_inode_ops; 178 inode->i_op = &cifs_dir_inode_ops;
@@ -213,8 +219,18 @@ int cifs_get_inode_info(struct inode **pinode,
213 pfindData = (FILE_ALL_INFO *)buf; 219 pfindData = (FILE_ALL_INFO *)buf;
214 /* could do find first instead but this returns more info */ 220 /* could do find first instead but this returns more info */
215 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, 221 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
216 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 222 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
217 CIFS_MOUNT_MAP_SPECIAL_CHR); 223 CIFS_MOUNT_MAP_SPECIAL_CHR);
224 /* BB optimize code so we do not make the above call
225 when server claims no NT SMB support and the above call
226 failed at least once - set flag in tcon or mount */
227 if((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
228 rc = SMBQueryInformation(xid, pTcon, search_path,
229 pfindData, cifs_sb->local_nls,
230 cifs_sb->mnt_cifs_flags &
231 CIFS_MOUNT_MAP_SPECIAL_CHR);
232 }
233
218 } 234 }
219 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ 235 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
220 if (rc) { 236 if (rc) {
@@ -320,6 +336,16 @@ int cifs_get_inode_info(struct inode **pinode,
320 on dirs */ 336 on dirs */
321 inode->i_mode = cifs_sb->mnt_dir_mode; 337 inode->i_mode = cifs_sb->mnt_dir_mode;
322 inode->i_mode |= S_IFDIR; 338 inode->i_mode |= S_IFDIR;
339 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
340 (cifsInfo->cifsAttrs & ATTR_SYSTEM) &&
341 /* No need to le64 convert size of zero */
342 (pfindData->EndOfFile == 0)) {
343 inode->i_mode = cifs_sb->mnt_file_mode;
344 inode->i_mode |= S_IFIFO;
345/* BB Finish for SFU style symlinks and devies */
346/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
347 (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */
348
323 } else { 349 } else {
324 inode->i_mode |= S_IFREG; 350 inode->i_mode |= S_IFREG;
325 /* treat the dos attribute of read-only as read-only 351 /* treat the dos attribute of read-only as read-only
@@ -359,7 +385,12 @@ int cifs_get_inode_info(struct inode **pinode,
359 inode->i_fop = &cifs_file_direct_ops; 385 inode->i_fop = &cifs_file_direct_ops;
360 else 386 else
361 inode->i_fop = &cifs_file_ops; 387 inode->i_fop = &cifs_file_ops;
388 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
389 inode->i_fop->lock = NULL;
362 inode->i_data.a_ops = &cifs_addr_ops; 390 inode->i_data.a_ops = &cifs_addr_ops;
391 if(pTcon->ses->server->maxBuf <
392 4096 + MAX_CIFS_HDR_SIZE)
393 inode->i_data.a_ops->readpages = NULL;
363 } else if (S_ISDIR(inode->i_mode)) { 394 } else if (S_ISDIR(inode->i_mode)) {
364 cFYI(1, (" Directory inode ")); 395 cFYI(1, (" Directory inode "));
365 inode->i_op = &cifs_dir_inode_ops; 396 inode->i_op = &cifs_dir_inode_ops;
@@ -577,7 +608,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
577 rc = cifs_get_inode_info(&newinode, full_path, NULL, 608 rc = cifs_get_inode_info(&newinode, full_path, NULL,
578 inode->i_sb,xid); 609 inode->i_sb,xid);
579 610
580 direntry->d_op = &cifs_dentry_ops; 611 if (pTcon->nocase)
612 direntry->d_op = &cifs_ci_dentry_ops;
613 else
614 direntry->d_op = &cifs_dentry_ops;
581 d_instantiate(direntry, newinode); 615 d_instantiate(direntry, newinode);
582 if (direntry->d_inode) 616 if (direntry->d_inode)
583 direntry->d_inode->i_nlink = 2; 617 direntry->d_inode->i_nlink = 2;
@@ -928,7 +962,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
928 struct cifsTconInfo *pTcon; 962 struct cifsTconInfo *pTcon;
929 char *full_path = NULL; 963 char *full_path = NULL;
930 int rc = -EACCES; 964 int rc = -EACCES;
931 int found = FALSE;
932 struct cifsFileInfo *open_file = NULL; 965 struct cifsFileInfo *open_file = NULL;
933 FILE_BASIC_INFO time_buf; 966 FILE_BASIC_INFO time_buf;
934 int set_time = FALSE; 967 int set_time = FALSE;
@@ -936,7 +969,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
936 __u64 uid = 0xFFFFFFFFFFFFFFFFULL; 969 __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
937 __u64 gid = 0xFFFFFFFFFFFFFFFFULL; 970 __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
938 struct cifsInodeInfo *cifsInode; 971 struct cifsInodeInfo *cifsInode;
939 struct list_head *tmp;
940 972
941 xid = GetXid(); 973 xid = GetXid();
942 974
@@ -961,7 +993,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
961 filemap_fdatawait(direntry->d_inode->i_mapping); 993 filemap_fdatawait(direntry->d_inode->i_mapping);
962 994
963 if (attrs->ia_valid & ATTR_SIZE) { 995 if (attrs->ia_valid & ATTR_SIZE) {
964 read_lock(&GlobalSMBSeslock);
965 /* To avoid spurious oplock breaks from server, in the case of 996 /* To avoid spurious oplock breaks from server, in the case of
966 inodes that we already have open, avoid doing path based 997 inodes that we already have open, avoid doing path based
967 setting of file size if we can do it by handle. 998 setting of file size if we can do it by handle.
@@ -969,40 +1000,23 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
969 when the local oplock break takes longer to flush 1000 when the local oplock break takes longer to flush
970 writebehind data than the SMB timeout for the SetPathInfo 1001 writebehind data than the SMB timeout for the SetPathInfo
971 request would allow */ 1002 request would allow */
972 list_for_each(tmp, &cifsInode->openFileList) { 1003 open_file = find_writable_file(cifsInode);
973 open_file = list_entry(tmp, struct cifsFileInfo, 1004 if (open_file) {
974 flist); 1005 __u16 nfid = open_file->netfid;
975 /* We check if file is open for writing first */ 1006 __u32 npid = open_file->pid;
976 if ((open_file->pfile) && 1007 rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
977 ((open_file->pfile->f_flags & O_RDWR) || 1008 nfid, npid, FALSE);
978 (open_file->pfile->f_flags & O_WRONLY))) { 1009 atomic_dec(&open_file->wrtPending);
979 if (open_file->invalidHandle == FALSE) { 1010 cFYI(1,("SetFSize for attrs rc = %d", rc));
980 /* we found a valid, writeable network 1011 if(rc == -EINVAL) {
981 file handle to use to try to set the 1012 int bytes_written;
982 file size */ 1013 rc = CIFSSMBWrite(xid, pTcon,
983 __u16 nfid = open_file->netfid; 1014 nfid, 0, attrs->ia_size,
984 __u32 npid = open_file->pid; 1015 &bytes_written, NULL, NULL,
985 read_unlock(&GlobalSMBSeslock); 1016 1 /* 45 seconds */);
986 found = TRUE; 1017 cFYI(1,("Wrt seteof rc %d", rc));
987 rc = CIFSSMBSetFileSize(xid, pTcon,
988 attrs->ia_size, nfid, npid,
989 FALSE);
990 cFYI(1, ("SetFileSize by handle "
991 "(setattrs) rc = %d", rc));
992 /* Do not need reopen and retry on
993 EAGAIN since we will retry by
994 pathname below */
995
996 /* now that we found one valid file
997 handle no sense continuing to loop
998 trying others, so break here */
999 break;
1000 }
1001 } 1018 }
1002 } 1019 }
1003 if (found == FALSE)
1004 read_unlock(&GlobalSMBSeslock);
1005
1006 if (rc != 0) { 1020 if (rc != 0) {
1007 /* Set file size by pathname rather than by handle 1021 /* Set file size by pathname rather than by handle
1008 either because no valid, writeable file handle for 1022 either because no valid, writeable file handle for
@@ -1013,7 +1027,30 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1013 cifs_sb->local_nls, 1027 cifs_sb->local_nls,
1014 cifs_sb->mnt_cifs_flags & 1028 cifs_sb->mnt_cifs_flags &
1015 CIFS_MOUNT_MAP_SPECIAL_CHR); 1029 CIFS_MOUNT_MAP_SPECIAL_CHR);
1016 cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc)); 1030 cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
1031 if(rc == -EINVAL) {
1032 __u16 netfid;
1033 int oplock = FALSE;
1034
1035 rc = SMBLegacyOpen(xid, pTcon, full_path,
1036 FILE_OPEN,
1037 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1038 CREATE_NOT_DIR, &netfid, &oplock,
1039 NULL, cifs_sb->local_nls,
1040 cifs_sb->mnt_cifs_flags &
1041 CIFS_MOUNT_MAP_SPECIAL_CHR);
1042 if (rc==0) {
1043 int bytes_written;
1044 rc = CIFSSMBWrite(xid, pTcon,
1045 netfid, 0,
1046 attrs->ia_size,
1047 &bytes_written, NULL,
1048 NULL, 1 /* 45 sec */);
1049 cFYI(1,("wrt seteof rc %d",rc));
1050 CIFSSMBClose(xid, pTcon, netfid);
1051 }
1052
1053 }
1017 } 1054 }
1018 1055
1019 /* Server is ok setting allocation size implicitly - no need 1056 /* Server is ok setting allocation size implicitly - no need
@@ -1026,24 +1063,22 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1026 rc = vmtruncate(direntry->d_inode, attrs->ia_size); 1063 rc = vmtruncate(direntry->d_inode, attrs->ia_size);
1027 cifs_truncate_page(direntry->d_inode->i_mapping, 1064 cifs_truncate_page(direntry->d_inode->i_mapping,
1028 direntry->d_inode->i_size); 1065 direntry->d_inode->i_size);
1029 } 1066 } else
1067 goto cifs_setattr_exit;
1030 } 1068 }
1031 if (attrs->ia_valid & ATTR_UID) { 1069 if (attrs->ia_valid & ATTR_UID) {
1032 cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid)); 1070 cFYI(1, ("UID changed to %d", attrs->ia_uid));
1033 uid = attrs->ia_uid; 1071 uid = attrs->ia_uid;
1034 /* entry->uid = cpu_to_le16(attr->ia_uid); */
1035 } 1072 }
1036 if (attrs->ia_valid & ATTR_GID) { 1073 if (attrs->ia_valid & ATTR_GID) {
1037 cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid)); 1074 cFYI(1, ("GID changed to %d", attrs->ia_gid));
1038 gid = attrs->ia_gid; 1075 gid = attrs->ia_gid;
1039 /* entry->gid = cpu_to_le16(attr->ia_gid); */
1040 } 1076 }
1041 1077
1042 time_buf.Attributes = 0; 1078 time_buf.Attributes = 0;
1043 if (attrs->ia_valid & ATTR_MODE) { 1079 if (attrs->ia_valid & ATTR_MODE) {
1044 cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode)); 1080 cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode));
1045 mode = attrs->ia_mode; 1081 mode = attrs->ia_mode;
1046 /* entry->mode = cpu_to_le16(attr->ia_mode); */
1047 } 1082 }
1048 1083
1049 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) 1084 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
@@ -1083,18 +1118,24 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1083 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime)); 1118 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1084 } else 1119 } else
1085 time_buf.LastWriteTime = 0; 1120 time_buf.LastWriteTime = 0;
1086 1121 /* Do not set ctime explicitly unless other time
1087 if (attrs->ia_valid & ATTR_CTIME) { 1122 stamps are changed explicitly (i.e. by utime()
1123 since we would then have a mix of client and
1124 server times */
1125
1126 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
1088 set_time = TRUE; 1127 set_time = TRUE;
1089 cFYI(1, (" CIFS - CTIME changed ")); /* BB probably no need */ 1128 /* Although Samba throws this field away
1129 it may be useful to Windows - but we do
1130 not want to set ctime unless some other
1131 timestamp is changing */
1132 cFYI(1, ("CIFS - CTIME changed "));
1090 time_buf.ChangeTime = 1133 time_buf.ChangeTime =
1091 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); 1134 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1092 } else 1135 } else
1093 time_buf.ChangeTime = 0; 1136 time_buf.ChangeTime = 0;
1094 1137
1095 if (set_time || time_buf.Attributes) { 1138 if (set_time || time_buf.Attributes) {
1096 /* BB what if setting one attribute fails (such as size) but
1097 time setting works? */
1098 time_buf.CreationTime = 0; /* do not change */ 1139 time_buf.CreationTime = 0; /* do not change */
1099 /* In the future we should experiment - try setting timestamps 1140 /* In the future we should experiment - try setting timestamps
1100 via Handle (SetFileInfo) instead of by path */ 1141 via Handle (SetFileInfo) instead of by path */
@@ -1133,12 +1174,21 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1133 &time_buf, cifs_sb->local_nls); */ 1174 &time_buf, cifs_sb->local_nls); */
1134 } 1175 }
1135 } 1176 }
1177 /* Even if error on time set, no sense failing the call if
1178 the server would set the time to a reasonable value anyway,
1179 and this check ensures that we are not being called from
1180 sys_utimes in which case we ought to fail the call back to
1181 the user when the server rejects the call */
1182 if((rc) && (attrs->ia_valid &&
1183 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
1184 rc = 0;
1136 } 1185 }
1137 1186
1138 /* do not need local check to inode_check_ok since the server does 1187 /* do not need local check to inode_check_ok since the server does
1139 that */ 1188 that */
1140 if (!rc) 1189 if (!rc)
1141 rc = inode_setattr(direntry->d_inode, attrs); 1190 rc = inode_setattr(direntry->d_inode, attrs);
1191cifs_setattr_exit:
1142 kfree(full_path); 1192 kfree(full_path);
1143 FreeXid(xid); 1193 FreeXid(xid);
1144 return rc; 1194 return rc;