@@ -220,6 +220,83 @@ static bool cachefiles_lookup_cookie(struct fscache_cookie *cookie)
220
220
return false;
221
221
}
222
222
223
+ /*
224
+ * Shorten the backing object to discard any dirty data and free up
225
+ * any unused granules.
226
+ */
227
+ static bool cachefiles_shorten_object (struct cachefiles_object * object ,
228
+ struct file * file , loff_t new_size )
229
+ {
230
+ struct cachefiles_cache * cache = object -> volume -> cache ;
231
+ struct inode * inode = file_inode (file );
232
+ loff_t i_size , dio_size ;
233
+ int ret ;
234
+
235
+ dio_size = round_up (new_size , CACHEFILES_DIO_BLOCK_SIZE );
236
+ i_size = i_size_read (inode );
237
+
238
+ trace_cachefiles_trunc (object , inode , i_size , dio_size ,
239
+ cachefiles_trunc_shrink );
240
+ ret = cachefiles_inject_remove_error ();
241
+ if (ret == 0 )
242
+ ret = vfs_truncate (& file -> f_path , dio_size );
243
+ if (ret < 0 ) {
244
+ trace_cachefiles_io_error (object , file_inode (file ), ret ,
245
+ cachefiles_trace_trunc_error );
246
+ cachefiles_io_error_obj (object , "Trunc-to-size failed %d" , ret );
247
+ cachefiles_remove_object_xattr (cache , object , file -> f_path .dentry );
248
+ return false;
249
+ }
250
+
251
+ if (new_size < dio_size ) {
252
+ trace_cachefiles_trunc (object , inode , dio_size , new_size ,
253
+ cachefiles_trunc_dio_adjust );
254
+ ret = cachefiles_inject_write_error ();
255
+ if (ret == 0 )
256
+ ret = vfs_fallocate (file , FALLOC_FL_ZERO_RANGE ,
257
+ new_size , dio_size );
258
+ if (ret < 0 ) {
259
+ trace_cachefiles_io_error (object , file_inode (file ), ret ,
260
+ cachefiles_trace_fallocate_error );
261
+ cachefiles_io_error_obj (object , "Trunc-to-dio-size failed %d" , ret );
262
+ cachefiles_remove_object_xattr (cache , object , file -> f_path .dentry );
263
+ return false;
264
+ }
265
+ }
266
+
267
+ return true;
268
+ }
269
+
270
+ /*
271
+ * Resize the backing object.
272
+ */
273
+ static void cachefiles_resize_cookie (struct netfs_cache_resources * cres ,
274
+ loff_t new_size )
275
+ {
276
+ struct cachefiles_object * object = cachefiles_cres_object (cres );
277
+ struct cachefiles_cache * cache = object -> volume -> cache ;
278
+ struct fscache_cookie * cookie = object -> cookie ;
279
+ const struct cred * saved_cred ;
280
+ struct file * file = cachefiles_cres_file (cres );
281
+ loff_t old_size = cookie -> object_size ;
282
+
283
+ _enter ("%llu->%llu" , old_size , new_size );
284
+
285
+ if (new_size < old_size ) {
286
+ cachefiles_begin_secure (cache , & saved_cred );
287
+ cachefiles_shorten_object (object , file , new_size );
288
+ cachefiles_end_secure (cache , saved_cred );
289
+ object -> cookie -> object_size = new_size ;
290
+ return ;
291
+ }
292
+
293
+ /* The file is being expanded. We don't need to do anything
294
+ * particularly. cookie->initial_size doesn't change and so the point
295
+ * at which we have to download before doesn't change.
296
+ */
297
+ cookie -> object_size = new_size ;
298
+ }
299
+
223
300
/*
224
301
* Commit changes to the object as we drop it.
225
302
*/
@@ -363,5 +440,6 @@ const struct fscache_cache_ops cachefiles_cache_ops = {
363
440
.withdraw_cookie = cachefiles_withdraw_cookie ,
364
441
.invalidate_cookie = cachefiles_invalidate_cookie ,
365
442
.begin_operation = cachefiles_begin_operation ,
443
+ .resize_cookie = cachefiles_resize_cookie ,
366
444
.prepare_to_write = cachefiles_prepare_to_write ,
367
445
};
0 commit comments