@@ -255,7 +255,7 @@ static void cifs_begin_writeback(struct netfs_io_request *wreq)
255255 struct cifs_io_request * req = container_of (wreq , struct cifs_io_request , rreq );
256256 int ret ;
257257
258- ret = cifs_get_writable_file (CIFS_I (wreq -> inode ), FIND_WR_ANY , & req -> cfile );
258+ ret = cifs_get_writable_file (CIFS_I (wreq -> inode ), FIND_ANY , & req -> cfile );
259259 if (ret ) {
260260 cifs_dbg (VFS , "No writable handle in writepages ret=%d\n" , ret );
261261 return ;
@@ -584,15 +584,8 @@ static int cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_
584584 *********************************************************************/
585585
586586 disposition = cifs_get_disposition (f_flags );
587-
588587 /* BB pass O_SYNC flag through on file attributes .. BB */
589-
590- /* O_SYNC also has bit for O_DSYNC so following check picks up either */
591- if (f_flags & O_SYNC )
592- create_options |= CREATE_WRITE_THROUGH ;
593-
594- if (f_flags & O_DIRECT )
595- create_options |= CREATE_NO_BUFFER ;
588+ create_options |= cifs_open_create_options (f_flags , create_options );
596589
597590retry_open :
598591 oparms = (struct cifs_open_parms ) {
@@ -963,7 +956,7 @@ int cifs_file_flush(const unsigned int xid, struct inode *inode,
963956 return tcon -> ses -> server -> ops -> flush (xid , tcon ,
964957 & cfile -> fid );
965958 }
966- rc = cifs_get_writable_file (CIFS_I (inode ), FIND_WR_ANY , & cfile );
959+ rc = cifs_get_writable_file (CIFS_I (inode ), FIND_ANY , & cfile );
967960 if (!rc ) {
968961 tcon = tlink_tcon (cfile -> tlink );
969962 rc = tcon -> ses -> server -> ops -> flush (xid , tcon , & cfile -> fid );
@@ -988,7 +981,7 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry)
988981 return - ERESTARTSYS ;
989982 mapping_set_error (inode -> i_mapping , rc );
990983
991- cfile = find_writable_file (cinode , FIND_WR_FSUID_ONLY );
984+ cfile = find_writable_file (cinode , FIND_FSUID_ONLY );
992985 rc = cifs_file_flush (xid , inode , cfile );
993986 if (!rc ) {
994987 if (cfile ) {
@@ -1068,32 +1061,29 @@ int cifs_open(struct inode *inode, struct file *file)
10681061
10691062 /* Get the cached handle as SMB2 close is deferred */
10701063 if (OPEN_FMODE (file -> f_flags ) & FMODE_WRITE ) {
1071- rc = cifs_get_writable_path (tcon , full_path ,
1072- FIND_WR_FSUID_ONLY |
1073- FIND_WR_NO_PENDING_DELETE ,
1074- & cfile );
1064+ rc = __cifs_get_writable_file (CIFS_I (inode ),
1065+ FIND_FSUID_ONLY |
1066+ FIND_NO_PENDING_DELETE |
1067+ FIND_OPEN_FLAGS ,
1068+ file -> f_flags , & cfile );
10751069 } else {
1076- rc = cifs_get_readable_path (tcon , full_path , & cfile );
1070+ cfile = __find_readable_file (CIFS_I (inode ),
1071+ FIND_NO_PENDING_DELETE |
1072+ FIND_OPEN_FLAGS ,
1073+ file -> f_flags );
1074+ rc = cfile ? 0 : - ENOENT ;
10771075 }
10781076 if (rc == 0 ) {
1079- unsigned int oflags = file -> f_flags & ~(O_CREAT |O_EXCL |O_TRUNC );
1080- unsigned int cflags = cfile -> f_flags & ~(O_CREAT |O_EXCL |O_TRUNC );
1081-
1082- if (cifs_convert_flags (oflags , 0 ) == cifs_convert_flags (cflags , 0 ) &&
1083- (oflags & (O_SYNC |O_DIRECT )) == (cflags & (O_SYNC |O_DIRECT ))) {
1084- file -> private_data = cfile ;
1085- spin_lock (& CIFS_I (inode )-> deferred_lock );
1086- cifs_del_deferred_close (cfile );
1087- spin_unlock (& CIFS_I (inode )-> deferred_lock );
1088- goto use_cache ;
1089- }
1090- _cifsFileInfo_put (cfile , true, false);
1091- } else {
1092- /* hard link on the defeered close file */
1093- rc = cifs_get_hardlink_path (tcon , inode , file );
1094- if (rc )
1095- cifs_close_deferred_file (CIFS_I (inode ));
1096- }
1077+ file -> private_data = cfile ;
1078+ spin_lock (& CIFS_I (inode )-> deferred_lock );
1079+ cifs_del_deferred_close (cfile );
1080+ spin_unlock (& CIFS_I (inode )-> deferred_lock );
1081+ goto use_cache ;
1082+ }
1083+ /* hard link on the deferred close file */
1084+ rc = cifs_get_hardlink_path (tcon , inode , file );
1085+ if (rc )
1086+ cifs_close_deferred_file (CIFS_I (inode ));
10971087
10981088 if (server -> oplocks )
10991089 oplock = REQ_OPLOCK ;
@@ -1314,13 +1304,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
13141304 rdwr_for_fscache = 1 ;
13151305
13161306 desired_access = cifs_convert_flags (cfile -> f_flags , rdwr_for_fscache );
1317-
1318- /* O_SYNC also has bit for O_DSYNC so following check picks up either */
1319- if (cfile -> f_flags & O_SYNC )
1320- create_options |= CREATE_WRITE_THROUGH ;
1321-
1322- if (cfile -> f_flags & O_DIRECT )
1323- create_options |= CREATE_NO_BUFFER ;
1307+ create_options |= cifs_open_create_options (cfile -> f_flags ,
1308+ create_options );
13241309
13251310 if (server -> ops -> get_lease_key )
13261311 server -> ops -> get_lease_key (inode , & cfile -> fid );
@@ -2524,10 +2509,33 @@ void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t
25242509 netfs_write_subrequest_terminated (& wdata -> subreq , result );
25252510}
25262511
2527- struct cifsFileInfo * find_readable_file (struct cifsInodeInfo * cifs_inode ,
2528- bool fsuid_only )
2512+ static bool open_flags_match (struct cifsInodeInfo * cinode ,
2513+ unsigned int oflags , unsigned int cflags )
2514+ {
2515+ struct inode * inode = & cinode -> netfs .inode ;
2516+ int crw = 0 , orw = 0 ;
2517+
2518+ oflags &= ~(O_CREAT | O_EXCL | O_TRUNC );
2519+ cflags &= ~(O_CREAT | O_EXCL | O_TRUNC );
2520+
2521+ if (cifs_fscache_enabled (inode )) {
2522+ if (OPEN_FMODE (cflags ) & FMODE_WRITE )
2523+ crw = 1 ;
2524+ if (OPEN_FMODE (oflags ) & FMODE_WRITE )
2525+ orw = 1 ;
2526+ }
2527+ if (cifs_convert_flags (oflags , orw ) != cifs_convert_flags (cflags , crw ))
2528+ return false;
2529+
2530+ return (oflags & (O_SYNC | O_DIRECT )) == (cflags & (O_SYNC | O_DIRECT ));
2531+ }
2532+
2533+ struct cifsFileInfo * __find_readable_file (struct cifsInodeInfo * cifs_inode ,
2534+ unsigned int find_flags ,
2535+ unsigned int open_flags )
25292536{
25302537 struct cifs_sb_info * cifs_sb = CIFS_SB (cifs_inode );
2538+ bool fsuid_only = find_flags & FIND_FSUID_ONLY ;
25312539 struct cifsFileInfo * open_file = NULL ;
25322540
25332541 /* only filter by fsuid on multiuser mounts */
@@ -2541,6 +2549,13 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
25412549 list_for_each_entry (open_file , & cifs_inode -> openFileList , flist ) {
25422550 if (fsuid_only && !uid_eq (open_file -> uid , current_fsuid ()))
25432551 continue ;
2552+ if ((find_flags & FIND_NO_PENDING_DELETE ) &&
2553+ open_file -> status_file_deleted )
2554+ continue ;
2555+ if ((find_flags & FIND_OPEN_FLAGS ) &&
2556+ !open_flags_match (cifs_inode , open_flags ,
2557+ open_file -> f_flags ))
2558+ continue ;
25442559 if (OPEN_FMODE (open_file -> f_flags ) & FMODE_READ ) {
25452560 if ((!open_file -> invalidHandle )) {
25462561 /* found a good file */
@@ -2559,17 +2574,17 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
25592574}
25602575
25612576/* Return -EBADF if no handle is found and general rc otherwise */
2562- int
2563- cifs_get_writable_file ( struct cifsInodeInfo * cifs_inode , int flags ,
2564- struct cifsFileInfo * * ret_file )
2577+ int __cifs_get_writable_file ( struct cifsInodeInfo * cifs_inode ,
2578+ unsigned int find_flags , unsigned int open_flags ,
2579+ struct cifsFileInfo * * ret_file )
25652580{
25662581 struct cifsFileInfo * open_file , * inv_file = NULL ;
25672582 struct cifs_sb_info * cifs_sb ;
25682583 bool any_available = false;
25692584 int rc = - EBADF ;
25702585 unsigned int refind = 0 ;
2571- bool fsuid_only = flags & FIND_WR_FSUID_ONLY ;
2572- bool with_delete = flags & FIND_WR_WITH_DELETE ;
2586+ bool fsuid_only = find_flags & FIND_FSUID_ONLY ;
2587+ bool with_delete = find_flags & FIND_WITH_DELETE ;
25732588 * ret_file = NULL ;
25742589
25752590 /*
@@ -2603,9 +2618,13 @@ cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
26032618 continue ;
26042619 if (with_delete && !(open_file -> fid .access & DELETE ))
26052620 continue ;
2606- if ((flags & FIND_WR_NO_PENDING_DELETE ) &&
2621+ if ((find_flags & FIND_NO_PENDING_DELETE ) &&
26072622 open_file -> status_file_deleted )
26082623 continue ;
2624+ if ((find_flags & FIND_OPEN_FLAGS ) &&
2625+ !open_flags_match (cifs_inode , open_flags ,
2626+ open_file -> f_flags ))
2627+ continue ;
26092628 if (OPEN_FMODE (open_file -> f_flags ) & FMODE_WRITE ) {
26102629 if (!open_file -> invalidHandle ) {
26112630 /* found a good writable file */
@@ -2722,17 +2741,7 @@ cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
27222741 cinode = CIFS_I (d_inode (cfile -> dentry ));
27232742 spin_unlock (& tcon -> open_file_lock );
27242743 free_dentry_path (page );
2725- * ret_file = find_readable_file (cinode , 0 );
2726- if (* ret_file ) {
2727- spin_lock (& cinode -> open_file_lock );
2728- if ((* ret_file )-> status_file_deleted ) {
2729- spin_unlock (& cinode -> open_file_lock );
2730- cifsFileInfo_put (* ret_file );
2731- * ret_file = NULL ;
2732- } else {
2733- spin_unlock (& cinode -> open_file_lock );
2734- }
2735- }
2744+ * ret_file = find_readable_file (cinode , FIND_ANY );
27362745 return * ret_file ? 0 : - ENOENT ;
27372746 }
27382747
@@ -2804,7 +2813,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
28042813 }
28052814
28062815 if ((OPEN_FMODE (smbfile -> f_flags ) & FMODE_WRITE ) == 0 ) {
2807- smbfile = find_writable_file (CIFS_I (inode ), FIND_WR_ANY );
2816+ smbfile = find_writable_file (CIFS_I (inode ), FIND_ANY );
28082817 if (smbfile ) {
28092818 rc = server -> ops -> flush (xid , tcon , & smbfile -> fid );
28102819 cifsFileInfo_put (smbfile );
0 commit comments