Skip to content

Commit d11b0b0

Browse files
lostjefflehsiangkao
authored andcommitted
cachefiles: unbind cachefiles gracefully in on-demand mode
Add a refcount to avoid the deadlock in on-demand read mode. The on-demand read mode will pin the corresponding cachefiles object for each anonymous fd. The cachefiles object is unpinned when the anonymous fd gets closed. When the user daemon exits and the fd of "/dev/cachefiles" device node gets closed, it will wait for all cahcefiles objects getting withdrawn. Then if there's any anonymous fd getting closed after the fd of the device node, the user daemon will hang forever, waiting for all objects getting withdrawn. To fix this, add a refcount indicating if there's any object pinned by anonymous fds. The cachefiles cache gets unbound and withdrawn when the refcount is decreased to 0. It won't change the behaviour of the original mode, in which case the cachefiles cache gets unbound and withdrawn as long as the fd of the device node gets closed. Signed-off-by: Jeffle Xu <jefflexu@linux.alibaba.com> Link: https://lore.kernel.org/r/20220509074028.74954-4-jefflexu@linux.alibaba.com Acked-by: David Howells <dhowells@redhat.com> Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
1 parent c838305 commit d11b0b0

3 files changed

Lines changed: 22 additions & 3 deletions

File tree

fs/cachefiles/daemon.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ static int cachefiles_daemon_open(struct inode *inode, struct file *file)
111111
INIT_LIST_HEAD(&cache->volumes);
112112
INIT_LIST_HEAD(&cache->object_list);
113113
spin_lock_init(&cache->object_list_lock);
114+
refcount_set(&cache->unbind_pincount, 1);
114115
xa_init_flags(&cache->reqs, XA_FLAGS_ALLOC);
115116
xa_init_flags(&cache->ondemand_ids, XA_FLAGS_ALLOC1);
116117

@@ -164,6 +165,20 @@ static void cachefiles_flush_reqs(struct cachefiles_cache *cache)
164165
xa_destroy(&cache->ondemand_ids);
165166
}
166167

168+
void cachefiles_put_unbind_pincount(struct cachefiles_cache *cache)
169+
{
170+
if (refcount_dec_and_test(&cache->unbind_pincount)) {
171+
cachefiles_daemon_unbind(cache);
172+
cachefiles_open = 0;
173+
kfree(cache);
174+
}
175+
}
176+
177+
void cachefiles_get_unbind_pincount(struct cachefiles_cache *cache)
178+
{
179+
refcount_inc(&cache->unbind_pincount);
180+
}
181+
167182
/*
168183
* Release a cache.
169184
*/
@@ -179,14 +194,12 @@ static int cachefiles_daemon_release(struct inode *inode, struct file *file)
179194

180195
if (cachefiles_in_ondemand_mode(cache))
181196
cachefiles_flush_reqs(cache);
182-
cachefiles_daemon_unbind(cache);
183197

184198
/* clean up the control file interface */
185199
cache->cachefilesd = NULL;
186200
file->private_data = NULL;
187-
cachefiles_open = 0;
188201

189-
kfree(cache);
202+
cachefiles_put_unbind_pincount(cache);
190203

191204
_leave("");
192205
return 0;

fs/cachefiles/internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ struct cachefiles_cache {
109109
char *rootdirname; /* name of cache root directory */
110110
char *secctx; /* LSM security context */
111111
char *tag; /* cache binding tag */
112+
refcount_t unbind_pincount;/* refcount to do daemon unbind */
112113
struct xarray reqs; /* xarray of pending on-demand requests */
113114
struct xarray ondemand_ids; /* xarray for ondemand_id allocation */
114115
u32 ondemand_id_next;
@@ -171,6 +172,8 @@ extern int cachefiles_has_space(struct cachefiles_cache *cache,
171172
* daemon.c
172173
*/
173174
extern const struct file_operations cachefiles_daemon_fops;
175+
extern void cachefiles_get_unbind_pincount(struct cachefiles_cache *cache);
176+
extern void cachefiles_put_unbind_pincount(struct cachefiles_cache *cache);
174177

175178
/*
176179
* error_inject.c

fs/cachefiles/ondemand.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ static int cachefiles_ondemand_fd_release(struct inode *inode,
1414
object->ondemand_id = CACHEFILES_ONDEMAND_ID_CLOSED;
1515
xa_erase(&cache->ondemand_ids, object_id);
1616
cachefiles_put_object(object, cachefiles_obj_put_ondemand_fd);
17+
cachefiles_put_unbind_pincount(cache);
1718
return 0;
1819
}
1920

@@ -169,6 +170,8 @@ static int cachefiles_ondemand_get_fd(struct cachefiles_req *req)
169170
load->fd = fd;
170171
req->msg.object_id = object_id;
171172
object->ondemand_id = object_id;
173+
174+
cachefiles_get_unbind_pincount(cache);
172175
return 0;
173176

174177
err_put_fd:

0 commit comments

Comments
 (0)