@@ -99,8 +99,268 @@ void cachefiles_put_object(struct cachefiles_object *object,
9999 _leave ("" );
100100}
101101
102+ /*
103+ * Adjust the size of a cache file if necessary to match the DIO size. We keep
104+ * the EOF marker a multiple of DIO blocks so that we don't fall back to doing
105+ * non-DIO for a partial block straddling the EOF, but we also have to be
106+ * careful of someone expanding the file and accidentally accreting the
107+ * padding.
108+ */
109+ static int cachefiles_adjust_size (struct cachefiles_object * object )
110+ {
111+ struct iattr newattrs ;
112+ struct file * file = object -> file ;
113+ uint64_t ni_size ;
114+ loff_t oi_size ;
115+ int ret ;
116+
117+ ni_size = object -> cookie -> object_size ;
118+ ni_size = round_up (ni_size , CACHEFILES_DIO_BLOCK_SIZE );
119+
120+ _enter ("{OBJ%x},[%llu]" ,
121+ object -> debug_id , (unsigned long long ) ni_size );
122+
123+ if (!file )
124+ return - ENOBUFS ;
125+
126+ oi_size = i_size_read (file_inode (file ));
127+ if (oi_size == ni_size )
128+ return 0 ;
129+
130+ inode_lock (file_inode (file ));
131+
132+ /* if there's an extension to a partial page at the end of the backing
133+ * file, we need to discard the partial page so that we pick up new
134+ * data after it */
135+ if (oi_size & ~PAGE_MASK && ni_size > oi_size ) {
136+ _debug ("discard tail %llx" , oi_size );
137+ newattrs .ia_valid = ATTR_SIZE ;
138+ newattrs .ia_size = oi_size & PAGE_MASK ;
139+ ret = cachefiles_inject_remove_error ();
140+ if (ret == 0 )
141+ ret = notify_change (& init_user_ns , file -> f_path .dentry ,
142+ & newattrs , NULL );
143+ if (ret < 0 )
144+ goto truncate_failed ;
145+ }
146+
147+ newattrs .ia_valid = ATTR_SIZE ;
148+ newattrs .ia_size = ni_size ;
149+ ret = cachefiles_inject_write_error ();
150+ if (ret == 0 )
151+ ret = notify_change (& init_user_ns , file -> f_path .dentry ,
152+ & newattrs , NULL );
153+
154+ truncate_failed :
155+ inode_unlock (file_inode (file ));
156+
157+ if (ret < 0 )
158+ trace_cachefiles_io_error (NULL , file_inode (file ), ret ,
159+ cachefiles_trace_notify_change_error );
160+ if (ret == - EIO ) {
161+ cachefiles_io_error_obj (object , "Size set failed" );
162+ ret = - ENOBUFS ;
163+ }
164+
165+ _leave (" = %d" , ret );
166+ return ret ;
167+ }
168+
169+ /*
170+ * Attempt to look up the nominated node in this cache
171+ */
172+ static bool cachefiles_lookup_cookie (struct fscache_cookie * cookie )
173+ {
174+ struct cachefiles_object * object ;
175+ struct cachefiles_cache * cache = cookie -> volume -> cache -> cache_priv ;
176+ const struct cred * saved_cred ;
177+ bool success ;
178+
179+ object = cachefiles_alloc_object (cookie );
180+ if (!object )
181+ goto fail ;
182+
183+ _enter ("{OBJ%x}" , object -> debug_id );
184+
185+ if (!cachefiles_cook_key (object ))
186+ goto fail_put ;
187+
188+ cookie -> cache_priv = object ;
189+
190+ cachefiles_begin_secure (cache , & saved_cred );
191+
192+ success = cachefiles_look_up_object (object );
193+ if (!success )
194+ goto fail_withdraw ;
195+
196+ cachefiles_see_object (object , cachefiles_obj_see_lookup_cookie );
197+
198+ spin_lock (& cache -> object_list_lock );
199+ list_add (& object -> cache_link , & cache -> object_list );
200+ spin_unlock (& cache -> object_list_lock );
201+ cachefiles_adjust_size (object );
202+
203+ cachefiles_end_secure (cache , saved_cred );
204+ _leave (" = t" );
205+ return true;
206+
207+ fail_withdraw :
208+ cachefiles_end_secure (cache , saved_cred );
209+ cachefiles_see_object (object , cachefiles_obj_see_lookup_failed );
210+ fscache_caching_failed (cookie );
211+ _debug ("failed c=%08x o=%08x" , cookie -> debug_id , object -> debug_id );
212+ /* The caller holds an access count on the cookie, so we need them to
213+ * drop it before we can withdraw the object.
214+ */
215+ return false;
216+
217+ fail_put :
218+ cachefiles_put_object (object , cachefiles_obj_put_alloc_fail );
219+ fail :
220+ return false;
221+ }
222+
223+ /*
224+ * Commit changes to the object as we drop it.
225+ */
226+ static void cachefiles_commit_object (struct cachefiles_object * object ,
227+ struct cachefiles_cache * cache )
228+ {
229+ bool update = false;
230+
231+ if (test_and_clear_bit (FSCACHE_COOKIE_LOCAL_WRITE , & object -> cookie -> flags ))
232+ update = true;
233+ if (test_and_clear_bit (FSCACHE_COOKIE_NEEDS_UPDATE , & object -> cookie -> flags ))
234+ update = true;
235+ if (update )
236+ cachefiles_set_object_xattr (object );
237+
238+ if (test_bit (CACHEFILES_OBJECT_USING_TMPFILE , & object -> flags ))
239+ cachefiles_commit_tmpfile (cache , object );
240+ }
241+
242+ /*
243+ * Finalise and object and close the VFS structs that we have.
244+ */
245+ static void cachefiles_clean_up_object (struct cachefiles_object * object ,
246+ struct cachefiles_cache * cache )
247+ {
248+ if (test_bit (FSCACHE_COOKIE_RETIRED , & object -> cookie -> flags )) {
249+ if (!test_bit (CACHEFILES_OBJECT_USING_TMPFILE , & object -> flags )) {
250+ cachefiles_see_object (object , cachefiles_obj_see_clean_delete );
251+ _debug ("- inval object OBJ%x" , object -> debug_id );
252+ cachefiles_delete_object (object , FSCACHE_OBJECT_WAS_RETIRED );
253+ } else {
254+ cachefiles_see_object (object , cachefiles_obj_see_clean_drop_tmp );
255+ _debug ("- inval object OBJ%x tmpfile" , object -> debug_id );
256+ }
257+ } else {
258+ cachefiles_see_object (object , cachefiles_obj_see_clean_commit );
259+ cachefiles_commit_object (object , cache );
260+ }
261+
262+ cachefiles_unmark_inode_in_use (object , object -> file );
263+ if (object -> file ) {
264+ fput (object -> file );
265+ object -> file = NULL ;
266+ }
267+ }
268+
269+ /*
270+ * Withdraw caching for a cookie.
271+ */
272+ static void cachefiles_withdraw_cookie (struct fscache_cookie * cookie )
273+ {
274+ struct cachefiles_object * object = cookie -> cache_priv ;
275+ struct cachefiles_cache * cache = object -> volume -> cache ;
276+ const struct cred * saved_cred ;
277+
278+ _enter ("o=%x" , object -> debug_id );
279+ cachefiles_see_object (object , cachefiles_obj_see_withdraw_cookie );
280+
281+ if (!list_empty (& object -> cache_link )) {
282+ spin_lock (& cache -> object_list_lock );
283+ cachefiles_see_object (object , cachefiles_obj_see_withdrawal );
284+ list_del_init (& object -> cache_link );
285+ spin_unlock (& cache -> object_list_lock );
286+ }
287+
288+ if (object -> file ) {
289+ cachefiles_begin_secure (cache , & saved_cred );
290+ cachefiles_clean_up_object (object , cache );
291+ cachefiles_end_secure (cache , saved_cred );
292+ }
293+
294+ cookie -> cache_priv = NULL ;
295+ cachefiles_put_object (object , cachefiles_obj_put_detach );
296+ }
297+
298+ /*
299+ * Invalidate the storage associated with a cookie.
300+ */
301+ static bool cachefiles_invalidate_cookie (struct fscache_cookie * cookie )
302+ {
303+ struct cachefiles_object * object = cookie -> cache_priv ;
304+ struct file * new_file , * old_file ;
305+ bool old_tmpfile ;
306+
307+ _enter ("o=%x,[%llu]" , object -> debug_id , object -> cookie -> object_size );
308+
309+ old_tmpfile = test_bit (CACHEFILES_OBJECT_USING_TMPFILE , & object -> flags );
310+
311+ if (!object -> file ) {
312+ fscache_resume_after_invalidation (cookie );
313+ _leave (" = t [light]" );
314+ return true;
315+ }
316+
317+ new_file = cachefiles_create_tmpfile (object );
318+ if (IS_ERR (new_file ))
319+ goto failed ;
320+
321+ /* Substitute the VFS target */
322+ _debug ("sub" );
323+ spin_lock (& object -> lock );
324+
325+ old_file = object -> file ;
326+ object -> file = new_file ;
327+ object -> content_info = CACHEFILES_CONTENT_NO_DATA ;
328+ set_bit (CACHEFILES_OBJECT_USING_TMPFILE , & object -> flags );
329+ set_bit (FSCACHE_COOKIE_NEEDS_UPDATE , & object -> cookie -> flags );
330+
331+ spin_unlock (& object -> lock );
332+ _debug ("subbed" );
333+
334+ /* Allow I/O to take place again */
335+ fscache_resume_after_invalidation (cookie );
336+
337+ if (old_file ) {
338+ if (!old_tmpfile ) {
339+ struct cachefiles_volume * volume = object -> volume ;
340+ struct dentry * fan = volume -> fanout [(u8 )cookie -> key_hash ];
341+
342+ inode_lock_nested (d_inode (fan ), I_MUTEX_PARENT );
343+ cachefiles_bury_object (volume -> cache , object , fan ,
344+ old_file -> f_path .dentry ,
345+ FSCACHE_OBJECT_INVALIDATED );
346+ }
347+ fput (old_file );
348+ }
349+
350+ _leave (" = t" );
351+ return true;
352+
353+ failed :
354+ _leave (" = f" );
355+ return false;
356+ }
357+
102358const struct fscache_cache_ops cachefiles_cache_ops = {
103359 .name = "cachefiles" ,
104360 .acquire_volume = cachefiles_acquire_volume ,
105361 .free_volume = cachefiles_free_volume ,
362+ .lookup_cookie = cachefiles_lookup_cookie ,
363+ .withdraw_cookie = cachefiles_withdraw_cookie ,
364+ .invalidate_cookie = cachefiles_invalidate_cookie ,
365+ .prepare_to_write = cachefiles_prepare_to_write ,
106366};
0 commit comments