/* * Create the appropriate buffers when given a page for data area and * the size of each buffer.. Use the bh->b_this_page linked list to * follow the buffers created. Return NULL if unable to create more * buffers. */ static struct buffer_head * create_buffers(unsigned long page, unsigned long size) { struct buffer_head *bh, *head; unsigned long offset; head = NULL; offset = PAGE_SIZE; while ((offset -= size) < PAGE_SIZE) { bh = get_unused_buffer_head(); if (!bh) goto no_grow; bh->b_this_page = head; head = bh; bh->b_data = (char *) (page+offset); bh->b_size = size; } return head; /* * In case anything failed, we just free everything we got. */ no_grow: bh = head; while (bh) { head = bh; bh = bh->b_this_page; put_unused_buffer_head(head); } return NULL; }
/* * Try to increase the number of buffers available: the size argument * is used to determine what kind of buffers we want. Currently only * 1024-byte buffers are supported by the rest of the system, but I * think this will change eventually. */ void grow_buffers(int size) { unsigned long page; int i; struct buffer_head *bh, *tmp; if ((size & 511) || (size > 4096)) { printk("grow_buffers: size = %d\n",size); return; } page = get_free_page(GFP_BUFFER); if (!page) return; tmp = NULL; i = 0; for (i = 0 ; i+size <= 4096 ; i += size) { bh = get_unused_buffer_head(); if (!bh) goto no_grow; bh->b_this_page = tmp; tmp = bh; bh->b_data = (char * ) (page+i); bh->b_size = size; } tmp = bh; while (1) { if (free_list) { tmp->b_next_free = free_list; tmp->b_prev_free = free_list->b_prev_free; free_list->b_prev_free->b_next_free = tmp; free_list->b_prev_free = tmp; } else { tmp->b_prev_free = tmp; tmp->b_next_free = tmp; } free_list = tmp; ++nr_buffers; if (tmp->b_this_page) tmp = tmp->b_this_page; else break; } tmp->b_this_page = bh; return; /* * In case anything failed, we just free everything we got. */ no_grow: bh = tmp; while (bh) { tmp = bh; bh = bh->b_this_page; put_unused_buffer_head(tmp); } free_page(page); }