diff options
author | J. Bruce Fields <bfields@redhat.com> | 2011-07-26 18:25:49 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2011-08-19 13:25:34 -0400 |
commit | 778fc546f749c588aa2f6cd50215d2715c374252 (patch) | |
tree | b3ffa04327884cd0491c3ee1677f0ffc589ebe9c /include/linux/fs.h | |
parent | 710b7216964d6455cf1b215c43b03a1a79008c7d (diff) |
locks: fix tracking of inprogress lease breaks
We currently use a bit in fl_flags to record whether a lease is being
broken, and set fl_type to the type (RDLCK or UNLCK) that it will
eventually have. This means that once the lease break starts, we forget
what the lease's type *used* to be. Breaking a read lease will then
result in blocking read opens, even though there's no conflict--because
the lease type is now F_UNLCK and we can no longer tell whether it was
previously a read or write lease.
So, instead keep fl_type as the original type (the type which we
enforce), and keep track of whether we're unlocking or merely
downgrading by replacing the single FL_INPROGRESS flag by
FL_UNLOCK_PENDING and FL_DOWNGRADE_PENDING flags.
To get this right we also need to track separate downgrade and break
times, to handle the case where a write-leased file gets conflicting
opens first for read, then later for write.
(I first considered just eliminating the downgrade behavior
completely--nfsv4 doesn't need it, and nobody as far as I can tell
actually uses it currently--but Jeremy Allison tells me that Windows
oplocks do behave this way, so Samba will probably use this some day.)
Reviewed-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'include/linux/fs.h')
-rw-r--r-- | include/linux/fs.h | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h index 327fdd4de85f..76460edf1648 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1065,7 +1065,8 @@ static inline int file_check_writeable(struct file *filp) | |||
1065 | #define FL_LEASE 32 /* lease held on this file */ | 1065 | #define FL_LEASE 32 /* lease held on this file */ |
1066 | #define FL_CLOSE 64 /* unlock on close */ | 1066 | #define FL_CLOSE 64 /* unlock on close */ |
1067 | #define FL_SLEEP 128 /* A blocking lock */ | 1067 | #define FL_SLEEP 128 /* A blocking lock */ |
1068 | #define FL_INPROGRESS 256 /* Lease is being broken */ | 1068 | #define FL_DOWNGRADE_PENDING 256 /* Lease is being downgraded */ |
1069 | #define FL_UNLOCK_PENDING 512 /* Lease is being broken */ | ||
1069 | 1070 | ||
1070 | /* | 1071 | /* |
1071 | * Special return value from posix_lock_file() and vfs_lock_file() for | 1072 | * Special return value from posix_lock_file() and vfs_lock_file() for |
@@ -1122,7 +1123,9 @@ struct file_lock { | |||
1122 | loff_t fl_end; | 1123 | loff_t fl_end; |
1123 | 1124 | ||
1124 | struct fasync_struct * fl_fasync; /* for lease break notifications */ | 1125 | struct fasync_struct * fl_fasync; /* for lease break notifications */ |
1125 | unsigned long fl_break_time; /* for nonblocking lease breaks */ | 1126 | /* for lease breaks: */ |
1127 | unsigned long fl_break_time; | ||
1128 | unsigned long fl_downgrade_time; | ||
1126 | 1129 | ||
1127 | const struct file_lock_operations *fl_ops; /* Callbacks for filesystems */ | 1130 | const struct file_lock_operations *fl_ops; /* Callbacks for filesystems */ |
1128 | const struct lock_manager_operations *fl_lmops; /* Callbacks for lockmanagers */ | 1131 | const struct lock_manager_operations *fl_lmops; /* Callbacks for lockmanagers */ |