linux/fs/btrfs/async-thread.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2007 Oracle.  All rights reserved.
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public
   6 * License v2 as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11 * General Public License for more details.
  12 *
  13 * You should have received a copy of the GNU General Public
  14 * License along with this program; if not, write to the
  15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  16 * Boston, MA 021110-1307, USA.
  17 */
  18
  19#include <linux/kthread.h>
  20#include <linux/slab.h>
  21#include <linux/list.h>
  22#include <linux/spinlock.h>
  23#include <linux/freezer.h>
  24#include "async-thread.h"
  25
  26#define WORK_QUEUED_BIT 0
  27#define WORK_DONE_BIT 1
  28#define WORK_ORDER_DONE_BIT 2
  29#define WORK_HIGH_PRIO_BIT 3
  30
  31/*
  32 * container for the kthread task pointer and the list of pending work
  33 * One of these is allocated per thread.
  34 */
  35struct btrfs_worker_thread {
  36        /* pool we belong to */
  37        struct btrfs_workers *workers;
  38
  39        /* list of struct btrfs_work that are waiting for service */
  40        struct list_head pending;
  41        struct list_head prio_pending;
  42
  43        /* list of worker threads from struct btrfs_workers */
  44        struct list_head worker_list;
  45
  46        /* kthread */
  47        struct task_struct *task;
  48
  49        /* number of things on the pending list */
  50        atomic_t num_pending;
  51
  52        /* reference counter for this struct */
  53        atomic_t refs;
  54
  55        unsigned long sequence;
  56
  57        /* protects the pending list. */
  58        spinlock_t lock;
  59
  60        /* set to non-zero when this thread is already awake and kicking */
  61        int working;
  62
  63        /* are we currently idle */
  64        int idle;
  65};
  66
  67static int __btrfs_start_workers(struct btrfs_workers *workers);
  68
  69/*
  70 * btrfs_start_workers uses kthread_run, which can block waiting for memory
  71 * for a very long time.  It will actually throttle on page writeback,
  72 * and so it may not make progress until after our btrfs worker threads
  73 * process all of the pending work structs in their queue
  74 *
  75 * This means we can't use btrfs_start_workers from inside a btrfs worker
  76 * thread that is used as part of cleaning dirty memory, which pretty much
  77 * involves all of the worker threads.
  78 *
  79 * Instead we have a helper queue who never has more than one thread
  80 * where we scheduler thread start operations.  This worker_start struct
  81 * is used to contain the work and hold a pointer to the queue that needs
  82 * another worker.
  83 */
  84struct worker_start {
  85        struct btrfs_work work;
  86        struct btrfs_workers *queue;
  87};
  88
  89static void start_new_worker_func(struct btrfs_work *work)
  90{
  91        struct worker_start *start;
  92        start = container_of(work, struct worker_start, work);
  93        __btrfs_start_workers(start->queue);
  94        kfree(start);
  95}
  96
  97/*
  98 * helper function to move a thread onto the idle list after it
  99 * has finished some requests.
 100 */
 101static void check_idle_worker(struct btrfs_worker_thread *worker)
 102{
 103        if (!worker->idle && atomic_read(&worker->num_pending) <
 104            worker->workers->idle_thresh / 2) {
 105                unsigned long flags;
 106                spin_lock_irqsave(&worker->workers->lock, flags);
 107                worker->idle = 1;
 108
 109                /* the list may be empty if the worker is just starting */
 110                if (!list_empty(&worker->worker_list)) {
 111                        list_move(&worker->worker_list,
 112                                 &worker->workers->idle_list);
 113                }
 114                spin_unlock_irqrestore(&worker->workers->lock, flags);
 115        }
 116}
 117
 118/*
 119 * helper function to move a thread off the idle list after new
 120 * pending work is added.
 121 */
 122static void check_busy_worker(struct btrfs_worker_thread *worker)
 123{
 124        if (worker->idle && atomic_read(&worker->num_pending) >=
 125            worker->workers->idle_thresh) {
 126                unsigned long flags;
 127                spin_lock_irqsave(&worker->workers->lock, flags);
 128                worker->idle = 0;
 129
 130                if (!list_empty(&worker->worker_list)) {
 131                        list_move_tail(&worker->worker_list,
 132                                      &worker->workers->worker_list);
 133                }
 134                spin_unlock_irqrestore(&worker->workers->lock, flags);
 135        }
 136}
 137
 138static void check_pending_worker_creates(struct btrfs_worker_thread *worker)
 139{
 140        struct btrfs_workers *workers = worker->workers;
 141        struct worker_start *start;
 142        unsigned long flags;
 143
 144        rmb();
 145        if (!workers->atomic_start_pending)
 146                return;
 147
 148        start = kzalloc(sizeof(*start), GFP_NOFS);
 149        if (!start)
 150                return;
 151
 152        start->work.func = start_new_worker_func;
 153        start->queue = workers;
 154
 155        spin_lock_irqsave(&workers->lock, flags);
 156        if (!workers->atomic_start_pending)
 157                goto out;
 158
 159        workers->atomic_start_pending = 0;
 160        if (workers->num_workers + workers->num_workers_starting >=
 161            workers->max_workers)
 162                goto out;
 163
 164        workers->num_workers_starting += 1;
 165        spin_unlock_irqrestore(&workers->lock, flags);
 166        btrfs_queue_worker(workers->atomic_worker_start, &start->work);
 167        return;
 168
 169out:
 170        kfree(start);
 171        spin_unlock_irqrestore(&workers->lock, flags);
 172}
 173
 174static noinline void run_ordered_completions(struct btrfs_workers *workers,
 175                                            struct btrfs_work *work)
 176{
 177        if (!workers->ordered)
 178                return;
 179
 180        set_bit(WORK_DONE_BIT, &work->flags);
 181
 182        spin_lock(&workers->order_lock);
 183
 184        while (1) {
 185                if (!list_empty(&workers->prio_order_list)) {
 186                        work = list_entry(workers->prio_order_list.next,
 187                                          struct btrfs_work, order_list);
 188                } else if (!list_empty(&workers->order_list)) {
 189                        work = list_entry(workers->order_list.next,
 190                                          struct btrfs_work, order_list);
 191                } else {
 192                        break;
 193                }
 194                if (!test_bit(WORK_DONE_BIT, &work->flags))
 195                        break;
 196
 197                /* we are going to call the ordered done function, but
 198                 * we leave the work item on the list as a barrier so
 199                 * that later work items that are done don't have their
 200                 * functions called before this one returns
 201                 */
 202                if (test_and_set_bit(WORK_ORDER_DONE_BIT, &work->flags))
 203                        break;
 204
 205                spin_unlock(&workers->order_lock);
 206
 207                work->ordered_func(work);
 208
 209                /* now take the lock again and drop our item from the list */
 210                spin_lock(&workers->order_lock);
 211                list_del(&work->order_list);
 212                spin_unlock(&workers->order_lock);
 213
 214                /*
 215                 * we don't want to call the ordered free functions
 216                 * with the lock held though
 217                 */
 218                work->ordered_free(work);
 219                spin_lock(&workers->order_lock);
 220        }
 221
 222        spin_unlock(&workers->order_lock);
 223}
 224
 225static void put_worker(struct btrfs_worker_thread *worker)
 226{
 227        if (atomic_dec_and_test(&worker->refs))
 228                kfree(worker);
 229}
 230
 231static int try_worker_shutdown(struct btrfs_worker_thread *worker)
 232{
 233        int freeit = 0;
 234
 235        spin_lock_irq(&worker->lock);
 236        spin_lock(&worker->workers->lock);
 237        if (worker->workers->num_workers > 1 &&
 238            worker->idle &&
 239            !worker->working &&
 240            !list_empty(&worker->worker_list) &&
 241            list_empty(&worker->prio_pending) &&
 242            list_empty(&worker->pending) &&
 243            atomic_read(&worker->num_pending) == 0) {
 244                freeit = 1;
 245                list_del_init(&worker->worker_list);
 246                worker->workers->num_workers--;
 247        }
 248        spin_unlock(&worker->workers->lock);
 249        spin_unlock_irq(&worker->lock);
 250
 251        if (freeit)
 252                put_worker(worker);
 253        return freeit;
 254}
 255
 256static struct btrfs_work *get_next_work(struct btrfs_worker_thread *worker,
 257                                        struct list_head *prio_head,
 258                                        struct list_head *head)
 259{
 260        struct btrfs_work *work = NULL;
 261        struct list_head *cur = NULL;
 262
 263        if(!list_empty(prio_head))
 264                cur = prio_head->next;
 265
 266        smp_mb();
 267        if (!list_empty(&worker->prio_pending))
 268                goto refill;
 269
 270        if (!list_empty(head))
 271                cur = head->next;
 272
 273        if (cur)
 274                goto out;
 275
 276refill:
 277        spin_lock_irq(&worker->lock);
 278        list_splice_tail_init(&worker->prio_pending, prio_head);
 279        list_splice_tail_init(&worker->pending, head);
 280
 281        if (!list_empty(prio_head))
 282                cur = prio_head->next;
 283        else if (!list_empty(head))
 284                cur = head->next;
 285        spin_unlock_irq(&worker->lock);
 286
 287        if (!cur)
 288                goto out_fail;
 289
 290out:
 291        work = list_entry(cur, struct btrfs_work, list);
 292
 293out_fail:
 294        return work;
 295}
 296
 297/*
 298 * main loop for servicing work items
 299 */
 300static int worker_loop(void *arg)
 301{
 302        struct btrfs_worker_thread *worker = arg;
 303        struct list_head head;
 304        struct list_head prio_head;
 305        struct btrfs_work *work;
 306
 307        INIT_LIST_HEAD(&head);
 308        INIT_LIST_HEAD(&prio_head);
 309
 310        do {
 311again:
 312                while (1) {
 313
 314
 315                        work = get_next_work(worker, &prio_head, &head);
 316                        if (!work)
 317                                break;
 318
 319                        list_del(&work->list);
 320                        clear_bit(WORK_QUEUED_BIT, &work->flags);
 321
 322                        work->worker = worker;
 323
 324                        work->func(work);
 325
 326                        atomic_dec(&worker->num_pending);
 327                        /*
 328                         * unless this is an ordered work queue,
 329                         * 'work' was probably freed by func above.
 330                         */
 331                        run_ordered_completions(worker->workers, work);
 332
 333                        check_pending_worker_creates(worker);
 334                        cond_resched();
 335                }
 336
 337                spin_lock_irq(&worker->lock);
 338                check_idle_worker(worker);
 339
 340                if (freezing(current)) {
 341                        worker->working = 0;
 342                        spin_unlock_irq(&worker->lock);
 343                        try_to_freeze();
 344                } else {
 345                        spin_unlock_irq(&worker->lock);
 346                        if (!kthread_should_stop()) {
 347                                cpu_relax();
 348                                /*
 349                                 * we've dropped the lock, did someone else
 350                                 * jump_in?
 351                                 */
 352                                smp_mb();
 353                                if (!list_empty(&worker->pending) ||
 354                                    !list_empty(&worker->prio_pending))
 355                                        continue;
 356
 357                                /*
 358                                 * this short schedule allows more work to
 359                                 * come in without the queue functions
 360                                 * needing to go through wake_up_process()
 361                                 *
 362                                 * worker->working is still 1, so nobody
 363                                 * is going to try and wake us up
 364name="L348"> 348                                /*
 265
 */


()) {

 353                                if (!y" class=3sref">list_empty(&am3;worker->pending) ||
 354                                    !efill" cl3ss="sref">refill;
worker->pending) ||
 355                                     0" id="L230" class="line" name="L230"> 236;
list_empty(cur = head 347 237);
c3r)
out;

 */
 237              *
worker->lock);
 338                ()) {

 _code" class="line" naet_L341"> _code"read.c#L341" id="L34TASK_INTERRUPTIBLE class="line" nTASK_INTERRUPTIBLE8                spin_lock_irq(&a3p;worker->pending) ||
 354                                    !il_init" 3lass="sref">list_splice_3ail_i37s/btrfs/async-thread.....................class="sref">worker->pending) ||
 355 >                                list_splice_3ail_i37;worker->lock);
 346                        if (! 238 href="+code=WORK_QUEUED_BIT"""""""""""""""""=worker" class="et_L341"> _code" class="line" naet_L341"> _code"read.c#L341" id="L34TASK_RUNNING class="line" nTASK_RUNNING6                        if (!list_empty(head 312                        if (!cur = prrrrrrrrrrrrrrrrr
list_empty                        cur = head 358               q" class=3sref">spin_unlock_irq
               qfill37" class="line" name="L237"> 238ef="fs/btrfs/async-thread.c#L217" id="L217" nnnnnnnnnnnnnnnn59addsame="" ing new="linne" name58               q" class=3ur)
nnnnnnnnnnnnnnnn5s="comment"> */
out_fail3
working = 0;
 342                         238;worker->lock);
 346                        if (!:
work3/a> = head 347                                 239);

                        if (!:
 342<> 243            work;

btrfs_worker_thread * 339a>                                 39d.c#L356" id="L356" class="line" name="L356">>>>>>>>>L295" i>                         239thread_should_stop()) {

work-__"et_L341"> _code" class="line" n__"et_L341"> _code"read.c#L341" id="L34TASK_RUNNING class="line" nTASK_RUNNING6                        if (!worker_loop(voi4 * 40 class="sref"}3"> 313 347                        list_head list_head btrfs_work *4a hre40free functions
              47" id="L347" class="line" name="L347"> 340ef="fs/btrfs/async-thread.c#59" id=w" nawaitass="a nanne"9"> 33       s="liread *              477 id="L347s/async-thread.c#L298" 4amp;<40.c#L218" id="L218" class="li5s="comment"> */
INIT_LIST_HEAD(4amp;<4 href=rfs_worker_thread" cthread47">"L247" class="line" namthread47">"L247" c 347wclass="line" namthreadL247" c 347arg;
 3400        struct work  href="+code=NULL" class="sref">NULL;
:
4a href="fs/btrfs/async-t4read.41code=cur" class="sref">cur = worker = arg;
argcan47" id="L347" class=can47" i03"                          344
 341st_empty( us up
worker->lock);
 249        work = worker->pending, flags);
 246                work4
 313->pending) ||
<="fs/btrfs/async-thread.c#L249" id="L249" classync-thre class="line" name="L246"> 246a>                                ;
 246 285         341r(btrfs_work, list);
worker =                                     4e=list_de4" class="sref">list_del<4a>(&a4p; 246                clear_bi4(42        if (! 342 class="sref">head->lock);
->                work->4a hre4="+code=worker" class=3" id="L323" class="l="fs/btrfs/async-thread.c#L249" id="L249" classssssssssssssssssssssssssssssssssssssssssslasssync-="line" name="L320"sync-="li.              argcan47" id="L347" class=can47r+code=fun4" class="sref">func(4a hre42"line" name="L342"> 3="L354" class="line" name="L354"> 354                                    !il_init" 3lass="sref">list_splice_3ail_i37s/btrfs/asyL318" class="line">;
 325
 246                worker->workers->n4amp;42fs/async-thread.c#L346" id="L346" class="linlass="sref">freeit;
 254}
num_pending);
argcan47" id="L347" class=can47r+="fs/btrf            * unless thi4 is a4 ordered work queue,argcan47" id="L347" class=can47r+ruct work-__"d="L327" class=="fs/btrfs/async-thread.c#L345" id= ="class4"sref">list_head  330 346                        if (!:
work = worker->                        work4rswork)         d *                  href="+code=worker" class="sref">worker->-> 249        work = worker->freeit;
 254}
btrfs_work *4a hre40fname="L334"> 337              4  286
work = worker->wo4kerbtrfs_work *4a hre40fn="fs/btrfa>);
btrfs_work *4a hre40fnruct                         awaitass="a nanne"9"> 33       s="liread +code=cur4ent" class="sref">curren4)43rg" class="sref">arg)
 33       s="liread id="L341"4class="line" name="L341"4 341<44t">                         7" class="line" namthread47">"L247" c 3474342;
    40" id="L340" class="line" na    40" id="    if (! 3400        struct  344
lock);
 3400        sass="_help54" id="L254" claass="_help54 id=d.c#4311" id="L311" class="li4e" na41344  4             } else {
spin_unlock_irq(&4mp;list_head lock);
list_head  347        4     44a>(& 310     worke4"+code=wo4k" class="sref">work4
 313->  4                        4    <44      INIT_LIST_HEAD(& 246         t;
 310     fs/async-thread.c#L249" id="L249" classync-thre classd="L3ne" name="L246"> 246d="L3ne" n    t; 350headsync-thread.c#L310" id="L310" class="line" name="L310"> 310     fs/async-thread.c#L249" id="L249" classync-thre class"""""d="L3ne" name="L246"> 246"""""d="L3ne" n    t;                    4     450head" class="sref">head  24 work = worker->,  24 work = ->work = worker m.c#L349" id="L349m="liner->pending)4||
 246 g" csh;
->prio_pe4ding<45L249" id="L249" class="line"-="li.              list_head list_head worker ass="_help54" id="L254" claass="_help54 id=lass4"sref">list_head  359  las4="sref">btrfs_work *4a hre40fame="L3604> 360 361                        awaitass="a nanne"9"> 33       s="liread ent">    4                        4   * 4orker->working is still 1,    lrts="lin18" class="li5.  T8" 4does="ot enforced="L2m=" ss="linetass="a nanne"9"> 33       s="liread e" class=4L363"> 363                        _up_untocescase yous/asyne" nemporarilyead.pastoctname="L331"> 331                       4L364"> 364name="L348"> 3484     4                         "L247" c 347
 3400        struct l                         argcan47" id="L347" class=can47" i03"                  pending" 4lass="sref">pending)4||
list_head pending)4||
l4.c#L35y" 4lass=3sref">list_empty(headist" class="sref">list);
worker kza hr            kza hr<    ifizeof(ass="line" nag" class="sref">argcan47" id="L347)a>               GFP_NOFS"sref">argcan47GFP_NOFSworker->headwork;
 347              3_head" class="sref"e" nde=work" class=e" n4r/*
argcan47" id="L3 hree50"t5liL313" ier_lrt8"  clas="class4"sref">li"sre3">work;
              3_head" cl>(&557c37              3_head" cl>(&557c37 310     fs/async-thread.c#L249" id=">->worker-&g2 nag" class="sref">argcan47" id="L3 h         ="L34TASK_INTERRUPTIBLE 4lass=47=workesync-thread.c#L310" id="L310" class="line" name="L310"> 310     worke4"+code=wo4k" class="sr>->2 nag" class="sref">argcan47" id="L3 hending) ||
INIT_LIST_HEAD(&  4            pending) ||
 24 work = ->worker->);
 361work = -> 328cur48=list" work = -> 353                    4/a3(                    4   work = ->         353                    4/ree50"t5l""""=s="line" name="L3584> 35848rio_hefs/async-thread.c#L249" id=">->->lockspin_unlock_irq
""k" c-%c-%d"d47">"L, c-thread.c#L249" id=""+co4a2" id="L4sync-threadnamd="4313" 4lass="namhrea href=>worker dnams="line" name="k" class=4sref">lock      4     48hould_stop()) {
list_he+ me="L353"> 353                    4/         ent">               q" c4ass=348=workesync-ths/btrfs/async-threaIS_ERR(&->->out_fail34 246(&->-> 353                    4/ending 3424     4                             kef="ne" name="L396"kef="L287"s= href="+cotasbtrfs/>-> 353                    4/s="sref"4);

argcan47" id="L3  id="L3584 claer" ef="fs/btrfs/asy4c-thr49ad work;
 347<4a>                      4     49=list"  24 work = worker->
work a hreadd_t4r/*
work4
 313         t; 49rio_hefs/async-thread.c#L249" id=">-> *list_h++7" class=can47r+="fs/btrf            _7c37 2394hread49s="lin-="li.              list_h--7" class=can47r+="fs/btrf            _         3d="L239fs/async-thread.4#L35849=workesync-thread.c#L310" idWARN_ON3" ier_lrt8"  cWARN_ONL287"s= href="+cotasbtrfs/"+co4a2" id="L4sync-thread.c#L313" ier_lrt8" id="L328" class="liL313" ier_lrt8"  clas="class4"sref">list_he<  0;
>
work = worker->wor49st" class="sref">l4.c#L35y" 4lass=3sref">41" id="L44TASK_RUNNING class="lin4" nTA4K_RUNNING6st_head  313
                 5=1sref"}35>>                      5="L4050=list"  24 work = worker->work = list_h--7" class=can47r+="fs/btrf           5      btr50rio_hefs/async-thread.c#L249>
work = worker->5     504RUNNING6st_head6 2395#59" 5d=w" n>work;
    5         477 id="L347s/a5ync-t50a>                5(4amp;<4 5ref=rfs_worker_thread" c5hread57">"L2de=work" class=rets           3400        struct w5lass="line" namthreadL245" c 357argwork<5a>  href="+code=NULL" cl5ss="s50adist" class="sref">list46"> 24 work = worker->list_h++7" class=can47r+="fs/btrf           5ef="fs/bt5fs/async-thread.c#L303" 5     51=list"  href="fs/btrfs/async-thread.c#L287" id="L287" cla"sref">work = worker->->(&5="fs/btrf5/async-thread.c#L249" id5"L24951=w" nawaitass="a nanne"9"> 33       s="liread *
fia>
a4does="ot enfoot atm=" snead.ct have
a4lot       s="liread *"L247" class="line" namthretoctdo right nowced="L2mc clst_headnullhs/bwe
arenead.ct y217"/asyncnag" cla     s="liread *w5 class="sref">btrfs_work5/a>, 51              * come in withsyne" nelimit
s="cofasyncnag" cs
are busy                     4L364"> 364name="L5        <5 href="+code=worke4e=cle5r_b4t51a>)
"L247" c 347argcan47"ead.a href="fs/btrfs/asyncead.a href=e=list_emp40" id="L340" class="line" name="L340"> 3400        struct argcan47" id="L347" class=can47" i03"                  pending" 4lass="sref"5f">func(4a hre42"line" name="L542"> 5="L354" class=a href="fs/btrfs/async-t4read.41code=cur" class="sref">cur =  32542fs/async-threa5.c#L356" id=3" id="L323" clruct list_he+ f="+e" name="L2= list_h)e<3" id="L323" clruct argcan47" idf="+e" name="L2= worker m.c#;3" id="L323" clruct w5t"4     42rk" class="sre5">wor52st" class="sref">l4.c#L35y" 4lass=3sref"5a> 33       s="liread *             5     53      7" class="line" namthrrrrrrrrr*hs/bwe
fia>
an ="+ccnag" c,tdonead.ct move
it
ofasyn       s="liread *INIT_LIST_HEAD4
maybnncatch
itINIT_LIST_HEADfuncINIT_LIST_HEAD
"L247" c 347 354                                    !il_init" 3lass="sref">list_splef">work4
 313         t;wo4kerbtr53L327" id="L327" class> =                  t;argcan47" idf="+e" name="L2=                                     4e=lis"fs/btrfs/async-thread.c#L3del<4a>(&a4p; 246       5ass="line5 n4me="L43t">           5     53read.c#L354" id="L354id="L355" class="lins= href="+cotasbtrfs/asyker->cur5en4)43rg" class="sre5">arg53d.c#L346" id="L346" cst_head6           5     54ad work;
4342a>                                ;
;
funclock);
 33       s="liread *37" class="line" name="L23*hs/bwe
pick a busy href, move
syncnref
ofasyncs="sc       s="liread *(&nne="L21w "/aevenlyibalans=dc       s="liread *cur5n 4lass=44=head" class="5ref">54a>)
"L247" c 3475ead         ,                                     4e=lis"fs/btrfs/async-thread.c#L3del<4a>(&a4p;->work = )4||
lock);
prio5pe4ding<45L249" id="L2495 clas5="line"-="li. ame=read.c#L310" id=  246 g" csh;
->()) {

work4
 313->  4           5 id="L3585 c4ass="45a>(&work;
  las4="sre5">btr55st" class="sref">l4.c#L35y" 4lass=3sref"5an class=5co4ment"45{
           5     5      awaitass="a nanne"9"> s="lelects a4does="ot enfootnnnakeasyncead. jobced="L2m18" ceisynr
fia>       s="liread *        5as4="com4ent">          5     5       _up_untocescase yous/asyone
ofasyncexe=p>nn busy  h4ef="c       s="liread * 348<5a>4     4               5     5   "L247" c 347
argcan47"fia>a href="fs/btrfs/asyncfia>a href=e=list_emp40" id="L340" class="line" name="L340"> 3400        struct l 5     5                 argcan47" id="L347" class=can47" i03"                  pending" 4lass="sref"5pending)4||
argcan47"flagthread.c#4311" iflagt"                  pending" 4lass="sref"5p)4||
cur = ->(5eadist" clde=work" class=retsyncs="class4"sref">list_h               pending" 4lass="sref"5 id="L3585 c4aer" 470head" class=<5 href57m_pitrass="sref">lock);
 347 24  24 ;
<>worker->  4           5 href="fs5bt4fs3as4nc37       5     53_heads= href="+cotasagaef="fs/btrfs/asynagaefhead:a> li"sre3"f="+e" name="L2=   4           5 a href="5nc37              3_5ead" 5l>(&557c37              3_head" cl>(&557c37 354 = list_he+ f="+e" name="L2= list_h #L31="L323" class="ref="fs/b4rfs/async-t5hending) ||
argcan47" idre3"f="+e" name="L2= worker m.c#id="L323" class="ref="fs/b4rfs/async-t5h) ||
->);
worker ass=id="L323" class="ref="fs/b4rfs/async-t5de"read.c5L341" id="L34TASK_RUNNIN5 clas58   list_head47" class=can47r+="fs/btrf           5         5  if (!cur58class="sref">work)        nde=work" class=e" n4llbaorker->                    5   list_h++7" class=can47r+="fs/btrf           5 class=3s5ef">spin_unlock_irq
 L287" id="restor=trfs/async-threa6"> L287" id="restor=      ;
<>worker->  4           5 7c37      5     58hould_stop()) {
"L247" c 347               q" c5ass=358L327" id="L327" class=="fs/btrfs/async-threayncs="-nc-thread.c#L30ENOMEM6out_fail35 24a href="f="+e" name="L246"> 24  24 ;
<>worker->  4           5/ending 3425     5                 ->                      5     59class="sref">work>work;

work;
 59rio_hefs/asyn nde=work" class=e" noun41code=cur" clasnoun4head               pending" 4lass="sref"5 class=3s5> *(&5_7c37 2395hread59s="liwork" class=e" n4llbaorker-> ->wor59              * come in with""""""""* we have
f="fastoctfia>
any  h4ef=", just       s="liread *)
c       s="liread * 313"L247" c 347>                      6="L40601="line" nameame="L354"> 354                                    !il_init" 3lass="sref">list_splef">work4
 313;
->btr60rio_hefs/asyname="L354"> 354                                    !il_init" 3lass="sref">list_splef">work4
 313         t;
->         t; 2396#59" 60s="lin-="li.               354 n4llbaorker->  4           6ent">    6         477 id="L347s/a6ync-t60=worke-="li.                                                  4e=lisn4llbaorker-> 246       6(4amp;<4 6ref=rfs_worker_thread" c6hread60line" name="L246"> 24a l<4a>(&a4p;->w6lass="line" namthreadL246" c 367arg work<6a>  href="+code=NULL" cl6ss="s6046" class="liawaitass="a nanne"9"> 33       s="liread * * *"L247" c 347->li"sre3"f="+e" name="L2ncs="clin<    ifizeof(assncs="clinlist_spl347" class=can47" i03"   sclass= href="+cotaslass="line" name="L328"> 328 L287" id="restor=trfs/async-threa6"> L287" id="restor=      ;
<>worker->  4           6="fs/btrf6/async-thread.c#L249" id6"L24961s="lin-="li. st_head6work;
"L2work;
w6 class="sref">btrfs_work6/a>, 61              * come in wit33       s="liread *work<6 href="+code=worke4e=cle6r_b4t61a>)
 * s="it id="L341"4class="line6trfs/asyn6-thread.c#L346" id="L3466 clas62ill 1,    lrts="lin18" class="a "/amake="L21 progresst/a>
want"L247" c 347func(4a hre42"line" name="L642"> 6="L354void&a4p;argcan47" id=347" class=can47" i0ENOass="li4e" na41c#L187" i4="L187" cla6read.c#L365"4id="L425" class="line6 name6"L325"="L323" class="ref="fs/b4rfs/async-t6r"fs/btrf6="4ref">42fs/async-threa6.c#L362s="lin-="li.    argcan47" id="L347" class=can47" i03"   MEM6argcan47"flagthread.c#4311" iflagt"                  pending" 4lass="sref"6r4amp;<4 6hi4 is a4 ordered work q6eue,<62read.c#L30retde=work" class=retswake347" class=can47ake"   MEM w6t"4     42rk" class="sre6">wor62st" class="sref">l4.c#L35y" 4lass=3sref"6a>             6     63     work 46"> 24  24 worker->  4           6_">func

->2 nag" class="sref">argcan47" id="L36         6  4 argcan47" id="L36 btrfs/as6sr4f">wo4kerbtr63L327" id="L327" class> = 
->worker-&g2 nag" class="sref">argcan47" id="L36="fs/btrf6/a4ync-t4read.cas4="sref6>btrf63NIT_LIST_HEAD" class="sref">ncs="clin<    ifizeof(assncs="clinlist_spl347" class=can47" i03"   sclass= href="+cotaslass="line" name="L328"> 328           6     63st" class="sref">l4.c#L35y" 4lass=3sref"6sref">cur6en4)43rg" class="sre6">arg6346" class="liawaitass="a nanne"9"> 33 by defid="ion weead.cre busy,nnakeaourselvesnoffasync="+c0E7">"L247" c 347           6     64      7" class="line" namthrrrrrrrrr*hs="s       s="liread *4342"L247" c 347funcwork 46"> 24  24 list_spl347" class=can47" i03"   sclass= href="+cotasbtrfs/async-thread.c4L318"4id="L318" class="line">;
<>worker-> ()) {

 list_spl347" class=can47" i03"   sclass= href="+cotasbtrfs/async-thread.c4L318"4id="L318" class="line">;
->argcan47" idf="+e" name="L2a6"> L287" trfs/async-threa6"> L287" !il_init" 3lass="sref">list_spl347" class=can47" i03"   sclass= href="+cotasbtrfs/async-thread.c4L318"4id="L318" class="line">;
<>worker->
cur6n 4lass=44=head" class="6ref">6446" class="liame="L354"> 354 =  3btrfne"0ENOid="L323" class="ref="fs/b4rfs/async-t6         6  4     450head" class="6ref">65   , workL354"> 354 =  3btrfne"0ENOMEM47" class=can47r+="fs/btrf           6fcreates<6 i4 (!work;
)4||
lock);
prio6pe4ding<45L249" id="L2496 clas6="line"-="li. ame=read.c#L310" id=ake347" class=can47ake"   ass="li4e" na41c#L187" i4="L187" cla6ss="line"6na4e="L345c#L286" id="L266" cl65hould_stop()) {
-> 353                    6 id="L3586 c4ass="45a>(& L287" id="restor=trfs/async-threa6"> L287" id="restor=      worker->  4           6         6  4   * 45      work;
  las4="sre6">btr65st" class="sref">l4.c#L35y" 4lass=3sref"6an class=6co4ment"45{
(&a4p;argcan47" id=347" class=can47" i0ENOass="li4e" na41c#L187" i4="L187" cla6>           6     6      ="L323" class="ref="fs/b4rfs/async-t6>="+code=6  4   * 4orker->worki6g is 66=list"   4           6>        6as4="com4ent">          6     6      >work;
 348<6a>4     4               6     66" class="sref">lock);
 *(&r" class="tde=nnnnnna>l 6     66ead.c#L298" 4amp;<40.c#L218" ad47">"L247" c 347(&a4p; 3400        struct (&a4p;argcan47" id=347" class=can47" i0ENOass="li4e" na41c#L187" i4="L187" cla6>)4||
(6eadist" cl   argcan47" id="L347" class=can47" i03"                  pending" 4lass="sref"6 id="L3586 c4aer" 470head" class=<6 href67   argcan47"flagthread.c#4311" iflagt"                  pending" 4lass="sref"67"> 347        6     63_heada>  348<6iL313" ier_lrt8"  clas="6lass46sref">li"sre3"fwaitass="a nanne"9"> 33 donead.ct requeue="L218">nn al    y340"a1"ist< ad47">"L247" c 347              3_6ead" 67"line"-="li. ame=read.c#L310" idtehreandlanc_bref="+e" nc-threatehreandlanc_bre              4e=lisWORK_QUEUED_BITf="+e" nc-threaWORK_QUEUED_BIT="+csn ()) {
                 6hending) ||
 id="L347" class=can47" i03"   MEM6a href="fs/btrfs/asyncfia>a href=e=lisa href="+code=btrfs_4thread.c#4311" id="L311" clng" class="sref"348  4           6h) ||
);

 *cur68ill 1,    lrts="lin18" classrrrrrrrrrrrrrrrr* int>rrupt handlf=e=     s="liread *                    6   "L247" c 347work 46"> 24  24 list_spl"+co4a2" id="L4sync-thread.c#L313" id="4313" 4lorder 24   4           6 class=3s6ef">spin_unlock_irq
      6     68hould_stop()) {
->                q" c6ass=368L327" id="L327" class=="fs/btttttttttttttttnit" 3lass="sref">list_spl"+co4a2" id="L4sync-thread.c#L313" id="4313" 4ler" corder 2yker->  4           6 endingout_fail36 24="L347s="L323" class="ref="fs/b4rfs/async-t6/ending 3426     6                 
->list_spl"+co4a2" id="L4sync-thread.c#L313" id="4313" 4lorder 2yker->  4           6 s="sref"6);
work;
 L287" trfs/async-threa6"> L287" !il_init" 3lass="sref">list_spl"+co4a2" id="L4sync-thread.c#L313" id="4313" 4lorder 24   4           6         6a>                      6     69class="sref">="L347s="L323" class="ref="fs/b4rfs/async-t687" cl us6up
->  4           6 ree50"t5642" class="line" name="L642"> 69rio_hefs/asyn>work;
 *(&6_7c37 2396hread69s="lin-="li.               24  24 worker->  4           6_        63d="L239fs/async-thread.6#L35869a>                6 h3ef="f36f="fs/btrfs/async-thr"""6""""
69NIT_LIST_HEADame=read.c#L310" idtehrebref="+e" nc-threatehrebre              4e=lisWORK_HIGH_PRIO_BITf="+e" nc-threaWORK_HIGH_PRIO_BIT="+csn                 6 endingwor69                
->2 nag" class="sref">argcan47" id="L363s="sref"64TASK_RUNNING class="lin6" nTA69d.c#L346" id=L347 nag" class="sref">argcan47" id="L37="sref"}37> 313->worker-&g2 nag" class="sref">argcan47" id="L37=1sref"}37>>                      7="L4070=list" argcan47" id="L37=2sref"}37>p
 btr70ref">li"sre3"fwaitass="a nanne"9"> 33d47">"L247" c 347
"L247" c 347 2397#59" 70 qfill37" class="line" name="L23*hbeen kicke>       s="liread *    7         477 id="L347s/a7ync-t70)
"L247" c 347 354 =  3btrfne"0ENOi247" c 347work<7a>  href="+code=NULL" cl7ss="s7046" class="lia354"> 354 =  3btrfne"0ENOMEM47" class=can47r+="fs/btrf           7d.c#L262 7                      lock);
-> 353                    7"     ->li"sre3"f="+e" name="L246"> L287" id="restor=trfs/async-threa6"> L287" id="restor=      worker->  4           7trfs/asyn7-thread.c#L249" id="L2497 clas71"line>work;
;
m4r/to:lx/@ad.ux.noa hx/@ad.ux.no!il_.
hx/.ad.ux.no kindly hosted3byiork; http://www.redpill-ad.pro.noa Redpill Ld.pro AS!il_,eprovider ofaLd.ux btnsulp>nn /a> operation3 services sins="1995.