Re: proposal for fine-grain dout control

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Nov 18, 2016 at 03:04:38PM +0100, Ilya Dryomov wrote:
> On Thu, Nov 17, 2016 at 5:32 AM,  <caifeng.zhu@xxxxxxxxxxx> 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@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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



[Index of Archives]     [CEPH Users]     [Ceph Large]     [Information on CEPH]     [Linux BTRFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux