Mercurial > illumos > illumos-gate
changeset 12039:4ba188c68c06 onnv_137
6821379 Cannot ftp get in binary mode of an Samfs offline file
author | Brian Utterback <Brian.Utterback@Sun.COM> |
---|---|
date | Mon, 29 Mar 2010 19:36:46 -0700 |
parents | a76f1fd5c122 |
children | 4962fe87590d |
files | usr/src/uts/common/fs/sockfs/socksyscalls.c |
diffstat | 1 files changed, 40 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fs/sockfs/socksyscalls.c Mon Mar 29 21:44:09 2010 -0400 +++ b/usr/src/uts/common/fs/sockfs/socksyscalls.c Mon Mar 29 19:36:46 2010 -0700 @@ -2247,6 +2247,7 @@ mblk_t *mp = NULL; int chain_size; int error; + clock_t deadlk_wait; short fflag; int ksize; struct vattr va; @@ -2277,12 +2278,27 @@ snfv = kmem_zalloc(sizeof (snf_vmap_desbinfo), KM_SLEEP); - /* Get vpm mappings for maxsize with read access */ - if (vpm_map_pages(fvp, fileoff, (size_t)maxsize, - (VPM_FETCHPAGE), snfv->snfv_vml, SNF_MAXVMAPS, - NULL, S_READ) != 0) { + /* + * Get vpm mappings for maxsize with read access. + * If the pages aren't available yet, we get + * DEADLK, so wait and try again a little later using + * an increasing wait. We might be here a long time. + * + * If delay_sig returns EINTR, be sure to exit and + * pass it up to the caller. + */ + deadlk_wait = 0; + while ((error = vpm_map_pages(fvp, fileoff, + (size_t)maxsize, (VPM_FETCHPAGE), snfv->snfv_vml, + SNF_MAXVMAPS, NULL, S_READ)) == EDEADLK) { + deadlk_wait += (deadlk_wait < 5) ? 1 : 4; + if ((error = delay_sig(deadlk_wait)) != 0) { + break; + } + } + if (error != 0) { kmem_free(snfv, sizeof (snf_vmap_desbinfo)); - error = EIO; + error = (error == EINTR) ? EINTR : EIO; goto out; } snfv->snfv_frtn.free_func = snf_vmap_desbfree; @@ -2359,14 +2375,28 @@ * because that's how error gets returned. * (segmap_getmapflt() never fails but segmap_fault() * does.) + * + * If the pages aren't available yet, we get + * DEADLK, so wait and try again a little later using + * an increasing wait. We might be here a long time. + * + * If delay_sig returns EINTR, be sure to exit and + * pass it up to the caller. */ - if (segmap_fault(kas.a_hat, segkmap, - (caddr_t)(uintptr_t)(((uintptr_t)base + mapoff) & - PAGEMASK), snfi->snfi_len, - F_SOFTLOCK, S_READ) != 0) { + deadlk_wait = 0; + while ((error = FC_ERRNO(segmap_fault(kas.a_hat, + segkmap, (caddr_t)(uintptr_t)(((uintptr_t)base + + mapoff) & PAGEMASK), snfi->snfi_len, F_SOFTLOCK, + S_READ))) == EDEADLK) { + deadlk_wait += (deadlk_wait < 5) ? 1 : 4; + if ((error = delay_sig(deadlk_wait)) != 0) { + break; + } + } + if (error != 0) { (void) segmap_release(segkmap, base, 0); kmem_free(snfi, sizeof (*snfi)); - error = EIO; + error = (error == EINTR) ? EINTR : EIO; goto out; } snfi->snfi_frtn.free_func = snf_smap_desbfree;