aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2009-02-23 15:43:11 -0500
committerSteve French <sfrench@us.ibm.com>2009-03-11 21:36:20 -0400
commit7fc8f4e95bf9564045985bb206af8e28a5e4e28f (patch)
treee2a7229e18132fe86c66bb3e06436e537dd28535 /fs/cifs/file.c
parentbe652445fdccb8e5d4391928c3b45324ea37f9e1 (diff)
[CIFS] reopen file via newer posix open protocol operation if available
If the network connection crashes, and we have to reopen files, preferentially use the newer cifs posix open protocol operation if the server supports it. Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c57
1 files changed, 51 insertions, 6 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 6411f5f65d72..6603cb4024fb 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -78,8 +78,36 @@ static inline int cifs_convert_flags(unsigned int flags)
78 return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | 78 return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
79 FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | 79 FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA |
80 FILE_READ_DATA); 80 FILE_READ_DATA);
81}
81 82
83static inline fmode_t cifs_posix_convert_flags(unsigned int flags)
84{
85 fmode_t posix_flags = 0;
82 86
87 if ((flags & O_ACCMODE) == O_RDONLY)
88 posix_flags = FMODE_READ;
89 else if ((flags & O_ACCMODE) == O_WRONLY)
90 posix_flags = FMODE_WRITE;
91 else if ((flags & O_ACCMODE) == O_RDWR) {
92 /* GENERIC_ALL is too much permission to request
93 can cause unnecessary access denied on create */
94 /* return GENERIC_ALL; */
95 posix_flags = FMODE_READ | FMODE_WRITE;
96 }
97 /* can not map O_CREAT or O_EXCL or O_TRUNC flags when
98 reopening a file. They had their effect on the original open */
99 if (flags & O_APPEND)
100 posix_flags |= (fmode_t)O_APPEND;
101 if (flags & O_SYNC)
102 posix_flags |= (fmode_t)O_SYNC;
103 if (flags & O_DIRECTORY)
104 posix_flags |= (fmode_t)O_DIRECTORY;
105 if (flags & O_NOFOLLOW)
106 posix_flags |= (fmode_t)O_NOFOLLOW;
107 if (flags & O_DIRECT)
108 posix_flags |= (fmode_t)O_DIRECT;
109
110 return posix_flags;
83} 111}
84 112
85static inline int cifs_get_disposition(unsigned int flags) 113static inline int cifs_get_disposition(unsigned int flags)
@@ -349,7 +377,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
349 int rc = -EACCES; 377 int rc = -EACCES;
350 int xid, oplock; 378 int xid, oplock;
351 struct cifs_sb_info *cifs_sb; 379 struct cifs_sb_info *cifs_sb;
352 struct cifsTconInfo *pTcon; 380 struct cifsTconInfo *tcon;
353 struct cifsFileInfo *pCifsFile; 381 struct cifsFileInfo *pCifsFile;
354 struct cifsInodeInfo *pCifsInode; 382 struct cifsInodeInfo *pCifsInode;
355 struct inode *inode; 383 struct inode *inode;
@@ -387,7 +415,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
387 } 415 }
388 416
389 cifs_sb = CIFS_SB(inode->i_sb); 417 cifs_sb = CIFS_SB(inode->i_sb);
390 pTcon = cifs_sb->tcon; 418 tcon = cifs_sb->tcon;
391 419
392/* can not grab rename sem here because various ops, including 420/* can not grab rename sem here because various ops, including
393 those that already have the rename sem can end up causing writepage 421 those that already have the rename sem can end up causing writepage
@@ -404,20 +432,37 @@ reopen_error_exit:
404 432
405 cFYI(1, ("inode = 0x%p file flags 0x%x for %s", 433 cFYI(1, ("inode = 0x%p file flags 0x%x for %s",
406 inode, file->f_flags, full_path)); 434 inode, file->f_flags, full_path));
407 desiredAccess = cifs_convert_flags(file->f_flags);
408 435
409 if (oplockEnabled) 436 if (oplockEnabled)
410 oplock = REQ_OPLOCK; 437 oplock = REQ_OPLOCK;
411 else 438 else
412 oplock = 0; 439 oplock = 0;
413 440
441 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
442 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
443 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
444 int oflags = (int) cifs_posix_convert_flags(file->f_flags);
445 /* can not refresh inode info since size could be stale */
446 rc = cifs_posix_open(full_path, NULL, inode->i_sb,
447 cifs_sb->mnt_file_mode /* ignored */,
448 oflags, &oplock, &netfid, xid);
449 if (rc == 0) {
450 cFYI(1, ("posix reopen succeeded"));
451 goto reopen_success;
452 }
453 /* fallthrough to retry open the old way on errors, especially
454 in the reconnect path it is important to retry hard */
455 }
456
457 desiredAccess = cifs_convert_flags(file->f_flags);
458
414 /* Can not refresh inode by passing in file_info buf to be returned 459 /* Can not refresh inode by passing in file_info buf to be returned
415 by SMBOpen and then calling get_inode_info with returned buf 460 by SMBOpen and then calling get_inode_info with returned buf
416 since file might have write behind data that needs to be flushed 461 since file might have write behind data that needs to be flushed
417 and server version of file size can be stale. If we knew for sure 462 and server version of file size can be stale. If we knew for sure
418 that inode was not dirty locally we could do this */ 463 that inode was not dirty locally we could do this */
419 464
420 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, 465 rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess,
421 CREATE_NOT_DIR, &netfid, &oplock, NULL, 466 CREATE_NOT_DIR, &netfid, &oplock, NULL,
422 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 467 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
423 CIFS_MOUNT_MAP_SPECIAL_CHR); 468 CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -426,6 +471,7 @@ reopen_error_exit:
426 cFYI(1, ("cifs_open returned 0x%x", rc)); 471 cFYI(1, ("cifs_open returned 0x%x", rc));
427 cFYI(1, ("oplock: %d", oplock)); 472 cFYI(1, ("oplock: %d", oplock));
428 } else { 473 } else {
474reopen_success:
429 pCifsFile->netfid = netfid; 475 pCifsFile->netfid = netfid;
430 pCifsFile->invalidHandle = false; 476 pCifsFile->invalidHandle = false;
431 up(&pCifsFile->fh_sem); 477 up(&pCifsFile->fh_sem);
@@ -439,7 +485,7 @@ reopen_error_exit:
439 go to server to get inode info */ 485 go to server to get inode info */
440 pCifsInode->clientCanCacheAll = false; 486 pCifsInode->clientCanCacheAll = false;
441 pCifsInode->clientCanCacheRead = false; 487 pCifsInode->clientCanCacheRead = false;
442 if (pTcon->unix_ext) 488 if (tcon->unix_ext)
443 rc = cifs_get_inode_info_unix(&inode, 489 rc = cifs_get_inode_info_unix(&inode,
444 full_path, inode->i_sb, xid); 490 full_path, inode->i_sb, xid);
445 else 491 else
@@ -467,7 +513,6 @@ reopen_error_exit:
467 cifs_relock_file(pCifsFile); 513 cifs_relock_file(pCifsFile);
468 } 514 }
469 } 515 }
470
471 kfree(full_path); 516 kfree(full_path);
472 FreeXid(xid); 517 FreeXid(xid);
473 return rc; 518 return rc;