Annotation of /trunk/kernel26-magellan/patches-2.6.16-r12/0112-2.6.16.12-fix-kcopyd-destructor.patch
Parent Directory | Revision Log
Revision 72 -
(hide annotations)
(download)
Mon Jun 5 09:25:38 2006 UTC (18 years, 3 months ago) by niro
File size: 3122 byte(s)
Mon Jun 5 09:25:38 2006 UTC (18 years, 3 months ago) by niro
File size: 3122 byte(s)
ver bump to 2.6.16-r12: - updated to linux-2.6.16.19 - updated to ck11
1 | niro | 72 | From: Alasdair G Kergon <agk@redhat.com> |
2 | Date: Mon, 24 Apr 2006 20:36:06 +0000 (-0700) | ||
3 | Subject: [PATCH] dm snapshot: fix kcopyd destructor | ||
4 | X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/stable/linux-2.6.16.y.git;a=commitdiff;h=f6a731290ca18b31fd447989319eb913d9c308d8 | ||
5 | |||
6 | [PATCH] dm snapshot: fix kcopyd destructor | ||
7 | |||
8 | Before removing a snapshot, wait for the completion of any kcopyd jobs using | ||
9 | it. | ||
10 | |||
11 | Do this by maintaining a count (nr_jobs) of how many outstanding jobs each | ||
12 | kcopyd_client has. | ||
13 | |||
14 | The snapshot destructor first unregisters the snapshot so that no new kcopyd | ||
15 | jobs (created by writes to the origin) will reference that particular | ||
16 | snapshot. kcopyd_client_destroy() is now run next to wait for the completion | ||
17 | of any outstanding jobs before the snapshot exception structures (that those | ||
18 | jobs reference) are freed. | ||
19 | |||
20 | Signed-off-by: Alasdair G Kergon <agk@redhat.com> | ||
21 | Signed-off-by: Andrew Morton <akpm@osdl.org> | ||
22 | Signed-off-by: Linus Torvalds <torvalds@osdl.org> | ||
23 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | ||
24 | --- | ||
25 | |||
26 | --- a/drivers/md/dm-snap.c | ||
27 | +++ b/drivers/md/dm-snap.c | ||
28 | @@ -542,8 +542,12 @@ static void snapshot_dtr(struct dm_targe | ||
29 | { | ||
30 | struct dm_snapshot *s = (struct dm_snapshot *) ti->private; | ||
31 | |||
32 | + /* Prevent further origin writes from using this snapshot. */ | ||
33 | + /* After this returns there can be no new kcopyd jobs. */ | ||
34 | unregister_snapshot(s); | ||
35 | |||
36 | + kcopyd_client_destroy(s->kcopyd_client); | ||
37 | + | ||
38 | exit_exception_table(&s->pending, pending_cache); | ||
39 | exit_exception_table(&s->complete, exception_cache); | ||
40 | |||
41 | @@ -552,7 +556,7 @@ static void snapshot_dtr(struct dm_targe | ||
42 | |||
43 | dm_put_device(ti, s->origin); | ||
44 | dm_put_device(ti, s->cow); | ||
45 | - kcopyd_client_destroy(s->kcopyd_client); | ||
46 | + | ||
47 | kfree(s); | ||
48 | } | ||
49 | |||
50 | --- a/drivers/md/kcopyd.c | ||
51 | +++ b/drivers/md/kcopyd.c | ||
52 | @@ -44,6 +44,9 @@ struct kcopyd_client { | ||
53 | struct page_list *pages; | ||
54 | unsigned int nr_pages; | ||
55 | unsigned int nr_free_pages; | ||
56 | + | ||
57 | + wait_queue_head_t destroyq; | ||
58 | + atomic_t nr_jobs; | ||
59 | }; | ||
60 | |||
61 | static struct page_list *alloc_pl(void) | ||
62 | @@ -293,10 +296,15 @@ static int run_complete_job(struct kcopy | ||
63 | int read_err = job->read_err; | ||
64 | unsigned int write_err = job->write_err; | ||
65 | kcopyd_notify_fn fn = job->fn; | ||
66 | + struct kcopyd_client *kc = job->kc; | ||
67 | |||
68 | - kcopyd_put_pages(job->kc, job->pages); | ||
69 | + kcopyd_put_pages(kc, job->pages); | ||
70 | mempool_free(job, _job_pool); | ||
71 | fn(read_err, write_err, context); | ||
72 | + | ||
73 | + if (atomic_dec_and_test(&kc->nr_jobs)) | ||
74 | + wake_up(&kc->destroyq); | ||
75 | + | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | @@ -431,6 +439,7 @@ static void do_work(void *ignored) | ||
80 | */ | ||
81 | static void dispatch_job(struct kcopyd_job *job) | ||
82 | { | ||
83 | + atomic_inc(&job->kc->nr_jobs); | ||
84 | push(&_pages_jobs, job); | ||
85 | wake(); | ||
86 | } | ||
87 | @@ -670,6 +679,9 @@ int kcopyd_client_create(unsigned int nr | ||
88 | return r; | ||
89 | } | ||
90 | |||
91 | + init_waitqueue_head(&kc->destroyq); | ||
92 | + atomic_set(&kc->nr_jobs, 0); | ||
93 | + | ||
94 | client_add(kc); | ||
95 | *result = kc; | ||
96 | return 0; | ||
97 | @@ -677,6 +689,9 @@ int kcopyd_client_create(unsigned int nr | ||
98 | |||
99 | void kcopyd_client_destroy(struct kcopyd_client *kc) | ||
100 | { | ||
101 | + /* Wait for completion of all jobs submitted by this client. */ | ||
102 | + wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs)); | ||
103 | + | ||
104 | dm_io_put(kc->nr_pages); | ||
105 | client_free_pages(kc); | ||
106 | client_del(kc); |