* Write, release buffer on completion. (Done by iodone * if async). Do not bother writing anything if the buffer * is invalid. * * Note that we set B_CACHE here, indicating that buffer is * fully valid and thus cacheable. This is true even of NFS * now so we set it generally. This could be set either here * or in biodone() since the I/O is synchronous. We put it * here. */
| 2232 | * here. |
| 2233 | */ |
| 2234 | int |
| 2235 | bufwrite(struct buf *bp) |
| 2236 | { |
| 2237 | int oldflags; |
| 2238 | struct vnode *vp; |
| 2239 | long space; |
| 2240 | int vp_md; |
| 2241 | |
| 2242 | CTR3(KTR_BUF, "bufwrite(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags); |
| 2243 | if ((bp->b_bufobj->bo_flag & BO_DEAD) != 0) { |
| 2244 | bp->b_flags |= B_INVAL | B_RELBUF; |
| 2245 | bp->b_flags &= ~B_CACHE; |
| 2246 | brelse(bp); |
| 2247 | return (ENXIO); |
| 2248 | } |
| 2249 | if (bp->b_flags & B_INVAL) { |
| 2250 | brelse(bp); |
| 2251 | return (0); |
| 2252 | } |
| 2253 | |
| 2254 | if (bp->b_flags & B_BARRIER) |
| 2255 | atomic_add_long(&barrierwrites, 1); |
| 2256 | |
| 2257 | oldflags = bp->b_flags; |
| 2258 | |
| 2259 | KASSERT(!(bp->b_vflags & BV_BKGRDINPROG), |
| 2260 | ("FFS background buffer should not get here %p", bp)); |
| 2261 | |
| 2262 | vp = bp->b_vp; |
| 2263 | if (vp) |
| 2264 | vp_md = vp->v_vflag & VV_MD; |
| 2265 | else |
| 2266 | vp_md = 0; |
| 2267 | |
| 2268 | /* |
| 2269 | * Mark the buffer clean. Increment the bufobj write count |
| 2270 | * before bundirty() call, to prevent other thread from seeing |
| 2271 | * empty dirty list and zero counter for writes in progress, |
| 2272 | * falsely indicating that the bufobj is clean. |
| 2273 | */ |
| 2274 | bufobj_wref(bp->b_bufobj); |
| 2275 | bundirty(bp); |
| 2276 | |
| 2277 | bp->b_flags &= ~B_DONE; |
| 2278 | bp->b_ioflags &= ~BIO_ERROR; |
| 2279 | bp->b_flags |= B_CACHE; |
| 2280 | bp->b_iocmd = BIO_WRITE; |
| 2281 | |
| 2282 | vfs_busy_pages(bp, 1); |
| 2283 | |
| 2284 | /* |
| 2285 | * Normal bwrites pipeline writes |
| 2286 | */ |
| 2287 | bp->b_runningbufspace = bp->b_bufsize; |
| 2288 | space = atomic_fetchadd_long(&runningbufspace, bp->b_runningbufspace); |
| 2289 | |
| 2290 | #ifdef RACCT |
| 2291 | if (racct_enable) { |
nothing calls this directly
no test coverage detected