int dbs_file_extend (dbe_storage_t * dbs, extent_t ** new_ext_ret, int is_in_sys_em) { extent_map_t * em; extent_t * new_ext = NULL; int n, n_allocated = 0; int32 em_n_free; dp_addr_t ext_first = dbs->dbs_n_pages; ASSERT_IN_DBS (dbs); if (dbf_no_disk) return 0; if (dbs->dbs_disks) { n = dbs_seg_extend (dbs, EXTENT_SZ); if (n != EXTENT_SZ) return 0; } else { mutex_enter (dbs->dbs_file_mtx); n = fd_extend (dbs, dbs->dbs_fd, EXTENT_SZ); mutex_leave (dbs->dbs_file_mtx); if (EXTENT_SZ != n) return 0; dbs->dbs_file_length += PAGE_SZ * EXTENT_SZ; dbs->dbs_n_pages+= EXTENT_SZ; dbs->dbs_n_free_pages+= EXTENT_SZ; } wi_storage_offsets (); em = dbs->dbs_extent_map; if (!em) { return n; } if (!is_in_sys_em) mutex_enter (em->em_mtx); if (dbs_check_extent_free_pages) { em_n_free = em_free_count (em, EXT_INDEX); if (em->em_n_free_pages != em_n_free) { log_error ("The %s free pages incorrect %d != %d actually free", em->em_name, em->em_n_free_pages, em_n_free); em->em_n_free_pages = em_n_free; } } if (em->em_n_free_pages < 16) { /* extending and the system extent has little space. Make this ext a system index ext. If allocating some other ext, retry and take the next ext for that. */ int fill; buffer_desc_t * last; last = page_set_last (em->em_buf); fill = LONG_REF (last->bd_buffer + DP_BLOB_LEN); if (fill + sizeof (extent_t) > PAGE_DATA_SZ) { dp_addr_t em_dp = ext_first + n_allocated; n_allocated++; last = page_set_extend (dbs, &em->em_buf, em_dp, DPF_EXTENT_MAP); LONG_SET (last->bd_buffer + DP_BLOB_LEN, sizeof (extent_t)); new_ext = (extent_t *) (last->bd_buffer + DP_DATA); } else { new_ext = (extent_t*) (last->bd_buffer + fill + DP_DATA); LONG_SET (last->bd_buffer + DP_BLOB_LEN, fill + sizeof (extent_t)); } em->em_n_pages += EXTENT_SZ; em->em_n_free_pages += EXTENT_SZ; new_ext->ext_flags = EXT_INDEX; new_ext->ext_dp = ext_first; if (gethash (DP_ADDR2VOID (new_ext->ext_dp), dbs->dbs_dp_to_extent_map)) GPF_T1 ("ext for new dp range already exists in dbs"); sethash (DP_ADDR2VOID (new_ext->ext_dp), em->em_dp_to_ext, (void*)new_ext); sethash (DP_ADDR2VOID (new_ext->ext_dp), dbs->dbs_dp_to_extent_map, (void*)em); new_ext->ext_prev = EXT_EXTENDS_NONE; if (n_allocated) { new_ext->ext_pages[0] = 1; em->em_n_free_pages--; } } /* there is a guarantee of at least 16 pages in the dbs sys extent map */ if (dbs->dbs_n_pages > dbs->dbs_n_pages_in_sets) { /* add a page of global free set and backup set */ buffer_desc_t * last = page_set_extend (dbs, &dbs->dbs_free_set, 0, DPF_FREE_SET); page_set_checksum_init (last->bd_buffer + DP_DATA); if (n_allocated) dbs_page_allocated (dbs, ext_first); last->bd_page = last->bd_physical_page = em_try_get_dp (em, EXT_INDEX, DP_ANY); if (!last->bd_page) GPF_T1 ("0 dp for page set page"); EM_DEC_FREE (em, EXT_INDEX); last = page_set_extend (dbs, &dbs->dbs_incbackup_set, 0, DPF_INCBACKUP_SET); page_set_checksum_init (last->bd_buffer + DP_DATA); last->bd_page = last->bd_physical_page = em_try_get_dp (em, EXT_INDEX, DP_ANY); if (!last->bd_page) GPF_T1 ("0 dp for page set page"); EM_DEC_FREE (em, EXT_INDEX); dbs->dbs_n_pages_in_sets += BITS_ON_PAGE; } if (dbs->dbs_n_pages > dbs->dbs_n_pages_in_extent_set) { buffer_desc_t * last = page_set_extend (dbs, &dbs->dbs_extent_set, 0, DPF_EXTENT_SET); last->bd_page = last->bd_physical_page = em_try_get_dp (em, EXT_INDEX, DP_ANY); if (!last->bd_page) GPF_T1 ("0 dp for extents alloc page"); EM_DEC_FREE (em, EXT_INDEX); LONG_SET (last->bd_buffer + DP_DATA, 1); /* the newly made ext is the 1st of this page of the ext set, so set the bm 1st bit to 1 */ page_set_checksum_init (last->bd_buffer + DP_DATA); dbs->dbs_n_pages_in_extent_set += EXTENT_SZ * BITS_ON_PAGE; } if (new_ext) { dbs_extent_allocated (dbs, ext_first); } *new_ext_ret = new_ext; if (!is_in_sys_em) mutex_leave (em->em_mtx); return n; }
int DBGP_NAME (page_wait_access) (DBGP_PARAMS it_cursor_t * itc, dp_addr_t dp, buffer_desc_t * buf_from, buffer_desc_t ** buf_ret, int mode, int max_change) { buffer_desc_t decoy; buffer_desc_t *buf; dp_addr_t phys_dp; itc->itc_to_reset = RWG_NO_WAIT; itc->itc_max_transit_change = max_change; itc->itc_must_kill_trx = 0; if (!dp) GPF_T1 ("Zero DP in page_fault_map_sem"); if (buf_from) { ITC_IN_TRANSIT (itc, dp, buf_from->bd_page); } else ASSERT_IN_MAP (itc->itc_tree, dp); buf = IT_DP_TO_BUF (itc->itc_tree, dp); if (!buf) { ra_req_t * ra = NULL; IT_DP_REMAP (itc->itc_tree, dp, phys_dp); #ifdef MTX_DEBUG em_check_dp (itc->itc_tree->it_extent_map, phys_dp); if (phys_dp != dp) em_check_dp (itc->itc_tree->it_extent_map, dp); #endif if ((DP_DELETED == phys_dp || dbs_is_free_page (itc->itc_tree->it_storage, phys_dp)) && !strchr (wi_inst.wi_open_mode, 'a')) { log_error ("Reference to page with free remap dp = %ld, remap = %ld", (long) phys_dp, (long) dp); if (0 && DBS_PAGE_IN_RANGE (itc->itc_tree->it_storage, phys_dp)) dbs_page_allocated (itc->itc_tree->it_storage, phys_dp); else { *buf_ret = PF_OF_DELETED; itc->itc_must_kill_trx = 1; itc->itc_to_reset = RWG_WAIT_ANY; ITC_LEAVE_MAPS (itc); return RWG_WAIT_ANY; } } memset (&decoy, 0, sizeof (buffer_desc_t)); decoy.bd_being_read = 1; if (PA_READ == mode) decoy.bd_readers = 1; else BD_SET_IS_WRITE (&decoy, 1); sethash (DP_ADDR2VOID (dp), &IT_DP_MAP (itc->itc_tree, dp)->itm_dp_to_buf, (void*)&decoy); ITC_LEAVE_MAPS (itc); buf = bp_get_buffer (NULL, BP_BUF_REQUIRED); is_read_pending++; buf->bd_being_read = 1; buf->bd_page = dp; buf->bd_storage = itc->itc_tree->it_storage; buf->bd_physical_page = phys_dp; BD_SET_IS_WRITE (buf, 0); buf->bd_write_waiting = NULL; if (buf_from && !itc->itc_landed) ra = itc_read_aside (itc, buf_from, dp); itc->itc_n_reads++; ITC_MARK_READ (itc); buf->bd_tree = itc->itc_tree; buf_disk_read (buf); is_read_pending--; if (ra) itc_read_ahead_blob (itc, ra, RAB_SPECULATIVE); if (buf_from) { ITC_IN_TRANSIT (itc, dp, buf_from->bd_page) } else