patch-2.1.1 linux/fs/locks.c

Next file: linux/fs/ncpfs/dir.c
Previous file: linux/drivers/sound/soundcard.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.0/linux/fs/locks.c linux/fs/locks.c
@@ -127,7 +127,6 @@
 			   unsigned int wait);
 static int posix_locks_deadlock(struct task_struct *my_task,
 				struct task_struct *blocked_task);
-static int locks_overlap(struct file_lock *fl1, struct file_lock *fl2);
 static void posix_remove_locks(struct file_lock **before, struct task_struct *task);
 static void flock_remove_locks(struct file_lock **before, struct file *filp);
 
@@ -136,6 +135,10 @@
 static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait);
 static char *lock_get_status(struct file_lock *fl, char *p, int id, char *pfx);
 
+static void locks_insert_block(struct file_lock *blocker, struct file_lock *waiter);
+static void locks_delete_block(struct file_lock *blocker, struct file_lock *waiter);
+static void locks_wake_up_blocks(struct file_lock *blocker, unsigned int wait);
+
 static struct file_lock *file_lock_table = NULL;
 
 /* Free lock not inserted in any queue.
@@ -152,13 +155,21 @@
 	return;
 }
 
+/* Check if two locks overlap each other.
+ */
+static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2)
+{
+	return ((fl1->fl_end >= fl2->fl_start) &&
+		(fl2->fl_end >= fl1->fl_start));
+}
+
 /* Insert waiter into blocker's block list.
  * We use a circular list so that processes can be easily woken up in
  * the order they blocked. The documentation doesn't require this but
  * it seems seems like the reasonable thing to do.
  */
-static inline void locks_insert_block(struct file_lock *blocker, 
-				      struct file_lock *waiter)
+static void locks_insert_block(struct file_lock *blocker, 
+			       struct file_lock *waiter)
 {
 	struct file_lock *prevblock;
 
@@ -180,8 +191,8 @@
 /* Remove waiter from blocker's block list.
  * When blocker ends up pointing to itself then the list is empty.
  */
-static inline void locks_delete_block(struct file_lock *blocker,
-				      struct file_lock *waiter)
+static void locks_delete_block(struct file_lock *blocker,
+			       struct file_lock *waiter)
 {
 	struct file_lock *nextblock;
 	struct file_lock *prevblock;
@@ -206,8 +217,7 @@
  * If told to wait then schedule the processes until the block list
  * is empty, otherwise empty the block list ourselves.
  */
-static inline void locks_wake_up_blocks(struct file_lock *blocker,
-					unsigned int wait)
+static void locks_wake_up_blocks(struct file_lock *blocker, unsigned int wait)
 {
 	struct file_lock *waiter;
 
@@ -305,8 +315,7 @@
 	struct flock flock;
 	struct inode *inode;
 
-	/*
-	 * Get arguments and validate them ...
+	/* Get arguments and validate them ...
 	 */
 
 	if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd]))
@@ -493,21 +502,14 @@
 	if ((fl = inode->i_flock) == NULL || (fl->fl_flags & FL_FLOCK))
 		return (0);
 	
-	/*
-	 * Search the lock list for this inode for locks that conflict with
+	/* Search the lock list for this inode for locks that conflict with
 	 * the proposed read/write.
 	 */
 	while (fl != NULL) {
-		if (fl->fl_owner == current ||
-		    fl->fl_end < offset || fl->fl_start >= offset + count)
-			goto next_lock;
-
-		/*
-		 * Block for writes against a "read" lock,
+		/* Block for writes against a "read" lock,
 		 * and both reads and writes against a "write" lock.
 		 */
-		if ((read_write == FLOCK_VERIFY_WRITE) ||
-		    (fl->fl_type == F_WRLCK)) {
+		if (posix_locks_conflict(fl, &tfl)) {
 			if (filp && (filp->f_flags & O_NONBLOCK))
 				return (-EAGAIN);
 			if (current->signal & ~current->blocked)
@@ -521,15 +523,13 @@
 
 			if (current->signal & ~current->blocked)
 				return (-ERESTARTSYS);
-			/*
-			 * If we've been sleeping someone might have
+			/* If we've been sleeping someone might have
 			 * changed the permissions behind our back.
 			 */
 			if ((inode->i_mode & (S_ISGID | S_IXGRP)) != S_ISGID)
 				break;
 			goto repeat;
 		}
-	next_lock:
 		fl = fl->fl_next;
 	}
 #endif
@@ -675,14 +675,6 @@
 	return (0);	/* This should never happen */
 }
 
-/* Check if two locks overlap each other.
- */
-static int locks_overlap(struct file_lock *fl1, struct file_lock *fl2)
-{
-	return ((fl1->fl_end >= fl2->fl_start) &&
-		(fl2->fl_end >= fl1->fl_start));
-}
-
 /* This function tests for deadlock condition before putting a process to
  * sleep. The detection scheme is no longer recursive. Recursive was neat,
  * but dangerous - we risked stack corruption if the lock data was bad, or
@@ -777,11 +769,8 @@
 			interruptible_sleep_on(&new_fl->fl_wait);
 			locks_delete_block(fl, new_fl);
 			if (current->signal & ~current->blocked) {
-				/* If we are here, than we were awakened
-				 * by a signal, so new_fl is still in the
-				 * block queue of fl. We need to remove 
-				 * new_fl and then free it.
-				 * 	Dmitry Gorodchanin 09/02/96.
+				/* Awakened by a signal. Free the new
+				 * lock and return an error.
 				 */
 				locks_free_lock(new_fl);
 				return (-ERESTARTSYS);
@@ -795,8 +784,8 @@
 }
 
 /* Add a POSIX style lock to a file.
- * We merge adjacent locks whenever possible. POSIX locks come after FLOCK
- * locks in the list and are sorted by owner task, then by starting address
+ * We merge adjacent locks whenever possible. POSIX locks are sorted by owner
+ * task, then by starting address
  *
  * Kai Petzke writes:
  * To make freeing a lock much faster, we keep a pointer to the lock before the
@@ -839,18 +828,17 @@
 			fl = fl->fl_next;
   		}
   	}
-	/*
-	 * Find the first old lock with the same owner as the new lock.
+
+	/* Find the first old lock with the same owner as the new lock.
 	 */
 	
 	before = &filp->f_inode->i_flock;
 
-	/* First skip FLOCK locks and locks owned by other processes.
+	/* First skip locks owned by other processes.
 	 */
 	while ((fl = *before) && (caller->fl_owner != fl->fl_owner)) {
 		before = &fl->fl_next;
 	}
-	
 
 	/* Process locks with this owner.
 	 */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov