- /* Did we set it? */
- if (*profile == NULL) {
- /*
- * No entries are available; this can only happen if all
- * of them are currently in the process of being reused;
- * if this happens, we sleep on the address of the first
- * element, and restart. This is less than ideal, but we
- * know it will work because we know that there will be a
- * wakeup on any entry currently in the process of being
- * reused.
- *
- * XXX Reccomend a two handed clock and more than 3 total
- * XXX cache entries at some point in the future.
- */
- /*
- * drop funnel and wait
- */
- (void)tsleep((void *)
- &global_user_profile_cache.profiles[0],
- PRIBIO, "app_profile", 0);
- goto restart;
- }
-
- /*
- * If it's currently busy, we've picked the one at the end of the
- * LRU list, but it's currently being actively used. We sleep on
- * its address and restart.
- */
- if ((*profile)->busy) {
- /*
- * drop funnel and wait
- */
- (void)tsleep((void *)
- *profile,
- PRIBIO, "app_profile", 0);
- goto restart;
- }
- (*profile)->busy = 1;
- (*profile)->user = user;
-
- /*
- * put dummy value in for now to get competing request to wait
- * above until we are finished
- *
- * Save the data_vp before setting it, so we can set it before
- * we kmem_free() or vrele(). If we don't do this, then we
- * have a potential funnel race condition we have to deal with.
- */
- data_vp = (*profile)->data_vp;
- (*profile)->data_vp = (struct vnode *)0xFFFFFFFF;
-
- /*
- * Age the cache here in all cases; this guarantees that we won't
- * be reusing only one entry over and over, once the system reaches
- * steady-state.
- */
- global_user_profile_cache.age+=1;
-
- if(data_vp != NULL) {
- kmem_free(kernel_map,
- (*profile)->buf_ptr, 4 * PAGE_SIZE);
- if ((*profile)->names_vp) {
- vnode_rele((*profile)->names_vp);
- (*profile)->names_vp = NULL;
- }
- vnode_rele(data_vp);
- }
-
- /* Try to open the appropriate users profile files */
- /* If neither file is present, try to create them */
- /* If one file is present and the other not, fail. */
- /* If the files do exist, check them for the app_file */
- /* requested and read it in if present */
-
- ret = kmem_alloc(kernel_map,
- (vm_offset_t *)&profile_data_string, PATH_MAX);
-
- if(ret) {
- (*profile)->data_vp = NULL;
- (*profile)->busy = 0;
- wakeup(*profile);
- return ENOMEM;
- }
-
- /* Split the buffer in half since we know the size of */
- /* our file path and our allocation is adequate for */
- /* both file path names */
- profile_names_string = profile_data_string + (PATH_MAX/2);
-
-
- strcpy(profile_data_string, cache_path);
- strcpy(profile_names_string, cache_path);
- profile_names_length = profile_data_length
- = strlen(profile_data_string);
- substring = profile_data_string + profile_data_length;
- sprintf(substring, "%x_data", user);
- substring = profile_names_string + profile_names_length;
- sprintf(substring, "%x_names", user);
-
- /* We now have the absolute file names */
-
- ret = kmem_alloc(kernel_map,
- (vm_offset_t *)&names_buf, 4 * PAGE_SIZE);
- if(ret) {
- kmem_free(kernel_map,
- (vm_offset_t)profile_data_string, PATH_MAX);
- (*profile)->data_vp = NULL;
- (*profile)->busy = 0;
- wakeup(*profile);
- return ENOMEM;
- }
-
- NDINIT(&nd_names, LOOKUP, FOLLOW | LOCKLEAF,
- UIO_SYSSPACE32, CAST_USER_ADDR_T(profile_names_string), &context);
- NDINIT(&nd_data, LOOKUP, FOLLOW | LOCKLEAF,
- UIO_SYSSPACE32, CAST_USER_ADDR_T(profile_data_string), &context);
-
- if ( (error = vn_open(&nd_data, FREAD | FWRITE, 0)) ) {
-#ifdef notdef
- printf("bsd_open_page_cache_files: CacheData file not found %s\n",
- profile_data_string);
-#endif
- kmem_free(kernel_map,
- (vm_offset_t)names_buf, 4 * PAGE_SIZE);
- kmem_free(kernel_map,
- (vm_offset_t)profile_data_string, PATH_MAX);
- (*profile)->data_vp = NULL;
- (*profile)->busy = 0;
- wakeup(*profile);
- return error;
- }
- data_vp = nd_data.ni_vp;
-
- if ( (error = vn_open(&nd_names, FREAD | FWRITE, 0)) ) {
- printf("bsd_open_page_cache_files: NamesData file not found %s\n",
- profile_data_string);
- kmem_free(kernel_map,
- (vm_offset_t)names_buf, 4 * PAGE_SIZE);
- kmem_free(kernel_map,
- (vm_offset_t)profile_data_string, PATH_MAX);
-
- vnode_rele(data_vp);
- vnode_put(data_vp);
-
- (*profile)->data_vp = NULL;
- (*profile)->busy = 0;
- wakeup(*profile);
- return error;
- }
- names_vp = nd_names.ni_vp;
-
- if ((error = vnode_size(names_vp, &file_size, &context)) != 0) {
- printf("bsd_open_page_cache_files: Can't stat name file %s\n", profile_names_string);
- kmem_free(kernel_map,
- (vm_offset_t)profile_data_string, PATH_MAX);
- kmem_free(kernel_map,
- (vm_offset_t)names_buf, 4 * PAGE_SIZE);
-
- vnode_rele(names_vp);
- vnode_put(names_vp);
- vnode_rele(data_vp);
- vnode_put(data_vp);
-
- (*profile)->data_vp = NULL;
- (*profile)->busy = 0;
- wakeup(*profile);
- return error;
- }
-
- size = file_size;
- if(size > 4 * PAGE_SIZE)
- size = 4 * PAGE_SIZE;
- buf_ptr = names_buf;
- resid_off = 0;
-
- while(size) {
- int resid_int;
- error = vn_rdwr(UIO_READ, names_vp, (caddr_t)buf_ptr,
- size, resid_off,
- UIO_SYSSPACE32, IO_NODELOCKED, kauth_cred_get(),
- &resid_int, p);
- resid = (vm_size_t) resid_int;
- if((error) || (size == resid)) {
- if(!error) {
- error = EINVAL;
- }
- kmem_free(kernel_map,
- (vm_offset_t)profile_data_string, PATH_MAX);
- kmem_free(kernel_map,
- (vm_offset_t)names_buf, 4 * PAGE_SIZE);
-
- vnode_rele(names_vp);
- vnode_put(names_vp);
- vnode_rele(data_vp);
- vnode_put(data_vp);
-
- (*profile)->data_vp = NULL;
- (*profile)->busy = 0;
- wakeup(*profile);
- return error;
- }
- buf_ptr += size-resid;
- resid_off += size-resid;
- size = resid;
- }
- kmem_free(kernel_map, (vm_offset_t)profile_data_string, PATH_MAX);
-
- (*profile)->names_vp = names_vp;
- (*profile)->data_vp = data_vp;
- (*profile)->buf_ptr = names_buf;
-
- /*
- * at this point, the both the names_vp and the data_vp have
- * both a valid usecount and an iocount held
- */
- return 0;
-
-}
-
-void
-bsd_close_page_cache_files(
- struct global_profile *profile)
-{
- vnode_put(profile->data_vp);
- vnode_put(profile->names_vp);
-
- profile->busy = 0;
- wakeup(profile);