On 20.04.19 01:29, Daniel Colascione wrote:
> The point I'm making, to be> very clear, is *NOT* that process monitoring is
> "not worth>
considering", but that process monitoring is subtle and complicated>
enough that it ought to be considered as a standalone project,>
independent of pidfds prope
On 20.04.19 01:02, Christian Brauner wrote:
> I'm sorry, who has agreed that a non-parent should be able to wait for
> process death?
> I know you proposed that but has anyone ever substantially supported this?
I actually support this.
One practical usecase I have in mind for some upcoming proje
On 20.04.19 02:17, Christian Brauner wrote:
> It's not off the table that we can add a pidfd_open() if that becomes> a real
> thing.
What are the exact semantics of pidfd_open() ?
--mtx
--
Enrico Weigelt, metux IT consult
Free software and Linux embedded engineering
i...@metux.net -- +49-151-
On 20.04.19 01:46, Daniel Colascione wrote:
> If you turn pidfd into an event stream, reads have to be destructive.
> If reads are destructive, you can't share pidfds instances between
> multiple readers.
Can't we find a way to duplicate them ? Someting like dup(), but
with actually duplicating t
On 19.04.19 23:48, Christian Brauner wrote:
> So is Android and we're not designing an interface for Android but for
> all of userspace.
> I hope this is clear. Service managers are quite important and systemd
> is the largest one
> and they can make good use of this feature.
Maybe just talk abou
On 19.04.19 23:21, Daniel Colascione wrote:
>> EPOLLIN on a pidfd could very well mean that data can be read via
>> a read() on the pidfd *other* than the exit status. The read could e.g.
>> give you a lean struct that indicates the type of state transition:
>> NOTIFY_EXIT,
>> NOTIFY_EXEC, etc..
On 19.04.19 23:24, Daniel Colascione wrote:
Hi folks,
I haven't followed the whole thread, so forgive me if I'm going to
write something dumb here ... but: this all feels a bit complicated
to me.
Why not just making the pidfd present a stream of events (which are
encoded as text lines) ? It wo
On Sat, Apr 20, 2019 at 02:26:15PM +0200, Oleg Nesterov wrote:
> On 04/20, Oleg Nesterov wrote:
> >
> > Note that we need
> > thread_group_empty() only for the case when the task is traced,
>
> Damn, sorry for noise... of course this is not true, I tried to say that
> notification won't come other
On 04/20, Oleg Nesterov wrote:
>
> Note that we need
> thread_group_empty() only for the case when the task is traced,
Damn, sorry for noise... of course this is not true, I tried to say that
notification won't come otherwise. Nevermind, lets discuss this when we
have a patch. I already got lost i
On 04/19, Christian Brauner wrote:
>
> > Just for the exit notification purposes, the states are:
> > if process has exit_state == 0, block.
> > if process is zombie/dead but not reaped, then return POLLIN
> > if process is reaped, then return POLLIN | POLLHUP
>
> Oleg was explicitly against EXIT_Z
On Fri, Apr 19, 2019 at 04:11:37PM -0700, Linus Torvalds wrote:
> On Fri, Apr 19, 2019 at 2:20 PM Joel Fernandes wrote:
> >
> > According to Linus, POLLHUP usually indicates that something is readable:
>
> Note that if you use the legacy interfaces (ie "select()"), then even
> just a plain POLLHU
On Sat, Apr 20, 2019 at 1:47 AM Daniel Colascione wrote:
>
> On Fri, Apr 19, 2019 at 4:12 PM Christian Brauner
> wrote:
> >
> > On Sat, Apr 20, 2019 at 12:46 AM Daniel Colascione
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 3:02 PM Christian Brauner
> > > wrote:
> > > >
> > > > On Fri, Apr
On Sat, Apr 20, 2019 at 1:30 AM Daniel Colascione wrote:
>
> On Fri, Apr 19, 2019 at 4:02 PM Christian Brauner
> wrote:
> >
> > On Sat, Apr 20, 2019 at 12:35 AM Daniel Colascione
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 2:48 PM Christian Brauner
> > > wrote:
> > > >
> > > > On Fri, Apr
On Fri, Apr 19, 2019 at 4:12 PM Christian Brauner wrote:
>
> On Sat, Apr 20, 2019 at 12:46 AM Daniel Colascione wrote:
> >
> > On Fri, Apr 19, 2019 at 3:02 PM Christian Brauner
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 11:48 PM Christian Brauner
> > > wrote:
> > > >
> > > > On Fri, Apr 1
On Fri, Apr 19, 2019 at 4:20 PM Christian Brauner wrote:
>
> On Sat, Apr 20, 2019 at 1:11 AM Linus Torvalds
> wrote:
> >
> > It's also worth noting that POLLERR/POLLHUP/POLLNVAL cannot be masked
> > for "poll()". Even if you only ask for POLLIN/POLLOUT, you will always
> > get POLLERR/POLLHUP not
On Fri, Apr 19, 2019 at 4:33 PM Linus Torvalds
wrote:
>
> On Fri, Apr 19, 2019 at 4:20 PM Christian Brauner
> wrote:
> >
> > On Sat, Apr 20, 2019 at 1:11 AM Linus Torvalds
> > wrote:
> > >
> > > It's also worth noting that POLLERR/POLLHUP/POLLNVAL cannot be masked
> > > for "poll()". Even if yo
On Fri, Apr 19, 2019 at 4:02 PM Christian Brauner wrote:
>
> On Sat, Apr 20, 2019 at 12:35 AM Daniel Colascione wrote:
> >
> > On Fri, Apr 19, 2019 at 2:48 PM Christian Brauner
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 11:21 PM Daniel Colascione
> > > wrote:
> > > >
> > > > On Fri, Apr 1
On Sat, Apr 20, 2019 at 1:11 AM Linus Torvalds
wrote:
>
> On Fri, Apr 19, 2019 at 2:20 PM Joel Fernandes wrote:
> >
> > According to Linus, POLLHUP usually indicates that something is readable:
>
> Note that if you use the legacy interfaces (ie "select()"), then even
> just a plain POLLHUP will a
On Sat, Apr 20, 2019 at 12:46 AM Daniel Colascione wrote:
>
> On Fri, Apr 19, 2019 at 3:02 PM Christian Brauner
> wrote:
> >
> > On Fri, Apr 19, 2019 at 11:48 PM Christian Brauner
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 11:21 PM Daniel Colascione
> > > wrote:
> > > >
> > > > On Fri, A
On Fri, Apr 19, 2019 at 2:20 PM Joel Fernandes wrote:
>
> According to Linus, POLLHUP usually indicates that something is readable:
Note that if you use the legacy interfaces (ie "select()"), then even
just a plain POLLHUP will always just show as "readable".
So for a lot of applications, it won
On Sat, Apr 20, 2019 at 12:35 AM Daniel Colascione wrote:
>
> On Fri, Apr 19, 2019 at 2:48 PM Christian Brauner
> wrote:
> >
> > On Fri, Apr 19, 2019 at 11:21 PM Daniel Colascione
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 1:57 PM Christian Brauner
> > > wrote:
> > > >
> > > > On Fri, Ap
On Fri, Apr 19, 2019 at 3:02 PM Christian Brauner wrote:
>
> On Fri, Apr 19, 2019 at 11:48 PM Christian Brauner
> wrote:
> >
> > On Fri, Apr 19, 2019 at 11:21 PM Daniel Colascione
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 1:57 PM Christian Brauner
> > > wrote:
> > > >
> > > > On Fri, Ap
On Fri, Apr 19, 2019 at 3:18 PM Christian Brauner wrote:
>
> On Sat, Apr 20, 2019 at 12:08 AM Daniel Colascione wrote:
> >
> > On Fri, Apr 19, 2019 at 2:45 PM Joel Fernandes
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 02:24:09PM -0700, Daniel Colascione wrote:
> > > > On Fri, Apr 19, 2019 at
On Fri, Apr 19, 2019 at 2:48 PM Christian Brauner wrote:
>
> On Fri, Apr 19, 2019 at 11:21 PM Daniel Colascione wrote:
> >
> > On Fri, Apr 19, 2019 at 1:57 PM Christian Brauner
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 10:34 PM Daniel Colascione
> > > wrote:
> > > >
> > > > On Fri, Apr 1
On Sat, Apr 20, 2019 at 12:08 AM Daniel Colascione wrote:
>
> On Fri, Apr 19, 2019 at 2:45 PM Joel Fernandes wrote:
> >
> > On Fri, Apr 19, 2019 at 02:24:09PM -0700, Daniel Colascione wrote:
> > > On Fri, Apr 19, 2019 at 2:20 PM Joel Fernandes
> > > wrote:
> > > >
> > > > On Fri, Apr 19, 2019 a
On Fri, Apr 19, 2019 at 2:45 PM Joel Fernandes wrote:
>
> On Fri, Apr 19, 2019 at 02:24:09PM -0700, Daniel Colascione wrote:
> > On Fri, Apr 19, 2019 at 2:20 PM Joel Fernandes
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 10:57:11PM +0200, Christian Brauner wrote:
> > > > On Fri, Apr 19, 2019 a
On Fri, Apr 19, 2019 at 11:48 PM Christian Brauner wrote:
>
> On Fri, Apr 19, 2019 at 11:21 PM Daniel Colascione wrote:
> >
> > On Fri, Apr 19, 2019 at 1:57 PM Christian Brauner
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 10:34 PM Daniel Colascione
> > > wrote:
> > > >
> > > > On Fri, Apr
On Fri, Apr 19, 2019 at 11:20 PM Joel Fernandes wrote:
>
> On Fri, Apr 19, 2019 at 10:57:11PM +0200, Christian Brauner wrote:
> > On Fri, Apr 19, 2019 at 10:34 PM Daniel Colascione
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 12:49 PM Joel Fernandes
> > > wrote:
> > > >
> > > > On Fri, Apr 1
On Fri, Apr 19, 2019 at 11:21 PM Daniel Colascione wrote:
>
> On Fri, Apr 19, 2019 at 1:57 PM Christian Brauner
> wrote:
> >
> > On Fri, Apr 19, 2019 at 10:34 PM Daniel Colascione
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 12:49 PM Joel Fernandes
> > > wrote:
> > > >
> > > > On Fri, Apr
On Fri, Apr 19, 2019 at 02:24:09PM -0700, Daniel Colascione wrote:
> On Fri, Apr 19, 2019 at 2:20 PM Joel Fernandes wrote:
> >
> > On Fri, Apr 19, 2019 at 10:57:11PM +0200, Christian Brauner wrote:
> > > On Fri, Apr 19, 2019 at 10:34 PM Daniel Colascione
> > > wrote:
> > > >
> > > > On Fri, Apr
On Fri, Apr 19, 2019 at 2:20 PM Joel Fernandes wrote:
>
> On Fri, Apr 19, 2019 at 10:57:11PM +0200, Christian Brauner wrote:
> > On Fri, Apr 19, 2019 at 10:34 PM Daniel Colascione
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 12:49 PM Joel Fernandes
> > > wrote:
> > > >
> > > > On Fri, Apr 19
On Fri, Apr 19, 2019 at 1:57 PM Christian Brauner wrote:
>
> On Fri, Apr 19, 2019 at 10:34 PM Daniel Colascione wrote:
> >
> > On Fri, Apr 19, 2019 at 12:49 PM Joel Fernandes
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 09:18:59PM +0200, Christian Brauner wrote:
> > > > On Fri, Apr 19, 2019 a
On Fri, Apr 19, 2019 at 10:57:11PM +0200, Christian Brauner wrote:
> On Fri, Apr 19, 2019 at 10:34 PM Daniel Colascione wrote:
> >
> > On Fri, Apr 19, 2019 at 12:49 PM Joel Fernandes
> > wrote:
> > >
> > > On Fri, Apr 19, 2019 at 09:18:59PM +0200, Christian Brauner wrote:
> > > > On Fri, Apr 19,
On Fri, Apr 19, 2019 at 10:01:00PM +0200, Christian Brauner wrote:
> On Fri, Apr 19, 2019 at 03:49:02PM -0400, Joel Fernandes wrote:
> > On Fri, Apr 19, 2019 at 09:18:59PM +0200, Christian Brauner wrote:
> > > On Fri, Apr 19, 2019 at 03:02:47PM -0400, Joel Fernandes wrote:
> > > > On Thu, Apr 18, 2
On Fri, Apr 19, 2019 at 10:34 PM Daniel Colascione wrote:
>
> On Fri, Apr 19, 2019 at 12:49 PM Joel Fernandes
> wrote:
> >
> > On Fri, Apr 19, 2019 at 09:18:59PM +0200, Christian Brauner wrote:
> > > On Fri, Apr 19, 2019 at 03:02:47PM -0400, Joel Fernandes wrote:
> > > > On Thu, Apr 18, 2019 at
On Fri, Apr 19, 2019 at 12:49 PM Joel Fernandes wrote:
>
> On Fri, Apr 19, 2019 at 09:18:59PM +0200, Christian Brauner wrote:
> > On Fri, Apr 19, 2019 at 03:02:47PM -0400, Joel Fernandes wrote:
> > > On Thu, Apr 18, 2019 at 07:26:44PM +0200, Christian Brauner wrote:
> > > > On April 18, 2019 7:23:
On Fri, Apr 19, 2019 at 03:49:02PM -0400, Joel Fernandes wrote:
> On Fri, Apr 19, 2019 at 09:18:59PM +0200, Christian Brauner wrote:
> > On Fri, Apr 19, 2019 at 03:02:47PM -0400, Joel Fernandes wrote:
> > > On Thu, Apr 18, 2019 at 07:26:44PM +0200, Christian Brauner wrote:
> > > > On April 18, 2019
On Fri, Apr 19, 2019 at 09:18:59PM +0200, Christian Brauner wrote:
> On Fri, Apr 19, 2019 at 03:02:47PM -0400, Joel Fernandes wrote:
> > On Thu, Apr 18, 2019 at 07:26:44PM +0200, Christian Brauner wrote:
> > > On April 18, 2019 7:23:38 PM GMT+02:00, Jann Horn
> > > wrote:
> > > >On Wed, Apr 17, 2
On Fri, Apr 19, 2019 at 09:22:33PM +0200, Christian Brauner wrote:
> On Fri, Apr 19, 2019 at 09:18:58PM +0200, Christian Brauner wrote:
> > On Fri, Apr 19, 2019 at 03:02:47PM -0400, Joel Fernandes wrote:
> > > On Thu, Apr 18, 2019 at 07:26:44PM +0200, Christian Brauner wrote:
> > > > On April 18, 2
On Fri, Apr 19, 2019 at 09:18:58PM +0200, Christian Brauner wrote:
> On Fri, Apr 19, 2019 at 03:02:47PM -0400, Joel Fernandes wrote:
> > On Thu, Apr 18, 2019 at 07:26:44PM +0200, Christian Brauner wrote:
> > > On April 18, 2019 7:23:38 PM GMT+02:00, Jann Horn
> > > wrote:
> > > >On Wed, Apr 17, 2
On Fri, Apr 19, 2019 at 03:02:47PM -0400, Joel Fernandes wrote:
> On Thu, Apr 18, 2019 at 07:26:44PM +0200, Christian Brauner wrote:
> > On April 18, 2019 7:23:38 PM GMT+02:00, Jann Horn wrote:
> > >On Wed, Apr 17, 2019 at 3:09 PM Oleg Nesterov wrote:
> > >> On 04/16, Joel Fernandes wrote:
> > >>
On Thu, Apr 18, 2019 at 12:14:58PM -0700, Linus Torvalds wrote:
> On Thu, Apr 18, 2019 at 11:58 AM Daniel Colascione wrote:
> >
> > On Thu, Apr 18, 2019 at 11:44 AM Jonathan Kowalski
> > wrote:
> > >
> > > Would using something other than POLLIN be an option (maybe POLLPRI)?
> > > The convention
On Thu, Apr 18, 2019 at 07:26:44PM +0200, Christian Brauner wrote:
> On April 18, 2019 7:23:38 PM GMT+02:00, Jann Horn wrote:
> >On Wed, Apr 17, 2019 at 3:09 PM Oleg Nesterov wrote:
> >> On 04/16, Joel Fernandes wrote:
> >> > On Tue, Apr 16, 2019 at 02:04:31PM +0200, Oleg Nesterov wrote:
> >> > >
On 04/18, Jann Horn wrote:
>
> On Wed, Apr 17, 2019 at 3:09 PM Oleg Nesterov wrote:
> > On 04/16, Joel Fernandes wrote:
> > > On Tue, Apr 16, 2019 at 02:04:31PM +0200, Oleg Nesterov wrote:
> > > >
> > > > Could you explain when it should return POLLIN? When the whole process
> > > > exits?
> > >
Just returned to work today dealing with "life" issues, apologies for the
delays in replying. :)
On Wed, Apr 17, 2019 at 03:09:41PM +0200, Oleg Nesterov wrote:
> On 04/16, Joel Fernandes wrote:
> >
> > On Tue, Apr 16, 2019 at 02:04:31PM +0200, Oleg Nesterov wrote:
> > >
> > > Could you explain whe
On Thu, Apr 18, 2019 at 11:58 AM Daniel Colascione wrote:
>
> On Thu, Apr 18, 2019 at 11:44 AM Jonathan Kowalski
> wrote:
> >
> > Would using something other than POLLIN be an option (maybe POLLPRI)?
> > The convention is to use it to indicate readability on the descriptor,
> > and also possibly
On Thu, Apr 18, 2019 at 11:44 AM Jonathan Kowalski wrote:
>
> On Tue, Apr 16, 2019 at 8:21 PM Joel Fernandes wrote:
> >
> > On Tue, Apr 16, 2019 at 02:04:31PM +0200, Oleg Nesterov wrote:
> > > On 04/11, Joel Fernandes (Google) wrote:
> > > >
> > > > +static unsigned int proc_tgid_base_poll(struct
On Tue, Apr 16, 2019 at 8:21 PM Joel Fernandes wrote:
>
> On Tue, Apr 16, 2019 at 02:04:31PM +0200, Oleg Nesterov wrote:
> > On 04/11, Joel Fernandes (Google) wrote:
> > >
> > > +static unsigned int proc_tgid_base_poll(struct file *file, struct
> > > poll_table_struct *pts)
> > > +{
> > > + int
On Thu, Apr 18, 2019 at 10:26 AM Christian Brauner wrote:
>
> On April 18, 2019 7:23:38 PM GMT+02:00, Jann Horn wrote:
> >On Wed, Apr 17, 2019 at 3:09 PM Oleg Nesterov wrote:
> >> On 04/16, Joel Fernandes wrote:
> >> > On Tue, Apr 16, 2019 at 02:04:31PM +0200, Oleg Nesterov wrote:
> >> > >
> >>
On April 18, 2019 7:23:38 PM GMT+02:00, Jann Horn wrote:
>On Wed, Apr 17, 2019 at 3:09 PM Oleg Nesterov wrote:
>> On 04/16, Joel Fernandes wrote:
>> > On Tue, Apr 16, 2019 at 02:04:31PM +0200, Oleg Nesterov wrote:
>> > >
>> > > Could you explain when it should return POLLIN? When the whole
>proce
On Wed, Apr 17, 2019 at 3:09 PM Oleg Nesterov wrote:
> On 04/16, Joel Fernandes wrote:
> > On Tue, Apr 16, 2019 at 02:04:31PM +0200, Oleg Nesterov wrote:
> > >
> > > Could you explain when it should return POLLIN? When the whole process
> > > exits?
> >
> > It returns POLLIN when the task is dead
On 04/16, Joel Fernandes wrote:
>
> On Tue, Apr 16, 2019 at 02:04:31PM +0200, Oleg Nesterov wrote:
> >
> > Could you explain when it should return POLLIN? When the whole process
> > exits?
>
> It returns POLLIN when the task is dead or doesn't exist anymore, or when it
> is in a zombie state and t
On Tue, Apr 16, 2019 at 03:20:51PM -0400, Joel Fernandes wrote:
> On Tue, Apr 16, 2019 at 02:04:31PM +0200, Oleg Nesterov wrote:
> > On 04/11, Joel Fernandes (Google) wrote:
> > >
> > > +static unsigned int proc_tgid_base_poll(struct file *file, struct
> > > poll_table_struct *pts)
> > > +{
> > >
On Tue, Apr 16, 2019 at 02:04:31PM +0200, Oleg Nesterov wrote:
> On 04/11, Joel Fernandes (Google) wrote:
> >
> > +static unsigned int proc_tgid_base_poll(struct file *file, struct
> > poll_table_struct *pts)
> > +{
> > + int poll_flags = 0;
> > + struct task_struct *task;
> > + struct pid *
On 04/16, Oleg Nesterov wrote:
>
> And ->wait_pidfd should probably
> live in task->signal_struct.
but this will need the additional cleanup in free_signal_struct(),
list_del(&sig->wait_pidfd->head).
Oleg.
On 04/11, Joel Fernandes (Google) wrote:
>
> +static unsigned int proc_tgid_base_poll(struct file *file, struct
> poll_table_struct *pts)
> +{
> + int poll_flags = 0;
> + struct task_struct *task;
> + struct pid *pid;
> +
> + task = get_proc_task(file->f_path.dentry->d_inode);
> +
On Fri, Apr 12, 2019 at 2:33 PM Andy Lutomirski wrote:
>
> Are you sure? I admit I'm not all that familiar with the innards of
> poll() on Linux, but I thought that the waitqueue only had to survive
> long enough to kick the polling thread and did *not* have to survive
> until poll() actually ret
[Resending due to accidental HTML. I need to take Joel's advice and
switch to a real email client]
On Fri, Apr 12, 2019 at 5:54 PM Daniel Colascione wrote:
>
> On Fri, Apr 12, 2019 at 5:09 PM Joel Fernandes wrote:
>>
>> Hi Andy!
>>
>> On Fri, Apr 12, 2019 at 02:32:53PM -0700, Andy Lutomirski wro
Hi Andy!
On Fri, Apr 12, 2019 at 02:32:53PM -0700, Andy Lutomirski wrote:
> On Thu, Apr 11, 2019 at 10:51 AM Joel Fernandes (Google)
> wrote:
> >
> > pidfd are /proc/pid directory file descriptors referring to a task group
> > leader. Android low memory killer (LMK) needs pidfd polling support to
On Thu, Apr 11, 2019 at 10:51 AM Joel Fernandes (Google)
wrote:
>
> pidfd are /proc/pid directory file descriptors referring to a task group
> leader. Android low memory killer (LMK) needs pidfd polling support to
> replace code that currently checks for existence of /proc/pid for
> knowing a proc
On Thu, Apr 11, 2019 at 10:02:32PM +0200, Christian Brauner wrote:
> On April 11, 2019 10:00:59 PM GMT+02:00, Joel Fernandes
> wrote:
> >On Thu, Apr 11, 2019 at 01:50:42PM -0400, Joel Fernandes (Google)
> >wrote:
> >> pidfd are /proc/pid directory file descriptors referring to a task
> >group
> >
On April 11, 2019 10:00:59 PM GMT+02:00, Joel Fernandes
wrote:
>On Thu, Apr 11, 2019 at 01:50:42PM -0400, Joel Fernandes (Google)
>wrote:
>> pidfd are /proc/pid directory file descriptors referring to a task
>group
>> leader. Android low memory killer (LMK) needs pidfd polling support
>to
>> repl
On Thu, Apr 11, 2019 at 01:50:42PM -0400, Joel Fernandes (Google) wrote:
> pidfd are /proc/pid directory file descriptors referring to a task group
> leader. Android low memory killer (LMK) needs pidfd polling support to
> replace code that currently checks for existence of /proc/pid for
> knowing
pidfd are /proc/pid directory file descriptors referring to a task group
leader. Android low memory killer (LMK) needs pidfd polling support to
replace code that currently checks for existence of /proc/pid for
knowing a process that is signalled to be killed has died, which is both
racy and slow. T
64 matches
Mail list logo