From 3a0dbbb40e89ae0f0ec901c5fa831a2c1a5ca9a3 Mon Sep 17 00:00:00 2001 From: Cheyenne Wills Date: Wed, 1 Jun 2022 09:10:12 -0600 Subject: [PATCH 08/12] afs: introduce afs_alloc_ncr/afs_free_ncr There is duplicated code for initializing a nocache_read_request and also freeing the associated storage in certain cases. Create a set of helper functions that allocates and frees a nocache_read_request and its associated structures. afs_alloc_ncr allocates a nocache_read_request structure and if not UKERNEL, will allocate and initialize the associated uio and iovec structures. afs_free_ncr releases a noncache_read_request structure and the associated uio and iovec structures if not UKERNEL. Update locations that allocate/free nocache_read_request structures to use the new functions. Change-Id: I80c0b4eb036bcb1223b73f4c1de2c12be362de42 --- src/afs/LINUX/osi_vnodeops.c | 37 +++++++----------- src/afs/UKERNEL/afs_usrops.c | 8 +++- src/afs/afs_bypasscache.c | 73 +++++++++++++++++++++++++++++++----- src/afs/afs_bypasscache.h | 3 +- 4 files changed, 85 insertions(+), 36 deletions(-) diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index a0c78c04d..9b5d05471 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -2537,7 +2537,6 @@ afs_linux_bypass_readpages(struct file *fp, struct address_space *mapping, struct list_head *page_list, unsigned num_pages) { afs_int32 page_ix; - struct uio *auio; afs_offs_t offset; struct iovec* iovecp; struct nocache_read_request *ancr; @@ -2552,20 +2551,10 @@ afs_linux_bypass_readpages(struct file *fp, struct address_space *mapping, afs_int32 page_count = 0; afs_int32 isize; - /* background thread must free: iovecp, auio, ancr */ - iovecp = osi_Alloc(num_pages * sizeof(struct iovec)); - - auio = osi_Alloc(sizeof(struct uio)); - auio->uio_iov = iovecp; - auio->uio_iovcnt = num_pages; - auio->uio_flag = UIO_READ; - auio->uio_seg = AFS_UIOSYS; - auio->uio_resid = num_pages * PAGE_SIZE; - - ancr = osi_Alloc(sizeof(struct nocache_read_request)); - ancr->auio = auio; - ancr->offset = auio->uio_offset; - ancr->length = auio->uio_resid; + ancr = afs_alloc_ncr(num_pages); + if (ancr == NULL) + return afs_convert_code(ENOMEM); + iovecp = ancr->auio->uio_iov; afs_lru_cache_init(&lrupages); @@ -2587,7 +2576,7 @@ afs_linux_bypass_readpages(struct file *fp, struct address_space *mapping, if(page_ix == 0) { offset = page_offset(pp); - ancr->offset = auio->uio_offset = offset; + ancr->offset = ancr->auio->uio_offset = offset; base_index = pp->index; } iovecp[page_ix].iov_len = PAGE_SIZE; @@ -2626,14 +2615,13 @@ afs_linux_bypass_readpages(struct file *fp, struct address_space *mapping, if(page_count) { afs_lru_cache_finalize(&lrupages); credp = crref(); + /* background thread frees the ancr */ code = afs_ReadNoCache(avc, ancr, credp); crfree(credp); } else { /* If there is nothing for the background thread to handle, * it won't be freeing the things that we never gave it */ - osi_Free(iovecp, num_pages * sizeof(struct iovec)); - osi_Free(auio, sizeof(struct uio)); - osi_Free(ancr, sizeof(struct nocache_read_request)); + afs_free_ncr(&ancr); } /* we do not flush, release, or unmap pages--that will be * done for us by the background thread as each page comes in @@ -2665,8 +2653,13 @@ afs_linux_bypass_readpage(struct file *fp, struct page *pp) ClearPageError(pp); /* receiver frees */ - auio = osi_Alloc(sizeof(struct uio)); - iovecp = osi_Alloc(sizeof(struct iovec)); + ancr = afs_alloc_ncr(1); + if (ancr == NULL) { + SetPageError(pp); + return afs_convert_code(ENOMEM); + } + auio = ancr->auio; + iovecp = auio->uio_iov; /* address can be NULL, because we overwrite it with 'pp', below */ setup_uio(auio, iovecp, NULL, page_offset(pp), @@ -2676,8 +2669,6 @@ afs_linux_bypass_readpage(struct file *fp, struct page *pp) get_page(pp); /* see above */ auio->uio_iov->iov_base = (void*) pp; /* the background thread will free this */ - ancr = osi_Alloc(sizeof(struct nocache_read_request)); - ancr->auio = auio; ancr->offset = page_offset(pp); ancr->length = PAGE_SIZE; diff --git a/src/afs/UKERNEL/afs_usrops.c b/src/afs/UKERNEL/afs_usrops.c index 0e38fb84b..80403c5bd 100644 --- a/src/afs/UKERNEL/afs_usrops.c +++ b/src/afs/UKERNEL/afs_usrops.c @@ -2398,12 +2398,16 @@ uafs_pread_nocache_r(int fd, char *buf, int len, off_t offset) } /* these get freed in PrefetchNoCache, so... */ - bparms = afs_osi_Alloc(sizeof(struct nocache_read_request)); + bparms = afs_alloc_ncr(0); + if (bparms == NULL) { + errno = ENOMEM; + return -1; + } code = afs_CreateReq(&bparms->areq, get_user_struct()->u_cred); if (code) { afs_DestroyReq(bparms->areq); - afs_osi_Free(bparms, sizeof(struct nocache_read_request)); + afs_free_ncr(&bparms); errno = code; return -1; } diff --git a/src/afs/afs_bypasscache.c b/src/afs/afs_bypasscache.c index c51bd25c7..e13a32e9d 100644 --- a/src/afs/afs_bypasscache.c +++ b/src/afs/afs_bypasscache.c @@ -111,7 +111,68 @@ int cache_bypass_strategy = NEVER_BYPASS_CACHE; afs_size_t cache_bypass_threshold = AFS_CACHE_BYPASS_DISABLED; /* file size > threshold triggers bypass */ int cache_bypass_prefetch = 1; /* Should we do prefetching ? */ +/* + * Allocate and initialize nocache_read_request/uid/iovec + * Returns NULL if memory allocation error. + */ +struct nocache_read_request * +afs_alloc_ncr(unsigned num_pages) +{ + struct nocache_read_request *ancr = NULL; +#if !defined(UKERNEL) + struct uio *auio = NULL; + struct iovec *iovecp = NULL; +#endif + + ancr = osi_Alloc(sizeof(*ancr)); + if (ancr == NULL) + goto error; +#if !defined(UKERNEL) + iovecp = osi_Alloc(num_pages * sizeof(*iovecp)); + if (iovecp == NULL) + goto error; + + auio = osi_Alloc(sizeof(*auio)); + if (auio == NULL) + goto error; + auio->uio_iov = iovecp; + auio->uio_iovcnt = num_pages; + auio->uio_flag = UIO_READ; + auio->uio_seg = AFS_UIOSYS; + auio->uio_offset = 0; + auio->uio_resid = num_pages * PAGE_SIZE; + + ancr->auio = auio; + ancr->offset = auio->uio_offset; + ancr->length = auio->uio_resid; +#endif + + return ancr; + + error: +#if !defined(UKERNEL) + osi_Free(iovecp, num_pages * sizeof(*iovecp)); + osi_Free(auio, sizeof(*auio)); +#endif + osi_Free(ancr, sizeof(*ancr)); + return NULL; +} +/* + * Free a nocache_read_request and associated structures + */ +void +afs_free_ncr(struct nocache_read_request **ancr) +{ + if (*ancr == NULL) + return; +#if !defined(UKERNEL) + osi_Free((*ancr)->auio->uio_iov, (*ancr)->auio->uio_iovcnt * sizeof(struct iovec)); + osi_Free((*ancr)->auio, sizeof(struct uio)); +#endif + osi_Free(*ancr, sizeof(struct nocache_read_request)); + *ancr = NULL; +} /* * This is almost exactly like the PFlush() routine in afs_pioctl.c, * but that routine is static. We are about to change a file from @@ -517,10 +578,7 @@ cleanup: AFS_GLOCK(); afs_DestroyReq(areq); AFS_GUNLOCK(); - osi_Free(bparms->auio->uio_iov, - bparms->auio->uio_iovcnt * sizeof(struct iovec)); - osi_Free(bparms->auio, sizeof(struct uio)); - osi_Free(bparms, sizeof(struct nocache_read_request)); + afs_free_ncr(&bparms); return code; } @@ -647,12 +705,7 @@ done: afs_DestroyReq(areq); osi_Free(tcallspec, sizeof(struct tlocal1)); - osi_Free(bparms, sizeof(struct nocache_read_request)); -#ifndef UKERNEL - /* in UKERNEL, the "pages" are passed in */ - osi_Free(iovecp, auio->uio_iovcnt * sizeof(struct iovec)); - osi_Free(auio, sizeof(struct uio)); -#endif + afs_free_ncr(&bparms); return code; } #endif diff --git a/src/afs/afs_bypasscache.h b/src/afs/afs_bypasscache.h index 37c5669b3..0c7542dd6 100644 --- a/src/afs/afs_bypasscache.h +++ b/src/afs/afs_bypasscache.h @@ -103,7 +103,8 @@ enum cache_bypass_strategies extern int cache_bypass_prefetch; extern int cache_bypass_strategy; extern afs_size_t cache_bypass_threshold; - +struct nocache_read_request *afs_alloc_ncr(unsigned num_pages); +void afs_free_ncr(struct nocache_read_request **ancr); void afs_TransitionToBypass(struct vcache *, afs_ucred_t *, int); void afs_TransitionToCaching(struct vcache *, afs_ucred_t *, int); -- 2.36.1