aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r--fs/cifs/dir.c66
1 files changed, 37 insertions, 29 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 461750e01364..3758965d73d5 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -225,6 +225,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
225 if (!(oflags & FMODE_READ)) 225 if (!(oflags & FMODE_READ))
226 write_only = true; 226 write_only = true;
227 227
228 mode &= ~current_umask();
228 rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode, 229 rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
229 pnetfid, presp_data, &oplock, full_path, 230 pnetfid, presp_data, &oplock, full_path,
230 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 231 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
@@ -281,6 +282,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
281 int create_options = CREATE_NOT_DIR; 282 int create_options = CREATE_NOT_DIR;
282 int oplock = 0; 283 int oplock = 0;
283 int oflags; 284 int oflags;
285 bool posix_create = false;
284 /* 286 /*
285 * BB below access is probably too much for mknod to request 287 * BB below access is probably too much for mknod to request
286 * but we have to do query and setpathinfo so requesting 288 * but we have to do query and setpathinfo so requesting
@@ -309,7 +311,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
309 return -ENOMEM; 311 return -ENOMEM;
310 } 312 }
311 313
312 mode &= ~current_umask();
313 if (oplockEnabled) 314 if (oplockEnabled)
314 oplock = REQ_OPLOCK; 315 oplock = REQ_OPLOCK;
315 316
@@ -328,12 +329,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
328 negotation. EREMOTE indicates DFS junction, which is not 329 negotation. EREMOTE indicates DFS junction, which is not
329 handled in posix open */ 330 handled in posix open */
330 331
331 if ((rc == 0) && (newinode == NULL)) 332 if (rc == 0) {
332 goto cifs_create_get_file_info; /* query inode info */ 333 posix_create = true;
333 else if (rc == 0) /* success, no need to query */ 334 if (newinode == NULL) /* query inode info */
334 goto cifs_create_set_dentry; 335 goto cifs_create_get_file_info;
335 else if ((rc != -EIO) && (rc != -EREMOTE) && 336 else /* success, no need to query */
336 (rc != -EOPNOTSUPP)) /* path not found or net err */ 337 goto cifs_create_set_dentry;
338 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
339 (rc != -EOPNOTSUPP) && (rc != -EINVAL))
337 goto cifs_create_out; 340 goto cifs_create_out;
338 /* else fallthrough to retry, using older open call, this is 341 /* else fallthrough to retry, using older open call, this is
339 case where server does not support this SMB level, and 342 case where server does not support this SMB level, and
@@ -464,7 +467,7 @@ cifs_create_set_dentry:
464 if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) { 467 if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
465 /* mknod case - do not leave file open */ 468 /* mknod case - do not leave file open */
466 CIFSSMBClose(xid, tcon, fileHandle); 469 CIFSSMBClose(xid, tcon, fileHandle);
467 } else if (newinode) { 470 } else if (!(posix_create) && (newinode)) {
468 cifs_fill_fileinfo(newinode, fileHandle, 471 cifs_fill_fileinfo(newinode, fileHandle,
469 cifs_sb->tcon, write_only); 472 cifs_sb->tcon, write_only);
470 } 473 }
@@ -606,7 +609,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
606 int xid; 609 int xid;
607 int rc = 0; /* to get around spurious gcc warning, set to zero here */ 610 int rc = 0; /* to get around spurious gcc warning, set to zero here */
608 int oplock = 0; 611 int oplock = 0;
609 int mode;
610 __u16 fileHandle = 0; 612 __u16 fileHandle = 0;
611 bool posix_open = false; 613 bool posix_open = false;
612 struct cifs_sb_info *cifs_sb; 614 struct cifs_sb_info *cifs_sb;
@@ -655,30 +657,36 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
655 } 657 }
656 cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode)); 658 cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode));
657 659
660 /* Posix open is only called (at lookup time) for file create now.
661 * For opens (rather than creates), because we do not know if it
662 * is a file or directory yet, and current Samba no longer allows
663 * us to do posix open on dirs, we could end up wasting an open call
664 * on what turns out to be a dir. For file opens, we wait to call posix
665 * open till cifs_open. It could be added here (lookup) in the future
666 * but the performance tradeoff of the extra network request when EISDIR
667 * or EACCES is returned would have to be weighed against the 50%
668 * reduction in network traffic in the other paths.
669 */
658 if (pTcon->unix_ext) { 670 if (pTcon->unix_ext) {
659 if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && 671 if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
660 (nd->flags & LOOKUP_OPEN)) { 672 (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
661 if (!((nd->intent.open.flags & O_CREAT) && 673 (nd->intent.open.flags & O_CREAT)) {
662 (nd->intent.open.flags & O_EXCL))) { 674 rc = cifs_posix_open(full_path, &newInode,
663 mode = nd->intent.open.create_mode & 675 parent_dir_inode->i_sb,
664 ~current_umask(); 676 nd->intent.open.create_mode,
665 rc = cifs_posix_open(full_path, &newInode,
666 parent_dir_inode->i_sb, mode,
667 nd->intent.open.flags, &oplock, 677 nd->intent.open.flags, &oplock,
668 &fileHandle, xid); 678 &fileHandle, xid);
669 /* 679 /*
670 * This code works around a bug in 680 * The check below works around a bug in POSIX
671 * samba posix open in samba versions 3.3.1 681 * open in samba versions 3.3.1 and earlier where
672 * and earlier where create works 682 * open could incorrectly fail with invalid parameter.
673 * but open fails with invalid parameter. 683 * If either that or op not supported returned, follow
674 * If either of these error codes are 684 * the normal lookup.
675 * returned, follow the normal lookup. 685 */
676 * Otherwise, the error during posix open 686 if ((rc == 0) || (rc == -ENOENT))
677 * is handled. 687 posix_open = true;
678 */ 688 else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP))
679 if ((rc != -EINVAL) && (rc != -EOPNOTSUPP)) 689 pTcon->broken_posix_open = true;
680 posix_open = true;
681 }
682 } 690 }
683 if (!posix_open) 691 if (!posix_open)
684 rc = cifs_get_inode_info_unix(&newInode, full_path, 692 rc = cifs_get_inode_info_unix(&newInode, full_path,