Merge lp:~sergei.glushchenko/percona-xtrabackup/2.2-xb-bug1375383 into lp:percona-xtrabackup/2.2

Proposed by Sergei Glushchenko
Status: Merged
Approved by: Alexey Kopytov
Approved revision: no longer in the source branch.
Merged at revision: 5035
Proposed branch: lp:~sergei.glushchenko/percona-xtrabackup/2.2-xb-bug1375383
Merge into: lp:percona-xtrabackup/2.2
Diff against target: 429 lines (+166/-150)
1 file modified
storage/innobase/os/os0file.cc (+166/-150)
To merge this branch: bzr merge lp:~sergei.glushchenko/percona-xtrabackup/2.2-xb-bug1375383
Reviewer Review Type Date Requested Status
Alexey Kopytov (community) Approve
Review via email: mp+237383@code.launchpad.net

Description of the change

1. os_file_handle_error_cond_exit to call ut_error instead of exit
2. Port fix for MySQL bug #54430 from 5.7 tree.

http://jenkins.percona.com/view/PXB%202.2/job/percona-xtrabackup-2.2-param/227/

To post a comment you must log in.
Revision history for this message
Alexey Kopytov (akopytov) wrote :

Sergei,

Wouldn't it be better to port the _current_ version of the code, rather than the original revision. That is, no HAVE_BROKEN_PREAD (HP-UX specific) code paths, and no spurious whitespace changes like in lines 289-290. Those have been fixed in later revisions.

review: Needs Information
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

I updated related code parts to the latest available state.

http://jenkins.percona.com/view/PXB%202.2/job/percona-xtrabackup-2.2-param/232/

Revision history for this message
Alexey Kopytov (akopytov) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'storage/innobase/os/os0file.cc'
2--- storage/innobase/os/os0file.cc 2014-09-15 08:52:36 +0000
3+++ storage/innobase/os/os0file.cc 2014-10-09 19:02:11 +0000
4@@ -66,6 +66,9 @@
5 /** Log segment id */
6 static const ulint IO_LOG_SEGMENT = 1;
7
8+/** Number of retries for partial I/O's */
9+static const ulint NUM_RETRIES_ON_PARTIAL_IO = 10;
10+
11 /* This specifies the file permissions InnoDB uses when it creates files in
12 Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to
13 my_umask */
14@@ -652,7 +655,7 @@
15 }
16
17 if (should_exit) {
18- exit(1);
19+ ut_error;
20 }
21 }
22
23@@ -2336,11 +2339,75 @@
24 #endif
25 }
26
27-#ifndef __WIN__
28+#ifndef _WIN32
29+/*******************************************************************//**
30+Does a syncronous read or write depending upon the type specified
31+In case of partial reads/writes the function tries
32+NUM_RETRIES_ON_PARTIAL_IO times to read/write the complete data.
33+@return number of bytes read/written, -1 if error */
34+static __attribute__((warn_unused_result))
35+ssize_t
36+os_file_io(
37+/*==========*/
38+ os_file_t file, /*!< in: handle to a file */
39+ void* buf, /*!< in: buffer where to read/write */
40+ ulint n, /*!< in: number of bytes to read/write */
41+ off_t offset, /*!< in: file offset from where to read/write */
42+ ulint type) /*!< in: type for read or write */
43+{
44+ ssize_t bytes_returned = 0;
45+ ssize_t n_bytes;
46+
47+ for (ulint i = 0; i < NUM_RETRIES_ON_PARTIAL_IO; ++i) {
48+ if (type == OS_FILE_READ ) {
49+ n_bytes = pread(file, buf, n, offset);
50+ } else {
51+ ut_ad(type == OS_FILE_WRITE);
52+ n_bytes = pwrite(file, buf, n, offset);
53+ }
54+
55+ if ((ulint) n_bytes == n) {
56+ bytes_returned += n_bytes;
57+ return(bytes_returned);
58+ } else if (n_bytes > 0 && (ulint) n_bytes < n) {
59+ /* For partial read/write scenario */
60+ if (type == OS_FILE_READ) {
61+ ib_logf(IB_LOG_LEVEL_WARN,
62+ "%lu bytes should have"
63+ " been read. Only %lu bytes"
64+ " read. Retrying again to read"
65+ " the remaining bytes.",
66+ (ulong) n, (ulong) n_bytes);
67+ } else {
68+ ib_logf(IB_LOG_LEVEL_WARN,
69+ "%lu bytes should have"
70+ " been written. Only %lu bytes"
71+ " written. Retrying again to"
72+ " write the remaining bytes.",
73+ (ulong) n, (ulong) n_bytes);
74+ }
75+
76+ buf = (uchar*) buf + (ulint) n_bytes;
77+ n -= (ulint) n_bytes;
78+ offset += n_bytes;
79+ bytes_returned += (ulint) n_bytes;
80+
81+ } else {
82+ break;
83+ }
84+ }
85+
86+ ib_logf(IB_LOG_LEVEL_WARN,
87+ "Retry attempts for %s partial data failed.",
88+ type == OS_FILE_READ ? "reading" : "writing");
89+
90+ return(bytes_returned);
91+}
92+
93 /*******************************************************************//**
94 Does a synchronous read operation in Posix.
95-@return number of bytes read, -1 if error */
96-static __attribute__((nonnull, warn_unused_result))
97+@return number of bytes read, -1 if error */
98+static __attribute__((warn_unused_result))
99 ssize_t
100 os_file_pread(
101 /*==========*/
102@@ -2349,10 +2416,8 @@
103 ulint n, /*!< in: number of bytes to read */
104 os_offset_t offset) /*!< in: file offset from where to read */
105 {
106- off_t offs;
107-#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
108- ssize_t n_bytes;
109-#endif /* HAVE_PREAD && !HAVE_BROKEN_PREAD */
110+ off_t offs;
111+ ssize_t read_bytes;
112
113 ut_ad(n);
114
115@@ -2360,98 +2425,45 @@
116 64-bit address */
117 offs = (off_t) offset;
118
119- if (sizeof(off_t) <= 4) {
120- if (offset != (os_offset_t) offs) {
121- ib_logf(IB_LOG_LEVEL_ERROR,
122- "File read at offset > 4 GB");
123- }
124+ if (sizeof(off_t) <= 4 && offset != (os_offset_t) offs) {
125+ ib_logf(IB_LOG_LEVEL_ERROR, "File read at offset > 4 GB");
126 }
127
128 os_n_file_reads++;
129
130-#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
131-#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8
132+# if defined(HAVE_ATOMIC_BUILTINS)
133 (void) os_atomic_increment_ulint(&os_n_pending_reads, 1);
134 (void) os_atomic_increment_ulint(&os_file_n_pending_preads, 1);
135 MONITOR_ATOMIC_INC(MONITOR_OS_PENDING_READS);
136-#else
137- os_mutex_enter(os_file_count_mutex);
138+# else
139+ mutex_enter(&os_file_count_mutex);
140 os_file_n_pending_preads++;
141 os_n_pending_reads++;
142 MONITOR_INC(MONITOR_OS_PENDING_READS);
143- os_mutex_exit(os_file_count_mutex);
144-#endif /* HAVE_ATOMIC_BUILTINS && UNIV_WORD == 8 */
145-
146- n_bytes = pread(file, buf, n, offs);
147-
148-#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8
149+ mutex_exit(&os_file_count_mutex);
150+# endif /* HAVE_ATOMIC_BUILTINS */
151+
152+ read_bytes = os_file_io(file, buf, n, offs, OS_FILE_READ);
153+
154+# ifdef HAVE_ATOMIC_BUILTINS
155 (void) os_atomic_decrement_ulint(&os_n_pending_reads, 1);
156 (void) os_atomic_decrement_ulint(&os_file_n_pending_preads, 1);
157 MONITOR_ATOMIC_DEC(MONITOR_OS_PENDING_READS);
158-#else
159- os_mutex_enter(os_file_count_mutex);
160+# else
161+ mutex_enter(&os_file_count_mutex);
162 os_file_n_pending_preads--;
163 os_n_pending_reads--;
164 MONITOR_DEC(MONITOR_OS_PENDING_READS);
165- os_mutex_exit(os_file_count_mutex);
166-#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD == 8 */
167-
168- return(n_bytes);
169-#else
170- {
171- off_t ret_offset;
172- ssize_t ret;
173-#ifndef UNIV_HOTBACKUP
174- ulint i;
175-#endif /* !UNIV_HOTBACKUP */
176-
177-#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8
178- (void) os_atomic_increment_ulint(&os_n_pending_reads, 1);
179- MONITOR_ATOMIC_INC(MONITOR_OS_PENDING_READS);
180-#else
181- os_mutex_enter(os_file_count_mutex);
182- os_n_pending_reads++;
183- MONITOR_INC(MONITOR_OS_PENDING_READS);
184- os_mutex_exit(os_file_count_mutex);
185-#endif /* HAVE_ATOMIC_BUILTINS && UNIV_WORD == 8 */
186-#ifndef UNIV_HOTBACKUP
187- /* Protect the seek / read operation with a mutex */
188- i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
189-
190- os_mutex_enter(os_file_seek_mutexes[i]);
191-#endif /* !UNIV_HOTBACKUP */
192-
193- ret_offset = lseek(file, offs, SEEK_SET);
194-
195- if (ret_offset < 0) {
196- ret = -1;
197- } else {
198- ret = read(file, buf, (ssize_t) n);
199- }
200-
201-#ifndef UNIV_HOTBACKUP
202- os_mutex_exit(os_file_seek_mutexes[i]);
203-#endif /* !UNIV_HOTBACKUP */
204-
205-#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8
206- (void) os_atomic_decrement_ulint(&os_n_pending_reads, 1);
207- MONITOR_ATOIC_DEC(MONITOR_OS_PENDING_READS);
208-#else
209- os_mutex_enter(os_file_count_mutex);
210- os_n_pending_reads--;
211- MONITOR_DEC(MONITOR_OS_PENDING_READS);
212- os_mutex_exit(os_file_count_mutex);
213-#endif /* HAVE_ATOMIC_BUILTINS && UNIV_WORD_SIZE == 8 */
214-
215- return(ret);
216- }
217-#endif
218+ mutex_exit(&os_file_count_mutex);
219+# endif /* HAVE_ATOMIC_BUILTINS */
220+
221+ return(read_bytes);
222 }
223
224 /*******************************************************************//**
225 Does a synchronous write operation in Posix.
226-@return number of bytes written, -1 if error */
227-static __attribute__((nonnull, warn_unused_result))
228+@return number of bytes written, -1 if error */
229+static __attribute__((warn_unused_result))
230 ssize_t
231 os_file_pwrite(
232 /*===========*/
233@@ -2460,95 +2472,49 @@
234 ulint n, /*!< in: number of bytes to write */
235 os_offset_t offset) /*!< in: file offset where to write */
236 {
237- ssize_t ret;
238- off_t offs;
239+ off_t offs;
240+ ssize_t written_bytes;
241
242 ut_ad(n);
243- ut_ad(!srv_read_only_mode);
244
245 /* If off_t is > 4 bytes in size, then we assume we can pass a
246 64-bit address */
247 offs = (off_t) offset;
248
249- if (sizeof(off_t) <= 4) {
250- if (offset != (os_offset_t) offs) {
251- ib_logf(IB_LOG_LEVEL_ERROR,
252- "File write at offset > 4 GB.");
253- }
254+ if (sizeof(off_t) <= 4 && offset != (os_offset_t) offs) {
255+ ib_logf(IB_LOG_LEVEL_ERROR, "file write at offset > 4 GB.");
256 }
257
258 os_n_file_writes++;
259
260-#if defined(HAVE_PWRITE) && !defined(HAVE_BROKEN_PREAD)
261-#if !defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8
262- os_mutex_enter(os_file_count_mutex);
263- os_file_n_pending_pwrites++;
264- os_n_pending_writes++;
265- MONITOR_INC(MONITOR_OS_PENDING_WRITES);
266- os_mutex_exit(os_file_count_mutex);
267-#else
268+#ifdef HAVE_ATOMIC_BUILTINS
269 (void) os_atomic_increment_ulint(&os_n_pending_writes, 1);
270 (void) os_atomic_increment_ulint(&os_file_n_pending_pwrites, 1);
271 MONITOR_ATOMIC_INC(MONITOR_OS_PENDING_WRITES);
272-#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD < 8 */
273-
274- ret = pwrite(file, buf, (ssize_t) n, offs);
275-
276-#if !defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8
277- os_mutex_enter(os_file_count_mutex);
278- os_file_n_pending_pwrites--;
279- os_n_pending_writes--;
280- MONITOR_DEC(MONITOR_OS_PENDING_WRITES);
281- os_mutex_exit(os_file_count_mutex);
282 #else
283+ mutex_enter(&os_file_count_mutex);
284+ os_file_n_pending_pwrites++;
285+ os_n_pending_writes++;
286+ MONITOR_INC(MONITOR_OS_PENDING_WRITES);
287+ mutex_exit(&os_file_count_mutex);
288+#endif /* HAVE_ATOMIC_BUILTINS */
289+
290+ written_bytes = os_file_io(
291+ file, (void*) buf, n, offs, OS_FILE_WRITE);
292+
293+#ifdef HAVE_ATOMIC_BUILTINS
294 (void) os_atomic_decrement_ulint(&os_n_pending_writes, 1);
295 (void) os_atomic_decrement_ulint(&os_file_n_pending_pwrites, 1);
296 MONITOR_ATOMIC_DEC(MONITOR_OS_PENDING_WRITES);
297-#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD < 8 */
298-
299- return(ret);
300 #else
301- {
302- off_t ret_offset;
303-# ifndef UNIV_HOTBACKUP
304- ulint i;
305-# endif /* !UNIV_HOTBACKUP */
306-
307- os_mutex_enter(os_file_count_mutex);
308- os_n_pending_writes++;
309- MONITOR_INC(MONITOR_OS_PENDING_WRITES);
310- os_mutex_exit(os_file_count_mutex);
311-
312-# ifndef UNIV_HOTBACKUP
313- /* Protect the seek / write operation with a mutex */
314- i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
315-
316- os_mutex_enter(os_file_seek_mutexes[i]);
317-# endif /* UNIV_HOTBACKUP */
318-
319- ret_offset = lseek(file, offs, SEEK_SET);
320-
321- if (ret_offset < 0) {
322- ret = -1;
323-
324- goto func_exit;
325- }
326-
327- ret = write(file, buf, (ssize_t) n);
328-
329-func_exit:
330-# ifndef UNIV_HOTBACKUP
331- os_mutex_exit(os_file_seek_mutexes[i]);
332-# endif /* !UNIV_HOTBACKUP */
333-
334- os_mutex_enter(os_file_count_mutex);
335- os_n_pending_writes--;
336- MONITOR_DEC(MONITOR_OS_PENDING_WRITES);
337- os_mutex_exit(os_file_count_mutex);
338-
339- return(ret);
340- }
341-#endif /* !UNIV_HOTBACKUP */
342+ mutex_enter(&os_file_count_mutex);
343+ os_file_n_pending_pwrites--;
344+ os_n_pending_writes--;
345+ MONITOR_DEC(MONITOR_OS_PENDING_WRITES);
346+ mutex_exit(&os_file_count_mutex);
347+#endif /* HAVE_ATOMIC_BUILTINS */
348+
349+ return(written_bytes);
350 }
351 #endif
352
353@@ -2659,6 +2625,13 @@
354 retry = os_file_handle_error(NULL, "read");
355
356 if (retry) {
357+#ifndef _WIN32
358+ if (ret > 0 && (ulint) ret < n) {
359+ buf = (uchar*) buf + (ulint) ret;
360+ offset += (ulint) ret;
361+ n -= (ulint) ret;
362+ }
363+#endif
364 goto try_again;
365 }
366
367@@ -2782,6 +2755,13 @@
368 retry = os_file_handle_error_no_exit(NULL, "read", FALSE);
369
370 if (retry) {
371+#ifndef _WIN32
372+ if (ret > 0 && (ulint) ret < n) {
373+ buf = (uchar*) buf + (ulint) ret;
374+ offset += ret;
375+ n -= (ulint) ret;
376+ }
377+#endif /* _WIN32 */
378 goto try_again;
379 }
380
381@@ -5047,6 +5027,7 @@
382 segment = os_aio_get_array_and_local_segment(&array, global_seg);
383 n = array->n_slots / array->n_segments;
384
385+wait_for_event:
386 /* Loop until we have found a completed request. */
387 for (;;) {
388 ibool any_reserved = FALSE;
389@@ -5108,6 +5089,41 @@
390 if (slot->ret == 0 && slot->n_bytes == (long) slot->len) {
391
392 ret = TRUE;
393+ } else if ((slot->ret == 0) && (slot->n_bytes > 0)
394+ && (slot->n_bytes < (long) slot->len)) {
395+ /* Partial read or write scenario */
396+ int submit_ret;
397+ struct iocb* iocb;
398+ slot->buf = (byte*)slot->buf + slot->n_bytes;
399+ slot->offset = slot->offset + slot->n_bytes;
400+ slot->len = slot->len - slot->n_bytes;
401+ /* Resetting the bytes read/written */
402+ slot->n_bytes = 0;
403+ slot->io_already_done = false;
404+ iocb = &(slot->control);
405+
406+ if (slot->type == OS_FILE_READ) {
407+ io_prep_pread(&slot->control, slot->file, slot->buf,
408+ slot->len, (off_t) slot->offset);
409+ } else {
410+ ut_a(slot->type == OS_FILE_WRITE);
411+ io_prep_pwrite(&slot->control, slot->file, slot->buf,
412+ slot->len, (off_t) slot->offset);
413+ }
414+ /* Resubmit an I/O request */
415+ submit_ret = io_submit(array->aio_ctx[segment], 1, &iocb);
416+ if (submit_ret < 0 ) {
417+ /* Aborting in case of submit failure */
418+ ib_logf(IB_LOG_LEVEL_FATAL,
419+ "Native Linux AIO interface. io_submit()"
420+ " call failed when resubmitting a partial"
421+ " I/O request on the file %s.",
422+ slot->name);
423+ } else {
424+ ret = false;
425+ os_mutex_exit(array->mutex);
426+ goto wait_for_event;
427+ }
428 } else {
429 errno = -slot->ret;
430

Subscribers

People subscribed via source and target branches