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
3 changes: 2 additions & 1 deletion Documentation/accounting/psi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ Triggers can be set on more than one psi metric and more than one trigger
for the same psi metric can be specified. However for each trigger a separate
file descriptor is required to be able to poll it separately from others,
therefore for each trigger a separate open() syscall should be made even
when opening the same psi interface file.
when opening the same psi interface file. Write operations to a file descriptor
with an already existing psi trigger will fail with EBUSY.

Monitors activate only when system enters stall state for the monitored
psi metric and deactivates upon exit from the stall state. While system is
Expand Down
8 changes: 4 additions & 4 deletions drivers/media/usb/em28xx/em28xx-cards.c
Original file line number Diff line number Diff line change
Expand Up @@ -3838,6 +3838,8 @@ static int em28xx_usb_probe(struct usb_interface *intf,
goto err_free;
}

kref_init(&dev->ref);

dev->devno = nr;
dev->model = id->driver_info;
dev->alt = -1;
Expand Down Expand Up @@ -3938,6 +3940,8 @@ static int em28xx_usb_probe(struct usb_interface *intf,
}

if (dev->board.has_dual_ts && em28xx_duplicate_dev(dev) == 0) {
kref_init(&dev->dev_next->ref);

dev->dev_next->ts = SECONDARY_TS;
dev->dev_next->alt = -1;
dev->dev_next->is_audio_only = has_vendor_audio &&
Expand Down Expand Up @@ -3992,12 +3996,8 @@ static int em28xx_usb_probe(struct usb_interface *intf,
em28xx_write_reg(dev, 0x0b, 0x82);
mdelay(100);
}

kref_init(&dev->dev_next->ref);
}

kref_init(&dev->ref);

request_modules(dev);

/*
Expand Down
1 change: 0 additions & 1 deletion drivers/net/can/usb/ems_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,6 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne

usb_unanchor_urb(urb);
usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
dev_kfree_skb(skb);

atomic_dec(&dev->active_tx_urbs);

Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,6 @@ area_cache_get(struct nfp_cpp *cpp, u32 id,
}

/* Adjust the start address to be cache size aligned */
cache->id = id;
cache->addr = addr & ~(u64)(cache->size - 1);

/* Re-init to the new ID and address */
Expand All @@ -892,6 +891,8 @@ area_cache_get(struct nfp_cpp *cpp, u32 id,
return NULL;
}

cache->id = id;

exit:
/* Adjust offset */
*offset = addr - cache->addr;
Expand Down
2 changes: 1 addition & 1 deletion include/linux/psi.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void cgroup_move_task(struct task_struct *p, struct css_set *to);

struct psi_trigger *psi_trigger_create(struct psi_group *group,
char *buf, size_t nbytes, enum psi_res res);
void psi_trigger_replace(void **trigger_ptr, struct psi_trigger *t);
void psi_trigger_destroy(struct psi_trigger *t);

__poll_t psi_trigger_poll(void **trigger_ptr, struct file *file,
poll_table *wait);
Expand Down
3 changes: 0 additions & 3 deletions include/linux/psi_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,6 @@ struct psi_trigger {
* events to one per window
*/
u64 last_event_time;

/* Refcounting to prevent premature destruction */
struct kref refcount;
};

struct psi_group {
Expand Down
1 change: 1 addition & 0 deletions include/sound/pcm.h
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ struct snd_pcm_runtime {
wait_queue_head_t tsleep; /* transfer sleep */
struct fasync_struct *fasync;
bool stop_operating; /* sync_stop will be called */
struct mutex buffer_mutex; /* protect for buffer changes */

/* -- private section -- */
void *private_data;
Expand Down
11 changes: 8 additions & 3 deletions kernel/cgroup/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -3638,15 +3638,20 @@ static ssize_t cgroup_pressure_write(struct kernfs_open_file *of, char *buf,
cgroup_get(cgrp);
cgroup_kn_unlock(of->kn);

/* Allow only one trigger per file descriptor */
if (ctx->psi.trigger) {
cgroup_put(cgrp);
return -EBUSY;
}

psi = cgroup_ino(cgrp) == 1 ? &psi_system : &cgrp->psi;
new = psi_trigger_create(psi, buf, nbytes, res);
if (IS_ERR(new)) {
cgroup_put(cgrp);
return PTR_ERR(new);
}

psi_trigger_replace(&ctx->psi.trigger, new);

smp_store_release(&ctx->psi.trigger, new);
cgroup_put(cgrp);

return nbytes;
Expand Down Expand Up @@ -3685,7 +3690,7 @@ static void cgroup_pressure_release(struct kernfs_open_file *of)
{
struct cgroup_file_ctx *ctx = of->priv;

psi_trigger_replace(&ctx->psi.trigger, NULL);
psi_trigger_destroy(ctx->psi.trigger);
}

bool cgroup_psi_enabled(void)
Expand Down
66 changes: 29 additions & 37 deletions kernel/sched/psi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1153,7 +1153,6 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group,
t->event = 0;
t->last_event_time = 0;
init_waitqueue_head(&t->event_wait);
kref_init(&t->refcount);

mutex_lock(&group->trigger_lock);

Expand Down Expand Up @@ -1182,15 +1181,19 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group,
return t;
}

static void psi_trigger_destroy(struct kref *ref)
void psi_trigger_destroy(struct psi_trigger *t)
{
struct psi_trigger *t = container_of(ref, struct psi_trigger, refcount);
struct psi_group *group = t->group;
struct psi_group *group;
struct task_struct *task_to_destroy = NULL;

if (static_branch_likely(&psi_disabled))
/*
* We do not check psi_disabled since it might have been disabled after
* the trigger got created.
*/
if (!t)
return;

group = t->group;
/*
* Wakeup waiters to stop polling. Can happen if cgroup is deleted
* from under a polling process.
Expand Down Expand Up @@ -1226,9 +1229,9 @@ static void psi_trigger_destroy(struct kref *ref)
mutex_unlock(&group->trigger_lock);

/*
* Wait for both *trigger_ptr from psi_trigger_replace and
* poll_task RCUs to complete their read-side critical sections
* before destroying the trigger and optionally the poll_task
* Wait for psi_schedule_poll_work RCU to complete its read-side
* critical section before destroying the trigger and optionally the
* poll_task.
*/
synchronize_rcu();
/*
Expand All @@ -1245,18 +1248,6 @@ static void psi_trigger_destroy(struct kref *ref)
kfree(t);
}

void psi_trigger_replace(void **trigger_ptr, struct psi_trigger *new)
{
struct psi_trigger *old = *trigger_ptr;

if (static_branch_likely(&psi_disabled))
return;

rcu_assign_pointer(*trigger_ptr, new);
if (old)
kref_put(&old->refcount, psi_trigger_destroy);
}

__poll_t psi_trigger_poll(void **trigger_ptr,
struct file *file, poll_table *wait)
{
Expand All @@ -1266,24 +1257,15 @@ __poll_t psi_trigger_poll(void **trigger_ptr,
if (static_branch_likely(&psi_disabled))
return DEFAULT_POLLMASK | EPOLLERR | EPOLLPRI;

rcu_read_lock();

t = rcu_dereference(*(void __rcu __force **)trigger_ptr);
if (!t) {
rcu_read_unlock();
t = smp_load_acquire(trigger_ptr);
if (!t)
return DEFAULT_POLLMASK | EPOLLERR | EPOLLPRI;
}
kref_get(&t->refcount);

rcu_read_unlock();

poll_wait(file, &t->event_wait, wait);

if (cmpxchg(&t->event, 1, 0) == 1)
ret |= EPOLLPRI;

kref_put(&t->refcount, psi_trigger_destroy);

return ret;
}

Expand All @@ -1307,14 +1289,24 @@ static ssize_t psi_write(struct file *file, const char __user *user_buf,

buf[buf_size - 1] = '\0';

new = psi_trigger_create(&psi_system, buf, nbytes, res);
if (IS_ERR(new))
return PTR_ERR(new);

seq = file->private_data;

/* Take seq->lock to protect seq->private from concurrent writes */
mutex_lock(&seq->lock);
psi_trigger_replace(&seq->private, new);

/* Allow only one trigger per file descriptor */
if (seq->private) {
mutex_unlock(&seq->lock);
return -EBUSY;
}

new = psi_trigger_create(&psi_system, buf, nbytes, res);
if (IS_ERR(new)) {
mutex_unlock(&seq->lock);
return PTR_ERR(new);
}

smp_store_release(&seq->private, new);
mutex_unlock(&seq->lock);

return nbytes;
Expand Down Expand Up @@ -1349,7 +1341,7 @@ static int psi_fop_release(struct inode *inode, struct file *file)
{
struct seq_file *seq = file->private_data;

psi_trigger_replace(&seq->private, NULL);
psi_trigger_destroy(seq->private);
return single_release(inode, file);
}

Expand Down
11 changes: 10 additions & 1 deletion net/packet/af_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -2248,8 +2248,11 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
copy_skb = skb_get(skb);
skb_head = skb->data;
}
if (copy_skb)
if (copy_skb) {
memset(&PACKET_SKB_CB(copy_skb)->sa.ll, 0,
sizeof(PACKET_SKB_CB(copy_skb)->sa.ll));
skb_set_owner_r(copy_skb, sk);
}
}
snaplen = po->rx_ring.frame_size - macoff;
if ((int)snaplen < 0) {
Expand Down Expand Up @@ -3368,6 +3371,8 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
sock_recv_ts_and_drops(msg, sk, skb);

if (msg->msg_name) {
const size_t max_len = min(sizeof(skb->cb),
sizeof(struct sockaddr_storage));
int copy_len;

/* If the address length field is there to be filled
Expand All @@ -3390,6 +3395,10 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
msg->msg_namelen = sizeof(struct sockaddr_ll);
}
}
if (WARN_ON_ONCE(copy_len > max_len)) {
copy_len = max_len;
msg->msg_namelen = copy_len;
}
memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, copy_len);
}

Expand Down
16 changes: 10 additions & 6 deletions net/sched/cls_u32.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,14 +390,19 @@ static int u32_init(struct tcf_proto *tp)
return 0;
}

static int u32_destroy_key(struct tc_u_knode *n, bool free_pf)
static void __u32_destroy_key(struct tc_u_knode *n)
{
struct tc_u_hnode *ht = rtnl_dereference(n->ht_down);

tcf_exts_destroy(&n->exts);
tcf_exts_put_net(&n->exts);
if (ht && --ht->refcnt == 0)
kfree(ht);
kfree(n);
}

static void u32_destroy_key(struct tc_u_knode *n, bool free_pf)
{
tcf_exts_put_net(&n->exts);
#ifdef CONFIG_CLS_U32_PERF
if (free_pf)
free_percpu(n->pf);
Expand All @@ -406,8 +411,7 @@ static int u32_destroy_key(struct tc_u_knode *n, bool free_pf)
if (free_pf)
free_percpu(n->pcpu_success);
#endif
kfree(n);
return 0;
__u32_destroy_key(n);
}

/* u32_delete_key_rcu should be called when free'ing a copied
Expand Down Expand Up @@ -903,13 +907,13 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
tca[TCA_RATE], ovr, extack);

if (err) {
u32_destroy_key(new, false);
__u32_destroy_key(new);
return err;
}

err = u32_replace_hw_knode(tp, new, flags, extack);
if (err) {
u32_destroy_key(new, false);
__u32_destroy_key(new);
return err;
}

Expand Down
2 changes: 2 additions & 0 deletions sound/core/pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
init_waitqueue_head(&runtime->tsleep);

runtime->status->state = SNDRV_PCM_STATE_OPEN;
mutex_init(&runtime->buffer_mutex);

substream->runtime = runtime;
substream->private_data = pcm->private_data;
Expand Down Expand Up @@ -1002,6 +1003,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
} else {
substream->runtime = NULL;
}
mutex_destroy(&runtime->buffer_mutex);
kfree(runtime);
put_pid(substream->pid);
substream->pid = NULL;
Expand Down
Loading
Loading