@@ -3307,53 +3307,56 @@ get_smb2_acl(struct cifs_sb_info *cifs_sb,
3307
3307
return pntsd ;
3308
3308
}
3309
3309
3310
+ static long smb3_zero_data (struct file * file , struct cifs_tcon * tcon ,
3311
+ loff_t offset , loff_t len , unsigned int xid )
3312
+ {
3313
+ struct cifsFileInfo * cfile = file -> private_data ;
3314
+ struct file_zero_data_information fsctl_buf ;
3315
+
3316
+ cifs_dbg (FYI , "Offset %lld len %lld\n" , offset , len );
3317
+
3318
+ fsctl_buf .FileOffset = cpu_to_le64 (offset );
3319
+ fsctl_buf .BeyondFinalZero = cpu_to_le64 (offset + len );
3320
+
3321
+ return SMB2_ioctl (xid , tcon , cfile -> fid .persistent_fid ,
3322
+ cfile -> fid .volatile_fid , FSCTL_SET_ZERO_DATA ,
3323
+ (char * )& fsctl_buf ,
3324
+ sizeof (struct file_zero_data_information ),
3325
+ 0 , NULL , NULL );
3326
+ }
3327
+
3310
3328
static long smb3_zero_range (struct file * file , struct cifs_tcon * tcon ,
3311
3329
loff_t offset , loff_t len , bool keep_size )
3312
3330
{
3313
3331
struct cifs_ses * ses = tcon -> ses ;
3314
- struct inode * inode ;
3315
- struct cifsInodeInfo * cifsi ;
3332
+ struct inode * inode = file_inode ( file ) ;
3333
+ struct cifsInodeInfo * cifsi = CIFS_I ( inode ) ;
3316
3334
struct cifsFileInfo * cfile = file -> private_data ;
3317
- struct file_zero_data_information fsctl_buf ;
3318
3335
long rc ;
3319
3336
unsigned int xid ;
3320
3337
__le64 eof ;
3321
3338
3322
3339
xid = get_xid ();
3323
3340
3324
- inode = d_inode (cfile -> dentry );
3325
- cifsi = CIFS_I (inode );
3326
-
3327
3341
trace_smb3_zero_enter (xid , cfile -> fid .persistent_fid , tcon -> tid ,
3328
3342
ses -> Suid , offset , len );
3329
3343
3344
+ inode_lock (inode );
3345
+ filemap_invalidate_lock (inode -> i_mapping );
3346
+
3330
3347
/*
3331
3348
* We zero the range through ioctl, so we need remove the page caches
3332
3349
* first, otherwise the data may be inconsistent with the server.
3333
3350
*/
3334
3351
truncate_pagecache_range (inode , offset , offset + len - 1 );
3335
3352
3336
3353
/* if file not oplocked can't be sure whether asking to extend size */
3337
- if (!CIFS_CACHE_READ (cifsi ))
3338
- if (keep_size == false) {
3339
- rc = - EOPNOTSUPP ;
3340
- trace_smb3_zero_err (xid , cfile -> fid .persistent_fid ,
3341
- tcon -> tid , ses -> Suid , offset , len , rc );
3342
- free_xid (xid );
3343
- return rc ;
3344
- }
3345
-
3346
- cifs_dbg (FYI , "Offset %lld len %lld\n" , offset , len );
3347
-
3348
- fsctl_buf .FileOffset = cpu_to_le64 (offset );
3349
- fsctl_buf .BeyondFinalZero = cpu_to_le64 (offset + len );
3354
+ rc = - EOPNOTSUPP ;
3355
+ if (keep_size == false && !CIFS_CACHE_READ (cifsi ))
3356
+ goto zero_range_exit ;
3350
3357
3351
- rc = SMB2_ioctl (xid , tcon , cfile -> fid .persistent_fid ,
3352
- cfile -> fid .volatile_fid , FSCTL_SET_ZERO_DATA ,
3353
- (char * )& fsctl_buf ,
3354
- sizeof (struct file_zero_data_information ),
3355
- 0 , NULL , NULL );
3356
- if (rc )
3358
+ rc = smb3_zero_data (file , tcon , offset , len , xid );
3359
+ if (rc < 0 )
3357
3360
goto zero_range_exit ;
3358
3361
3359
3362
/*
@@ -3366,6 +3369,8 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
3366
3369
}
3367
3370
3368
3371
zero_range_exit :
3372
+ filemap_invalidate_unlock (inode -> i_mapping );
3373
+ inode_unlock (inode );
3369
3374
free_xid (xid );
3370
3375
if (rc )
3371
3376
trace_smb3_zero_err (xid , cfile -> fid .persistent_fid , tcon -> tid ,
0 commit comments