~percona-dev/percona-server/bug693818

102.1.1 by kinoyasu
add header and rule, as the first step of the reordering patch for separate release
1
# name       : innodb_buffer_pool_shm.patch
2
# introduced : 12
3
# maintainer : Yasufumi
4
#
5
#!!! notice !!!
6
# Any small change to this file in the main branch
7
# should be done or reviewed by the maintainer!
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
8
diff -ruN a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c
9
--- a/storage/innodb_plugin/buf/buf0buf.c	2010-07-14 16:32:49.669501663 +0900
10
+++ b/storage/innodb_plugin/buf/buf0buf.c	2010-07-14 16:40:16.149438645 +0900
71 by kinoyasu
adjust innodb_buffer_pool_shm.patch to be built with UNIV_DEBUG definition
11
@@ -53,6 +53,10 @@
12
 #include "page0zip.h"
13
 #include "trx0trx.h"
14
 #include "srv0start.h"
15
+#include "que0que.h"
16
+#include "read0read.h"
17
+#include "row0row.h"
18
+#include "ha_prototypes.h"
19
 
20
 /* prototypes for new functions added to ha_innodb.cc */
21
 trx_t* innobase_get_trx();
22
@@ -310,6 +314,30 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
23
 UNIV_INTERN ibool		buf_debug_prints = FALSE;
24
 #endif /* UNIV_DEBUG */
25
 
26
+/* Buffer pool shared memory segment information */
27
+typedef	struct buf_shm_info_struct	buf_shm_info_t;
28
+
29
+struct buf_shm_info_struct {
30
+	char	head_str[8];
31
+	ulint	binary_id;
32
+	ibool	is_new;		/* during initializing */
33
+	ibool	clean;		/* clean shutdowned and free */
34
+	ibool	reusable;	/* reusable */
35
+	ulint	buf_pool_size;	/* backup value */
36
+	ulint	page_size;	/* backup value */
37
+	ulint	frame_offset;	/* offset of the first frame based on chunk->mem */
38
+	ulint	zip_hash_offset;
39
+	ulint	zip_hash_n;
40
+
41
+	ulint	checksum;
42
+
43
+	buf_pool_t	buf_pool_backup;
44
+	buf_chunk_t	chunk_backup;
45
+
46
+	ib_uint64_t	dummy;
47
+};
48
+
49
+#define BUF_SHM_INFO_HEAD "XTRA_SHM"
50
 #endif /* !UNIV_HOTBACKUP */
51
 
52
 /********************************************************************//**
71 by kinoyasu
adjust innodb_buffer_pool_shm.patch to be built with UNIV_DEBUG definition
53
@@ -756,6 +784,45 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
54
 #endif /* UNIV_SYNC_DEBUG */
55
 }
56
 
57
+static
58
+void
59
+buf_block_reuse(
60
+/*============*/
61
+	buf_block_t*	block,
62
+	ptrdiff_t	frame_offset)
63
+{
64
+	/* block_init */
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
65
+	block->frame += frame_offset;
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
66
+
67
+	UNIV_MEM_DESC(block->frame, UNIV_PAGE_SIZE, block);
68
+
69
+	block->index = NULL;
70
+
71
+#ifdef UNIV_DEBUG
72
+	/* recreate later */
73
+	block->page.in_page_hash = FALSE;
74
+	block->page.in_zip_hash = FALSE;
75
+#endif /* UNIV_DEBUG */
76
+
77
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
78
+	block->n_pointers = 0;
79
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
80
+
81
+	if (block->page.zip.data)
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
82
+		block->page.zip.data += frame_offset;
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
83
+
84
+	block->is_hashed = FALSE;
85
+
86
+	mutex_create(&block->mutex, SYNC_BUF_BLOCK);
87
+
88
+	rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
89
+	ut_ad(rw_lock_validate(&(block->lock)));
90
+
91
+#ifdef UNIV_SYNC_DEBUG
92
+	rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
93
+#endif /* UNIV_SYNC_DEBUG */
94
+}
95
+
96
 /********************************************************************//**
97
 Allocates a chunk of buffer frames.
98
 @return	chunk, or NULL on failure */
124.1.1 by kinoyasu
fix bug649408
99
@@ -768,26 +835,188 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
100
 {
101
 	buf_block_t*	block;
102
 	byte*		frame;
103
+	ulint		zip_hash_n = 0;
104
+	ulint		zip_hash_mem_size = 0;
83.2.3 by kinoyasu
adjust not to cause warnings with -Wall
105
+	hash_table_t*	zip_hash_tmp = NULL;
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
106
 	ulint		i;
107
+	buf_shm_info_t*	shm_info = NULL;
108
 
109
 	/* Round down to a multiple of page size,
110
 	although it already should be. */
111
 	mem_size = ut_2pow_round(mem_size, UNIV_PAGE_SIZE);
112
+
124.1.1 by kinoyasu
fix bug649408
113
+	srv_buffer_pool_shm_is_reused = FALSE;
114
+
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
115
+	if (srv_buffer_pool_shm_key) {
116
+		/* zip_hash size */
117
+		zip_hash_n = (mem_size / UNIV_PAGE_SIZE) * 2;
118
+		zip_hash_mem_size = ut_2pow_round(hash_create_needed(zip_hash_n)
119
+						  + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
120
+	}
121
+
122
 	/* Reserve space for the block descriptors. */
123
 	mem_size += ut_2pow_round((mem_size / UNIV_PAGE_SIZE) * (sizeof *block)
124
 				  + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
125
+	if (srv_buffer_pool_shm_key) {
126
+		 mem_size += ut_2pow_round(sizeof(buf_shm_info_t)
127
+					   + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
128
+		 mem_size += zip_hash_mem_size;
129
+	}
130
 
131
 	chunk->mem_size = mem_size;
132
+
133
+	if (srv_buffer_pool_shm_key) {
134
+		ulint	binary_id;
135
+		ibool	is_new;
136
+
137
+		ut_a(buf_pool->n_chunks == 1);
138
+
139
+		fprintf(stderr,
108.2.1 by Vadim Tkachenko
Fix error messages for buffer pool in shm
140
+		"InnoDB: Warning: The innodb_buffer_pool_shm_key option has been specified.\n"
141
+		"InnoDB: Do not change the following between restarts of the server while this option is being used:\n"
142
+		"InnoDB:   * the mysqld executable between restarts of the server.\n"
112 by Vadim Tkachenko
fix mistyping
143
+		"InnoDB:   * the value of innodb_buffer_pool_size.\n"
144
+		"InnoDB:   * the value of innodb_page_size.\n"
145
+		"InnoDB:   * datafiles created by InnoDB during this session.\n"
108.2.1 by Vadim Tkachenko
Fix error messages for buffer pool in shm
146
+		"InnoDB: Otherwise, data corruption in datafiles may result.\n");
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
147
+
148
+		/* FIXME: This is vague id still */
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
149
+		binary_id = (ulint) ((byte*)mtr_commit - (byte*)btr_root_get)
150
+			  + (ulint) ((byte*)os_get_os_version - (byte*)buf_calc_page_new_checksum)
151
+			  + (ulint) ((byte*)page_dir_find_owner_slot - (byte*)dfield_data_is_binary_equal)
152
+			  + (ulint) ((byte*)que_graph_publish - (byte*)dict_casedn_str)
153
+			  + (ulint) ((byte*)read_view_oldest_copy_or_open_new - (byte*)fil_space_get_version)
154
+			  + (ulint) ((byte*)rec_get_n_extern_new - (byte*)fsp_get_size_low)
155
+			  + (ulint) ((byte*)row_get_trx_id_offset - (byte*)ha_create_func)
156
+			  + (ulint) ((byte*)srv_set_io_thread_op_info - (byte*)thd_is_replication_slave_thread)
157
+			  + (ulint) ((byte*)mutex_create_func - (byte*)ibuf_inside)
158
+			  + (ulint) ((byte*)trx_set_detailed_error - (byte*)lock_check_trx_id_sanity)
159
+			  + (ulint) ((byte*)ut_time - (byte*)mem_heap_strdup);
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
160
+
161
+		chunk->mem = os_shm_alloc(&chunk->mem_size, srv_buffer_pool_shm_key, &is_new);
162
+
163
+		if (UNIV_UNLIKELY(chunk->mem == NULL)) {
164
+			return(NULL);
165
+		}
119.1.1 by kinoyasu
- New static bool option innodb_buffer_pool_shm_checksum for bug643650
166
+init_again:
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
167
+#ifdef UNIV_SET_MEM_TO_ZERO
168
+		if (is_new) {
169
+			memset(chunk->mem, '\0', chunk->mem_size);
170
+		}
171
+#endif
117.1.1 by kinoyasu
fix bug643650: change to use ut_fold_binary_32 for checksum
172
+		/* for ut_fold_binary_32(), these values should be 32-bit aligned */
173
+		ut_a(sizeof(buf_shm_info_t) % 4 == 0);
174
+		ut_a((ulint)chunk->mem % 4 == 0);
175
+		ut_a(chunk->mem_size % 4 == 0);
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
176
+
177
+		shm_info = chunk->mem;
178
+
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
179
+		zip_hash_tmp = (hash_table_t*)((byte*)chunk->mem + chunk->mem_size - zip_hash_mem_size);
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
180
+
181
+		if (is_new) {
182
+			strncpy(shm_info->head_str, BUF_SHM_INFO_HEAD, 8);
183
+			shm_info->binary_id = binary_id;
184
+			shm_info->is_new = TRUE;	/* changed to FALSE when the initialization is finished */
185
+			shm_info->clean = FALSE;	/* changed to TRUE when free the segment. */
186
+			shm_info->reusable = FALSE;	/* changed to TRUE when validation is finished. */
187
+			shm_info->buf_pool_size = srv_buf_pool_size;
188
+			shm_info->page_size = srv_page_size;
189
+			shm_info->zip_hash_offset = chunk->mem_size - zip_hash_mem_size;
190
+			shm_info->zip_hash_n = zip_hash_n;
191
+		} else {
192
+			ulint	checksum;
193
+
194
+			if (strncmp(shm_info->head_str, BUF_SHM_INFO_HEAD, 8)) {
195
+				fprintf(stderr,
196
+				"InnoDB: Error: The shared memory segment seems not to be for buffer pool.\n");
197
+				return(NULL);
198
+			}
199
+			if (shm_info->binary_id != binary_id) {
200
+				fprintf(stderr,
201
+				"InnoDB: Error: The shared memory segment seems not to be for this binary.\n");
202
+				return(NULL);
203
+			}
204
+			if (shm_info->is_new) {
205
+				fprintf(stderr,
206
+				"InnoDB: Error: The shared memory was not initialized yet.\n");
207
+				return(NULL);
208
+			}
209
+			if (shm_info->buf_pool_size != srv_buf_pool_size) {
210
+				fprintf(stderr,
211
+				"InnoDB: Error: srv_buf_pool_size is different (shm=%lu current=%lu).\n",
212
+				shm_info->buf_pool_size, srv_buf_pool_size);
213
+				return(NULL);
214
+			}
215
+			if (shm_info->page_size != srv_page_size) {
216
+				fprintf(stderr,
217
+				"InnoDB: Error: srv_page_size is different (shm=%lu current=%lu).\n",
218
+				shm_info->page_size, srv_page_size);
219
+				return(NULL);
220
+			}
119.1.1 by kinoyasu
- New static bool option innodb_buffer_pool_shm_checksum for bug643650
221
+			if (!shm_info->reusable) {
222
+				fprintf(stderr,
223
+				"InnoDB: Warning: The shared memory has unrecoverable contents.\n"
224
+				"InnoDB: The shared memory segment is initialized.\n");
225
+				is_new = TRUE;
226
+				goto init_again;
227
+			}
228
+			if (!shm_info->clean) {
229
+				fprintf(stderr,
230
+				"InnoDB: Warning: The shared memory was not shut down cleanly.\n"
231
+				"InnoDB: The shared memory segment is initialized.\n");
232
+				is_new = TRUE;
233
+				goto init_again;
234
+			}
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
235
+
236
+			ut_a(shm_info->zip_hash_offset == chunk->mem_size - zip_hash_mem_size);
237
+			ut_a(shm_info->zip_hash_n == zip_hash_n);
238
+
239
+			/* check checksum */
119.1.1 by kinoyasu
- New static bool option innodb_buffer_pool_shm_checksum for bug643650
240
+			if (srv_buffer_pool_shm_checksum) {
241
+				checksum = ut_fold_binary_32((byte*)chunk->mem + sizeof(buf_shm_info_t),
242
+							     chunk->mem_size - sizeof(buf_shm_info_t));
243
+			} else {
244
+				checksum = BUF_NO_CHECKSUM_MAGIC;
245
+			}
246
+
247
+			if (shm_info->checksum != BUF_NO_CHECKSUM_MAGIC
248
+			    && shm_info->checksum != checksum) {
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
249
+				fprintf(stderr,
250
+				"InnoDB: Error: checksum of the shared memory is not match. "
251
+				"(stored=%lu calculated=%lu)\n",
252
+				shm_info->checksum, checksum);
253
+				return(NULL);
254
+			}
255
+
256
+			/* flag to use the segment. */
257
+			shm_info->clean = FALSE;	/* changed to TRUE when free the segment. */
258
+		}
259
+
260
+		/* init zip_hash contents */
261
+		if (is_new) {
262
+			hash_create_init(zip_hash_tmp, zip_hash_n);
263
+		} else {
264
+			/* adjust offset is done later */
265
+			hash_create_reuse(zip_hash_tmp);
124.1.1 by kinoyasu
fix bug649408
266
+
267
+			srv_buffer_pool_shm_is_reused = TRUE;
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
268
+		}
269
+	} else {
270
 	chunk->mem = os_mem_alloc_large(&chunk->mem_size);
271
 
272
 	if (UNIV_UNLIKELY(chunk->mem == NULL)) {
273
 
274
 		return(NULL);
275
 	}
276
+	}
277
 
278
 	/* Allocate the block descriptors from
279
 	the start of the memory block. */
280
+	if (srv_buffer_pool_shm_key) {
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
281
+		chunk->blocks = (buf_block_t*)((byte*)chunk->mem + sizeof(buf_shm_info_t));
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
282
+	} else {
283
 	chunk->blocks = chunk->mem;
284
+	}
285
 
286
 	/* Align a pointer to the first frame.  Note that when
287
 	os_large_page_size is smaller than UNIV_PAGE_SIZE,
124.1.1 by kinoyasu
fix bug649408
288
@@ -795,8 +1024,13 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
289
 	it is bigger, we may allocate more blocks than requested. */
290
 
291
 	frame = ut_align(chunk->mem, UNIV_PAGE_SIZE);
292
+	if (srv_buffer_pool_shm_key) {
293
+		/* reserve zip_hash space and always -1 for reproductibity */
294
+		chunk->size = (chunk->mem_size - zip_hash_mem_size) / UNIV_PAGE_SIZE - 1;
295
+	} else {
296
 	chunk->size = chunk->mem_size / UNIV_PAGE_SIZE
297
 		- (frame != chunk->mem);
298
+	}
299
 
300
 	/* Subtract the space needed for block descriptors. */
301
 	{
124.1.1 by kinoyasu
fix bug649408
302
@@ -810,6 +1044,98 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
303
 		chunk->size = size;
304
 	}
305
 
306
+	if (shm_info && !(shm_info->is_new)) {
307
+		/* convert the shared memory segment for reuse */
308
+		ptrdiff_t	phys_offset;
309
+		ptrdiff_t	logi_offset;
310
+		ptrdiff_t	blocks_offset;
311
+		void*		previous_frame_address;
312
+
313
+		if (chunk->size < shm_info->chunk_backup.size) {
314
+			fprintf(stderr,
315
+			"InnoDB: Error: The buffer pool became smaller because of allocated address.\n"
316
+			"InnoDB: Retrying may avoid this situation.\n");
317
+			shm_info->clean = TRUE; /* release the flag for retrying */
318
+			return(NULL);
319
+		}
320
+
321
+		chunk->size = shm_info->chunk_backup.size;
119.1.1 by kinoyasu
- New static bool option innodb_buffer_pool_shm_checksum for bug643650
322
+		phys_offset = frame - ((byte*)chunk->mem + shm_info->frame_offset);
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
323
+		logi_offset = frame - chunk->blocks[0].frame;
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
324
+		previous_frame_address = chunk->blocks[0].frame;
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
325
+		blocks_offset = (byte*)chunk->blocks - (byte*)shm_info->chunk_backup.blocks;
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
326
+
327
+		if (phys_offset || logi_offset || blocks_offset) {
328
+			fprintf(stderr,
329
+			"InnoDB: Buffer pool in the shared memory segment should be converted.\n"
330
+			"InnoDB: Previous frames in address      : %p\n"
331
+			"InnoDB: Previous frames were located    : %p\n"
332
+			"InnoDB: Current frames should be located: %p\n"
333
+			"InnoDB: Pysical offset                  : %ld (%#lx)\n"
334
+			"InnoDB: Logical offset (frames)         : %ld (%#lx)\n"
335
+			"InnoDB: Logical offset (blocks)         : %ld (%#lx)\n",
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
336
+				(byte*)chunk->mem + shm_info->frame_offset,
337
+				chunk->blocks[0].frame, frame,
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
338
+				phys_offset, phys_offset, logi_offset, logi_offset,
339
+				blocks_offset, blocks_offset);
340
+		} else {
341
+			fprintf(stderr,
342
+			"InnoDB: Buffer pool in the shared memory segment can be used as it is.\n");
343
+		}
344
+
345
+		if (phys_offset) {
346
+			fprintf(stderr,
347
+			"InnoDB: Aligning physical offset...");
348
+
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
349
+			memmove(frame, (byte*)chunk->mem + shm_info->frame_offset,
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
350
+				chunk->size * UNIV_PAGE_SIZE);
351
+
352
+			fprintf(stderr,
353
+			" Done.\n");
354
+		}
355
+
119.1.1 by kinoyasu
- New static bool option innodb_buffer_pool_shm_checksum for bug643650
356
+		/* buf_block_t */
357
+		block = chunk->blocks;
358
+		for (i = chunk->size; i--; ) {
359
+			buf_block_reuse(block, logi_offset);
360
+			block++;
361
+		}
362
+
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
363
+		if (logi_offset || blocks_offset) {
364
+			fprintf(stderr,
365
+			"InnoDB: Aligning logical offset...");
366
+
367
+
368
+			/* buf_pool_t buf_pool_backup */
369
+			UT_LIST_OFFSET(flush_list, buf_page_t, shm_info->buf_pool_backup.flush_list,
370
+					previous_frame_address, logi_offset, blocks_offset);
371
+			UT_LIST_OFFSET(free, buf_page_t, shm_info->buf_pool_backup.free,
372
+					previous_frame_address, logi_offset, blocks_offset);
373
+			UT_LIST_OFFSET(LRU, buf_page_t, shm_info->buf_pool_backup.LRU,
374
+					previous_frame_address, logi_offset, blocks_offset);
375
+			if (shm_info->buf_pool_backup.LRU_old)
376
+				shm_info->buf_pool_backup.LRU_old =
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
377
+					(buf_page_t*)((byte*)(shm_info->buf_pool_backup.LRU_old)
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
378
+						+ (((void*)shm_info->buf_pool_backup.LRU_old > previous_frame_address)
379
+						  ? logi_offset : blocks_offset));
380
+
381
+			UT_LIST_OFFSET(unzip_LRU, buf_block_t, shm_info->buf_pool_backup.unzip_LRU,
382
+					previous_frame_address, logi_offset, blocks_offset);
383
+
384
+			UT_LIST_OFFSET(zip_list, buf_page_t, shm_info->buf_pool_backup.zip_clean,
385
+					previous_frame_address, logi_offset, blocks_offset);
386
+			for (i = 0; i < BUF_BUDDY_SIZES_MAX; i++) {
387
+				UT_LIST_OFFSET(zip_list, buf_page_t, shm_info->buf_pool_backup.zip_free[i],
388
+					previous_frame_address, logi_offset, blocks_offset);
389
+			}
390
+
391
+			HASH_OFFSET(zip_hash_tmp, buf_page_t, hash,
392
+					previous_frame_address, logi_offset, blocks_offset);
393
+
394
+			fprintf(stderr,
395
+			" Done.\n");
396
+		}
397
+	} else {
398
 	/* Init block structs and assign frames for them. Then we
399
 	assign the frames to the first blocks (we already mapped the
400
 	memory above). */
124.1.1 by kinoyasu
fix bug649408
401
@@ -833,6 +1159,11 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
402
 		block++;
403
 		frame += UNIV_PAGE_SIZE;
404
 	}
405
+	}
406
+
407
+	if (shm_info) {
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
408
+		shm_info->frame_offset = chunk->blocks[0].frame - (byte*)chunk->mem;
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
409
+	}
410
 
411
 	return(chunk);
412
 }
124.1.1 by kinoyasu
fix bug649408
413
@@ -1014,6 +1345,8 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
414
 		UNIV_MEM_UNDESC(block);
415
 	}
416
 
417
+	ut_a(!srv_buffer_pool_shm_key);
418
+
419
 	os_mem_free_large(chunk->mem, chunk->mem_size);
420
 }
421
 
124.1.1 by kinoyasu
fix bug649408
422
@@ -1063,7 +1396,10 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
423
 	srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
424
 
425
 	buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
426
+	/* zip_hash is allocated to shm when srv_buffer_pool_shm_key is enabled */
427
+	if (!srv_buffer_pool_shm_key) {
428
 	buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
429
+	}
430
 
431
 	buf_pool->last_printout_time = time(NULL);
432
 
124.1.1 by kinoyasu
fix bug649408
433
@@ -1078,6 +1414,86 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
434
 	--------------------------- */
435
 	/* All fields are initialized by mem_zalloc(). */
436
 
437
+	if (srv_buffer_pool_shm_key) {
438
+		buf_shm_info_t*	shm_info;
439
+
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
440
+		ut_a((byte*)chunk->blocks == (byte*)chunk->mem + sizeof(buf_shm_info_t));
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
441
+		shm_info = chunk->mem;
442
+
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
443
+		buf_pool->zip_hash = (hash_table_t*)((byte*)chunk->mem + shm_info->zip_hash_offset);
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
444
+
445
+		if(shm_info->is_new) {
446
+			shm_info->is_new = FALSE; /* initialization was finished */
447
+		} else {
448
+			buf_block_t*	block = chunk->blocks;
449
+			buf_page_t*	b;
450
+
451
+			/* shm_info->buf_pool_backup should be converted */
452
+			/* at buf_chunk_init(). So copy simply. */
453
+			buf_pool->flush_list 		= shm_info->buf_pool_backup.flush_list;
454
+			buf_pool->freed_page_clock 	= shm_info->buf_pool_backup.freed_page_clock;
455
+			buf_pool->free			= shm_info->buf_pool_backup.free;
456
+			buf_pool->LRU			= shm_info->buf_pool_backup.LRU;
457
+			buf_pool->LRU_old		= shm_info->buf_pool_backup.LRU_old;
458
+			buf_pool->LRU_old_len		= shm_info->buf_pool_backup.LRU_old_len;
459
+			buf_pool->unzip_LRU		= shm_info->buf_pool_backup.unzip_LRU;
460
+			buf_pool->zip_clean		= shm_info->buf_pool_backup.zip_clean;
461
+			for (i = 0; i < BUF_BUDDY_SIZES_MAX; i++) {
462
+				buf_pool->zip_free[i]	= shm_info->buf_pool_backup.zip_free[i];
463
+			}
464
+
465
+			for (i = 0; i < chunk->size; i++, block++) {
466
+				if (buf_block_get_state(block)
467
+				    == BUF_BLOCK_FILE_PAGE) {
468
+					ut_d(block->page.in_page_hash = TRUE);
469
+					HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
470
+						    buf_page_address_fold(
471
+							    block->page.space,
472
+							    block->page.offset),
473
+						    &block->page);
474
+				}
475
+			}
476
+
477
+			for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
478
+			     b = UT_LIST_GET_NEXT(zip_list, b)) {
479
+				ut_ad(!b->in_flush_list);
480
+				ut_ad(b->in_LRU_list);
481
+
482
+				ut_d(b->in_page_hash = TRUE);
483
+				HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
484
+					    buf_page_address_fold(b->space, b->offset), b);
485
+			}
486
+
487
+			for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
488
+			     b = UT_LIST_GET_NEXT(flush_list, b)) {
489
+				ut_ad(b->in_flush_list);
490
+				ut_ad(b->in_LRU_list);
491
+
492
+				switch (buf_page_get_state(b)) {
493
+				case BUF_BLOCK_ZIP_DIRTY:
494
+					ut_d(b->in_page_hash = TRUE);
495
+					HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
496
+						    buf_page_address_fold(b->space,
497
+							    		  b->offset), b);
498
+					break;
499
+				case BUF_BLOCK_FILE_PAGE:
500
+					/* uncompressed page */
501
+					break;
502
+				case BUF_BLOCK_ZIP_FREE:
503
+				case BUF_BLOCK_ZIP_PAGE:
504
+				case BUF_BLOCK_NOT_USED:
505
+				case BUF_BLOCK_READY_FOR_USE:
506
+				case BUF_BLOCK_MEMORY:
507
+				case BUF_BLOCK_REMOVE_HASH:
508
+					ut_error;
509
+					break;
510
+				}
511
+			}
512
+
513
+
514
+		}
515
+	}
516
+
517
 	mutex_exit(&LRU_list_mutex);
518
 	rw_lock_x_unlock(&page_hash_latch);
519
 	buf_pool_mutex_exit();
124.1.1 by kinoyasu
fix bug649408
520
@@ -1102,6 +1518,34 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
521
 	buf_chunk_t*	chunk;
522
 	buf_chunk_t*	chunks;
523
 
524
+	if (srv_buffer_pool_shm_key) {
525
+		buf_shm_info_t*	shm_info;
526
+
527
+		ut_a(buf_pool->n_chunks == 1);
528
+
529
+		chunk = buf_pool->chunks;
530
+		shm_info = chunk->mem;
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
531
+		ut_a((byte*)chunk->blocks == (byte*)chunk->mem + sizeof(buf_shm_info_t));
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
532
+
533
+		/* validation the shared memory segment doesn't have unrecoverable contents. */
534
+		/* Currently, validation became not needed */
535
+		shm_info->reusable = TRUE;
536
+
537
+		memcpy(&(shm_info->buf_pool_backup), buf_pool, sizeof(buf_pool_t));
538
+		memcpy(&(shm_info->chunk_backup), chunk, sizeof(buf_chunk_t));
539
+
540
+		if (srv_fast_shutdown < 2) {
119.1.1 by kinoyasu
- New static bool option innodb_buffer_pool_shm_checksum for bug643650
541
+			if (srv_buffer_pool_shm_checksum) {
542
+				shm_info->checksum = ut_fold_binary_32((byte*)chunk->mem + sizeof(buf_shm_info_t),
543
+								       chunk->mem_size - sizeof(buf_shm_info_t));
544
+			} else {
545
+				shm_info->checksum = BUF_NO_CHECKSUM_MAGIC;
546
+			}
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
547
+			shm_info->clean = TRUE;
548
+		}
549
+
550
+		os_shm_free(chunk->mem, chunk->mem_size);
551
+	} else {
552
 	chunks = buf_pool->chunks;
553
 	chunk = chunks + buf_pool->n_chunks;
554
 
124.1.1 by kinoyasu
fix bug649408
555
@@ -1110,10 +1554,13 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
556
 		would fail at shutdown. */
557
 		os_mem_free_large(chunk->mem, chunk->mem_size);
558
 	}
559
+	}
560
 
561
 	mem_free(buf_pool->chunks);
562
 	hash_table_free(buf_pool->page_hash);
563
+	if (!srv_buffer_pool_shm_key) {
564
 	hash_table_free(buf_pool->zip_hash);
565
+	}
566
 	mem_free(buf_pool);
567
 	buf_pool = NULL;
568
 }
124.1.1 by kinoyasu
fix bug649408
569
@@ -1308,6 +1755,11 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
570
 	//buf_pool_mutex_enter();
571
 	mutex_enter(&LRU_list_mutex);
572
 
573
+	if (srv_buffer_pool_shm_key) {
574
+		/* Cannot support shrink */
575
+		goto func_done;
576
+	}
577
+
578
 shrink_again:
579
 	if (buf_pool->n_chunks <= 1) {
580
 
124.1.1 by kinoyasu
fix bug649408
581
@@ -1551,6 +2003,11 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
582
 buf_pool_resize(void)
583
 /*=================*/
584
 {
585
+	if (srv_buffer_pool_shm_key) {
586
+		/* Cannot support resize */
587
+		return;
588
+	}
589
+
590
 	//buf_pool_mutex_enter();
591
 	mutex_enter(&LRU_list_mutex);
592
 
593
diff -ruN a/storage/innodb_plugin/ha/hash0hash.c b/storage/innodb_plugin/ha/hash0hash.c
594
--- a/storage/innodb_plugin/ha/hash0hash.c	2010-06-04 00:49:59.000000000 +0900
595
+++ b/storage/innodb_plugin/ha/hash0hash.c	2010-07-14 16:40:16.150438366 +0900
596
@@ -128,6 +128,70 @@
597
 }
598
 
599
 /*************************************************************//**
600
+*/
601
+UNIV_INTERN
602
+ulint
603
+hash_create_needed(
604
+/*===============*/
605
+	ulint	n)
606
+{
607
+	ulint	prime;
608
+	ulint	offset;
609
+
610
+	prime = ut_find_prime(n);
611
+
612
+	offset = (sizeof(hash_table_t) + 7) / 8;
613
+	offset *= 8;
614
+
615
+	return(offset + sizeof(hash_cell_t) * prime);
616
+}
617
+
618
+UNIV_INTERN
619
+void
620
+hash_create_init(
621
+/*=============*/
622
+	hash_table_t*	table,
623
+	ulint		n)
624
+{
625
+	ulint	prime;
626
+	ulint	offset;
627
+
628
+	prime = ut_find_prime(n);
629
+
630
+	offset = (sizeof(hash_table_t) + 7) / 8;
631
+	offset *= 8;
632
+
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
633
+	table->array = (hash_cell_t*)(((byte*)table) + offset);
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
634
+	table->n_cells = prime;
635
+# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
636
+	table->adaptive = FALSE;
637
+# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
638
+	table->n_mutexes = 0;
639
+	table->mutexes = NULL;
640
+	table->heaps = NULL;
641
+	table->heap = NULL;
642
+	ut_d(table->magic_n = HASH_TABLE_MAGIC_N);
643
+
644
+	/* Initialize the cell array */
645
+	hash_table_clear(table);
646
+}
647
+
648
+UNIV_INTERN
649
+void
650
+hash_create_reuse(
651
+/*==============*/
652
+	hash_table_t*	table)
653
+{
654
+	ulint	offset;
655
+
656
+	offset = (sizeof(hash_table_t) + 7) / 8;
657
+	offset *= 8;
658
+
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
659
+	table->array = (hash_cell_t*)(((byte*)table) + offset);
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
660
+	ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
661
+}
662
+
663
+/*************************************************************//**
664
 Frees a hash table. */
665
 UNIV_INTERN
666
 void
667
diff -ruN a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
668
--- a/storage/innodb_plugin/handler/ha_innodb.cc	2010-07-14 16:34:18.597725479 +0900
669
+++ b/storage/innodb_plugin/handler/ha_innodb.cc	2010-07-14 16:40:16.159323612 +0900
166.3.1 by kinoyasu
backport adaptive_checkpoint=keep_average and innodb_log_block_size from XtraDB on 5.5.7 dev-branch
670
@@ -198,6 +198,7 @@
119.1.1 by kinoyasu
- New static bool option innodb_buffer_pool_shm_checksum for bug643650
671
 static my_bool	innobase_create_status_file		= FALSE;
672
 static my_bool	innobase_stats_on_metadata		= TRUE;
673
 static my_bool	innobase_use_sys_stats_table		= FALSE;
674
+static my_bool	innobase_buffer_pool_shm_checksum	= TRUE;
675
 
676
 static char*	internal_innobase_data_file_path	= NULL;
677
 
166.3.1 by kinoyasu
backport adaptive_checkpoint=keep_average and innodb_log_block_size from XtraDB on 5.5.7 dev-branch
678
@@ -2457,6 +2458,7 @@
119.1.1 by kinoyasu
- New static bool option innodb_buffer_pool_shm_checksum for bug643650
679
 	srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
680
 	srv_use_checksums = (ibool) innobase_use_checksums;
681
 	srv_fast_checksum = (ibool) innobase_fast_checksum;
682
+	srv_buffer_pool_shm_checksum = (ibool) innobase_buffer_pool_shm_checksum;
683
 
684
 #ifdef HAVE_LARGE_PAGES
685
         if ((os_use_large_pages = (ibool) my_use_large_pages))
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
686
@@ -11405,6 +11407,16 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
687
   "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
77 by kinoyasu
port and adjust the part of the patches to 5.1.49: But query_cache_with_comments.patch, response-time-distribution.patch, mysql_remove_eol_carret.patch, log_connection_error.patch, status_wait_query_cache_mutex.patch and sql_no_fcache.patch were not ported yet. Please port them.
688
   NULL, NULL, 128*1024*1024L, 32*1024*1024L, LONGLONG_MAX, 1024*1024L);
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
689
 
690
+static MYSQL_SYSVAR_UINT(buffer_pool_shm_key, srv_buffer_pool_shm_key,
691
+  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
108.2.1 by Vadim Tkachenko
Fix error messages for buffer pool in shm
692
+  "[experimental] The key value of shared memory segment for the buffer pool. 0 (default) disables the feature.",
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
693
+  NULL, NULL, 0, 0, INT_MAX32, 0);
694
+
119.1.1 by kinoyasu
- New static bool option innodb_buffer_pool_shm_checksum for bug643650
695
+static MYSQL_SYSVAR_BOOL(buffer_pool_shm_checksum, innobase_buffer_pool_shm_checksum,
696
+  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
697
+  "Enable buffer_pool_shm checksum validation (enabled by default).",
698
+  NULL, NULL, TRUE);
699
+
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
700
 static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
701
   PLUGIN_VAR_RQCMDARG,
702
   "Helps in performance tuning in heavily concurrent environments.",
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
703
@@ -11680,6 +11692,8 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
704
   MYSQL_SYSVAR(additional_mem_pool_size),
705
   MYSQL_SYSVAR(autoextend_increment),
706
   MYSQL_SYSVAR(buffer_pool_size),
707
+  MYSQL_SYSVAR(buffer_pool_shm_key),
119.1.1 by kinoyasu
- New static bool option innodb_buffer_pool_shm_checksum for bug643650
708
+  MYSQL_SYSVAR(buffer_pool_shm_checksum),
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
709
   MYSQL_SYSVAR(checksums),
710
   MYSQL_SYSVAR(fast_checksum),
711
   MYSQL_SYSVAR(commit_concurrency),
712
diff -ruN a/storage/innodb_plugin/handler/innodb_patch_info.h b/storage/innodb_plugin/handler/innodb_patch_info.h
713
--- a/storage/innodb_plugin/handler/innodb_patch_info.h	2010-07-14 16:34:18.603733950 +0900
714
+++ b/storage/innodb_plugin/handler/innodb_patch_info.h	2010-07-14 16:40:16.164323927 +0900
715
@@ -47,5 +47,6 @@
716
 {"innodb_fast_checksum","Using the checksum on 32bit-unit calculation","incompatible for unpatched ver.","http://www.percona.com/docs/wiki/percona-xtradb"},
717
 {"innodb_files_extend","allow >4GB transaction log files, and can vary universal page size of datafiles","incompatible for unpatched ver.","http://www.percona.com/docs/wiki/percona-xtradb"},
718
 {"innodb_sys_tables_sys_indexes","Expose InnoDB SYS_TABLES and SYS_INDEXES schema tables","","http://www.percona.com/docs/wiki/percona-xtradb"},
719
+{"innodb_buffer_pool_shm","Put buffer pool contents to shared memory segment and reuse it at clean restart [experimental]","","http://www.percona.com/docs/wiki/percona-xtradb"},
720
 {NULL, NULL, NULL, NULL}
721
 };
722
diff -ruN a/storage/innodb_plugin/include/buf0buf.h b/storage/innodb_plugin/include/buf0buf.h
723
--- a/storage/innodb_plugin/include/buf0buf.h	2010-07-14 16:33:23.823323393 +0900
724
+++ b/storage/innodb_plugin/include/buf0buf.h	2010-07-14 16:40:16.166323436 +0900
71 by kinoyasu
adjust innodb_buffer_pool_shm.patch to be built with UNIV_DEBUG definition
725
@@ -36,6 +36,7 @@
726
 #include "ut0rbt.h"
727
 #ifndef UNIV_HOTBACKUP
728
 #include "os0proc.h"
729
+#include "srv0srv.h"
730
 
731
 /** @name Modes for buf_page_get_gen */
732
 /* @{ */
733
@@ -1301,7 +1302,10 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
734
 /**********************************************************************//**
735
 Compute the hash fold value for blocks in buf_pool->zip_hash. */
736
 /* @{ */
737
-#define BUF_POOL_ZIP_FOLD_PTR(ptr) ((ulint) (ptr) / UNIV_PAGE_SIZE)
738
+/* the fold should be relative when srv_buffer_pool_shm_key is enabled */
739
+#define BUF_POOL_ZIP_FOLD_PTR(ptr) (!srv_buffer_pool_shm_key\
740
+					?((ulint) (ptr) / UNIV_PAGE_SIZE)\
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
741
+					:((ulint) ((byte*)ptr - (byte*)(buf_pool->chunks->blocks->frame)) / UNIV_PAGE_SIZE))
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
742
 #define BUF_POOL_ZIP_FOLD(b) BUF_POOL_ZIP_FOLD_PTR((b)->frame)
743
 #define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b))
744
 /* @} */
745
diff -ruN a/storage/innodb_plugin/include/hash0hash.h b/storage/innodb_plugin/include/hash0hash.h
746
--- a/storage/innodb_plugin/include/hash0hash.h	2010-06-04 00:49:59.000000000 +0900
747
+++ b/storage/innodb_plugin/include/hash0hash.h	2010-07-14 16:40:16.168323262 +0900
748
@@ -49,6 +49,28 @@
749
 hash_create(
750
 /*========*/
751
 	ulint	n);	/*!< in: number of array cells */
752
+
753
+/*************************************************************//**
754
+*/
755
+UNIV_INTERN
756
+ulint
757
+hash_create_needed(
758
+/*===============*/
759
+	ulint	n);
760
+
761
+UNIV_INTERN
762
+void
763
+hash_create_init(
764
+/*=============*/
765
+	hash_table_t*	table,
766
+	ulint		n);
767
+
768
+UNIV_INTERN
769
+void
770
+hash_create_reuse(
771
+/*==============*/
772
+	hash_table_t*	table);
773
+
774
 #ifndef UNIV_HOTBACKUP
775
 /*************************************************************//**
776
 Creates a mutex array to protect a hash table. */
777
@@ -327,6 +349,33 @@
778
 		}\
779
 	}\
780
 } while (0)
781
+
782
+/********************************************************************//**
783
+Align nodes with moving location.*/
784
+#define HASH_OFFSET(TABLE, NODE_TYPE, PTR_NAME, FADDR, FOFFSET, BOFFSET) \
785
+do {\
786
+	ulint		i2222;\
787
+	ulint		cell_count2222;\
788
+\
789
+	cell_count2222 = hash_get_n_cells(TABLE);\
790
+\
791
+	for (i2222 = 0; i2222 < cell_count2222; i2222++) {\
792
+		NODE_TYPE*	node2222;\
793
+\
794
+		if ((TABLE)->array[i2222].node) \
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
795
+			(TABLE)->array[i2222].node = (void*)((byte*)(TABLE)->array[i2222].node \
796
+			+ (((TABLE)->array[i2222].node > (void*)FADDR)?FOFFSET:BOFFSET));\
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
797
+		node2222 = HASH_GET_FIRST((TABLE), i2222);\
798
+\
799
+		while (node2222) {\
800
+			if (node2222->PTR_NAME) \
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
801
+				node2222->PTR_NAME = (void*)((byte*)(node2222->PTR_NAME) \
802
+				+ ((((void*)node2222->PTR_NAME) > (void*)FADDR)?FOFFSET:BOFFSET));\
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
803
+\
804
+			node2222 = node2222->PTR_NAME;\
805
+		}\
806
+	}\
807
+} while (0)
808
 
809
 /************************************************************//**
810
 Gets the mutex index for a fold value in a hash table.
811
diff -ruN a/storage/innodb_plugin/include/os0proc.h b/storage/innodb_plugin/include/os0proc.h
812
--- a/storage/innodb_plugin/include/os0proc.h	2010-06-04 00:49:59.000000000 +0900
813
+++ b/storage/innodb_plugin/include/os0proc.h	2010-07-14 16:40:16.169321536 +0900
814
@@ -32,6 +32,11 @@
815
 #ifdef UNIV_LINUX
816
 #include <sys/ipc.h>
817
 #include <sys/shm.h>
818
+#else
819
+# if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H
820
+#include <sys/ipc.h>
821
+#include <sys/shm.h>
822
+# endif
823
 #endif
824
 
825
 typedef void*			os_process_t;
826
@@ -70,6 +75,29 @@
827
 	ulint	size);			/*!< in: size returned by
828
 					os_mem_alloc_large() */
829
 
830
+
831
+/****************************************************************//**
832
+Allocates or attaches and reuses shared memory segment.
833
+The content is not cleared automatically.
834
+@return	allocated memory */
835
+UNIV_INTERN
836
+void*
837
+os_shm_alloc(
838
+/*=========*/
839
+	ulint*	n,			/*!< in/out: number of bytes */
840
+	uint	key,
841
+	ibool*	is_new);
842
+
843
+/****************************************************************//**
844
+Detach shared memory segment. */
845
+UNIV_INTERN
846
+void
847
+os_shm_free(
848
+/*========*/
849
+	void	*ptr,			/*!< in: pointer returned by
850
+					os_shm_alloc() */
851
+	ulint	size);			/*!< in: size returned by
852
+					os_shm_alloc() */
853
 #ifndef UNIV_NONINL
854
 #include "os0proc.ic"
855
 #endif
856
diff -ruN a/storage/innodb_plugin/include/srv0srv.h b/storage/innodb_plugin/include/srv0srv.h
857
--- a/storage/innodb_plugin/include/srv0srv.h	2010-07-14 16:32:49.695323045 +0900
858
+++ b/storage/innodb_plugin/include/srv0srv.h	2010-07-14 16:40:16.171325784 +0900
124.1.1 by kinoyasu
fix bug649408
859
@@ -156,6 +156,10 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
860
 extern ulint	srv_mem_pool_size;
861
 extern ulint	srv_lock_table_size;
862
 
863
+extern uint	srv_buffer_pool_shm_key;
124.1.1 by kinoyasu
fix bug649408
864
+extern ibool	srv_buffer_pool_shm_is_reused;
119.1.1 by kinoyasu
- New static bool option innodb_buffer_pool_shm_checksum for bug643650
865
+extern ibool	srv_buffer_pool_shm_checksum;
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
866
+
867
 extern ibool	srv_thread_concurrency_timer_based;
868
 
869
 extern ulint	srv_n_file_io_threads;
870
diff -ruN a/storage/innodb_plugin/include/ut0lst.h b/storage/innodb_plugin/include/ut0lst.h
871
--- a/storage/innodb_plugin/include/ut0lst.h	2010-06-04 00:49:59.000000000 +0900
872
+++ b/storage/innodb_plugin/include/ut0lst.h	2010-07-14 16:40:16.172321547 +0900
873
@@ -257,5 +257,48 @@
874
 	ut_a(ut_list_node_313 == NULL);					\
875
 } while (0)
876
 
877
+/********************************************************************//**
878
+Align nodes with moving location.
879
+@param NAME		the name of the list
880
+@param TYPE		node type
881
+@param BASE		base node (not a pointer to it)
882
+@param OFFSET		offset moved */
883
+#define UT_LIST_OFFSET(NAME, TYPE, BASE, FADDR, FOFFSET, BOFFSET)	\
884
+do {									\
885
+	ulint	ut_list_i_313;						\
886
+	TYPE*	ut_list_node_313;					\
887
+									\
888
+	if ((BASE).start)						\
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
889
+		(BASE).start = (void*)((byte*)((BASE).start)			\
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
890
+			+ (((void*)((BASE).start) > (void*)FADDR)?FOFFSET:BOFFSET));\
891
+	if ((BASE).end)							\
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
892
+		(BASE).end   = (void*)((byte*)((BASE).end)			\
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
893
+			+ (((void*)((BASE).end) > (void*)FADDR)?FOFFSET:BOFFSET));\
894
+									\
895
+	ut_list_node_313 = (BASE).start;				\
896
+									\
897
+	for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) {		\
898
+		ut_a(ut_list_node_313);					\
899
+		if ((ut_list_node_313->NAME).prev)			\
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
900
+			(ut_list_node_313->NAME).prev = (void*)((byte*)((ut_list_node_313->NAME).prev)\
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
901
+				+ (((void*)((ut_list_node_313->NAME).prev) > (void*)FADDR)?FOFFSET:BOFFSET));\
902
+		if ((ut_list_node_313->NAME).next)			\
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
903
+			(ut_list_node_313->NAME).next =	(void*)((byte*)((ut_list_node_313->NAME).next)\
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
904
+				+ (((void*)((ut_list_node_313->NAME).next)> (void*)FADDR)?FOFFSET:BOFFSET));\
905
+		ut_list_node_313 = (ut_list_node_313->NAME).next;	\
906
+	}								\
907
+									\
908
+	ut_a(ut_list_node_313 == NULL);					\
909
+									\
910
+	ut_list_node_313 = (BASE).end;					\
911
+									\
912
+	for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) {		\
913
+		ut_a(ut_list_node_313);					\
914
+		ut_list_node_313 = (ut_list_node_313->NAME).prev;	\
915
+	}								\
916
+									\
917
+	ut_a(ut_list_node_313 == NULL);					\
918
+} while (0)
919
+
920
 #endif
921
 
124.1.1 by kinoyasu
fix bug649408
922
diff -ruN a/storage/innodb_plugin/log/log0recv.c b/storage/innodb_plugin/log/log0recv.c
923
--- a/storage/innodb_plugin/log/log0recv.c	2010-10-01 15:25:27.106299166 +0900
924
+++ b/storage/innodb_plugin/log/log0recv.c	2010-10-01 15:26:33.689261436 +0900
133 by kinoyasu
port maintainer-Yasufumi patches for 5.1.52
925
@@ -2899,6 +2899,7 @@
124.1.1 by kinoyasu
fix bug649408
926
 /*==========================*/
927
 {
928
 	ut_a(!recv_needed_recovery);
929
+	ut_a(!srv_buffer_pool_shm_is_reused);
930
 
931
 	recv_needed_recovery = TRUE;
932
 
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
933
diff -ruN a/storage/innodb_plugin/os/os0proc.c b/storage/innodb_plugin/os/os0proc.c
934
--- a/storage/innodb_plugin/os/os0proc.c	2010-06-04 00:49:59.000000000 +0900
935
+++ b/storage/innodb_plugin/os/os0proc.c	2010-07-14 16:40:16.174322953 +0900
936
@@ -229,3 +229,173 @@
937
 	}
938
 #endif
939
 }
940
+
941
+/****************************************************************//**
942
+Allocates or attaches and reuses shared memory segment.
943
+The content is not cleared automatically.
944
+@return	allocated memory */
945
+UNIV_INTERN
946
+void*
947
+os_shm_alloc(
948
+/*=========*/
949
+	ulint*	n,			/*!< in/out: number of bytes */
950
+	uint	key,
951
+	ibool*	is_new)
952
+{
953
+	void*	ptr;
115.1.1 by kinoyasu
fix innodb_buffer_pool_shm.patch for -Wpointer-arith warnings of GCC
954
+#if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
955
+	ulint	size;
956
+	int	shmid;
957
+
958
+	*is_new = FALSE;
959
+	fprintf(stderr,
108.2.1 by Vadim Tkachenko
Fix error messages for buffer pool in shm
960
+		"InnoDB: The shared memory segment containing the buffer pool is: key  %#x (%d).\n",
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
961
+		key, key);
962
+# if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
963
+	if (!os_use_large_pages || !os_large_page_size) {
964
+		goto skip;
965
+	}
966
+
967
+	/* Align block size to os_large_page_size */
968
+	ut_ad(ut_is_2pow(os_large_page_size));
969
+	size = ut_2pow_round(*n + (os_large_page_size - 1),
970
+			     os_large_page_size);
971
+
972
+	shmid = shmget((key_t)key, (size_t)size,
973
+			IPC_CREAT | IPC_EXCL | SHM_HUGETLB | SHM_R | SHM_W);
974
+	if (shmid < 0) {
975
+		if (errno == EEXIST) {
976
+			fprintf(stderr,
108.2.1 by Vadim Tkachenko
Fix error messages for buffer pool in shm
977
+				"InnoDB: HugeTLB: The shared memory segment exists.\n");
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
978
+			shmid = shmget((key_t)key, (size_t)size,
979
+					SHM_HUGETLB | SHM_R | SHM_W);
980
+			if (shmid < 0) {
981
+				fprintf(stderr,
108.2.1 by Vadim Tkachenko
Fix error messages for buffer pool in shm
982
+					"InnoDB: HugeTLB: Warning: Failed to allocate %lu bytes. (reuse) errno %d\n",
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
983
+					size, errno);
984
+				goto skip;
985
+			} else {
986
+				fprintf(stderr,
987
+					"InnoDB: HugeTLB: The existent shared memory segment is used.\n");
988
+			}
989
+		} else {
990
+			fprintf(stderr,
108.2.1 by Vadim Tkachenko
Fix error messages for buffer pool in shm
991
+				"InnoDB: HugeTLB: Warning: Failed to allocate %lu bytes. (new) errno %d\n",
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
992
+				size, errno);
993
+			goto skip;
994
+		}
995
+	} else {
996
+		*is_new = TRUE;
997
+		fprintf(stderr,
108.2.1 by Vadim Tkachenko
Fix error messages for buffer pool in shm
998
+			"InnoDB: HugeTLB: A new shared memory segment has been created .\n");
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
999
+	}
1000
+
1001
+	ptr = shmat(shmid, NULL, 0);
1002
+	if (ptr == (void *)-1) {
1003
+		fprintf(stderr,
1004
+			"InnoDB: HugeTLB: Warning: Failed to attach shared memory segment, errno %d\n",
1005
+			errno);
1006
+		ptr = NULL;
1007
+	}
1008
+
1009
+	if (ptr) {
1010
+		*n = size;
1011
+		os_fast_mutex_lock(&ut_list_mutex);
1012
+		ut_total_allocated_memory += size;
1013
+		os_fast_mutex_unlock(&ut_list_mutex);
1014
+		UNIV_MEM_ALLOC(ptr, size);
1015
+		return(ptr);
1016
+	}
1017
+skip:
1018
+	*is_new = FALSE;
1019
+# endif /* HAVE_LARGE_PAGES && defined UNIV_LINUX */
1020
+# ifdef HAVE_GETPAGESIZE
1021
+	size = getpagesize();
1022
+# else
1023
+	size = UNIV_PAGE_SIZE;
1024
+# endif
1025
+	/* Align block size to system page size */
1026
+	ut_ad(ut_is_2pow(size));
1027
+	size = *n = ut_2pow_round(*n + (size - 1), size);
1028
+
1029
+	shmid = shmget((key_t)key, (size_t)size,
1030
+			IPC_CREAT | IPC_EXCL | SHM_R | SHM_W);
1031
+	if (shmid < 0) {
1032
+		if (errno == EEXIST) {
1033
+			fprintf(stderr,
108.2.1 by Vadim Tkachenko
Fix error messages for buffer pool in shm
1034
+				"InnoDB: A shared memory segment containing the buffer pool seems to already exist.\n");
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
1035
+			shmid = shmget((key_t)key, (size_t)size,
1036
+					SHM_R | SHM_W);
1037
+			if (shmid < 0) {
1038
+				fprintf(stderr,
108.2.1 by Vadim Tkachenko
Fix error messages for buffer pool in shm
1039
+					"InnoDB: Warning: Failed to allocate %lu bytes. (reuse) errno %d\n",
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
1040
+					size, errno);
1041
+				ptr = NULL;
1042
+				goto end;
1043
+			} else {
1044
+				fprintf(stderr,
1045
+					"InnoDB: The existent shared memory segment is used.\n");
1046
+			}
1047
+		} else {
1048
+			fprintf(stderr,
108.2.1 by Vadim Tkachenko
Fix error messages for buffer pool in shm
1049
+				"InnoDB: Warning: Failed to allocate %lu bytes. (new) errno %d\n",
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
1050
+				size, errno);
1051
+			ptr = NULL;
1052
+			goto end;
1053
+		}
1054
+	} else {
1055
+		*is_new = TRUE;
1056
+		fprintf(stderr,
108.2.1 by Vadim Tkachenko
Fix error messages for buffer pool in shm
1057
+			"InnoDB: A new shared memory segment has been created.\n");
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
1058
+	}
1059
+
1060
+	ptr = shmat(shmid, NULL, 0);
1061
+	if (ptr == (void *)-1) {
1062
+		fprintf(stderr,
1063
+			"InnoDB: Warning: Failed to attach shared memory segment, errno %d\n",
1064
+			errno);
1065
+		ptr = NULL;
1066
+	}
1067
+
1068
+	if (ptr) {
1069
+		*n = size;
1070
+		os_fast_mutex_lock(&ut_list_mutex);
1071
+		ut_total_allocated_memory += size;
1072
+		os_fast_mutex_unlock(&ut_list_mutex);
1073
+		UNIV_MEM_ALLOC(ptr, size);
1074
+	}
1075
+end:
1076
+#else /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
1077
+	fprintf(stderr, "InnoDB: shared memory segment is not supported.\n");
1078
+	ptr = NULL;
1079
+#endif /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
1080
+	return(ptr);
1081
+}
1082
+
1083
+/****************************************************************//**
1084
+Detach shared memory segment. */
1085
+UNIV_INTERN
1086
+void
1087
+os_shm_free(
1088
+/*========*/
1089
+	void	*ptr,			/*!< in: pointer returned by
1090
+					os_shm_alloc() */
1091
+	ulint	size)			/*!< in: size returned by
1092
+					os_shm_alloc() */
1093
+{
1094
+	os_fast_mutex_lock(&ut_list_mutex);
1095
+	ut_a(ut_total_allocated_memory >= size);
1096
+	os_fast_mutex_unlock(&ut_list_mutex);
1097
+
1098
+#if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H
1099
+	if (!shmdt(ptr)) {
1100
+		os_fast_mutex_lock(&ut_list_mutex);
1101
+		ut_a(ut_total_allocated_memory >= size);
1102
+		ut_total_allocated_memory -= size;
1103
+		os_fast_mutex_unlock(&ut_list_mutex);
1104
+		UNIV_MEM_FREE(ptr, size);
1105
+	}
1106
+#else /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
1107
+	fprintf(stderr, "InnoDB: shared memory segment is not supported.\n");
1108
+#endif /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
1109
+}
1110
diff -ruN a/storage/innodb_plugin/srv/srv0srv.c b/storage/innodb_plugin/srv/srv0srv.c
1111
--- a/storage/innodb_plugin/srv/srv0srv.c	2010-07-14 16:33:23.848391648 +0900
1112
+++ b/storage/innodb_plugin/srv/srv0srv.c	2010-07-14 16:40:16.177323553 +0900
124.1.1 by kinoyasu
fix bug649408
1113
@@ -211,6 +211,11 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
1114
 UNIV_INTERN ulint	srv_mem_pool_size	= ULINT_MAX;
1115
 UNIV_INTERN ulint	srv_lock_table_size	= ULINT_MAX;
1116
 
1117
+/* key value for shm */
1118
+UNIV_INTERN uint	srv_buffer_pool_shm_key	= 0;
124.1.1 by kinoyasu
fix bug649408
1119
+UNIV_INTERN ibool	srv_buffer_pool_shm_is_reused = FALSE;
119.1.1 by kinoyasu
- New static bool option innodb_buffer_pool_shm_checksum for bug643650
1120
+UNIV_INTERN ibool	srv_buffer_pool_shm_checksum = TRUE;
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
1121
+
1122
 /* This parameter is deprecated. Use srv_n_io_[read|write]_threads
1123
 instead. */
1124
 UNIV_INTERN ulint	srv_n_file_io_threads	= ULINT_MAX;
1125
diff -ruN a/storage/innodb_plugin/srv/srv0start.c b/storage/innodb_plugin/srv/srv0start.c
1126
--- a/storage/innodb_plugin/srv/srv0start.c	2010-07-14 16:33:23.851391514 +0900
1127
+++ b/storage/innodb_plugin/srv/srv0start.c	2010-07-14 16:40:16.180321173 +0900
175 by kinoyasu
Yasufumi patches are ported to 5.1.54
1128
@@ -1744,6 +1744,8 @@
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
1129
 		Note that this is not as heavy weight as it seems. At
1130
 		this point there will be only ONE page in the buf_LRU
1131
 		and there must be no page in the buf_flush list. */
124.1.1 by kinoyasu
fix bug649408
1132
+		/* buffer_pool_shm should not be reused when recovery was needed. */
1133
+		if (!srv_buffer_pool_shm_is_reused)
63.1.1 by kinoyasu
add innodb_buffer_pool_shm_key option
1134
 		buf_pool_invalidate();
1135
 
1136
 		/* We always try to do a recovery, even if the database had