Messages in this thread Patch in this message |  | | Date | Fri, 14 Feb 1997 00:47:58 -0800 | From | "Leonard N. Zubkoff" <> | Subject | 2.0.x Disk Performance Problem - Solved |
| |
A month or so ago tenthumbs@cybernex.net and I both reported performance problems with disk I/O in recent 2.0.x kernels. In my case, the most serious problem was an e2fsck run that took 60 minutes when it should have taken 5 or 6. I'd also noticed problems with mke2fs for several months but had never gotten around to investigating further. I've now tracked this problem down and corrected it.
It turns out this performance problem was inadvertently introduced by a correction made to fs/buffer.c in the 2.0.21 patch. The addition of a missing "++nr_buffers_size[isize];" revealed a latent problem in the load average computations in maybe_shrink_lav_buffers, which caused shrink_specific_buffers to be called inappropriately, wasting many cycles trying to reclaim buffers where there were none to be had.
Specifically, the first calculation in the comparison
bdf_prm.b_un.lav_const * buffers_lav[nlist]*total_n_buffers < total_lav * (nr_buffers_size[nlist] - nr_buffers_st[nlist][BUF_SHARED]))
can become negative or overflow. When it becomes negative, the comparison will succeeed when it should not. One of the failures I logged was:
1884 * 73 * 21375 < 8812 * ( 57 - 0 )
The enclosed patch divides both sides of this comparison by total_lav * total_n_buffers, which preserves the comparison while avoiding large multiplications.
Leonard
--- linux/fs/buffer.c- Fri Sep 20 07:00:35 1996 +++ linux/fs/buffer.c Thu Feb 13 23:21:42 1997 @@ -1535,10 +1535,11 @@ if (n_sizes > 1) for(nlist = 0; nlist < NR_SIZES; nlist++) { - if(nlist == isize) continue; - if(nr_buffers_size[nlist] && - bdf_prm.b_un.lav_const * buffers_lav[nlist]*total_n_buffers < - total_lav * (nr_buffers_size[nlist] - nr_buffers_st[nlist][BUF_SHARED])) + if (nlist == isize) continue; + if (nr_buffers_size[nlist] > 0 && + total_lav > 0 && total_n_buffers > 0 && + bdf_prm.b_un.lav_const * buffers_lav[nlist] / total_lav < + (nr_buffers_size[nlist] - nr_buffers_st[nlist][BUF_SHARED]) / total_n_buffers) if(shrink_specific_buffers(6, bufferindex_size[nlist])) return 1; }
|  |