| 68 | }; |
| 69 | |
| 70 | static vm_object_t |
| 71 | sg_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, |
| 72 | vm_ooffset_t foff, struct ucred *cred) |
| 73 | { |
| 74 | struct sglist *sg; |
| 75 | vm_object_t object; |
| 76 | vm_pindex_t npages, pindex; |
| 77 | int i; |
| 78 | |
| 79 | /* |
| 80 | * Offset should be page aligned. |
| 81 | */ |
| 82 | if (foff & PAGE_MASK) |
| 83 | return (NULL); |
| 84 | |
| 85 | /* |
| 86 | * The scatter/gather list must only include page-aligned |
| 87 | * ranges. |
| 88 | */ |
| 89 | npages = 0; |
| 90 | sg = handle; |
| 91 | for (i = 0; i < sg->sg_nseg; i++) { |
| 92 | if ((sg->sg_segs[i].ss_paddr % PAGE_SIZE) != 0 || |
| 93 | (sg->sg_segs[i].ss_len % PAGE_SIZE) != 0) |
| 94 | return (NULL); |
| 95 | npages += sg->sg_segs[i].ss_len / PAGE_SIZE; |
| 96 | } |
| 97 | |
| 98 | /* |
| 99 | * The scatter/gather list has a fixed size. Refuse requests |
| 100 | * to map beyond that. |
| 101 | */ |
| 102 | size = round_page(size); |
| 103 | pindex = OFF_TO_IDX(foff) + OFF_TO_IDX(size); |
| 104 | if (pindex > npages || pindex < OFF_TO_IDX(foff) || |
| 105 | pindex < OFF_TO_IDX(size)) |
| 106 | return (NULL); |
| 107 | |
| 108 | /* |
| 109 | * Allocate a new object and associate it with the |
| 110 | * scatter/gather list. It is ok for our purposes to have |
| 111 | * multiple VM objects associated with the same scatter/gather |
| 112 | * list because scatter/gather lists are static. This is also |
| 113 | * simpler than ensuring a unique object per scatter/gather |
| 114 | * list. |
| 115 | */ |
| 116 | object = vm_object_allocate(OBJT_SG, npages); |
| 117 | object->handle = sglist_hold(sg); |
| 118 | TAILQ_INIT(&object->un_pager.sgp.sgp_pglist); |
| 119 | return (object); |
| 120 | } |
| 121 | |
| 122 | static void |
| 123 | sg_pager_dealloc(vm_object_t object) |
nothing calls this directly
no test coverage detected