Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crypto/seqiv.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ static void seqiv_aead_encrypt_complete2(struct aead_request *req, int err)
struct aead_request *subreq = aead_request_ctx(req);
struct crypto_aead *geniv;

if (err == -EINPROGRESS)
if (err == -EINPROGRESS || err == -EBUSY)
return;

if (err)
Expand Down
7 changes: 3 additions & 4 deletions fs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
inode->i_wb_frn_history = 0;
#endif

if (security_inode_alloc(inode))
goto out;
spin_lock_init(&inode->i_lock);
lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key);

Expand Down Expand Up @@ -228,11 +226,12 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
inode->i_fsnotify_mask = 0;
#endif
inode->i_flctx = NULL;

if (unlikely(security_inode_alloc(inode)))
return -ENOMEM;
this_cpu_inc(nr_inodes);

return 0;
out:
return -ENOMEM;
}
EXPORT_SYMBOL(inode_init_always);

Expand Down
11 changes: 9 additions & 2 deletions fs/nfs/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,21 @@ nfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
{
struct nfs_fattr *fattr = NULL;
struct nfs_fh *server_fh = nfs_exp_embedfh(fid->raw);
size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size;
size_t fh_size = offsetof(struct nfs_fh, data);
const struct nfs_rpc_ops *rpc_ops;
struct dentry *dentry;
struct inode *inode;
int len = EMBED_FH_OFF + XDR_QUADLEN(fh_size);
int len = EMBED_FH_OFF;
u32 *p = fid->raw;
int ret;

/* Initial check of bounds */
if (fh_len < len + XDR_QUADLEN(fh_size) ||
fh_len > XDR_QUADLEN(NFS_MAXFHSIZE))
return NULL;
/* Calculate embedded filehandle size */
fh_size += server_fh->size;
len += XDR_QUADLEN(fh_size);
/* NULL translates to ESTALE */
if (fh_len < len || fh_type != len)
return NULL;
Expand Down
2 changes: 1 addition & 1 deletion fs/pstore/ram_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig,
sig ^= PERSISTENT_RAM_SIG;

if (prz->buffer->sig == sig) {
if (buffer_size(prz) == 0) {
if (buffer_size(prz) == 0 && buffer_start(prz) == 0) {
pr_debug("found existing empty buffer\n");
return 0;
}
Expand Down
10 changes: 9 additions & 1 deletion fs/smb/client/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -5090,7 +5090,8 @@ void cifs_oplock_break(struct work_struct *work)
struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
oplock_break);
struct inode *inode = d_inode(cfile->dentry);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct super_block *sb = inode->i_sb;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifsInodeInfo *cinode = CIFS_I(inode);
struct cifs_tcon *tcon;
struct TCP_Server_Info *server;
Expand All @@ -5100,6 +5101,12 @@ void cifs_oplock_break(struct work_struct *work)
__u64 persistent_fid, volatile_fid;
__u16 net_fid;

/*
* Hold a reference to the superblock to prevent it and its inodes from
* being freed while we are accessing cinode. Otherwise, _cifsFileInfo_put()
* may release the last reference to the sb and trigger inode eviction.
*/
cifs_sb_active(sb);
wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
TASK_UNINTERRUPTIBLE);

Expand Down Expand Up @@ -5172,6 +5179,7 @@ void cifs_oplock_break(struct work_struct *work)
cifs_put_tlink(tlink);
out:
cifs_done_oplock_break(cinode);
cifs_sb_deactive(sb);
}

/*
Expand Down
19 changes: 10 additions & 9 deletions mm/memcontrol.c
Original file line number Diff line number Diff line change
Expand Up @@ -3255,12 +3255,12 @@ void mod_objcg_state(struct obj_cgroup *objcg, struct pglist_data *pgdat,
* accumulating over a page of vmstat data or when pgdat or idx
* changes.
*/
if (stock->cached_objcg != objcg) {
if (READ_ONCE(stock->cached_objcg) != objcg) {
old = drain_obj_stock(stock);
obj_cgroup_get(objcg);
stock->nr_bytes = atomic_read(&objcg->nr_charged_bytes)
? atomic_xchg(&objcg->nr_charged_bytes, 0) : 0;
stock->cached_objcg = objcg;
WRITE_ONCE(stock->cached_objcg, objcg);
stock->cached_pgdat = pgdat;
} else if (stock->cached_pgdat != pgdat) {
/* Flush the existing cached vmstat data */
Expand Down Expand Up @@ -3314,7 +3314,7 @@ static bool consume_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes)
local_lock_irqsave(&memcg_stock.stock_lock, flags);

stock = this_cpu_ptr(&memcg_stock);
if (objcg == stock->cached_objcg && stock->nr_bytes >= nr_bytes) {
if (objcg == READ_ONCE(stock->cached_objcg) && stock->nr_bytes >= nr_bytes) {
stock->nr_bytes -= nr_bytes;
ret = true;
}
Expand All @@ -3326,7 +3326,7 @@ static bool consume_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes)

static struct obj_cgroup *drain_obj_stock(struct memcg_stock_pcp *stock)
{
struct obj_cgroup *old = stock->cached_objcg;
struct obj_cgroup *old = READ_ONCE(stock->cached_objcg);

if (!old)
return NULL;
Expand Down Expand Up @@ -3379,7 +3379,7 @@ static struct obj_cgroup *drain_obj_stock(struct memcg_stock_pcp *stock)
stock->cached_pgdat = NULL;
}

stock->cached_objcg = NULL;
WRITE_ONCE(stock->cached_objcg, NULL);
/*
* The `old' objects needs to be released by the caller via
* obj_cgroup_put() outside of memcg_stock_pcp::stock_lock.
Expand All @@ -3390,10 +3390,11 @@ static struct obj_cgroup *drain_obj_stock(struct memcg_stock_pcp *stock)
static bool obj_stock_flush_required(struct memcg_stock_pcp *stock,
struct mem_cgroup *root_memcg)
{
struct obj_cgroup *objcg = READ_ONCE(stock->cached_objcg);
struct mem_cgroup *memcg;

if (stock->cached_objcg) {
memcg = obj_cgroup_memcg(stock->cached_objcg);
if (objcg) {
memcg = obj_cgroup_memcg(objcg);
if (memcg && mem_cgroup_is_descendant(memcg, root_memcg))
return true;
}
Expand All @@ -3412,10 +3413,10 @@ static void refill_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes,
local_lock_irqsave(&memcg_stock.stock_lock, flags);

stock = this_cpu_ptr(&memcg_stock);
if (stock->cached_objcg != objcg) { /* reset if necessary */
if (READ_ONCE(stock->cached_objcg) != objcg) { /* reset if necessary */
old = drain_obj_stock(stock);
obj_cgroup_get(objcg);
stock->cached_objcg = objcg;
WRITE_ONCE(stock->cached_objcg, objcg);
stock->nr_bytes = atomic_read(&objcg->nr_charged_bytes)
? atomic_xchg(&objcg->nr_charged_bytes, 0) : 0;
allow_uncharge = true; /* Allow uncharge when objcg changes */
Expand Down
21 changes: 16 additions & 5 deletions net/ipv4/inet_connection_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -773,21 +773,31 @@ static bool reqsk_queue_unlink(struct request_sock *req)
found = __sk_nulls_del_node_init_rcu(req_to_sk(req));
spin_unlock(lock);
}
if (timer_pending(&req->rsk_timer) && del_timer_sync(&req->rsk_timer))
reqsk_put(req);

return found;
}

bool inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req)
static bool __inet_csk_reqsk_queue_drop(struct sock *sk,
struct request_sock *req,
bool from_timer)
{
bool unlinked = reqsk_queue_unlink(req);

if (!from_timer && timer_delete_sync(&req->rsk_timer))
reqsk_put(req);

if (unlinked) {
reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req);
reqsk_put(req);
}

return unlinked;
}

bool inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req)
{
return __inet_csk_reqsk_queue_drop(sk, req, false);
}
EXPORT_SYMBOL(inet_csk_reqsk_queue_drop);

void inet_csk_reqsk_queue_drop_and_put(struct sock *sk, struct request_sock *req)
Expand Down Expand Up @@ -883,7 +893,7 @@ static void reqsk_timer_handler(struct timer_list *t)

if (!inet_ehash_insert(req_to_sk(nreq), req_to_sk(oreq), NULL)) {
/* delete timer */
inet_csk_reqsk_queue_drop(sk_listener, nreq);
__inet_csk_reqsk_queue_drop(sk_listener, nreq, true);
goto no_ownership;
}

Expand All @@ -909,7 +919,8 @@ static void reqsk_timer_handler(struct timer_list *t)
}

drop:
inet_csk_reqsk_queue_drop_and_put(oreq->rsk_listener, oreq);
__inet_csk_reqsk_queue_drop(sk_listener, oreq, true);
reqsk_put(oreq);
}

static void reqsk_queue_hash_req(struct request_sock *req,
Expand Down
2 changes: 1 addition & 1 deletion net/ipv6/mcast.c
Original file line number Diff line number Diff line change
Expand Up @@ -803,8 +803,8 @@ static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
} else {
im->mca_crcount = idev->mc_qrv;
}
in6_dev_put(pmc->idev);
ip6_mc_clear_src(pmc);
in6_dev_put(pmc->idev);
kfree_rcu(pmc, rcu);
}
}
Expand Down
12 changes: 10 additions & 2 deletions net/vmw_vsock/virtio_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -581,8 +581,9 @@ static void virtio_transport_rx_work(struct work_struct *work)
do {
virtqueue_disable_cb(vq);
for (;;) {
unsigned int len, payload_len;
struct virtio_vsock_hdr *hdr;
struct sk_buff *skb;
unsigned int len;

if (!virtio_transport_more_replies(vsock)) {
/* Stop rx until the device processes already
Expand All @@ -599,12 +600,19 @@ static void virtio_transport_rx_work(struct work_struct *work)
vsock->rx_buf_nr--;

/* Drop short/long packets */
if (unlikely(len < sizeof(struct virtio_vsock_hdr) ||
if (unlikely(len < sizeof(*hdr) ||
len > virtio_vsock_skb_len(skb))) {
kfree_skb(skb);
continue;
}

hdr = virtio_vsock_hdr(skb);
payload_len = le32_to_cpu(hdr->len);
if (unlikely(payload_len > len - sizeof(*hdr))) {
kfree_skb(skb);
continue;
}

virtio_vsock_skb_rx_put(skb);
virtio_transport_deliver_tap_pkt(skb);
virtio_transport_recv_pkt(&virtio_transport, skb);
Expand Down