1*88fd7a1bSsevan.\" $NetBSD: bufferio.9,v 1.18 2019/09/12 21:08:35 sevan Exp $ 21098217eSriastradh.\" 31098217eSriastradh.\" Copyright (c) 2015 The NetBSD Foundation, Inc. 41098217eSriastradh.\" All rights reserved. 51098217eSriastradh.\" 61098217eSriastradh.\" This code is derived from software contributed to The NetBSD Foundation 71098217eSriastradh.\" by Taylor R. Campbell. 81098217eSriastradh.\" 91098217eSriastradh.\" Redistribution and use in source and binary forms, with or without 101098217eSriastradh.\" modification, are permitted provided that the following conditions 111098217eSriastradh.\" are met: 121098217eSriastradh.\" 1. Redistributions of source code must retain the above copyright 131098217eSriastradh.\" notice, this list of conditions and the following disclaimer. 141098217eSriastradh.\" 2. Redistributions in binary form must reproduce the above copyright 151098217eSriastradh.\" notice, this list of conditions and the following disclaimer in the 161098217eSriastradh.\" documentation and/or other materials provided with the distribution. 171098217eSriastradh.\" 181098217eSriastradh.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 191098217eSriastradh.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 201098217eSriastradh.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 211098217eSriastradh.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 221098217eSriastradh.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 231098217eSriastradh.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 241098217eSriastradh.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 251098217eSriastradh.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 261098217eSriastradh.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 271098217eSriastradh.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 281098217eSriastradh.\" POSSIBILITY OF SUCH DAMAGE. 291098217eSriastradh.\" 30*88fd7a1bSsevan.Dd September 12, 2019 311098217eSriastradh.Dt BUFFERIO 9 321098217eSriastradh.Os 331098217eSriastradh.Sh NAME 341098217eSriastradh.Nm BUFFERIO , 351098217eSriastradh.Nm biodone , 361098217eSriastradh.Nm biowait , 371098217eSriastradh.Nm getiobuf , 381098217eSriastradh.Nm putiobuf , 391098217eSriastradh.Nm nestiobuf_setup , 401098217eSriastradh.Nm nestiobuf_done 411098217eSriastradh.Nd block I/O buffer transfers 421098217eSriastradh.Sh SYNOPSIS 431098217eSriastradh.In sys/buf.h 441098217eSriastradh.Ft void 45*88fd7a1bSsevan.Fn biodone "buf_t *bp" 461098217eSriastradh.Ft int 47*88fd7a1bSsevan.Fn biowait "buf_t *bp" 48*88fd7a1bSsevan.Ft buf_t * 491098217eSriastradh.Fn getiobuf "struct vnode *vp" "bool waitok" 501098217eSriastradh.Ft void 51*88fd7a1bSsevan.Fn putiobuf "buf_t *bp" 521098217eSriastradh.Ft void 53*88fd7a1bSsevan.Fn nestiobuf_setup "buf_t *mbp" "buf_t *bp" "int offset" \ 541098217eSriastradh "size_t size" 551098217eSriastradh.Ft void 56*88fd7a1bSsevan.Fn nestiobuf_done "buf_t *mbp" "int donebytes" "int error" 571098217eSriastradh.Sh DESCRIPTION 581098217eSriastradhThe 591098217eSriastradh.Nm 601098217eSriastradhsubsystem manages block I/O buffer transfers, described by the 611098217eSriastradh.Vt "struct buf" 621098217eSriastradhstructure, which serves multiple purposes between users in 631098217eSriastradh.Nm , 641098217eSriastradhusers in 651098217eSriastradh.Xr buffercache 9 , 661098217eSriastradhand users in block device drivers to execute transfers to physical 671098217eSriastradhdisks. 681098217eSriastradh.Sh BLOCK DEVICE USERS 691098217eSriastradhUsers of 701098217eSriastradh.Nm 711098217eSriastradhwishing to submit a buffer for block I/O transfer must obtain a 721098217eSriastradh.Vt "struct buf" , 731098217eSriastradhe.g. via 741098217eSriastradh.Fn getiobuf , 751098217eSriastradhfill its parameters, and submit it to a block device with 761098217eSriastradh.Xr bdev_strategy 9 , 771098217eSriastradhusually via 781098217eSriastradh.Xr VOP_STRATEGY 9 . 791098217eSriastradh.Pp 801098217eSriastradhThe parameters to an I/O transfer described by 811098217eSriastradh.Fa bp 821098217eSriastradhare specified by the following 831098217eSriastradh.Vt "struct buf" 841098217eSriastradhfields: 85*88fd7a1bSsevan.Bl -tag -width 6n -offset abcd 861098217eSriastradh.It Fa bp Ns Li "->b_flags" 871098217eSriastradhFlags specifying the type of transfer. 88*88fd7a1bSsevan.Bl -tag -width 6n -compact 891098217eSriastradh.It Dv B_READ 901098217eSriastradhTransfer is read from device. 911098217eSriastradhIf not set, transfer is write to device. 921098217eSriastradh.It Dv B_ASYNC 931098217eSriastradhAsynchronous I/O. 94ba2aeff9SriastradhCaller must not provide 951098217eSriastradh.Fa bp Ns Li "->b_iodone" 961098217eSriastradhand must not call 971098217eSriastradh.Fn biowait bp . 981098217eSriastradh.El 997643fefeSriastradhFor legibility, callers should indicate writes by passing the 1007643fefeSriastradhpseudo-flag 1017643fefeSriastradh.Dv B_WRITE , 1025bd51b95Sriastradhwhich is zero. 1031098217eSriastradh.It Fa bp Ns Li "->b_data" 1041098217eSriastradhPointer to kernel virtual address of source/target for transfer. 1051098217eSriastradh.It Fa bp Ns Li "->b_bcount" 1061098217eSriastradhNonnegative number of bytes requested for transfer. 1071098217eSriastradh.It Fa bp Ns Li "->b_blkno" 1081098217eSriastradhBlock number at which to do transfer. 1091098217eSriastradh.It Fa bp Ns Li "->b_iodone" 110ba2aeff9SriastradhI/O completion callback. 1111098217eSriastradh.Dv B_ASYNC 112ba2aeff9Sriastradhmust not be set in 113ba2aeff9Sriastradh.Fa bp Ns Li "->b_flags" . 1141098217eSriastradh.El 1151098217eSriastradh.Pp 1161098217eSriastradhAdditionally, if the I/O transfer is a write associated with a 1171098217eSriastradh.Xr vnode 9 1181098217eSriastradh.Fa vp , 1191098217eSriastradhthen before the user submits it to a block device, the user must 1201098217eSriastradhincrement 1211098217eSriastradh.Fa vp Ns Li "->v_numoutput" . 1221098217eSriastradhThe user must not acquire 1237cfc1b80Sriastradh.Fa vp Ns Ap s 1241098217eSriastradhvnode lock between incrementing 1251098217eSriastradh.Fa vp Ns Li "->v_numoutput" 1261098217eSriastradhand submitting 1271098217eSriastradh.Fa bp 12888f86411Sriastradhto a block device \(em doing so will likely cause deadlock with the 1291098217eSriastradhsyncer. 1301098217eSriastradh.Pp 131ba2aeff9SriastradhBlock I/O transfer completion may be notified by the 132ba2aeff9Sriastradh.Fa bp Ns Li "->b_iodone" 133ba2aeff9Sriastradhcallback, by signalling 134ba2aeff9Sriastradh.Fn biowait 135ba2aeff9Sriastradhwaiters, or not at all in the 136ba2aeff9Sriastradh.Dv B_ASYNC 137ba2aeff9Sriastradhcase. 1381098217eSriastradh.Bl -dash 1391098217eSriastradh.It 140ba2aeff9SriastradhIf the user sets the 1411098217eSriastradh.Fa bp Ns Li "->b_iodone" 142078e20efSriastradhcallback to a 143078e20efSriastradh.Pf non- Dv NULL 144078e20efSriastradhfunction pointer, it will be called in soft interrupt context when the 145078e20efSriastradhI/O transfer is complete. 1461098217eSriastradhThe user 1471098217eSriastradh.Em may not 1481098217eSriastradhcall 1491098217eSriastradh.Fn biowait bp 1501098217eSriastradhin this case. 151ba2aeff9Sriastradh.It 152ba2aeff9SriastradhIf 153ba2aeff9Sriastradh.Dv B_ASYNC 154ba2aeff9Sriastradhis set, then the I/O transfer is asynchronous and the user will not be 155ba2aeff9Sriastradhnotified when it is completed. 156ba2aeff9SriastradhThe user 157ba2aeff9Sriastradh.Em may not 158ba2aeff9Sriastradhcall 159ba2aeff9Sriastradh.Fn biowait bp 160ba2aeff9Sriastradhin this case. 161ba2aeff9Sriastradh.It 162ba2aeff9SriastradhOtherwise, if 163ba2aeff9Sriastradh.Fa bp Ns Li "->b_iodone" 164078e20efSriastradhis 165078e20efSriastradh.Dv NULL 166078e20efSriastradhand 167ba2aeff9Sriastradh.Dv B_ASYNC 168ba2aeff9Sriastradhis not specified, the user may wait for the I/O transfer to complete 169ba2aeff9Sriastradhwith 170ba2aeff9Sriastradh.Fn biowait bp . 1711098217eSriastradh.El 172e90024bfSriastradh.Pp 173e90024bfSriastradhOnce an I/O transfer has completed, its 174b2d5d8d7Sriastradh.Vt "struct buf" 175e90024bfSriastradhmay be reused, but the user must first clear the 176e90024bfSriastradh.Dv BO_DONE 177e90024bfSriastradhflag of 178e90024bfSriastradh.Fa bp Ns Li "->b_oflags" 179e90024bfSriastradhbefore reusing it. 1801098217eSriastradh.Sh NESTED I/O TRANSFERS 1811098217eSriastradhSometimes an I/O transfer from a single buffer in memory cannot go to a 1821098217eSriastradhsingle location on a block device: it must be split up into smaller 1831098217eSriastradhtransfers for each segment of the memory buffer. 1841098217eSriastradh.Pp 1851098217eSriastradhAfter initializing the 1861098217eSriastradh.Li b_flags , 1871098217eSriastradh.Li b_data , 1881098217eSriastradhand 1891098217eSriastradh.Li b_bcount 1901098217eSriastradhparameters of an I/O transfer for the buffer, called the 1911098217eSriastradh.Em master 1921098217eSriastradhbuffer, the user can issue smaller transfers for segments of the buffer 1931098217eSriastradhusing 1941098217eSriastradh.Fn nestiobuf_setup . 195808424fbSriastradhWhen nested I/O transfers complete, in any order, they debit from the 196808424fbSriastradhamount of work left to be done in the master buffer. 1971098217eSriastradhIf any segments of the buffer were skipped, the user can report this 1981098217eSriastradhwith 1991098217eSriastradh.Fn nestiobuf_done 2001098217eSriastradhto debit the skipped part of the work. 2011098217eSriastradh.Pp 2021098217eSriastradhThe master buffer's I/O transfer is completed when all nested buffers' 2031098217eSriastradhI/O transfers are completed, and if 2041098217eSriastradh.Fn nestiobuf_done 2051098217eSriastradhis called in the case of skipped segments. 2061098217eSriastradh.Pp 2071098217eSriastradhFor writes associated with a vnode 2081098217eSriastradh.Fa vp , 2091098217eSriastradh.Fn nestiobuf_setup 2101098217eSriastradhaccounts for 2111098217eSriastradh.Fa vp Ns Li "->v_numoutput" , 2121098217eSriastradhso the caller is not allowed to acquire 2137cfc1b80Sriastradh.Fa vp Ns Ap s 2141098217eSriastradhvnode lock before submitting the nested I/O transfer to a block 2151098217eSriastradhdevice. 2161098217eSriastradhHowever, the caller is responsible for accounting the master buffer in 2171098217eSriastradh.Fa vp Ns Li "->v_numoutput" . 2181098217eSriastradhThis must be done very carefully because after incrementing 2191098217eSriastradh.Fa vp Ns Li "->v_numoutput" , 2201098217eSriastradhthe caller is not allowed to acquire 2217cfc1b80Sriastradh.Fa vp Ns Ap s 2221098217eSriastradhvnode lock before either calling 2231098217eSriastradh.Fn nestiobuf_done 2241098217eSriastradhor submitting the last nested I/O transfer to a block device. 2251098217eSriastradh.Pp 2261098217eSriastradhFor example: 2271098217eSriastradh.Bd -literal -offset abcd 2285bd51b95Sriastradhstruct buf *mbp, *bp; 2295bd51b95Sriastradhsize_t skipped = 0; 2305bd51b95Sriastradhunsigned i; 2315bd51b95Sriastradhint error = 0; 2325bd51b95Sriastradh 2335bd51b95Sriastradhmbp = getiobuf(vp, true); 2345bd51b95Sriastradhmbp->b_data = data; 2355bd51b95Sriastradhmbp->b_resid = mbp->b_bcount = datalen; 2365bd51b95Sriastradhmbp->b_flags = B_WRITE; 2375bd51b95Sriastradh 238185edd37SriastradhKASSERT(0 < nsegs); 239185edd37SriastradhKASSERT(datalen == nsegs*segsz); 2405bd51b95Sriastradhfor (i = 0; i < nsegs; i++) { 2415bd51b95Sriastradh struct vnode *devvp; 2425bd51b95Sriastradh daddr_t blkno; 2435bd51b95Sriastradh 2445bd51b95Sriastradh vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2455bd51b95Sriastradh error = VOP_BMAP(vp, i*segsz, &devvp, &blkno, NULL); 2465bd51b95Sriastradh VOP_UNLOCK(vp); 24779047ecbSriastradh if (error == 0 && blkno == -1) 2485bd51b95Sriastradh error = EIO; 2495bd51b95Sriastradh if (error) { 250185edd37Sriastradh /* Give up early, don't try to handle holes. */ 251185edd37Sriastradh skipped += datalen - i*segsz; 2525bd51b95Sriastradh break; 2535bd51b95Sriastradh } 2545bd51b95Sriastradh 2555bd51b95Sriastradh bp = getiobuf(vp, true); 2565bd51b95Sriastradh nestiobuf_setup(bp, mbp, i*segsz, segsz); 2575bd51b95Sriastradh bp->b_blkno = blkno; 2585bd51b95Sriastradh if (i == nsegs - 1) /* Last segment. */ 2595bd51b95Sriastradh break; 2605bd51b95Sriastradh VOP_STRATEGY(devvp, bp); 2615bd51b95Sriastradh} 2625bd51b95Sriastradh 2635bd51b95Sriastradh/* 2645bd51b95Sriastradh * Account v_numoutput for master write. 2655bd51b95Sriastradh * (Must not vn_lock before last VOP_STRATEGY!) 2665bd51b95Sriastradh */ 2675bd51b95Sriastradhmutex_enter(&vp->v_interlock); 2685bd51b95Sriastradhvp->v_numoutput++; 2695bd51b95Sriastradhmutex_exit(&vp->v_interlock); 2705bd51b95Sriastradh 2715bd51b95Sriastradhif (skipped) 2725bd51b95Sriastradh nestiobuf_done(mbp, skipped, error); 2735bd51b95Sriastradhelse 2745bd51b95Sriastradh VOP_STRATEGY(devvp, bp); 2751098217eSriastradh.Ed 2761098217eSriastradh.Sh BLOCK DEVICE DRIVERS 2771098217eSriastradhBlock device drivers implement a 2781098217eSriastradh.Sq strategy 2791098217eSriastradhmethod, in the 2801098217eSriastradh.Li d_strategy 2811098217eSriastradhmember of 2821098217eSriastradh.Li struct bdevsw 2831098217eSriastradh.Pq Xr driver 9 , 2841098217eSriastradhto queue a buffer for disk I/O. 2851098217eSriastradhThe inputs to the strategy method are: 286*88fd7a1bSsevan.Bl -tag -width 6n -offset abcd 2871098217eSriastradh.It Fa bp Ns Li "->b_flags" 2881098217eSriastradhFlags specifying the type of transfer. 289*88fd7a1bSsevan.Bl -tag -width 6n -compact 2901098217eSriastradh.It Dv B_READ 2911098217eSriastradhTransfer is read from device. 2921098217eSriastradhIf not set, transfer is write to device. 2931098217eSriastradh.El 2941098217eSriastradh.It Fa bp Ns Li "->b_data" 2951098217eSriastradhPointer to kernel virtual address of source/target for transfer. 2961098217eSriastradh.It Fa bp Ns Li "->b_bcount" 2971098217eSriastradhNonnegative number of bytes requested for transfer. 2981098217eSriastradh.It Fa bp Ns Li "->b_blkno" 2991098217eSriastradhBlock number at which to do transfer, relative to partition start. 3001098217eSriastradh.El 3011098217eSriastradh.Pp 3021098217eSriastradhIf the strategy method uses 3031098217eSriastradh.Xr bufq 9 , 3041098217eSriastradhit must additionally initialize the following fields before queueing 3051098217eSriastradh.Fa bp 3061098217eSriastradhwith 3071098217eSriastradh.Xr bufq_put 9 : 308*88fd7a1bSsevan.Bl -tag -width 6n -offset abcd 3091098217eSriastradh.It Fa bp Ns Li "->b_rawblkno" 3101098217eSriastradhBlock number relative to volume start. 3111098217eSriastradh.El 3121098217eSriastradh.Pp 3131098217eSriastradhWhen the I/O transfer is complete, whether it succeeded or failed, the 3141098217eSriastradhstrategy method must: 3151098217eSriastradh.Bl -dash 3161098217eSriastradh.It 3171098217eSriastradhSet 3181098217eSriastradh.Fa bp Ns Li "->b_error" 3191098217eSriastradhto zero on success, or to an 3201098217eSriastradh.Xr errno 2 3211098217eSriastradherror code on failure. 3221098217eSriastradh.It 3231098217eSriastradhSet 3241098217eSriastradh.Fa bp Ns Li "->b_resid" 3251098217eSriastradhto the number of bytes remaining to transfer, whether on success or 3261098217eSriastradhon failure. 3275586a441SriastradhIf no bytes were transferred, this must be set to 3281098217eSriastradh.Fa bp Ns Li "->b_bcount" . 3291098217eSriastradh.It 3301098217eSriastradhCall 331a6a845b4Sriastradh.Fn biodone bp . 3321098217eSriastradh.El 3331098217eSriastradh.Sh FUNCTIONS 3341098217eSriastradh.Bl -tag -width abcd 3351098217eSriastradh.It Fn biodone bp 3361098217eSriastradhNotify that the I/O transfer described by 3371098217eSriastradh.Fa bp 3381098217eSriastradhhas completed. 3391098217eSriastradh.Pp 3401098217eSriastradhTo be called by a block device driver. 3411098217eSriastradhCaller must first set 3421098217eSriastradh.Fa bp Ns Li "->b_error" 3431098217eSriastradhto an error code and 3441098217eSriastradh.Fa bp Ns Li "->b_resid" 3451098217eSriastradhto the number of bytes remaining to transfer. 3461098217eSriastradh.It Fn biowait bp 3471098217eSriastradhWait for the synchronous I/O transfer described by 3481098217eSriastradh.Fa bp 3491098217eSriastradhto complete. 3501098217eSriastradhReturns the value of 3511098217eSriastradh.Fa bp Ns Li "->b_error" . 3521098217eSriastradh.Pp 3531098217eSriastradhTo be called by a user requesting the I/O transfer. 3541098217eSriastradh.Pp 3551098217eSriastradhMay not be called if 3561098217eSriastradh.Fa bp 35788f86411Sriastradhhas a callback or is asynchronous \(em that is, if 358ba2aeff9Sriastradh.Fa bp Ns Li "->b_iodone" 359ba2aeff9Sriastradhis set, or if 3601098217eSriastradh.Dv B_ASYNC 3611098217eSriastradhis set in 3621098217eSriastradh.Fa bp Ns Li "->b_flags" . 3631098217eSriastradh.It Fn getiobuf vp waitok 3641098217eSriastradhAllocate a 365b2d5d8d7Sriastradh.Vt "struct buf" 3661098217eSriastradhfor an I/O transfer. 3671098217eSriastradhIf 3681098217eSriastradh.Fa vp 369078e20efSriastradhis 370078e20efSriastradh.Pf non- Dv NULL , 371078e20efSriastradhthe transfer is associated with it. 3721098217eSriastradhIf 3731098217eSriastradh.Fa waitok 3741098217eSriastradhis false, 3756bcaafafSriastradhreturns 3766bcaafafSriastradh.Dv NULL 3776bcaafafSriastradhif none can be allocated immediately. 3781098217eSriastradh.Pp 379d05efdd6SriastradhThe resulting 380b2d5d8d7Sriastradh.Vt "struct buf" 381d05efdd6Sriastradhpointer must eventually be passed to 382d05efdd6Sriastradh.Fn putiobuf 383d05efdd6Sriastradhto release it. 384d05efdd6SriastradhDo 385d05efdd6Sriastradh.Em not 386d05efdd6Sriastradhuse 387d05efdd6Sriastradh.Xr brelse 9 . 388d05efdd6Sriastradh.Pp 389ba2aeff9SriastradhThe buffer may not be used for an asynchronous I/O transfer, because 390ba2aeff9Sriastradhthere is no way to know when it is completed and may be safely passed 391ba2aeff9Sriastradhto 392ba2aeff9Sriastradh.Fn putiobuf . 393ba2aeff9SriastradhAsynchronous I/O transfers are allowed only for buffers in the 394ba2aeff9Sriastradh.Xr buffercache 9 . 395ba2aeff9Sriastradh.Pp 3961098217eSriastradhMay sleep if 3971098217eSriastradh.Fa waitok 3981098217eSriastradhis true. 3991098217eSriastradh.It Fn putiobuf bp 4001098217eSriastradhFree 4011098217eSriastradh.Fa bp , 4021098217eSriastradhwhich must have been allocated by 4031098217eSriastradh.Fn getiobuf . 4041098217eSriastradhEither 4051098217eSriastradh.Fa bp 4061098217eSriastradhmust never have been submitted to a block device, or the I/O transfer 4071098217eSriastradhmust have completed. 4081098217eSriastradh.El 4091098217eSriastradh.Sh CODE REFERENCES 4101098217eSriastradhThe 4111098217eSriastradh.Nm 4121098217eSriastradhsubsystem is implemented in 4131098217eSriastradh.Pa sys/kern/vfs_bio.c . 4141098217eSriastradh.Sh SEE ALSO 4151098217eSriastradh.Xr buffercache 9 , 4161098217eSriastradh.Xr bufq 9 4171098217eSriastradh.Sh BUGS 4181098217eSriastradhThe 4191098217eSriastradh.Nm 42057ae0bf4Sriastradhabstraction provides no way to cancel an I/O transfer once it has been 4211098217eSriastradhsubmitted to a block device. 4221098217eSriastradh.Pp 4231098217eSriastradhThe 4241098217eSriastradh.Nm 4251098217eSriastradhabstraction provides no way to do I/O transfers with non-kernel pages, 4261098217eSriastradhe.g. directly to buffers in userland without copying into the kernel 4271098217eSriastradhfirst. 4281098217eSriastradh.Pp 4291098217eSriastradhThe 4301098217eSriastradh.Vt "struct buf" 4311098217eSriastradhtype is all mixed up with the 4321098217eSriastradh.Xr buffercache 9 . 4331098217eSriastradh.Pp 4341098217eSriastradhThe 4351098217eSriastradh.Nm 4361098217eSriastradhabstraction is a totally idiotic API design. 4371098217eSriastradh.Pp 4381098217eSriastradhThe 4391098217eSriastradh.Li v_numoutput 4401098217eSriastradhaccounting required of 4411098217eSriastradh.Nm 4421098217eSriastradhcallers is asinine. 443