@@ -238,6 +238,23 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
238
238
return rc ;
239
239
}
240
240
241
+ static bool
242
+ cifs_has_mand_locks (struct cifsInodeInfo * cinode )
243
+ {
244
+ struct cifs_fid_locks * cur ;
245
+ bool has_locks = false;
246
+
247
+ down_read (& cinode -> lock_sem );
248
+ list_for_each_entry (cur , & cinode -> llist , llist ) {
249
+ if (!list_empty (& cur -> locks )) {
250
+ has_locks = true;
251
+ break ;
252
+ }
253
+ }
254
+ up_read (& cinode -> lock_sem );
255
+ return has_locks ;
256
+ }
257
+
241
258
struct cifsFileInfo *
242
259
cifs_new_fileinfo (struct cifs_fid * fid , struct file * file ,
243
260
struct tcon_link * tlink , __u32 oplock )
@@ -248,6 +265,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
248
265
struct cifsFileInfo * cfile ;
249
266
struct cifs_fid_locks * fdlocks ;
250
267
struct cifs_tcon * tcon = tlink_tcon (tlink );
268
+ struct TCP_Server_Info * server = tcon -> ses -> server ;
251
269
252
270
cfile = kzalloc (sizeof (struct cifsFileInfo ), GFP_KERNEL );
253
271
if (cfile == NULL )
@@ -276,12 +294,22 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
276
294
INIT_WORK (& cfile -> oplock_break , cifs_oplock_break );
277
295
mutex_init (& cfile -> fh_mutex );
278
296
297
+ /*
298
+ * If the server returned a read oplock and we have mandatory brlocks,
299
+ * set oplock level to None.
300
+ */
301
+ if (oplock == server -> vals -> oplock_read &&
302
+ cifs_has_mand_locks (cinode )) {
303
+ cFYI (1 , "Reset oplock val from read to None due to mand locks" );
304
+ oplock = 0 ;
305
+ }
306
+
279
307
spin_lock (& cifs_file_list_lock );
280
- if (fid -> pending_open -> oplock != CIFS_OPLOCK_NO_CHANGE )
308
+ if (fid -> pending_open -> oplock != CIFS_OPLOCK_NO_CHANGE && oplock )
281
309
oplock = fid -> pending_open -> oplock ;
282
310
list_del (& fid -> pending_open -> olist );
283
311
284
- tlink_tcon ( tlink ) -> ses -> server -> ops -> set_fid (cfile , fid , oplock );
312
+ server -> ops -> set_fid (cfile , fid , oplock );
285
313
286
314
list_add (& cfile -> tlist , & tcon -> openFileList );
287
315
/* if readable file instance put first in list*/
@@ -1422,6 +1450,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
1422
1450
struct cifsFileInfo * cfile = (struct cifsFileInfo * )file -> private_data ;
1423
1451
struct cifs_tcon * tcon = tlink_tcon (cfile -> tlink );
1424
1452
struct TCP_Server_Info * server = tcon -> ses -> server ;
1453
+ struct inode * inode = cfile -> dentry -> d_inode ;
1425
1454
1426
1455
if (posix_lck ) {
1427
1456
int posix_lock_type ;
@@ -1459,6 +1488,21 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
1459
1488
if (!rc )
1460
1489
goto out ;
1461
1490
1491
+ /*
1492
+ * Windows 7 server can delay breaking lease from read to None
1493
+ * if we set a byte-range lock on a file - break it explicitly
1494
+ * before sending the lock to the server to be sure the next
1495
+ * read won't conflict with non-overlapted locks due to
1496
+ * pagereading.
1497
+ */
1498
+ if (!CIFS_I (inode )-> clientCanCacheAll &&
1499
+ CIFS_I (inode )-> clientCanCacheRead ) {
1500
+ cifs_invalidate_mapping (inode );
1501
+ cFYI (1 , "Set no oplock for inode=%p due to mand locks" ,
1502
+ inode );
1503
+ CIFS_I (inode )-> clientCanCacheRead = false;
1504
+ }
1505
+
1462
1506
rc = server -> ops -> mand_lock (xid , cfile , flock -> fl_start , length ,
1463
1507
type , 1 , 0 , wait_flag );
1464
1508
if (rc ) {
@@ -2103,15 +2147,7 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
2103
2147
} else {
2104
2148
rc = copied ;
2105
2149
pos += copied ;
2106
- /*
2107
- * When we use strict cache mode and cifs_strict_writev was run
2108
- * with level II oplock (indicated by leave_pages_clean field of
2109
- * CIFS_I(inode)), we can leave pages clean - cifs_strict_writev
2110
- * sent the data to the server itself.
2111
- */
2112
- if (!CIFS_I (inode )-> leave_pages_clean ||
2113
- !(cifs_sb -> mnt_cifs_flags & CIFS_MOUNT_STRICT_IO ))
2114
- set_page_dirty (page );
2150
+ set_page_dirty (page );
2115
2151
}
2116
2152
2117
2153
if (rc > 0 ) {
@@ -2462,8 +2498,8 @@ ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
2462
2498
}
2463
2499
2464
2500
static ssize_t
2465
- cifs_pagecache_writev (struct kiocb * iocb , const struct iovec * iov ,
2466
- unsigned long nr_segs , loff_t pos , bool cache_ex )
2501
+ cifs_writev (struct kiocb * iocb , const struct iovec * iov ,
2502
+ unsigned long nr_segs , loff_t pos )
2467
2503
{
2468
2504
struct file * file = iocb -> ki_filp ;
2469
2505
struct cifsFileInfo * cfile = (struct cifsFileInfo * )file -> private_data ;
@@ -2485,12 +2521,8 @@ cifs_pagecache_writev(struct kiocb *iocb, const struct iovec *iov,
2485
2521
server -> vals -> exclusive_lock_type , NULL ,
2486
2522
CIFS_WRITE_OP )) {
2487
2523
mutex_lock (& inode -> i_mutex );
2488
- if (!cache_ex )
2489
- cinode -> leave_pages_clean = true;
2490
2524
rc = __generic_file_aio_write (iocb , iov , nr_segs ,
2491
- & iocb -> ki_pos );
2492
- if (!cache_ex )
2493
- cinode -> leave_pages_clean = false;
2525
+ & iocb -> ki_pos );
2494
2526
mutex_unlock (& inode -> i_mutex );
2495
2527
}
2496
2528
@@ -2517,60 +2549,32 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
2517
2549
struct cifsFileInfo * cfile = (struct cifsFileInfo * )
2518
2550
iocb -> ki_filp -> private_data ;
2519
2551
struct cifs_tcon * tcon = tlink_tcon (cfile -> tlink );
2520
- ssize_t written , written2 ;
2521
- /*
2522
- * We need to store clientCanCacheAll here to prevent race
2523
- * conditions - this value can be changed during an execution
2524
- * of generic_file_aio_write. For CIFS it can be changed from
2525
- * true to false only, but for SMB2 it can be changed both from
2526
- * true to false and vice versa. So, we can end up with a data
2527
- * stored in the cache, not marked dirty and not sent to the
2528
- * server if this value changes its state from false to true
2529
- * after cifs_write_end.
2530
- */
2531
- bool cache_ex = cinode -> clientCanCacheAll ;
2532
- bool cache_read = cinode -> clientCanCacheRead ;
2533
- int rc ;
2534
- loff_t saved_pos ;
2552
+ ssize_t written ;
2535
2553
2536
- if (cache_ex ) {
2554
+ if (cinode -> clientCanCacheAll ) {
2537
2555
if (cap_unix (tcon -> ses ) &&
2538
- ((cifs_sb -> mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL ) == 0 ) &&
2539
- (CIFS_UNIX_FCNTL_CAP & le64_to_cpu (
2540
- tcon -> fsUnixInfo .Capability )))
2556
+ (CIFS_UNIX_FCNTL_CAP & le64_to_cpu (tcon -> fsUnixInfo .Capability ))
2557
+ && ((cifs_sb -> mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL ) == 0 ))
2541
2558
return generic_file_aio_write (iocb , iov , nr_segs , pos );
2542
- return cifs_pagecache_writev (iocb , iov , nr_segs , pos , cache_ex );
2559
+ return cifs_writev (iocb , iov , nr_segs , pos );
2543
2560
}
2544
-
2545
2561
/*
2546
- * For files without exclusive oplock in strict cache mode we need to
2547
- * write the data to the server exactly from the pos to pos+len-1 rather
2548
- * than flush all affected pages because it may cause a error with
2549
- * mandatory locks on these pages but not on the region from pos to
2550
- * ppos+len-1.
2562
+ * For non-oplocked files in strict cache mode we need to write the data
2563
+ * to the server exactly from the pos to pos+len-1 rather than flush all
2564
+ * affected pages because it may cause a error with mandatory locks on
2565
+ * these pages but not on the region from pos to ppos+len-1.
2551
2566
*/
2552
2567
written = cifs_user_writev (iocb , iov , nr_segs , pos );
2553
- if (!cache_read || written <= 0 )
2554
- return written ;
2555
-
2556
- saved_pos = iocb -> ki_pos ;
2557
- iocb -> ki_pos = pos ;
2558
- /* we have a read oplock - need to store a data in the page cache */
2559
- if (cap_unix (tcon -> ses ) &&
2560
- ((cifs_sb -> mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL ) == 0 ) &&
2561
- (CIFS_UNIX_FCNTL_CAP & le64_to_cpu (
2562
- tcon -> fsUnixInfo .Capability )))
2563
- written2 = generic_file_aio_write (iocb , iov , nr_segs , pos );
2564
- else
2565
- written2 = cifs_pagecache_writev (iocb , iov , nr_segs , pos ,
2566
- cache_ex );
2567
- /* errors occured during writing - invalidate the page cache */
2568
- if (written2 < 0 ) {
2569
- rc = cifs_invalidate_mapping (inode );
2570
- if (rc )
2571
- written = (ssize_t )rc ;
2572
- else
2573
- iocb -> ki_pos = saved_pos ;
2568
+ if (written > 0 && cinode -> clientCanCacheRead ) {
2569
+ /*
2570
+ * Windows 7 server can delay breaking level2 oplock if a write
2571
+ * request comes - break it on the client to prevent reading
2572
+ * an old data.
2573
+ */
2574
+ cifs_invalidate_mapping (inode );
2575
+ cFYI (1 , "Set no oplock for inode=%p after a write operation" ,
2576
+ inode );
2577
+ cinode -> clientCanCacheRead = false;
2574
2578
}
2575
2579
return written ;
2576
2580
}
@@ -3577,6 +3581,13 @@ void cifs_oplock_break(struct work_struct *work)
3577
3581
struct cifs_tcon * tcon = tlink_tcon (cfile -> tlink );
3578
3582
int rc = 0 ;
3579
3583
3584
+ if (!cinode -> clientCanCacheAll && cinode -> clientCanCacheRead &&
3585
+ cifs_has_mand_locks (cinode )) {
3586
+ cFYI (1 , "Reset oplock to None for inode=%p due to mand locks" ,
3587
+ inode );
3588
+ cinode -> clientCanCacheRead = false;
3589
+ }
3590
+
3580
3591
if (inode && S_ISREG (inode -> i_mode )) {
3581
3592
if (cinode -> clientCanCacheRead )
3582
3593
break_lease (inode , O_RDONLY );
0 commit comments