Skip to content

Commit 2990c89

Browse files
committed
Merge tag 'netfs-fixes-20211207' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
Pull netfslib fixes from David Howells: - Fix a lockdep warning and potential deadlock. This is takes the simple approach of offloading the write-to-cache done from within a network filesystem read to a worker thread to avoid taking the sb_writer lock from the cache backing filesystem whilst holding the mmap lock on an inode from the network filesystem. Jan Kara posits a scenario whereby this can cause deadlock[1], though it's quite complex and I think requires someone in userspace to actually do I/O on the cache files. Matthew Wilcox isn't so certain, though[2]. An alternative way to fix this, suggested by Darrick Wong, might be to allow cachefiles to prevent userspace from performing I/O upon the file - something like an exclusive open - but that's beyond the scope of a fix here if we do want to make such a facility in the future. - In some of the error handling paths where netfs_ops->cleanup() is called, the arguments are transposed[3]. gcc doesn't complain because one of the parameters is void* and one of the values is void*. Link: https://lore.kernel.org/r/[email protected]/ [1] Link: https://lore.kernel.org/r/Ya9eDiFCE2fO7K/[email protected]/ [2] Link: https://lore.kernel.org/r/[email protected]/ [3] * tag 'netfs-fixes-20211207' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: netfs: fix parameter of cleanup() netfs: Fix lockdep warning from taking sb_writers whilst holding mmap_lock
2 parents 3a49cc2 + 3cfef1b commit 2990c89

File tree

1 file changed

+8
-13
lines changed

1 file changed

+8
-13
lines changed

fs/netfs/read_helper.c

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -354,16 +354,11 @@ static void netfs_rreq_write_to_cache_work(struct work_struct *work)
354354
netfs_rreq_do_write_to_cache(rreq);
355355
}
356356

357-
static void netfs_rreq_write_to_cache(struct netfs_read_request *rreq,
358-
bool was_async)
357+
static void netfs_rreq_write_to_cache(struct netfs_read_request *rreq)
359358
{
360-
if (was_async) {
361-
rreq->work.func = netfs_rreq_write_to_cache_work;
362-
if (!queue_work(system_unbound_wq, &rreq->work))
363-
BUG();
364-
} else {
365-
netfs_rreq_do_write_to_cache(rreq);
366-
}
359+
rreq->work.func = netfs_rreq_write_to_cache_work;
360+
if (!queue_work(system_unbound_wq, &rreq->work))
361+
BUG();
367362
}
368363

369364
/*
@@ -558,7 +553,7 @@ static void netfs_rreq_assess(struct netfs_read_request *rreq, bool was_async)
558553
wake_up_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS);
559554

560555
if (test_bit(NETFS_RREQ_WRITE_TO_CACHE, &rreq->flags))
561-
return netfs_rreq_write_to_cache(rreq, was_async);
556+
return netfs_rreq_write_to_cache(rreq);
562557

563558
netfs_rreq_completed(rreq, was_async);
564559
}
@@ -960,7 +955,7 @@ int netfs_readpage(struct file *file,
960955
rreq = netfs_alloc_read_request(ops, netfs_priv, file);
961956
if (!rreq) {
962957
if (netfs_priv)
963-
ops->cleanup(netfs_priv, folio_file_mapping(folio));
958+
ops->cleanup(folio_file_mapping(folio), netfs_priv);
964959
folio_unlock(folio);
965960
return -ENOMEM;
966961
}
@@ -1191,7 +1186,7 @@ int netfs_write_begin(struct file *file, struct address_space *mapping,
11911186
goto error;
11921187
have_folio_no_wait:
11931188
if (netfs_priv)
1194-
ops->cleanup(netfs_priv, mapping);
1189+
ops->cleanup(mapping, netfs_priv);
11951190
*_folio = folio;
11961191
_leave(" = 0");
11971192
return 0;
@@ -1202,7 +1197,7 @@ int netfs_write_begin(struct file *file, struct address_space *mapping,
12021197
folio_unlock(folio);
12031198
folio_put(folio);
12041199
if (netfs_priv)
1205-
ops->cleanup(netfs_priv, mapping);
1200+
ops->cleanup(mapping, netfs_priv);
12061201
_leave(" = %d", ret);
12071202
return ret;
12081203
}

0 commit comments

Comments
 (0)