All of lore.kernel.org
 help / color / mirror / Atom feed
From: caifeng.zhu@uniswdc.com
To: Ilya Dryomov <idryomov@gmail.com>
Cc: caifeng.zhu@uniswdc.com, Ceph Development <ceph-devel@vger.kernel.org>
Subject: Re: proposal for fine-grain dout control
Date: Mon, 21 Nov 2016 11:17:35 +0800	[thread overview]
Message-ID: <20161121031734.GA33595@T530I> (raw)
In-Reply-To: <CAOi1vP94GDwABdfphqWDc2nZ4pp3GFZVXUnhNFgMuc21fpUknA@mail.gmail.com>

On Fri, Nov 18, 2016 at 03:04:38PM +0100, Ilya Dryomov wrote:
> On Thu, Nov 17, 2016 at 5:32 AM,  <caifeng.zhu@uniswdc.com> wrote:
> > Currently dout control is based on module and trace level.
> > In practice, we find that it is much easier to control dout
> > by specifying module, file, function and line, as done by
> > kernel rbd/cephfs client module. The paragraphs below try to
> > propose a way to implement similar control at the ceph server
> > side.
> >
> > As the kernel clients, we can define control points (called
> > doutpoints later) for dout in the macro dout_impl and collect
> > them into a seperate ELF section, like below:
> >
> >  #define dout_impl(cct, sub, v)                                         \
> >    do {                                                                 \
> > -  if (cct->_conf->subsys.should_gather(sub, v)) {                      \
> > +  static doutpoint_t *_dop;                                            \
> > +  DOUTPOINT(TOSTR(sub), __FILE__, __func__, __LINE__);                 \
> > +                                                                       \
> > +  if (cct->_conf->subsys.should_gather(sub, v) ||                      \
> > +      doutpoint_active(_dop)) {                                        \
> >
> > In the above code, DOUTPOINT will define a doutpoint and ask linker
> > to collect it into an ELF section, such as "set_doutpoint". Instead of
> > adding __attribute__((section("set_doutpoint"))) to variables, we resort
> > to inline ASM like below:
> >
> > +typedef struct doutpoint {
> > +       const char *    dop_module;     // module
> > +       const char *    dop_file;       // file name
> > +       const char *    dop_func;       // function name
> > +       int             dop_line;       // line no
> > +       volatile int    dop_state;      // state 0:off, 1:on
> > +} doutpoint_t;
> >
> > +#define        TOSTR(a)        #a
> > +#define DOUTPOINT(module, file, func, line)                             \
> > +do {                                                                    \
> > +   __asm__(".pushsection set_doutpoint, \"aw\", @progbits" "\n"         \
> > +           ".align 32"   "\n"                                           \
> > +           "416:"        "\n"                                           \
> > +           ".quad %c1"   "\n"                                           \
> > +           ".quad %c2"   "\n"                                           \
> > +           ".quad %c3"   "\n"                                           \
> > +           ".long %c4"   "\n"                                           \
> > +           ".long 0"     "\n"                                           \
> > +           ".popsection" "\n"                                           \
> > +           "leaq 416b(%%rip), %0" "\n"                                  \
> > +           : "=r"(_dop)                                                 \
> > +           : "i"(module), "i"(file), "i"(func), "i"(line));             \
> > +} while(0)
> >
> > The reason for inline ASM is that: in C++, there are inline and template
> > functions. static variables defined in these functions will be automatically
> > added attributes by the compiler. thus it impossible to collect all doutpoints
> > into one section.
> >
> > There is another problem to consider: collect doutpoints of shared libs into
> > the main executable. We solve the problem by defining a constructor function
> > and a weak function. The contructor function will automatically register doupoints
> > of shared libs into the main executable. The weak function is to be overriden by
> > the main executable, providing where to register doutponits.
> >
> > //
> > // in common/dout.h
> > //
> > +typedef struct doutsection {
> > +       doutpoint_t *   start;
> > +       doutpoint_t *   stop;
> > +} doutsection_t;
> >
> > //
> > // in common/dout.cc
> > //
> > +extern doutpoint_t __start_set_doutpoint[]
> > +       __attribute__((weak, visibility("hidden")));
> > +extern doutpoint_t __stop_set_doutpoint[]
> > +       __attribute__((weak, visibility("hidden")));
> > +
> > +extern void doutsection_global(doutsection_t **s, int *n)
> > +       __attribute__((weak));
> > +
> > +
> > +static void
> > +doutsection_array(doutsection_t **s, int *n)
> > +{
> > +       static doutsection_t _sections[10];
> > +
> > +       /*
> > +        * If doutsection_global is defined, provide
> > +        * from the global one; otherwise, fall back
> > +        * to local ones.
> > +        */
> > +       if (doutsection_global)
> > +               doutsection_global(s, n);
> > +       else {
> > +               *s = _sections;
> > +               *n = 10;
> > +       }
> > +}
> > +
> > +/*
> > + * The 'contructor' attribute means the function will be
> > + * called after dynamic linking for the library or before
> > + * entering into main for the executable.
> > + */
> > +void __attribute__((constructor))
> > +doutpoint_register(void)
> > +{
> > +       int i, n;
> > +       doutsection_t *s;
> > +
> > +       doutsection_array(&s, &n);
> > +       for (i = 0; i < n; i++, s++) {
> > +               if (!s->start) {
> > +                       s->start = __start_set_doutpoint;
> > +                       s->stop = __stop_set_doutpoint;
> > +                       return;
> > +               }
> > +       }
> > +}
> >
> > //
> > // in global/global_init.cc
> > //
> > void
> > doutsection_global(doutsection_t **s, int *n)
> > {
> >         static doutsection_t _sections[10];
> >
> >         *s = _sections;
> >         *n = 10;
> > }
> >
> > There are some shortcomings of the proposal: mainly archtecture
> > dependency and compiler dependency. DOUTPOINT exploits one x86
> > instruction; weak symbol support may be different on different
> > compilers.
> >
> > Glad and eager to hear your opinions!
> > If it is useful, I'll post the whole patch.
> 
> As someone who has experience with kernel dynamic_debug mechanism,
> I wish we had a subsystem/level mechanism in the kernel client instead.
> While sometimes handy, enabling only a few selected douts doesn't come
> useful that often - more frequently the dout you really need isn't
> there and you end up fiddling with "perf probe" and others, longing for
> a good scriptable dynamic tracer.
> 
> It looks like you are proposing this as an addition to the existing
> module/level scheme and not as a replacement though, so it's just an
> observation...

Yes, the proposal is an improvement, rather than a replacement. 

When analyzing a problem, we usually started with gross-grained info. After
some analysis and study, we can pinpoint the problem. At that time,we need 
fine-grained info. For the current dout, when pinpointing a problem, usually 
I'm flooded with too much info. By fine-grained dout control, it is much
easier to get what I really want.

> 
> Thanks,
> 
>                 Ilya
> --
> To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



  reply	other threads:[~2016-11-21  3:20 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-17  4:32 proposal for fine-grain dout control caifeng.zhu
2016-11-18 14:04 ` Ilya Dryomov
2016-11-21  3:17   ` caifeng.zhu [this message]
2016-11-18 14:14 ` John Spray
2016-11-21  2:55   ` caifeng.zhu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20161121031734.GA33595@T530I \
    --to=caifeng.zhu@uniswdc.com \
    --cc=ceph-devel@vger.kernel.org \
    --cc=idryomov@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.