[CIFS] One more posix open patch on the way
From: Steve French
Date: Fri May 22 2009 - 22:29:03 EST
One small additional fix to posix open is being reviewed to address
something Jeff and JRA noticed this morning.
After discussion today on samba-technical about the posix lookup open
regression, and looking at a problem with cifs posix open to one
particular Samba version, Jeff and JRA realized that Samba server's
behavior changed in this area (posix open behavior on files vs.
directories) too. To make this behavior consistent, JRA just made a
fix to Samba server to alter how it handles open of directories (now
returning the equivalent of EISDIR instead of success). Since we don't
know at lookup time whether the inode is a directory or file (and thus
whether posix open will succeed with most current Samba server), I am
testing a change which avoids the posix open code on lookup open (just
issues posix open on creates). This gets the semantic benefits we
want (posix byte range locks, improved write semantics etc. on newly
created files) and file create still is fast, and we avoid the problem
that Jeff noticed this morning with "openat" (and some open directory
calls) of non-cached directories to one version of Samba server, and
will work with future Samba versions (which include the fix jra just
pushed into Samba server).
The small fix attached (or something like it), is a mustfix before
2.6.30 goes out, but want to give Shirish, and Jeff time to look at
it. The main part (other than a trivial rc mapping change) is this
change to cifs_lookup
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index f49d684..c306d3f 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -660,8 +660,16 @@ cifs_lookup(struct inode *parent_dir_inode,
struct dentry *direntry,
if (pTcon->unix_ext) {
if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
(nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open) {
- if (!((nd->intent.open.flags & O_CREAT) &&
- (nd->intent.open.flags & O_EXCL))) {
+ if (nd->intent.open.flags & O_CREAT) {
+ /* POSIX open here is only called for file
+ create. It does not help much for file opens
+ because we do not know if it is a file
+ or directory, and current Samba no
+ longer allows us to do posix open on dirs,
+ so we could end up wasting an open
+ call on what turns out to be a dir.
+ For file opens, we call posix open
+ in cifs_open */
rc = cifs_posix_open(full_path, &newInode,
parent_dir_inode->i_sb,
nd->intent.open.create_mode,
--
Thanks,
Steve
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index f49d684..c306d3f 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -660,8 +660,16 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
if (pTcon->unix_ext) {
if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
(nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open) {
- if (!((nd->intent.open.flags & O_CREAT) &&
- (nd->intent.open.flags & O_EXCL))) {
+ if (nd->intent.open.flags & O_CREAT) {
+ /* POSIX open here is only called for file
+ create. It does not help much for file opens
+ because we do not know if it is a file
+ or directory, and current Samba no
+ longer allows us to do posix open on dirs,
+ so we could end up wasting an open
+ call on what turns out to be a dir.
+ For file opens, we call posix open
+ in cifs_open */
rc = cifs_posix_open(full_path, &newInode,
parent_dir_inode->i_sb,
nd->intent.open.create_mode,
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index e2fe998..f465aaf 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -79,6 +79,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
{ErrQuota, -EDQUOT},
{ErrNotALink, -ENOLINK},
{ERRnetlogonNotStarted, -ENOPROTOOPT},
+ {ERRisdir, -EISDIR},
{ERRsymlink, -EOPNOTSUPP},
{ErrTooManyLinks, -EMLINK},
{0, 0}
@@ -368,7 +369,7 @@ static const struct {
ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STARTED}, {
ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STOPPED}, {
ERRHRD, ERRgeneral, NT_STATUS_COULD_NOT_INTERPRET}, {
- ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, {
+ ERRDOS, ERRisdir, NT_STATUS_FILE_IS_A_DIRECTORY}, {
ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED}, {
ERRDOS, 51, NT_STATUS_REMOTE_NOT_LISTENING}, {
ERRDOS, 52, NT_STATUS_DUPLICATE_NAME}, {
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index c5084d2..5481525 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -110,6 +110,7 @@
/* Below errors are used internally (do not come over the wire) for passthrough
from STATUS codes to POSIX only */
+#define ERRisdir 0xFFFC
#define ERRsymlink 0xFFFD
#define ErrTooManyLinks 0xFFFE