]> git.sur5r.net Git - bacula/bacula/blob - bacula/platforms/freebsd/pthreads-fix.txt
3dda1308ac33b9f81eaf06e3ee50649643a181ef
[bacula/bacula] / bacula / platforms / freebsd / pthreads-fix.txt
1 From: "Dan Langille" <dan@langille.org>
2 To: bacula-users@lists.sourceforge.net
3 Subject: [Bacula-users] FreeBSD - large backups to tape
4 Date: Mon, 20 Oct 2003 15:29:18 -0400
5
6 Kern and I have been working on a FreeBSD/Bacula problem.  
7 He's asked me to post this to the list.  The problem was within the
8 FreeBSD pthreads library.  A solution has been found.
9
10 PROBLEM DESCRIPTION:
11
12 The FreeBSD pthreads library does not properly handle End Of Tape.
13 This problem will be fixed in FreeBSD 4.9.
14
15 UPDATE 2004/02/24: Note, the problem was apparently not fixed in
16     4.9-RELEASE. 4.9-RELEASE contained a partial patch that did not
17     prevent data loss. To date, the latest FreeBSD -RELEASE versions
18     (4.9-RELEASE and 5.2.1-RELEASE) are *broken* as shipped. If
19     you are running one of these systems, please either patch
20     your system as described below or upgrade to -STABLE or
21     -CURRENT immediately.
22
23     We expect 4.10-RELEASE to be available within a few weeks
24     (written 24 Apr 2004) and 5.3-RELEASE to be available in a
25     few months.  4.10 and 5.3 *should* contain the fix, but we
26     can't know for sure until we've had a chance to test them.
27
28 The bug results in more data being written than the tape will
29 hold because of a lost status code.  Any backup which involving
30 more than one tape would have data lost.
31
32 DEMONSTRATION:
33
34 To demonstrate the problem, tapetest.c can be obtained from 
35 http://www.freebsd.org/cgi/query-pr.cgi?pr=56274
36
37 tapetest.c can also be found in the Bacula source distribution
38 in <bacula-source>/platforms/freebsd/tapetest.c
39
40 This tests without pthreads:
41
42  *  If you build this program with:
43  *
44  *  c++ -g -O2 -Wall -c tapetest.c
45  *  c++ -g -O2 -Wall tapetest.o -o tapetest
46  *
47  *  Procedure for testing tape
48  *  ./tapetest /dev/your-tape-device
49  *  rewind
50  *  rawfill
51  *  rewind
52  *  scan
53  *
54  *  The output will be something like:
55  *
56  * ========
57  *  Rewound /dev/nsa0
58  *  *Begin writing blocks of 64512 bytes.
59  *  ++++++++++++++++++++ ...
60  *  Write failed.  Last block written=17294. stat=0 ERR=Unknown error: 0
61  *  weof_dev
62  *  Wrote EOF to /dev/nsa0
63  *  *Rewound /dev/nsa0
64  *  *Starting scan at file 0
65  *  17294 blocks of 64512 bytes in file 0
66  *  End of File mark.
67  *  End of File mark.
68  *  End of tape
69  *  Total files=1, blocks=17294, bytes = 1115670528
70  * ========
71  *
72  *  which is correct. Notice that the return status is
73  *  0, while in the example below, which fails, the return
74  *  status is -1.
75
76 This tests with pthreads:
77
78  *  If you build this program with:
79  *
80  *  c++ -g -O2 -Wall -pthread -c tapetest.c
81  *  c++ -g -O2 -Wall -pthread tapetest.o -o tapetest
82  *    Note, we simply added -pthread compared to the
83  *    previous example.
84  *
85  *  Procedure for testing tape
86  *  ./tapetest /dev/your-tape-device
87  *  rewind
88  *  rawfill
89  *  rewind
90  *  scan
91  *
92  *  The output will be something like:
93  *
94  * ========
95  *    Rewound /dev/nsa0
96  *    *Begin writing blocks of 64512 bytes.
97  *    +++++++++++++++++++++++++++++ ...
98  *    Write failed.  Last block written=17926. stat=-1 ERR=No space left on device
99  *    weof_dev
100  *    Wrote EOF to /dev/nsa0
101  *    *Rewound /dev/nsa0
102  *    *Starting scan at file 0
103  *    17913 blocks of 64512 bytes in file 0
104  *    End of File mark.
105  *    End of File mark.
106  *    End of tape
107  *    Total files=1, blocks=17913, bytes = 1155603456
108  * ========
109  *
110  * which is incorrect because it wrote 17,926 blocks and the
111  * status on the last block written is stat=-1, which is incorrect.
112  * In addition only 17,913 blocks were read back.
113  *
114  * Similarly, if you ran this test on 4.9-RELEASE or 5.2.1-RELEASE
115  * (these versions contain an incomplete patch) then you would
116  * probably see something like this:
117  *
118  * ========
119  *    Rewound /dev/nsa0
120  *    *Begin writing blocks of 64512 bytes.
121  *    +++++++++++++++ [...]
122  *    weof_dev
123  *    Wrote EOF to /dev/nsa0
124  *    Write failed.  Last block written=271163. stat=-1 ERR=No space left on device
125  *    *Rewound /dev/nsa0
126  *    *Starting scan at file 0
127  *    Bad status from read -1. ERR=Input/output error
128  *    271163 blocks of 64512 bytes in file 0
129  * ========
130  *
131  * The above output is also incorrect. The block counts match,
132  * but note the -1 error code on the read and write. This is
133  * just as dangerous as the first example. If you see this
134  * output then you should patch or upgrade to -STABLE or -CURRENT
135  * immediately.
136
137 If you get the same number of blocks written and read WHEN using 
138 pthreads, AND the test with pthreads enabled returns a stat=0
139 on the last write, and the scan operation returns no error
140 code, then you've been correctly patched. It is important that
141 stat=0 rather than -1 even if the correct number of blocks
142 are read back. If the status is -1 on the pthreads test, you
143 will lose data.
144
145 SOLUTION:
146
147 For FreeBSD versions prior to 4.10-RELEASE and 5.3-RELEASE you
148 have two choices to ensure proper backups.  These instructions
149 assume you are familiar with patching FreeBSD and already have
150 the FreeBSD source code installed on your machine.
151
152 For FreeBSD 4.x:
153
154 Do one of the following:
155
156 - cvsup and build your system to FreeBSD 4.x-STABLE after the
157   date Mon Dec 29 15:18:01 2003 UTC
158
159 - Apply this patch.
160
161   http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc_r/uthread/uthread_write.c.diff?r1=1.16.2.6&r2=1.16.2.8
162
163   To apply the patch, follow these instructions as root.  
164
165     cd /usr/src/lib/libc_r/uthread/
166     fetch -o pthread.diff 'http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc_r/uthread/uthread_write.c.diff?r1=1.16.2.6&r2=1.16.2.8'
167     patch < pthread.diff
168     cd ..
169     make all install
170
171 For FreeBSD 5.x:
172
173 Do one of the following:
174
175 - cvsup and build your system to FreeBSD -CURRENT after the
176   date Wed Dec 17 16:44:03 2003 UTC
177
178 - Apply this patch.
179
180   http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc_r/uthread/uthread_write.c.diff?r1=1.22&r2=1.23
181
182  Wed Dec 17 16:44:03 2003 UTC
183
184   To apply the patch, follow these instructions as root.  
185
186     cd /usr/src/lib/libc_r/uthread/
187     fetch -o pthread.diff 'http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc_r/uthread/uthread_write.c.diff?r1=1.22&r2=1.23'
188     patch < pthread.diff
189     cd ..
190     make all install
191
192 After patching your system as shown above, 
193 you should then recompile Bacula to get the new library
194 code included by doing:
195
196   cd <bacula-source>
197   make clean
198   make 
199   ...
200
201
202 TESTING:
203
204 I suggest running tapetest on your patched system and then
205 conducting a backup which spans two tapes.  Restore the data
206 and compare to the original.  If not identical, please let us know.