patch-1.3.85 linux/fs/locks.c
Next file: linux/fs/nfs/nfsiod.c
Previous file: linux/fs/inode.c
Back to the patch index
Back to the overall index
- Lines: 101
- Date:
Mon Apr 8 12:13:18 1996
- Orig file:
v1.3.84/linux/fs/locks.c
- Orig date:
Fri Apr 5 13:35:28 1996
diff -u --recursive --new-file v1.3.84/linux/fs/locks.c linux/fs/locks.c
@@ -51,21 +51,24 @@
*
* Removed some race conditions in flock_lock_file(), marked other possible
* races. Just grep for FIXME to see them.
- * Dmitry Gorodchanin (begemot@bgm.rosprint.net), Feb 09, 1996.
+ * Dmitry Gorodchanin (begemot@bgm.rosprint.net), February 09, 1996.
*
* Addressed Dmitry's concerns. Deadlock checking no longer recursive.
* Lock allocation changed to GFP_ATOMIC as we can't afford to sleep
* once we've checked for blocking and deadlocking.
- * Andy Walker (andy@lysaker.kvaerner.no), Apr 03, 1996.
+ * Andy Walker (andy@lysaker.kvaerner.no), April 03, 1996.
*
* NOTE:
* Starting to look at mandatory locks - using SunOS as a model.
* Probably a configuration option because mandatory locking can cause
* all sorts of chaos with runaway processes.
+ *
+ * Initial implementation of mandatory locks. SunOS turned out to be
+ * a rotten model, so I implemented the "obvious" semantics.
+ * See 'linux/Documentation/mandatory.txt' for details.
+ * Andy Walker (andy@lysaker.kvaerner.no), April 06, 1996.
*/
-#include <asm/segment.h>
-
#include <linux/malloc.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -73,6 +76,7 @@
#include <linux/stat.h>
#include <linux/fcntl.h>
+#include <asm/segment.h>
#define OFFSET_MAX ((off_t)0x7fffffff) /* FIXME: move elsewhere? */
@@ -282,6 +286,63 @@
}
return;
+}
+
+int locks_verify(int read_write, struct inode *inode, struct file *filp,
+ unsigned int offset, unsigned int count)
+{
+ /* Candidates for mandatory locking have the setgid bit set
+ * but no group execute bit - an otherwise meaningless combination.
+ */
+ if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+ return (locks_locked_mandatory(read_write, inode, filp,
+ offset, count));
+ return (0);
+}
+
+int locks_locked_mandatory(int read_write, struct inode *inode,
+ struct file *filp, unsigned int offset,
+ unsigned int count)
+{
+ struct file_lock *fl;
+
+repeat:
+ /*
+ * Search the lock list for this inode for locks that conflict with
+ * the proposed read/write.
+ */
+ for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
+ if (fl->fl_flags == F_FLOCK ||
+ (fl->fl_flags == F_POSIX && fl->fl_owner == current))
+ continue;
+ if (fl->fl_end < offset ||
+ fl->fl_start >= offset + count)
+ continue;
+ /*
+ * 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 (filp && (filp->f_flags & O_NONBLOCK))
+ return (-EAGAIN);
+ if (current->signal & ~current->blocked)
+ return (-ERESTARTSYS);
+ if (posix_locks_deadlock(current, fl->fl_owner))
+ return (-EDEADLOCK);
+ interruptible_sleep_on(&fl->fl_wait);
+ if (current->signal & ~current->blocked)
+ return (-ERESTARTSYS);
+ /*
+ * 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;
+ }
+ }
+ return (0);
}
/* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this