Exemplo n.º 1
0
/*
 * osprd_process_request(d, req)
 *   Called when the user reads or writes a sector.
 *   Should perform the read or write, as appropriate.
 */
static void osprd_process_request(osprd_info_t *d, struct request *req)
{
	if (!blk_fs_request(req)) {
		end_request(req, 0);
		return;
	}

	// EXERCISE: Perform the read or write request by copying data between
	// our data array and the request's buffer.
	// Hint: The 'struct request' argument tells you what kind of request
	// this is, and which sectors are being read or written.
	// Read about 'struct request' in <linux/blkdev.h>.
	// Consider the 'req->sector', 'req->current_nr_sectors', and
	// 'req->buffer' members, and the rq_data_dir() function.

	// Your code here.
		//eprintk("Should process request...\n");
	if (rq_data_dir(req) == READ)
	{
		osp_spin_lock(&d->mutex);
		memcpy(req->buffer, d->data + req->sector * SECTOR_SIZE, req->current_nr_sectors * SECTOR_SIZE);
		osp_spin_unlock(&d->mutex);
	}
	else
	{
		osp_spin_lock(&d->mutex);
		memcpy(d->data + req->sector * SECTOR_SIZE, req->buffer, req->current_nr_sectors * SECTOR_SIZE);
		osp_spin_unlock(&d->mutex);
	}

	end_request(req, 1);
}
Exemplo n.º 2
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// DONE EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.

		// Your code here.
		if (filp->f_flags == (filp->f_flags | F_OSPRD_LOCKED)) {
			filp->f_flags &= ~F_OSPRD_LOCKED;
			if(filp_writable) {
				osp_spin_lock(&(d->mutex));
				d->write_lock_proc = -1;
				d->write_lock = 0;
				osp_spin_unlock(&(d->mutex));
			}
			else {
				osp_spin_lock(&(d->mutex));
				remove_from_read(&(d->read_lock_procs), current->pid);
				d->read_locks--;
				osp_spin_unlock(&(d->mutex));
			}
			// wake up tasks in wait queue:
			wake_up_all(&(d->blockq));
		}
		// This line avoids compiler warnings; you may remove it.
		// (void) filp_writable, (void) d;

	}
	return 0;
}
Exemplo n.º 3
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
        if (filp) {
                osprd_info_t *d = file2osprd(filp);
                int filp_writable = filp->f_mode & FMODE_WRITE;

                // EXERCISE: If the user closes a ramdisk file that holds
                // a lock, release the lock.  Also wake up blocked processes
                // as appropriate.

    osp_spin_lock(&d->mutex);
    if((filp->f_flags & F_OSPRD_LOCKED) == 0)
    {
      osp_spin_unlock(&d->mutex);
      return 0;
    }
    else
    {
      if(filp_writable != 0)
      {
        d->write_lock = 0;
                                d->write_lock_pid = -1;
      }
      else
      {
        d->read_locks--;
                                
                                // Clear this PID from the read lock list
                                pid_list_t prev = d->read_lock_pids;
                                pid_list_t curr = d->read_lock_pids;
                                while(curr != NULL)
                                {
                                        if(curr->pid == current->pid)
                                        {
            if(prev == NULL)
              d->read_lock_pids = curr->next;
            else
              prev->next = curr->next;
                                                break;
                                        }
                                        else
                                        {
                                                prev = curr;
                                                curr = curr->next;
                                        }
                                }
      }
      
      wake_up_all(&d->blockq);
    }
    osp_spin_unlock(&d->mutex);
                // This line avoids compiler warnings; you may remove it.
                (void) filp_writable, (void) d;

        }

        return 0;
}
Exemplo n.º 4
0
/*
 * osprd_process_request(d, req)
 *   Called when the user reads or writes a sector.
 *   Should perform the read or write, as appropriate.
 */
static void osprd_process_request(osprd_info_t *d, struct request *req)
{
	if (!blk_fs_request(req)) {
		end_request(req, 0);
		return;
	}

	// EXERCISE: Perform the read or write request by copying data between
	// our data array and the request's buffer.
	// Hint: The 'struct request' argument tells you what kind of request
	// this is, and which sectors are being read or written.
	// Read about 'struct request' in <linux/blkdev.h>.
	// Consider the 'req->sector', 'req->current_nr_sectors', and
	// 'req->buffer' members, and the rq_data_dir() function.
    //
    // req->sector == Target location
    // req->current_nr_sectors == Number of sectors in first segment of request
    // req->buffer == Map of first segment
    // rq_data_dir() == macro to get data direction(READ or WRITE)

	// Your code here.
    int sector = (int)(req->sector);
    uint8_t *ptr = d->data + (sector * SECTOR_SIZE);
    int size = (int)(req->current_nr_sectors * SECTOR_SIZE);
    // DEBUG: just prints that request was received

    //check that the ptr didn't go "off the end"
    if (ptr + size > d->data + SECTOR_SIZE*nsectors)
    {
        printk(KERN_WARNING "request past the end of the device!\n");
        end_request(req, 0);
    }

    //just copy the memory from the osprd_info struct to the request (it's a read)
    switch (rq_data_dir(req))
    {
        case READ:
            osp_spin_lock(&d->mutex);
            memcpy(req->buffer, ptr, size);
            osp_spin_unlock(&d->mutex);
            break;
        case WRITE:
            osp_spin_lock(&d->mutex);
            memcpy(ptr, req->buffer, size);
            osp_spin_unlock(&d->mutex);
            break;
        default: //error
            break;
    }
	end_request(req, 1);
}
Exemplo n.º 5
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.
		osp_spin_lock (&d->mutex);
		if (filp->f_flags & F_OSPRD_LOCKED)
		{	
			if (filp_writable)
			{
				d->number_write_lock --;
				d->write_lock_holder = -1;
			}

			else
			{
				d->number_read_lock--;
				int clearReturn = clear_current_reader(pid_list_head, pid_list_tail);
				if (clearReturn == -ENOTTY)
					return -ENOTTY;
			}
		}
		filp->f_flags = filp->f_flags & ~F_OSPRD_LOCKED;
		osp_spin_unlock (&d->mutex);
		wake_up_all (&(d->blockq));

			}

	return 0;
}
Exemplo n.º 6
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{

	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.

		// Your code here.
		osp_spin_lock(&d->mutex);

		if(filp->f_flags & F_OSPRD_LOCKED)
        {
			if (filp_writable != 0)
				d->write_locks--;
			else
				d->read_locks--;

			wake_up_all(&d->blockq);
            filp->f_flags &= !F_OSPRD_LOCKED;
		}
		osp_spin_unlock(&d->mutex);

		// This line avoids compiler warnings; you may remove it.
		// (void) filp_writable, (void) d;

	}

	return 0;
}
Exemplo n.º 7
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = ((filp->f_mode & FMODE_WRITE) != 0);
		int i;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.

		osp_spin_lock(&d->mutex);
		if (filp->f_flags & F_OSPRD_LOCKED) {
			if (filp_writable) {
				d->write_locked = 0;
				d->write_proc = -1;
			}
			else {
				d->num_read_locks--;
				for (i = 0; i < OSPRD_MAJOR; i++) {
					if (d->read_procs[i] == current->pid) {
						d->read_procs[i] = -1;
						break;
					}
				}
			}
		}

		filp->f_flags ^= F_OSPRD_LOCKED;
		osp_spin_unlock(&d->mutex);
		wake_up_all(&d->blockq);
	}

	return 0;
}
Exemplo n.º 8
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.
		osp_spin_lock (&d->mutex);
		if (filp->f_flags & F_OSPRD_LOCKED)
		{	
			if (filp_writable)
			{
				d->number_write_lock --;
				d->write_lock_holder = -1;
			}

			else
			{
				d->number_read_lock--;
				d->pid_list_head = list_remove_element(d->pid_list_head,current->pid);
				//if (d->pid_list_head == NULL)
				//	return -ENOTTY;
			}
		}
		filp->f_flags = filp->f_flags & ~F_OSPRD_LOCKED;
		osp_spin_unlock (&d->mutex);
		wake_up_all (&(d->blockq));
		//delete_check_deadlock_list (current->pid,d);
			}

	return 0;
}
Exemplo n.º 9
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
    if (filp) {
        osprd_info_t *d = file2osprd(filp);
        int filp_writable = filp->f_mode & FMODE_WRITE;

        // EXERCISE: If the user closes a ramdisk file that holds
        // a lock, release the lock.  Also wake up blocked processes
        // as appropriate.

        // Your code here.

        // This line avoids compiler warnings; you may remove it.
        (void) filp_writable, (void) d;
        osp_spin_lock(&d->mutex);
        remove_pid_from_pid_array(d->pid_array, d->pid_count, current->pid);
        d->pid_count--;
        d->n_write_locks = 0;
        d->n_read_locks = 0;
        osp_spin_unlock(&d->mutex);
        wake_up_all(&d->blockq);

    }

    return 0;
}
Exemplo n.º 10
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.
		
		if (filp->f_flags & F_OSPRD_LOCKED) {
			if (filp_writable) {
				if (d->write_lock == 1) d->write_lock = 0;
				else eprintk("file attempted to unlock write lock it didn't have\n");			
			}
			else {
				osp_spin_lock(&(d->mutex));

				if (d->read_lock > 0) d->read_lock--;
				else eprintk("file attempted to unlock read lock it didn't have\n");
				osp_spin_unlock(&(d->mutex));
			}			
		}

		wake_up_all(&(d->blockq));
	}

	return 0;
}
Exemplo n.º 11
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{

	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;
		pid_t pid = current->pid;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.

		// Your code here.
		// Check to make sure has lock
		if (!(filp->f_flags & F_OSPRD_LOCKED)) {
			return 0;
		}

		// Clear the locked flag
		filp->f_flags &= ~(F_OSPRD_LOCKED);

		// Increase the number of finished written tasks atomically if needed
		if(filp_writable) {
			osp_spin_lock(&d->mutex);
			d->ticket_head++;
			d->write_locks--;
			osp_spin_unlock(&d->mutex);
		}
		else {
			osp_spin_lock(&d->mutex);
			d->ticket_head++;
			d->read_locks--;
			osp_spin_unlock(&d->mutex);	
		}

		// This needs to be atomic to avoid nodes removing themselves
		// While others are checking the same list
		osp_spin_lock(&g_mutex);
		remove_node (&d->lock_list, pid);
		osp_spin_unlock(&g_mutex);

		// We're done with the lock, notify everyone
		wake_up_all(&d->blockq);
	}

	return 0;
}
Exemplo n.º 12
0
int check_dead_lock(int writable, osprd_info_t *d) {
	pid_node_t *pointer;
	if(writable) {
		osp_spin_lock(&(d->mutex));
		pointer = d->write_locking_pids.head;
		while(pointer) {
			if(pointer->pid == current->pid) {
				osp_spin_unlock(&(d->mutex));	
				return 1;
			}
			pointer = pointer->next;
		}

		pointer = d->read_locking_pids.head;
		while(pointer) {
			if(pointer->pid == current->pid) {
				osp_spin_unlock(&(d->mutex));	
				return 1;
			}
			pointer = pointer->next;
		}
	} else {
		osp_spin_lock(&(d->mutex));
		pointer = d->write_locking_pids.head;
		while(pointer) {
			if(pointer->pid == current->pid) {
				osp_spin_unlock(&(d->mutex));	
				return 1;
			}
			pointer = pointer->next;
		}

		pointer = d->read_locking_pids.head;
		while(pointer) {
			if(pointer->pid == current->pid && d->head_write == 1) {
				osp_spin_unlock(&(d->mutex));	
				return 1;
			}
			pointer = pointer->next;
		}

	}
	osp_spin_unlock(&(d->mutex));	
	return 0;
}
Exemplo n.º 13
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.

    printk("attempting to close and release\n");
		if ((filp->f_flags & F_OSPRD_LOCKED) != 0)
		{
		  printk("inside filp flag\n");
		  osp_spin_lock(&d->mutex);
		  filp->f_flags &= !F_OSPRD_LOCKED;
		  if (filp_writable)
		  {
		    d->num_write--;
		    d->write_pid = -1;
		  }
		  else
		  {
		    d->num_read--;
		    pid_list_t curr = d->read_pids;
		    // If first on the list
		    if (current->pid == curr->pid)
		      d->read_pids = curr->next;
		    else
		    {
		      while (curr->next != NULL)
		      {
		        // Find pid to skip over and connect
		        if (current->pid == curr->next->pid)
		        {
		          curr->next = curr->next->next;
		          break;
		        }
		        else
		          curr = curr->next;
		      }
		    }
		  }
		  wake_up_all(&d->blockq);
		  osp_spin_unlock(&d->mutex);
		  
		}

		// This line avoids compiler warnings; you may remove it.
		(void) filp_writable, (void) d;

	}

	return 0;
}
Exemplo n.º 14
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.

		// Your code here.
		
		if(!(filp->f_flags & F_OSPRD_LOCKED))
			return 0;
		
		osp_spin_lock(&d->mutex);
		
		if(filp_writable) {
			d->write_lock_count--;
			d->current_write_pid = -1;
			wake_up_all(&d->blockq);
		}
		else {
			d->read_lock_count--;
			process_queue_t temp = d->read_queue;
			process_queue_t placeholder = d->read_queue;
		
			while(placeholder != NULL) {
		
				if((placeholder->pid == current->pid) && (temp == NULL)) {
					d->read_queue = placeholder->next;
				}
				else if(placeholder->pid == current->pid) {
					temp->next = placeholder->next;
					break;
				}
			
				temp = placeholder;
				placeholder = placeholder->next;
			}
			
			wake_up_all(&d->blockq);
		}
		filp->f_flags &= ~F_OSPRD_LOCKED;
		osp_spin_unlock(&d->mutex);

		// This line avoids compiler warnings; you may remove it.
		(void) filp_writable, (void) d;

	}

	return 0;
}
Exemplo n.º 15
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.
		// eprintk("***************TRYING TO RELEASE*****************\n");

		// Your code here.
		osp_spin_lock(&(d->mutex));
		if(!d) return -1;
		if((filp->f_flags & F_OSPRD_LOCKED) == 0) {
			osp_spin_unlock(&(d->mutex));
			return 0;
		}
		if(filp_writable) {
			// eprintk("***************GOING TO REMOVE*****************\n");
			// osp_spin_lock(&(d->mutex));
			remove_pid_list(&(d->write_locking_pids), current->pid);
			// eprintk("***************WRITE LOCK LENGTH: %d*****************\n", d->write_locking_pids.size);
		} else {
			// osp_spin_lock(&(d->mutex));
			remove_pid_list(&(d->read_locking_pids), current->pid);			
		}
		
		if(d->write_locking_pids.size == 0 && d->read_locking_pids.size == 0) {
			filp->f_flags &= !F_OSPRD_LOCKED;
		}	
		osp_spin_unlock(&(d->mutex));

		wake_up_all(&(d->blockq));

		return 0;
	}

	return 0;
}
Exemplo n.º 16
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.

		// Your code here.
		osp_spin_lock(&(d->mutex));

		if (!pidInList(d->writeLockingPids, current->pid) && !(pidInList(d->readLockingPids, current->pid))) {
			osp_spin_unlock(&(d->mutex));
			return -EINVAL;
		}

		if (pidInList(d->writeLockingPids, current->pid)) {
			removeFromList(&(d->writeLockingPids), current->pid);	
		}

		if (pidInList(d->readLockingPids, current->pid)) {
			removeFromList(&(d->readLockingPids), current->pid);
		}

		if (d->readLockingPids == NULL && d->writeLockingPids == NULL) {
			filp->f_flags &= !F_OSPRD_LOCKED;
		}
		
		osp_spin_unlock(&(d->mutex));
		wake_up_all(&(d->blockq));

		// This line avoids compiler warnings; you may remove it.
		(void) filp_writable, (void) d;

	}

	return 0;
}
Exemplo n.º 17
0
int check_deadlock(osprd_info_t *d)
{
	//osp_spin_lock(&d->mutex);
	pid_list_t depend_head = d->check_deadlock_list_head;
	pid_list_t depend_tail = d->check_deadlock_list_tail;
	pid_list_t p = depend_head;
	if (p == NULL)
	{
		//osp_spin_unlock(&d->mutex);
		return 0;
	}
	eprintk ("haha1");
	if(pid_in_list(depend_head,depend_tail,current->pid,1))
	{	
		eprintk ("before return 1");
		//osp_spin_unlock(&d->mutex);
		return 1;
	}
	int i = 0;
	while(i < NOSPRD)
	{
		eprintk("in while loop");
		osprd_info_t *od = &osprds[i];
			if (od == d)
				continue;
		osp_spin_lock(&od->mutex);
		pid_list_t od_head = od->check_deadlock_list_head;
		pid_list_t od_tail = od->check_deadlock_list_tail;
		while(p!=NULL)
		{
			eprintk ("in second while loop");
			if(pid_in_list(od_head,od_tail,p->pid,0))
				{
					int count = find_pid_list(od_head,od_tail,p->pid);
					if(find_until_count(od_head,od_tail,current->pid,count))
						{
							eprintk ("before return1~");
							
							return 1;
						}
				}
			p = p->next;
				
		}
		osp_spin_unlock(&od->mutex);
		i++;

	}
	eprintk ("before return 0");
	//osp_spin_unlock(&od->mutex);
	return 0;
}
Exemplo n.º 18
0
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	int r;
	r = 0;
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.
		//r = osprd_ioctl (inode, filp, OSPRDIOCRELEASE, 0);
		// Your code here.

		// This line avoids compiler warnings; you may remove it.
		(void) filp_writable, (void) d;
		if (!(filp->f_flags & F_OSPRD_LOCKED))
			{r = -EINVAL; }
		
		// Otherwise, clear the lock from filp->f_flags, wake up
		// the wait queue, perform any additional accounting steps
		// you need, and return 0.
		else 
		{

			osp_spin_lock(&(d->mutex));
			// Clear lock flag.
			filp->f_flags &= ~F_OSPRD_LOCKED;
			//d->mutex.lock = 0;
			d->n_writel = 0;
			d->n_readl = 0;

				
			// Wake queue.
			if(waitqueue_active(&d->blockq) == 0){
				eprintk("Tail: %d head: %d\n", d->ticket_tail, d->ticket_head);				
				//d->ticket_head = d->ticket_tail;
				d->ticket_tail += d->desync;
				d->desync = 0;
			}
			
			
			osp_spin_unlock(&(d->mutex));	
			wake_up_all(&d->blockq);		
				
			r = 0;
		}

	}

	return r;
}
Exemplo n.º 19
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.

        // if the file held a write lock, want to release it.
        if (filp_writable)
        {
            osp_spin_lock(&d->mutex);
            if (d->write_lock)
            {
                d->write_lock = 0;
                d->write_lock_owner = -1;
            }
            wake_up_all(&d->blockq);
            osp_spin_unlock(&d->mutex);
        }
        else
        {
            osp_spin_lock(&d->mutex);
            if (d->read_locks && (filp->f_flags & F_OSPRD_LOCKED))
                d->read_locks--;
            if (!d->read_locks) //if this was the last lock to go
                wake_up_all(&d->blockq);
            osp_spin_unlock(&d->mutex);
        }

		// This line avoids compiler warnings; you may remove it.
		(void) filp_writable, (void) d;

	}

	return 0;
}
Exemplo n.º 20
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
//almost done
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		if (d != NULL) {
			osp_spinlock_t *lock = &(d->mutex);
			wait_queue_head_t *blockq = &(d->blockq);
			
			int readlock = in_pid_array(d->pid_read_lock, current->pid);
			int writelock = in_pid_array(d->pid_write_lock, current->pid);

			osp_spin_lock(lock);
			
			if (readlock) 
				remove_from_pid_array(&d->pid_read_lock, current->pid);
			if (writelock) 
				remove_from_pid_array(&d->pid_write_lock, current->pid);

			if (!readlock && !writelock) {
				osp_spin_unlock(lock);
				return -EINVAL;
			}
			
			if (readlock == NULL && writelock == NULL) {
				filp->f_flags &= !F_OSPRD_LOCKED;
			}
			
			osp_spin_unlock(lock);
			wake_up_all(blockq);
		}
		else
			return 1;
		
	}

	return 0;
}
Exemplo n.º 21
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
    if (filp) {
        osprd_info_t *d = file2osprd(filp);

        if (d == NULL)
            return 1;

        osp_spin_lock(&(d->mutex));

        // If the file hasn't locked the ramdisk, return -EINVAL
        if (!pidInList(d->writeLockingPids, current->pid) && !(pidInList(d->readLockingPids, current->pid)))
        {
            osp_spin_unlock(&(d->mutex));
            return -EINVAL;
        }

        if (pidInList(d->writeLockingPids, current->pid))
        {
            removeFromList(&d->writeLockingPids, current->pid);
        }

        if (pidInList(d->readLockingPids, current->pid))
        {
            removeFromList(&d->readLockingPids, current->pid);
        }

        // Clear the lock from filp->f_flags if no processes (not just current process) hold any lock.
        if (d->readLockingPids == NULL && d->writeLockingPids == NULL)
        {
            filp->f_flags &= !F_OSPRD_LOCKED;
        }

        osp_spin_unlock(&(d->mutex));
        wake_up_all(&(d->blockq));
    }

    return 0;
}
Exemplo n.º 22
0
Arquivo: osprd.c Projeto: micwa/ucla
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.

        osp_spin_lock(&d->mutex);

        if (try_release_lock(d, filp, filp_writable))
        {
            osp_spin_unlock(&d->mutex);
            wake_up_all(&d->blockq);
        }
        else
        {
            osp_spin_unlock(&d->mutex);
        }
	}
	return 0;
}
Exemplo n.º 23
0
/*
 * osprd_process_request(d, req)
 *   Called when the user reads or writes a sector.
 *   Should perform the read or write, as appropriate.
 */
static void osprd_process_request(osprd_info_t *d, struct request *req)
{
	if (!blk_fs_request(req)) {
		end_request(req, 0);
		return;
	}

	// EXERCISE: Perform the read or write request by copying data between
	// our data array and the request's buffer.
	// Hint: The 'struct request' argument tells you what kind of request
	// this is, and which sectors are being read or written.
	// Read about 'struct request' in <linux/blkdev.h>.
	// Consider the 'req->sector', 'req->current_nr_sectors', and
	// 'req->buffer' members, and the rq_data_dir() function.
	
	// Check for overwrite
	if (req->sector + req->current_nr_sectors > nsectors)
	  end_request(req, 0);

	// If reading request
	if (rq_data_dir(req) == READ)
	{
	  // Read to buffer sector from data
	  memcpy (req->buffer, 
	          d->data + req->sector * SECTOR_SIZE, 
	          req->current_nr_sectors * SECTOR_SIZE);
	}
	// Writing request
	else if (rq_data_dir(req) == WRITE)
	{
    osp_spin_lock(&d->mutex);
	  // Write to data sector from buffer
	  memcpy (d->data + req->sector * SECTOR_SIZE, 
	          req->buffer, 
	          req->current_nr_sectors * SECTOR_SIZE);
    osp_spin_unlock(&d->mutex);
	}
	else
    end_request(req, 0);
  
	end_request(req, 1);
}
Exemplo n.º 24
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.

		// Your code here.
		osp_spin_lock(&d->mutex);
		// When the file is closed;
		if ((filp->f_flags & F_OSPRD_LOCKED) != 0)
		{
			filp->f_flags &= ~F_OSPRD_LOCKED;
			if (filp_writable)
			{
				remove_from_list(d->write_locking_pids, current->pid);
				// eprintk("Write done!\n");
				// print_list(d->write_locking_pids);
			}
			else
			{
				remove_from_list(d->read_locking_pids, current->pid);
				// eprintk("Read done!\n");
				// print_list(d->read_locking_pids);
			}
			// eprintk("Locking command release!\n");
			wake_up_all(&d->blockq);
		}
		osp_spin_unlock(&d->mutex);

		// This line avoids compiler warnings; you may remove it.
		(void) filp_writable, (void) d;

	}

	return 0;
}
Exemplo n.º 25
0
Arquivo: osprd.c Projeto: tsleeve/lab2
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.

		// Your code here.

		// This line avoids compiler warnings; you may remove it.
		
		osp_spin_lock(&d->mutex);
		char wake = 't';
		if(d->readlockPids->num > 1)
		{
			findpid(d->readlockPids,current->pid,'r');
			wake = 'f';
		}
		else if(d->readlockPids->num == 1)
		{
			findpid(d->readlockPids,current->pid,'r');
			filp->f_flags &= ~F_OSPRD_LOCKED;
		}
		else //must be a writer.....
		{
			d->nwriters = 0;
			filp->f_flags &= ~F_OSPRD_LOCKED;
		}
		osp_spin_unlock(&d->mutex);
		if(wake == 't')
			wake_up_all(&d->blockq);
		(void) filp_writable, (void) d;
	return 0;
	}

	return 0;
}
Exemplo n.º 26
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
  if (filp) {
    osprd_info_t *d = file2osprd(filp);
    int filp_writable = filp->f_mode & FMODE_WRITE;
    
    // EXERCISE: If the user closes a ramdisk file that holds
    // a lock, release the lock.  Also wake up blocked processes
    // as appropriate.
    
    // Your code here.
    if(filp->f_flags & F_OSPRD_LOCKED)
      {
	osp_spin_lock(&d->mutex);
	if(filp_writable)
	  {
	    d->write_lock_size = 0;
	    d->write_pid = -1;
	  }
	else
	  { 
	    d->read_lock_size--;
	    release_read_lock(d->read_pids, NULL);
	  }
	if(d->read_lock_size == 0 && d->write_lock_size ==0)
	  wake_up_all(&d->blockq);
	filp->f_flags ^= F_OSPRD_LOCKED;
	osp_spin_unlock(&d->mutex);
      }
    
    
    // This line avoids compiler warnings; you may remove it.
    (void) filp_writable, (void) d;
    
  }
  
  return 0;
}
Exemplo n.º 27
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.

		// Your code here.
        // lock the mutex
        osp_spin_lock(&(d->mutex));
        if (filp_writable) {  //fire the writer
            if (filp->f_flags&F_OSPRD_LOCKED && d->num_writer!=0) {
                filp->f_flags &= ~F_OSPRD_LOCKED;
            }
            d->num_writer=0;
            d->current_popular_writer=-1;
        }else{               //a reader is tired of reading
            if (filp->f_flags && d->num_reader!=0) {
                d->num_reader--;
            }
            if (d->num_reader==0) {  //we can unlock if no reader is interested in reading
                filp->f_flags &= ~F_OSPRD_LOCKED;
            }
        }
        wake_up_all(&(d->blockq));
        osp_spin_unlock(&(d->mutex));

		// This line avoids compiler warnings; you may remove it.
		(void) filp_writable, (void) d;

	}

	return 0;
}
Exemplo n.º 28
0
// This function is called when a /dev/osprdX file is finally closed.
// (If the file descriptor was dup2ed, this function is called only when the
// last copy is closed.)
static int osprd_close_last(struct inode *inode, struct file *filp)
{
	if (filp) {
		osprd_info_t *d = file2osprd(filp);
		int filp_writable = filp->f_mode & FMODE_WRITE;

		// EXERCISE: If the user closes a ramdisk file that holds
		// a lock, release the lock.  Also wake up blocked processes
		// as appropriate.

		// Your code here.

		// This line avoids compiler warnings; you may remove it.
		(void) filp_writable, (void) d;
        if (!(filp->f_flags & F_OSPRD_LOCKED)) return -EINVAL; // file was not locked
        
        // file is locked case:
        osp_spin_lock(&(d->mutex));
        // lock while running and clear flag
        filp->f_flags = filp->f_flags & ~F_OSPRD_LOCKED;
        d->deadlock = 0;
        d->readLocks = 0;
        d->writeLocks = 0;
        
        int active = waitqueue_active(&d->blockq);
        if (active == 0) {
            d->ticket_tail = d->ticket_tail + d->numInterrupt;
            d->numInterrupt = 0;
        }
        osp_spin_unlock(&(d->mutex));
        wake_up_all(&d->blockq);
        // wake up all tasks in blocked queue
        return 0;
	}
	return 0;
}
Exemplo n.º 29
0
/*
 * osprd_ioctl(inode, filp, cmd, arg)
 *   Called to perform an ioctl on the named file.
 */
int osprd_ioctl(struct inode *inode, struct file *filp,
		unsigned int cmd, unsigned long arg)
{
	osprd_info_t *d = file2osprd(filp);	// device info
	int r = 0;			// return value: initially 0

	// is file open for writing?
	int filp_writable = (filp->f_mode & FMODE_WRITE) != 0;

	// This line avoids compiler warnings; you may remove it.
	(void) filp_writable, (void) d;

	// Set 'r' to the ioctl's return value: 0 on success, negative on error

	if (cmd == OSPRDIOCACQUIRE) {

		// EXERCISE: Lock the ramdisk.
		//
		// If *filp is open for writing (filp_writable), then attempt
		// to write-lock the ramdisk; otherwise attempt to read-lock
		// the ramdisk.
		//
                // This lock request must block using 'd->blockq' until:
		// 1) no other process holds a write lock;
		// 2) either the request is for a read lock, or no other process
		//    holds a read lock; and
		// 3) lock requests should be serviced in order, so no process
		//    that blocked earlier is still blocked waiting for the
		//    lock.
		//
		// If a process acquires a lock, mark this fact by setting
		// 'filp->f_flags |= F_OSPRD_LOCKED'.  You also need to
		// keep track of how many read and write locks are held:
		// change the 'osprd_info_t' structure to do this.
		//
		// Also wake up processes waiting on 'd->blockq' as needed.
		//
		// If the lock request would cause a deadlock, return -EDEADLK.
		// If the lock request blocks and is awoken by a signal, then
		// return -ERESTARTSYS.
		// Otherwise, if we can grant the lock request, return 0.

		// 'd->ticket_head' and 'd->ticket_tail' should help you
		// service lock requests in order.  These implement a ticket
		// order: 'ticket_tail' is the next ticket, and 'ticket_head'
		// is the ticket currently being served.  You should set a local
		// variable to 'd->ticket_head' and increment 'd->ticket_head'.
		// Then, block at least until 'd->ticket_tail == local_ticket'.
		// (Some of these operations are in a critical section and must
		// be protected by a spinlock; which ones?)

		// Your code here (instead of the next two lines).
		// eprintk("Attempting to acquire\n");
		// r = -ENOTTY;

        osp_spin_lock(&d->mutex);

        unsigned local_ticket = d->ticket_head++;
        osp_spin_unlock(&d->mutex);

        int wei_ret = wait_event_interruptible(d->blockq, d->write_locks == 0 &&
                            (!filp_writable || d->read_locks == 0) &&
                            d->ticket_tail == local_ticket);

        if(wei_ret == -ERESTARTSYS)
        {
            osp_spin_lock(&d->mutex);

            //if process is killed, ticket expires.
            //add to dead_ticket array
            //d->dt_len++;
            //d->dead_tickets[d->dt_len++] = local_ticket;

            d->dead_tickets[d->dt_len] = local_ticket;
            d->dt_len++;
            if (d->dt_len == d->dt_cap) {
                d->dt_cap *= 2;
                unsigned *temp_dt = kzalloc(sizeof(unsigned) *d->dt_cap,
                                        GFP_ATOMIC);
                memcpy(temp_dt, d->dead_tickets, sizeof(unsigned) *d->dt_len);
                kfree(d->dead_tickets);
                d->dead_tickets = temp_dt;
            }
            while (is_ticket_tail_dead(d)) {
                d->ticket_tail++;
            }
            osp_spin_unlock(&d->mutex);
            return -ERESTARTSYS;

        }

        osp_spin_lock(&d->mutex);

        if (filp_writable)
            d->write_locks++;
        else
            d->read_locks++;

        filp->f_flags |= F_OSPRD_LOCKED;

        do
        {
            d->ticket_tail++;

        } while (is_ticket_tail_dead(d));

        osp_spin_unlock(&d->mutex);


	} else if (cmd == OSPRDIOCTRYACQUIRE) {

		// EXERCISE: ATTEMPT to lock the ramdisk.
		//
		// This is just like OSPRDIOCACQUIRE, except it should never
		// block.  If OSPRDIOCACQUIRE would block or return deadlock,
		// OSPRDIOCTRYACQUIRE should return -EBUSY.
		// Otherwise, if we can grant the lock request, return 0.

		// Your code here (instead of the next two lines).

        osp_spin_lock(&d->mutex);

        if (d->write_locks == 0 &&
                (!filp_writable || d->read_locks == 0) &&
                d->ticket_tail == d->ticket_head)
        {

            if (filp_writable)
                d->write_locks++;
            else
                d->read_locks++;

            filp->f_flags |= F_OSPRD_LOCKED;

        }
        else
            r = -EBUSY;

        osp_spin_unlock(&d->mutex);

		//eprintk("Attempting to try acquire\n");
		//r = -ENOTTY;

	} else if (cmd == OSPRDIOCRELEASE) {

		// EXERCISE: Unlock the ramdisk.
		//
		// If the file hasn't locked the ramdisk, return -EINVAL.
		// Otherwise, clear the lock from filp->f_flags, wake up
		// the wait queue, perform any additional accounting steps
		// you need, and return 0.

		// Your code here (instead of the next line).
		osp_spin_lock(&d->mutex);

        if (!filp->f_flags & F_OSPRD_LOCKED)
            r = -EINVAL;
        else
        {
            if (filp_writable)
                d->write_locks--;
            else
                d->read_locks--;

            wake_up_all(&d->blockq);
            filp->f_flags &= !F_OSPRD_LOCKED;

        }

        osp_spin_unlock(&d->mutex);

        //r = -ENOTTY;

	} else
		r = -ENOTTY; /* unknown command */
	return r;
}
Exemplo n.º 30
0
int osprd_ioctl(struct inode *inode, struct file *filp,
		unsigned int cmd, unsigned long arg)
{
	osprd_info_t *d = file2osprd(filp);	// device info
	int r = 0;			// return value: initially 0

	// is file open for writing?
	int filp_writable = (filp->f_mode & FMODE_WRITE) != 0;

	// This line avoids compiler warnings; you may remove it.
	(void) filp_writable, (void) d;

	// Set 'r' to the ioctl's return value: 0 on success, negative on error
	int my_ticket = 0;
	int i;
	if (cmd == OSPRDIOCACQUIRE) {

		// EXERCISE: Lock the ramdisk.
		//
		// If *filp is open for writing (filp_writable), then attempt
		// to write-lock the ramdisk; otherwise attempt to read-lock
		// the ramdisk.
		//
                // This lock request must block using 'd->blockq' until:
		// 1) no other process holds a write lock;
		// 2) either the request is for a read lock, or no other process
		//    holds a read lock; and
		// 3) lock requests should be serviced in order, so no process
		//    that blocked earlier is still blocked waiting for the
		//    lock.
		//
		// If a process acquires a lock, mark this fact by setting
		// 'filp->f_flags |= F_OSPRD_LOCKED'.  You also need to
		// keep track of how many read and write locks are held:
		// change the 'osprd_info_t' structure to do this.
		//
		// Also wake up processes waiting on 'd->blockq' as needed.
		//
		// If the lock request would cause a deadlock, return -EDEADLK.
		// If the lock request blocks and is awoken by a signal, then
		// return -ERESTARTSYS.
		// Otherwise, if we can grant the lock request, return 0.

		// 'd->ticket_head' and 'd->ticket_tail' should help you
		// service lock requests in order.  These implement a ticket
		// order: 'ticket_tail' is the next ticket, and 'ticket_head'
		// is the ticket currently being served.  You should set a local
		// variable to 'd->ticket_head' and increment 'd->ticket_head'.
		// Then, block at least until 'd->ticket_tail == local_ticket'.
		// (Some of these operations are in a critical section and must
		// be protected by a spinlock; which ones?)

		
		//Checking for simple deadlock
		if (d->write_proc == current->pid)
			return -EDEADLK;
		//int i;
		for (i = 0; i < OSPRD_MAJOR; i++)
		{
			if (d->read_procs[i] == current->pid)
				return -EDEADLK;
		}
		//if (d->write_proc == current->pid)
		
		osp_spin_lock(&d->mutex);
		my_ticket = d->ticket_head;
		d->ticket_head++;
		osp_spin_unlock(&d->mutex);
		
		if (filp_writable) //may be inverted for incorrect logic
		{

			r = wait_event_interruptible(d->blockq, d->ticket_tail == my_ticket && d->write_locked == 0 && d->num_read_locked == 0);
			if (r == -ERESTARTSYS)
			{
				//reset_ticket_queues(my_ticket, d);
				if (my_ticket == d->ticket_tail)
					d->ticket_tail++;
				else
					d->ticket_head--;
				return -ERESTARTSYS;
			}
			osp_spin_lock(&d->mutex);
			d->write_proc = current->pid;
			d->write_locked = 1;
			
		
		}
		else //required for reading
		{
			r = wait_event_interruptible(d->blockq, d->ticket_tail >= my_ticket && d->write_locked == 0);
			if (r == -ERESTARTSYS)
			{
				if (my_ticket == d->ticket_tail)
					d->ticket_tail++;
				else
					d->ticket_head--;
				//reset_ticket_queues(my_ticket, d);
				return -ERESTARTSYS;
			}
			osp_spin_lock(&d->mutex);
			d->num_read_locked++;
			for (i = 0; i<OSPRD_MAJOR; i++)
			{
				if (d->read_procs[i] == -1)
				{
					d->read_procs[i] = current->pid;
					break;
				}
				
			}
		}
		d->ticket_tail++; 
		filp->f_flags |= F_OSPRD_LOCKED;
		osp_spin_unlock(&d->mutex);

	} else if (cmd == OSPRDIOCTRYACQUIRE) {

		// EXERCISE: ATTEMPT to lock the ramdisk.
		//
		// This is just like OSPRDIOCACQUIRE, except it should never
		// block.  If OSPRDIOCACQUIRE would block or return deadlock,
		// OSPRDIOCTRYACQUIRE should return -EBUSY.
		// Otherwise, if we can grant the lock request, return 0.

		// Your code here (instead of the next two lines).
		//if (d->write_proc == current->pid)
		//	return -EBUSY;
		//int i;
		if (filp_writable)
		{
			if (d->num_read_locked > 0 || d->write_locked == 1)
			{
				return -EBUSY;
			}
			//Otherwise acquire the write lock!
			osp_spin_lock(&d->mutex);
			//my_ticket = d->ticket_head++;
			d->write_locked = 1;
			d->write_proc = current->pid;
		}
		else //again the read case 
		{
			if (d->write_locked == 1)
				return -EBUSY;
			osp_spin_lock(&d->mutex);
			d->num_read_locked++;
			for (i = 0; i<OSPRD_MAJOR; i++)
			{
				if (d->read_procs[i] == -1)
				{
					d->read_procs[i] = current->pid;
					break;
				}
			}
		}
		d->ticket_tail++;
		d->ticket_head++;
		filp->f_flags |= F_OSPRD_LOCKED;
		osp_spin_unlock(&d->mutex);

	} else if (cmd == OSPRDIOCRELEASE) {

		// EXERCISE: Unlock the ramdisk.
		//
		// If the file hasn't locked the ramdisk, return -EINVAL.
		// Otherwise, clear the lock from filp->f_flags, wake up
		// the wait queue, perform any additional accounting steps
		// you need, and return 0.
		if ((filp->f_flags & F_OSPRD_LOCKED) == 0)
			return -EINVAL;
		osp_spin_lock(&d->mutex);
		if (filp_writable)
		{
			d->write_proc = -1;
			d->write_locked = 0;
		}
		else
		{
			d->num_read_locked--;
			for (i = 0; i<OSPRD_MAJOR; i++)
			{
				if(d->read_procs[i] == current->pid)
				{
					d->read_procs[i] = -1;
					break;
				}
			}
		}
		filp->f_flags ^= F_OSPRD_LOCKED;
		osp_spin_unlock(&d->mutex);
		wake_up_all(&d->blockq);
		r = 0;

	} else
		r = -ENOTTY; /* unknown command */
	return r;
}