int GLWorker::SignalWorker(Work *work, bool worker_exit) { int ret = 0; if (worker_exit_) return -EINVAL; TRY_RETURN(pthread_mutex_lock(&lock_), "lock GLThread"); worker_work_ = work; worker_exit_ = worker_exit; ret = pthread_cond_signal(&work_ready_cond_); if (ret) { ALOGE("Failed to signal GLThread caller %d", ret); pthread_mutex_unlock(&lock_); return ret; } ret = pthread_cond_wait(&work_done_cond_, &lock_); if (ret) { ALOGE("Failed to wait on GLThread %d", ret); pthread_mutex_unlock(&lock_); return ret; } ret = worker_ret_; if (ret) { pthread_mutex_unlock(&lock_); return ret; } TRY_RETURN(pthread_mutex_unlock(&lock_), "unlock GLThread"); return ret; }
int GLWorker::Init() { int ret = 0; worker_work_ = NULL; worker_exit_ = false; worker_ret_ = -1; ret = pthread_cond_init(&work_ready_cond_, NULL); if (ret) { ALOGE("Failed to int GLThread condition %d", ret); return ret; } ret = pthread_cond_init(&work_done_cond_, NULL); if (ret) { ALOGE("Failed to int GLThread condition %d", ret); pthread_cond_destroy(&work_ready_cond_); return ret; } ret = pthread_mutex_init(&lock_, NULL); if (ret) { ALOGE("Failed to init GLThread lock %d", ret); pthread_cond_destroy(&work_ready_cond_); pthread_cond_destroy(&work_done_cond_); return ret; } ret = pthread_create(&thread_, NULL, StartRoutine, this); if (ret) { ALOGE("Failed to create GLThread %d", ret); pthread_cond_destroy(&work_ready_cond_); pthread_cond_destroy(&work_done_cond_); pthread_mutex_destroy(&lock_); return ret; } initialized_ = true; TRY_RETURN(pthread_mutex_lock(&lock_), "lock GLThread"); while (!worker_exit_ && worker_ret_ != 0) TRY(pthread_cond_wait(&work_done_cond_, &lock_), "wait on condition", goto out_unlock); ret = worker_ret_; out_unlock: int unlock_ret = pthread_mutex_unlock(&lock_); if (unlock_ret) { ret = unlock_ret; ALOGE("Failed to unlock GLThread %d", unlock_ret); } return ret; }
NTSTATUS LklMount(IN PDEVICE_OBJECT dev,IN PVPB vpb) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_OBJECT volume_device=NULL; PLKLVCB vcb = NULL; LARGE_INTEGER AllocationSize; ULONG ioctlSize; int sectors; PSTR dev_name; STATFS my_stat; ULONG rc; CHECK_OUT(dev == lklfsd.device, STATUS_INVALID_DEVICE_REQUEST); CHECK_OUT(FLAG_ON(lklfsd.flags, VFS_UNLOAD_PENDING),STATUS_UNRECOGNIZED_VOLUME); DbgPrint("Mount volume"); status = IoCreateDevice(lklfsd.driver, sizeof(LKLVCB), NULL, FILE_DEVICE_DISK_FILE_SYSTEM, 0, FALSE, &volume_device); CHECK_OUT(!NT_SUCCESS(status), status); if (dev->AlignmentRequirement > volume_device->AlignmentRequirement) volume_device->AlignmentRequirement = dev->AlignmentRequirement; CLEAR_FLAG(volume_device->Flags, DO_DEVICE_INITIALIZING); volume_device->StackSize = (CCHAR)(dev->StackSize+1); CreateVcb(volume_device,dev,vpb,&AllocationSize); vcb = (PLKLVCB) volume_device->DeviceExtension; if(!FLAG_ON(vcb->flags, VFS_VCB_FLAGS_VCB_INITIALIZED)) TRY_RETURN(STATUS_INSUFFICIENT_RESOURCES); // yup, here we read the disk geometry ioctlSize = sizeof(DISK_GEOMETRY); status = BlockDeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &vcb->disk_geometry, &ioctlSize); CHECK_OUT(!NT_SUCCESS(status), status); ioctlSize = sizeof(PARTITION_INFORMATION); status = BlockDeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &vcb->partition_information, &ioctlSize); CHECK_OUT(!NT_SUCCESS(status), status); int bytes_per_sector = 0; switch (vcb->disk_geometry.BytesPerSector) { case 256: bytes_per_sector = 8; break; case 512: bytes_per_sector = 9; break; case 1024: bytes_per_sector = 10; break; case 2048: bytes_per_sector = 11; break; case 4096: bytes_per_sector = 12; break; case 8192: bytes_per_sector = 13; break; } sectors = vcb->partition_information.PartitionLength.QuadPart >> bytes_per_sector; // try a linux mount if this fails, then we fail to mount // the volume ExAcquireResourceExclusiveLite(&(lklfsd.global_resource), TRUE); lklfsd.no_mounts++; status = sys_mount_wrapper(vcb->target_device, sectors, &vcb->linux_device); DbgPrint("Mounting device '%s' retstatus=%d", dev_name, status); ExFreePool(dev_name); RELEASE(&(lklfsd.global_resource)); CHECK_OUT(!NT_SUCCESS(status), status); //get info about the successfully mounted volume rc = sys_statfs_wrapper(vcb->linux_device.mnt, &my_stat); vpb->DeviceObject = volume_device; // complete vpb fields #define UNKNOWN_LABEL "Local Disk" CharToWchar(vpb->VolumeLabel, UNKNOWN_LABEL , sizeof(UNKNOWN_LABEL)); vpb->VolumeLabel[sizeof(UNKNOWN_LABEL)] = 0; vpb->VolumeLabelLength = sizeof(UNKNOWN_LABEL)*2; vpb->SerialNumber = my_stat.f_type; try_exit: if(!NT_SUCCESS(status)) { ExAcquireResourceExclusiveLite(&(lklfsd.global_resource), TRUE); lklfsd.no_mounts--; RELEASE(&(lklfsd.global_resource)); if(volume_device) { FreeVcb((PLKLVCB) volume_device->DeviceExtension); IoDeleteDevice(volume_device); } } return status; }
// // FSCTL_LOCK_VOLUME // NTSTATUS DDKAPI VfsLockVolume(PIRP irp, PIO_STACK_LOCATION stack_location) { NTSTATUS status = STATUS_UNSUCCESSFUL; PDEVICE_OBJECT device = NULL; PLKLVCB vcb; BOOLEAN notified = FALSE; BOOLEAN resource_acquired = FALSE; PFILE_OBJECT file_obj = NULL; // request to fs device not permited device = stack_location->DeviceObject; CHECK_OUT(device == lklfsd.device, STATUS_INVALID_DEVICE_REQUEST); // get vcb vcb = (PLKLVCB)device->DeviceExtension; ASSERT(vcb); // file object - should be the file object for a volume open, // even so we accept it for any open file file_obj = stack_location->FileObject; ASSERT(file_obj); // notify volume locked FsRtlNotifyVolumeEvent(file_obj, FSRTL_VOLUME_LOCK); notified = TRUE; // acquire vcb lock ExAcquireResourceSharedLite(&vcb->vcb_resource, TRUE); resource_acquired = TRUE; // check lock flag if (FLAG_ON(vcb->flags, VFS_VCB_FLAGS_VOLUME_LOCKED)) { VfsReportError("Volume already locked"); TRY_RETURN(STATUS_ACCESS_DENIED); } // abort if open files still exist if (vcb->open_count) { VfsReportError("Open files still exist"); TRY_RETURN(STATUS_ACCESS_DENIED); } // release lock RELEASE(&vcb->vcb_resource); resource_acquired = FALSE; // purge volume VfsPurgeVolume(vcb, TRUE); ExAcquireResourceExclusiveLite(&vcb->vcb_resource, TRUE); resource_acquired = TRUE; // if there are still open referneces we can't lock the volume if (vcb->reference_count > 1) { VfsReportError("Could not purge cached files"); TRY_RETURN(STATUS_ACCESS_DENIED); } // set flag in both vcb and vpb structures SET_FLAG(vcb->flags, VFS_VCB_FLAGS_VOLUME_LOCKED); SetVpbFlag(vcb->vpb, VFS_VCB_FLAGS_VOLUME_LOCKED); DbgPrint("*** Volume LOCKED ***\n"); status = STATUS_SUCCESS; try_exit: if (resource_acquired) RELEASE(&vcb->vcb_resource); if (!NT_SUCCESS(status) && notified) FsRtlNotifyVolumeEvent(file_obj, FSRTL_VOLUME_LOCK_FAILED); return status; }
// // IRP_MJ_DEVICE_CONTROL - is synchronous // NTSTATUS DDKAPI VfsDeviceControl(PDEVICE_OBJECT device, PIRP irp) { NTSTATUS status=STATUS_SUCCESS; BOOLEAN top_level; ULONG ioctl = 0; PIO_STACK_LOCATION stack_location = NULL; PIO_STACK_LOCATION next_stack_location = NULL; BOOLEAN complete_request = FALSE; PLKLVCB vcb = NULL; PLKLFCB fcb = NULL; PFILE_OBJECT file = NULL; PDEVICE_OBJECT targetDevice = NULL; ASSERT(device); ASSERT(irp); top_level = LklIsIrpTopLevel(irp); FsRtlEnterFileSystem(); stack_location = IoGetCurrentIrpStackLocation(irp); ASSERT(stack_location); ioctl = stack_location->Parameters.DeviceIoControl.IoControlCode; if (ioctl == IOCTL_PREPARE_TO_UNLOAD) { complete_request = TRUE; DbgPrint("Prepare to unload"); status = LklPrepareToUnload(device,irp); TRY_RETURN(status); } file = stack_location->FileObject; ASSERT(file); fcb = (PLKLFCB) file->FsContext; CHECK_OUT(fcb == NULL, STATUS_INVALID_PARAMETER); if (fcb->id.type == VCB) { vcb = (PLKLVCB) fcb; } else { vcb = fcb->vcb; } CHECK_OUT(vcb == NULL, STATUS_INVALID_PARAMETER); targetDevice = vcb->target_device; // Pass on the IOCTL to the driver below complete_request = FALSE; next_stack_location = IoGetNextIrpStackLocation(irp); *next_stack_location = *stack_location; IoSetCompletionRoutine(irp, LklIoctlCompletion, NULL, TRUE, TRUE, TRUE); status = IoCallDriver(targetDevice, irp); try_exit: if(complete_request) LklCompleteRequest(irp, status); if (top_level) IoSetTopLevelIrp(NULL); FsRtlExitFileSystem(); return status; }