mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
vfs-6.8-rc6.fixes
-----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCZddOmwAKCRCRxhvAZXjc oq1lAQDus0SGgwuwArdHtbbVj+gTs4s5XKvuGI6mqRiLvgvTzwD/TTNnOqJjWacS on7XxDHgnjbMR2r90W/MuyPPjtAPkgA= =i2E/ -----END PGP SIGNATURE----- Merge tag 'vfs-6.8-rc6.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs fixes from Christian Brauner: - Fix a memory leak in cachefiles - Restrict aio cancellations to I/O submitted through the aio interfaces as this is otherwise causing issues for I/O submitted via io_uring - Increase buffer for afs volume status to avoid overflow - Fix a missing zero-length check in unbuffered writes in the netfs library. If generic_write_checks() returns zero make netfs_unbuffered_write_iter() return right away - Prevent a leak in i_dio_count caused by netfs_begin_read() operating past i_size. It will return early and leave i_dio_count incremented - Account for ipv4 addresses as well as ipv6 addresses when processing incoming callbacks in afs * tag 'vfs-6.8-rc6.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: fs/aio: Restrict kiocb_set_cancel_fn() to I/O submitted via libaio afs: Increase buffer size in afs_update_volume_status() afs: Fix ignored callbacks over ipv4 cachefiles: fix memory leak in cachefiles_add_cache() netfs: Fix missing zero-length check in unbuffered write netfs: Fix i_dio_count leak on DIO read past i_size
This commit is contained in:
commit
1c892cdd8f
@ -321,8 +321,7 @@ struct afs_net {
|
||||
struct list_head fs_probe_slow; /* List of afs_server to probe at 5m intervals */
|
||||
struct hlist_head fs_proc; /* procfs servers list */
|
||||
|
||||
struct hlist_head fs_addresses4; /* afs_server (by lowest IPv4 addr) */
|
||||
struct hlist_head fs_addresses6; /* afs_server (by lowest IPv6 addr) */
|
||||
struct hlist_head fs_addresses; /* afs_server (by lowest IPv6 addr) */
|
||||
seqlock_t fs_addr_lock; /* For fs_addresses[46] */
|
||||
|
||||
struct work_struct fs_manager;
|
||||
@ -561,8 +560,7 @@ struct afs_server {
|
||||
struct afs_server __rcu *uuid_next; /* Next server with same UUID */
|
||||
struct afs_server *uuid_prev; /* Previous server with same UUID */
|
||||
struct list_head probe_link; /* Link in net->fs_probe_list */
|
||||
struct hlist_node addr4_link; /* Link in net->fs_addresses4 */
|
||||
struct hlist_node addr6_link; /* Link in net->fs_addresses6 */
|
||||
struct hlist_node addr_link; /* Link in net->fs_addresses6 */
|
||||
struct hlist_node proc_link; /* Link in net->fs_proc */
|
||||
struct list_head volumes; /* RCU list of afs_server_entry objects */
|
||||
struct afs_server *gc_next; /* Next server in manager's list */
|
||||
|
@ -90,8 +90,7 @@ static int __net_init afs_net_init(struct net *net_ns)
|
||||
INIT_LIST_HEAD(&net->fs_probe_slow);
|
||||
INIT_HLIST_HEAD(&net->fs_proc);
|
||||
|
||||
INIT_HLIST_HEAD(&net->fs_addresses4);
|
||||
INIT_HLIST_HEAD(&net->fs_addresses6);
|
||||
INIT_HLIST_HEAD(&net->fs_addresses);
|
||||
seqlock_init(&net->fs_addr_lock);
|
||||
|
||||
INIT_WORK(&net->fs_manager, afs_manage_servers);
|
||||
|
@ -38,7 +38,7 @@ struct afs_server *afs_find_server(struct afs_net *net, const struct rxrpc_peer
|
||||
seq++; /* 2 on the 1st/lockless path, otherwise odd */
|
||||
read_seqbegin_or_lock(&net->fs_addr_lock, &seq);
|
||||
|
||||
hlist_for_each_entry_rcu(server, &net->fs_addresses6, addr6_link) {
|
||||
hlist_for_each_entry_rcu(server, &net->fs_addresses, addr_link) {
|
||||
estate = rcu_dereference(server->endpoint_state);
|
||||
alist = estate->addresses;
|
||||
for (i = 0; i < alist->nr_addrs; i++)
|
||||
@ -177,10 +177,8 @@ added_dup:
|
||||
* bit, but anything we might want to do gets messy and memory
|
||||
* intensive.
|
||||
*/
|
||||
if (alist->nr_ipv4 > 0)
|
||||
hlist_add_head_rcu(&server->addr4_link, &net->fs_addresses4);
|
||||
if (alist->nr_addrs > alist->nr_ipv4)
|
||||
hlist_add_head_rcu(&server->addr6_link, &net->fs_addresses6);
|
||||
if (alist->nr_addrs > 0)
|
||||
hlist_add_head_rcu(&server->addr_link, &net->fs_addresses);
|
||||
|
||||
write_sequnlock(&net->fs_addr_lock);
|
||||
|
||||
@ -511,10 +509,8 @@ static void afs_gc_servers(struct afs_net *net, struct afs_server *gc_list)
|
||||
|
||||
list_del(&server->probe_link);
|
||||
hlist_del_rcu(&server->proc_link);
|
||||
if (!hlist_unhashed(&server->addr4_link))
|
||||
hlist_del_rcu(&server->addr4_link);
|
||||
if (!hlist_unhashed(&server->addr6_link))
|
||||
hlist_del_rcu(&server->addr6_link);
|
||||
if (!hlist_unhashed(&server->addr_link))
|
||||
hlist_del_rcu(&server->addr_link);
|
||||
}
|
||||
write_sequnlock(&net->fs_lock);
|
||||
|
||||
|
@ -353,7 +353,7 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key)
|
||||
{
|
||||
struct afs_server_list *new, *old, *discard;
|
||||
struct afs_vldb_entry *vldb;
|
||||
char idbuf[16];
|
||||
char idbuf[24];
|
||||
int ret, idsz;
|
||||
|
||||
_enter("");
|
||||
@ -361,7 +361,7 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key)
|
||||
/* We look up an ID by passing it as a decimal string in the
|
||||
* operation's name parameter.
|
||||
*/
|
||||
idsz = sprintf(idbuf, "%llu", volume->vid);
|
||||
idsz = snprintf(idbuf, sizeof(idbuf), "%llu", volume->vid);
|
||||
|
||||
vldb = afs_vl_lookup_vldb(volume->cell, key, idbuf, idsz);
|
||||
if (IS_ERR(vldb)) {
|
||||
|
9
fs/aio.c
9
fs/aio.c
@ -593,6 +593,13 @@ void kiocb_set_cancel_fn(struct kiocb *iocb, kiocb_cancel_fn *cancel)
|
||||
struct kioctx *ctx = req->ki_ctx;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* kiocb didn't come from aio or is neither a read nor a write, hence
|
||||
* ignore it.
|
||||
*/
|
||||
if (!(iocb->ki_flags & IOCB_AIO_RW))
|
||||
return;
|
||||
|
||||
if (WARN_ON_ONCE(!list_empty(&req->ki_list)))
|
||||
return;
|
||||
|
||||
@ -1509,7 +1516,7 @@ static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb)
|
||||
req->ki_complete = aio_complete_rw;
|
||||
req->private = NULL;
|
||||
req->ki_pos = iocb->aio_offset;
|
||||
req->ki_flags = req->ki_filp->f_iocb_flags;
|
||||
req->ki_flags = req->ki_filp->f_iocb_flags | IOCB_AIO_RW;
|
||||
if (iocb->aio_flags & IOCB_FLAG_RESFD)
|
||||
req->ki_flags |= IOCB_EVENTFD;
|
||||
if (iocb->aio_flags & IOCB_FLAG_IOPRIO) {
|
||||
|
@ -168,6 +168,8 @@ error_unsupported:
|
||||
dput(root);
|
||||
error_open_root:
|
||||
cachefiles_end_secure(cache, saved_cred);
|
||||
put_cred(cache->cache_cred);
|
||||
cache->cache_cred = NULL;
|
||||
error_getsec:
|
||||
fscache_relinquish_cache(cache_cookie);
|
||||
cache->cache = NULL;
|
||||
|
@ -816,6 +816,7 @@ static void cachefiles_daemon_unbind(struct cachefiles_cache *cache)
|
||||
cachefiles_put_directory(cache->graveyard);
|
||||
cachefiles_put_directory(cache->store);
|
||||
mntput(cache->mnt);
|
||||
put_cred(cache->cache_cred);
|
||||
|
||||
kfree(cache->rootdirname);
|
||||
kfree(cache->secctx);
|
||||
|
@ -477,6 +477,9 @@ ssize_t netfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
|
||||
_enter("%llx,%zx,%llx", iocb->ki_pos, iov_iter_count(from), i_size_read(inode));
|
||||
|
||||
if (!iov_iter_count(from))
|
||||
return 0;
|
||||
|
||||
if ((iocb->ki_flags & IOCB_DIRECT) ||
|
||||
test_bit(NETFS_ICTX_UNBUFFERED, &ictx->flags))
|
||||
return netfs_unbuffered_write_iter(iocb, from);
|
||||
|
@ -139,6 +139,9 @@ ssize_t netfs_unbuffered_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
|
||||
_enter("%llx,%zx,%llx", iocb->ki_pos, iov_iter_count(from), i_size_read(inode));
|
||||
|
||||
if (!iov_iter_count(from))
|
||||
return 0;
|
||||
|
||||
trace_netfs_write_iter(iocb, from);
|
||||
netfs_stat(&netfs_n_rh_dio_write);
|
||||
|
||||
@ -146,7 +149,7 @@ ssize_t netfs_unbuffered_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = generic_write_checks(iocb, from);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
goto out;
|
||||
ret = file_remove_privs(file);
|
||||
if (ret < 0)
|
||||
|
@ -748,6 +748,8 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync)
|
||||
|
||||
if (!rreq->submitted) {
|
||||
netfs_put_request(rreq, false, netfs_rreq_trace_put_no_submit);
|
||||
if (rreq->origin == NETFS_DIO_READ)
|
||||
inode_dio_end(rreq->inode);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
@ -352,6 +352,8 @@ enum rw_hint {
|
||||
* unrelated IO (like cache flushing, new IO generation, etc).
|
||||
*/
|
||||
#define IOCB_DIO_CALLER_COMP (1 << 22)
|
||||
/* kiocb is a read or write operation submitted by fs/aio.c. */
|
||||
#define IOCB_AIO_RW (1 << 23)
|
||||
|
||||
/* for use in trace events */
|
||||
#define TRACE_IOCB_STRINGS \
|
||||
|
Loading…
Reference in New Issue
Block a user