aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2009-03-04 14:54:08 -0500
committerSteve French <sfrench@us.ibm.com>2009-03-11 21:36:21 -0400
commit64cc2c63694a03393985ffc8b178e72f52dd8a06 (patch)
tree819161cd3f6b4268b5ff21dfb0c427496134fef5
parent276a74a4835ad86d6da42f3a084b060afc5656e8 (diff)
[CIFS] work around bug in Samba server handling for posix open
Samba server (version 3.3.1 and earlier, and 3.2.8 and earlier) incorrectly required the O_CREAT flag on posix open (even when a file was not being created). This disables posix open (create is still ok) after the first attempt returns EINVAL (and logs an error, once, recommending that they update their server). Acked-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r--fs/cifs/CHANGES2
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/file.c16
3 files changed, 16 insertions, 3 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index b33c8412e2c8..fc977dfe9593 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -11,6 +11,8 @@ to better ensure that we wait for server to write all of the data to
11server disk (not just write it over the network). Add new mount 11server disk (not just write it over the network). Add new mount
12parameter to allow user to disable sending the (slow) SMB flush on 12parameter to allow user to disable sending the (slow) SMB flush on
13fsync if desired (fsync still flushes all cached write data to the server). 13fsync if desired (fsync still flushes all cached write data to the server).
14Posix file open support added (turned off after one attempt if server
15fails to support it properly, as with Samba server versions prior to 3.3.2)
14 16
15Version 1.56 17Version 1.56
16------------ 18------------
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 44ff94d37e18..9fbf4dff5da6 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -299,6 +299,7 @@ struct cifsTconInfo {
299 bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol 299 bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol
300 for this mount even if server would support */ 300 for this mount even if server would support */
301 bool local_lease:1; /* check leases (only) on local system not remote */ 301 bool local_lease:1; /* check leases (only) on local system not remote */
302 bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
302 bool need_reconnect:1; /* connection reset, tid now invalid */ 303 bool need_reconnect:1; /* connection reset, tid now invalid */
303 /* BB add field for back pointer to sb struct(s)? */ 304 /* BB add field for back pointer to sb struct(s)? */
304}; 305};
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 7bef4cce572a..81747acca4c4 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -328,7 +328,8 @@ int cifs_open(struct inode *inode, struct file *file)
328 else 328 else
329 oplock = 0; 329 oplock = 0;
330 330
331 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && 331 if (!tcon->broken_posix_open && tcon->unix_ext &&
332 (tcon->ses->capabilities & CAP_UNIX) &&
332 (CIFS_UNIX_POSIX_PATH_OPS_CAP & 333 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
333 le64_to_cpu(tcon->fsUnixInfo.Capability))) { 334 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
334 int oflags = (int) cifs_posix_convert_flags(file->f_flags); 335 int oflags = (int) cifs_posix_convert_flags(file->f_flags);
@@ -344,11 +345,20 @@ int cifs_open(struct inode *inode, struct file *file)
344 cifs_posix_open_inode_helper(inode, file, pCifsInode, 345 cifs_posix_open_inode_helper(inode, file, pCifsInode,
345 pCifsFile, oplock, netfid); 346 pCifsFile, oplock, netfid);
346 goto out; 347 goto out;
348 } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
349 if (tcon->ses->serverNOS)
350 cERROR(1, ("server %s of type %s returned"
351 " unexpected error on SMB posix open"
352 ", disabling posix open support."
353 " Check if server update available.",
354 tcon->ses->serverName,
355 tcon->ses->serverNOS));
356 tcon->broken_posix_open = true;
347 } else if ((rc != -EIO) && (rc != -EREMOTE) && 357 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
348 (rc != -EOPNOTSUPP)) /* path not found or net err */ 358 (rc != -EOPNOTSUPP)) /* path not found or net err */
349 goto out; 359 goto out;
350 /* fallthrough to retry open the old way on operation 360 /* else fallthrough to retry open the old way on network i/o
351 not supported or DFS errors */ 361 or DFS errors */
352 } 362 }
353 363
354 desiredAccess = cifs_convert_flags(file->f_flags); 364 desiredAccess = cifs_convert_flags(file->f_flags);