aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ceph/locks.c58
-rw-r--r--fs/cifs/file.c26
-rw-r--r--fs/lockd/svcsubs.c20
-rw-r--r--fs/locks.c108
-rw-r--r--fs/nfs/delegation.c28
-rw-r--r--fs/nfs/nfs4state.c52
-rw-r--r--fs/nfs/pagelist.c8
-rw-r--r--fs/nfs/write.c30
-rw-r--r--fs/nfsd/nfs4state.c18
-rw-r--r--fs/read_write.c2
-rw-r--r--include/linux/fs.h3
11 files changed, 155 insertions, 198 deletions
diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c
index 917656ea8dcf..19beeed83233 100644
--- a/fs/ceph/locks.c
+++ b/fs/ceph/locks.c
@@ -253,18 +253,15 @@ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count)
253 *fcntl_count = 0; 253 *fcntl_count = 0;
254 *flock_count = 0; 254 *flock_count = 0;
255 255
256 spin_lock(&inode->i_lock);
257 for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
258 if (lock->fl_flags & FL_POSIX)
259 ++(*fcntl_count);
260 }
261
262 ctx = inode->i_flctx; 256 ctx = inode->i_flctx;
263 if (ctx) { 257 if (ctx) {
258 spin_lock(&inode->i_lock);
259 list_for_each_entry(lock, &ctx->flc_posix, fl_list)
260 ++(*fcntl_count);
264 list_for_each_entry(lock, &ctx->flc_flock, fl_list) 261 list_for_each_entry(lock, &ctx->flc_flock, fl_list)
265 ++(*flock_count); 262 ++(*flock_count);
263 spin_unlock(&inode->i_lock);
266 } 264 }
267 spin_unlock(&inode->i_lock);
268 dout("counted %d flock locks and %d fcntl locks", 265 dout("counted %d flock locks and %d fcntl locks",
269 *flock_count, *fcntl_count); 266 *flock_count, *fcntl_count);
270} 267}
@@ -279,7 +276,7 @@ int ceph_encode_locks_to_buffer(struct inode *inode,
279 int num_fcntl_locks, int num_flock_locks) 276 int num_fcntl_locks, int num_flock_locks)
280{ 277{
281 struct file_lock *lock; 278 struct file_lock *lock;
282 struct file_lock_context *ctx; 279 struct file_lock_context *ctx = inode->i_flctx;
283 int err = 0; 280 int err = 0;
284 int seen_fcntl = 0; 281 int seen_fcntl = 0;
285 int seen_flock = 0; 282 int seen_flock = 0;
@@ -288,34 +285,31 @@ int ceph_encode_locks_to_buffer(struct inode *inode,
288 dout("encoding %d flock and %d fcntl locks", num_flock_locks, 285 dout("encoding %d flock and %d fcntl locks", num_flock_locks,
289 num_fcntl_locks); 286 num_fcntl_locks);
290 287
288 if (!ctx)
289 return 0;
290
291 spin_lock(&inode->i_lock); 291 spin_lock(&inode->i_lock);
292 for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { 292 list_for_each_entry(lock, &ctx->flc_flock, fl_list) {
293 if (lock->fl_flags & FL_POSIX) { 293 ++seen_fcntl;
294 ++seen_fcntl; 294 if (seen_fcntl > num_fcntl_locks) {
295 if (seen_fcntl > num_fcntl_locks) { 295 err = -ENOSPC;
296 err = -ENOSPC; 296 goto fail;
297 goto fail;
298 }
299 err = lock_to_ceph_filelock(lock, &flocks[l]);
300 if (err)
301 goto fail;
302 ++l;
303 } 297 }
298 err = lock_to_ceph_filelock(lock, &flocks[l]);
299 if (err)
300 goto fail;
301 ++l;
304 } 302 }
305 303 list_for_each_entry(lock, &ctx->flc_flock, fl_list) {
306 ctx = inode->i_flctx; 304 ++seen_flock;
307 if (ctx) { 305 if (seen_flock > num_flock_locks) {
308 list_for_each_entry(lock, &ctx->flc_flock, fl_list) { 306 err = -ENOSPC;
309 ++seen_flock; 307 goto fail;
310 if (seen_flock > num_flock_locks) {
311 err = -ENOSPC;
312 goto fail;
313 }
314 err = lock_to_ceph_filelock(lock, &flocks[l]);
315 if (err)
316 goto fail;
317 ++l;
318 } 308 }
309 err = lock_to_ceph_filelock(lock, &flocks[l]);
310 if (err)
311 goto fail;
312 ++l;
319 } 313 }
320fail: 314fail:
321 spin_unlock(&inode->i_lock); 315 spin_unlock(&inode->i_lock);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 96b7e9b7706d..ea78f6f81ce2 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1109,11 +1109,6 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
1109 return rc; 1109 return rc;
1110} 1110}
1111 1111
1112/* copied from fs/locks.c with a name change */
1113#define cifs_for_each_lock(inode, lockp) \
1114 for (lockp = &inode->i_flock; *lockp != NULL; \
1115 lockp = &(*lockp)->fl_next)
1116
1117struct lock_to_push { 1112struct lock_to_push {
1118 struct list_head llist; 1113 struct list_head llist;
1119 __u64 offset; 1114 __u64 offset;
@@ -1128,8 +1123,9 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
1128{ 1123{
1129 struct inode *inode = cfile->dentry->d_inode; 1124 struct inode *inode = cfile->dentry->d_inode;
1130 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 1125 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1131 struct file_lock *flock, **before; 1126 struct file_lock *flock;
1132 unsigned int count = 0, i = 0; 1127 struct file_lock_context *flctx = inode->i_flctx;
1128 unsigned int count = 0, i;
1133 int rc = 0, xid, type; 1129 int rc = 0, xid, type;
1134 struct list_head locks_to_send, *el; 1130 struct list_head locks_to_send, *el;
1135 struct lock_to_push *lck, *tmp; 1131 struct lock_to_push *lck, *tmp;
@@ -1137,10 +1133,12 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
1137 1133
1138 xid = get_xid(); 1134 xid = get_xid();
1139 1135
1136 if (!flctx)
1137 goto out;
1138
1140 spin_lock(&inode->i_lock); 1139 spin_lock(&inode->i_lock);
1141 cifs_for_each_lock(inode, before) { 1140 list_for_each(el, &flctx->flc_posix) {
1142 if ((*before)->fl_flags & FL_POSIX) 1141 count++;
1143 count++;
1144 } 1142 }
1145 spin_unlock(&inode->i_lock); 1143 spin_unlock(&inode->i_lock);
1146 1144
@@ -1151,7 +1149,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
1151 * added to the list while we are holding cinode->lock_sem that 1149 * added to the list while we are holding cinode->lock_sem that
1152 * protects locking operations of this inode. 1150 * protects locking operations of this inode.
1153 */ 1151 */
1154 for (; i < count; i++) { 1152 for (i = 0; i < count; i++) {
1155 lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL); 1153 lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL);
1156 if (!lck) { 1154 if (!lck) {
1157 rc = -ENOMEM; 1155 rc = -ENOMEM;
@@ -1162,10 +1160,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
1162 1160
1163 el = locks_to_send.next; 1161 el = locks_to_send.next;
1164 spin_lock(&inode->i_lock); 1162 spin_lock(&inode->i_lock);
1165 cifs_for_each_lock(inode, before) { 1163 list_for_each_entry(flock, &flctx->flc_posix, fl_list) {
1166 flock = *before;
1167 if ((flock->fl_flags & FL_POSIX) == 0)
1168 continue;
1169 if (el == &locks_to_send) { 1164 if (el == &locks_to_send) {
1170 /* 1165 /*
1171 * The list ended. We don't have enough allocated 1166 * The list ended. We don't have enough allocated
@@ -1185,7 +1180,6 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
1185 lck->length = length; 1180 lck->length = length;
1186 lck->type = type; 1181 lck->type = type;
1187 lck->offset = flock->fl_start; 1182 lck->offset = flock->fl_start;
1188 el = el->next;
1189 } 1183 }
1190 spin_unlock(&inode->i_lock); 1184 spin_unlock(&inode->i_lock);
1191 1185
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index d12ff4e2dbe7..5300bb53835f 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -164,12 +164,15 @@ nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file,
164{ 164{
165 struct inode *inode = nlmsvc_file_inode(file); 165 struct inode *inode = nlmsvc_file_inode(file);
166 struct file_lock *fl; 166 struct file_lock *fl;
167 struct file_lock_context *flctx = inode->i_flctx;
167 struct nlm_host *lockhost; 168 struct nlm_host *lockhost;
168 169
170 if (!flctx || list_empty_careful(&flctx->flc_posix))
171 return 0;
169again: 172again:
170 file->f_locks = 0; 173 file->f_locks = 0;
171 spin_lock(&inode->i_lock); 174 spin_lock(&inode->i_lock);
172 for (fl = inode->i_flock; fl; fl = fl->fl_next) { 175 list_for_each_entry(fl, &flctx->flc_posix, fl_list) {
173 if (fl->fl_lmops != &nlmsvc_lock_operations) 176 if (fl->fl_lmops != &nlmsvc_lock_operations)
174 continue; 177 continue;
175 178
@@ -223,18 +226,21 @@ nlm_file_inuse(struct nlm_file *file)
223{ 226{
224 struct inode *inode = nlmsvc_file_inode(file); 227 struct inode *inode = nlmsvc_file_inode(file);
225 struct file_lock *fl; 228 struct file_lock *fl;
229 struct file_lock_context *flctx = inode->i_flctx;
226 230
227 if (file->f_count || !list_empty(&file->f_blocks) || file->f_shares) 231 if (file->f_count || !list_empty(&file->f_blocks) || file->f_shares)
228 return 1; 232 return 1;
229 233
230 spin_lock(&inode->i_lock); 234 if (flctx && !list_empty_careful(&flctx->flc_posix)) {
231 for (fl = inode->i_flock; fl; fl = fl->fl_next) { 235 spin_lock(&inode->i_lock);
232 if (fl->fl_lmops == &nlmsvc_lock_operations) { 236 list_for_each_entry(fl, &flctx->flc_posix, fl_list) {
233 spin_unlock(&inode->i_lock); 237 if (fl->fl_lmops == &nlmsvc_lock_operations) {
234 return 1; 238 spin_unlock(&inode->i_lock);
239 return 1;
240 }
235 } 241 }
242 spin_unlock(&inode->i_lock);
236 } 243 }
237 spin_unlock(&inode->i_lock);
238 file->f_locks = 0; 244 file->f_locks = 0;
239 return 0; 245 return 0;
240} 246}
diff --git a/fs/locks.c b/fs/locks.c
index 055df53f19de..e50bb4d9e757 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -157,9 +157,6 @@ static int target_leasetype(struct file_lock *fl)
157int leases_enable = 1; 157int leases_enable = 1;
158int lease_break_time = 45; 158int lease_break_time = 45;
159 159
160#define for_each_lock(inode, lockp) \
161 for (lockp = &inode->i_flock; *lockp != NULL; lockp = &(*lockp)->fl_next)
162
163/* 160/*
164 * The global file_lock_list is only used for displaying /proc/locks, so we 161 * The global file_lock_list is only used for displaying /proc/locks, so we
165 * keep a list on each CPU, with each list protected by its own spinlock via 162 * keep a list on each CPU, with each list protected by its own spinlock via
@@ -218,6 +215,7 @@ locks_get_lock_context(struct inode *inode)
218 goto out; 215 goto out;
219 216
220 INIT_LIST_HEAD(&new->flc_flock); 217 INIT_LIST_HEAD(&new->flc_flock);
218 INIT_LIST_HEAD(&new->flc_posix);
221 219
222 /* 220 /*
223 * Assign the pointer if it's not already assigned. If it is, then 221 * Assign the pointer if it's not already assigned. If it is, then
@@ -241,6 +239,7 @@ locks_free_lock_context(struct file_lock_context *ctx)
241{ 239{
242 if (ctx) { 240 if (ctx) {
243 WARN_ON_ONCE(!list_empty(&ctx->flc_flock)); 241 WARN_ON_ONCE(!list_empty(&ctx->flc_flock));
242 WARN_ON_ONCE(!list_empty(&ctx->flc_posix));
244 kmem_cache_free(flctx_cache, ctx); 243 kmem_cache_free(flctx_cache, ctx);
245 } 244 }
246} 245}
@@ -809,21 +808,26 @@ void
809posix_test_lock(struct file *filp, struct file_lock *fl) 808posix_test_lock(struct file *filp, struct file_lock *fl)
810{ 809{
811 struct file_lock *cfl; 810 struct file_lock *cfl;
811 struct file_lock_context *ctx;
812 struct inode *inode = file_inode(filp); 812 struct inode *inode = file_inode(filp);
813 813
814 ctx = inode->i_flctx;
815 if (!ctx || list_empty_careful(&ctx->flc_posix)) {
816 fl->fl_type = F_UNLCK;
817 return;
818 }
819
814 spin_lock(&inode->i_lock); 820 spin_lock(&inode->i_lock);
815 for (cfl = file_inode(filp)->i_flock; cfl; cfl = cfl->fl_next) { 821 list_for_each_entry(cfl, &ctx->flc_posix, fl_list) {
816 if (!IS_POSIX(cfl)) 822 if (posix_locks_conflict(fl, cfl)) {
817 continue; 823 locks_copy_conflock(fl, cfl);
818 if (posix_locks_conflict(fl, cfl)) 824 if (cfl->fl_nspid)
819 break; 825 fl->fl_pid = pid_vnr(cfl->fl_nspid);
826 goto out;
827 }
820 } 828 }
821 if (cfl) { 829 fl->fl_type = F_UNLCK;
822 locks_copy_conflock(fl, cfl); 830out:
823 if (cfl->fl_nspid)
824 fl->fl_pid = pid_vnr(cfl->fl_nspid);
825 } else
826 fl->fl_type = F_UNLCK;
827 spin_unlock(&inode->i_lock); 831 spin_unlock(&inode->i_lock);
828 return; 832 return;
829} 833}
@@ -983,16 +987,20 @@ out:
983 987
984static int __posix_lock_file(struct inode *inode, struct file_lock *request, struct file_lock *conflock) 988static int __posix_lock_file(struct inode *inode, struct file_lock *request, struct file_lock *conflock)
985{ 989{
986 struct file_lock *fl; 990 struct file_lock *fl, *tmp;
987 struct file_lock *new_fl = NULL; 991 struct file_lock *new_fl = NULL;
988 struct file_lock *new_fl2 = NULL; 992 struct file_lock *new_fl2 = NULL;
989 struct file_lock *left = NULL; 993 struct file_lock *left = NULL;
990 struct file_lock *right = NULL; 994 struct file_lock *right = NULL;
991 struct file_lock **before; 995 struct file_lock_context *ctx;
992 int error; 996 int error;
993 bool added = false; 997 bool added = false;
994 LIST_HEAD(dispose); 998 LIST_HEAD(dispose);
995 999
1000 ctx = locks_get_lock_context(inode);
1001 if (!ctx)
1002 return -ENOMEM;
1003
996 /* 1004 /*
997 * We may need two file_lock structures for this operation, 1005 * We may need two file_lock structures for this operation,
998 * so we get them in advance to avoid races. 1006 * so we get them in advance to avoid races.
@@ -1013,8 +1021,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
1013 * blocker's list of waiters and the global blocked_hash. 1021 * blocker's list of waiters and the global blocked_hash.
1014 */ 1022 */
1015 if (request->fl_type != F_UNLCK) { 1023 if (request->fl_type != F_UNLCK) {
1016 for_each_lock(inode, before) { 1024 list_for_each_entry(fl, &ctx->flc_posix, fl_list) {
1017 fl = *before;
1018 if (!IS_POSIX(fl)) 1025 if (!IS_POSIX(fl))
1019 continue; 1026 continue;
1020 if (!posix_locks_conflict(request, fl)) 1027 if (!posix_locks_conflict(request, fl))
@@ -1044,29 +1051,25 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
1044 if (request->fl_flags & FL_ACCESS) 1051 if (request->fl_flags & FL_ACCESS)
1045 goto out; 1052 goto out;
1046 1053
1047 /* 1054 /* Find the first old lock with the same owner as the new lock */
1048 * Find the first old lock with the same owner as the new lock. 1055 list_for_each_entry(fl, &ctx->flc_posix, fl_list) {
1049 */ 1056 if (posix_same_owner(request, fl))
1050 1057 break;
1051 before = &inode->i_flock;
1052
1053 /* First skip locks owned by other processes. */
1054 while ((fl = *before) && (!IS_POSIX(fl) ||
1055 !posix_same_owner(request, fl))) {
1056 before = &fl->fl_next;
1057 } 1058 }
1058 1059
1059 /* Process locks with this owner. */ 1060 /* Process locks with this owner. */
1060 while ((fl = *before) && posix_same_owner(request, fl)) { 1061 list_for_each_entry_safe_from(fl, tmp, &ctx->flc_posix, fl_list) {
1061 /* Detect adjacent or overlapping regions (if same lock type) 1062 if (!posix_same_owner(request, fl))
1062 */ 1063 break;
1064
1065 /* Detect adjacent or overlapping regions (if same lock type) */
1063 if (request->fl_type == fl->fl_type) { 1066 if (request->fl_type == fl->fl_type) {
1064 /* In all comparisons of start vs end, use 1067 /* In all comparisons of start vs end, use
1065 * "start - 1" rather than "end + 1". If end 1068 * "start - 1" rather than "end + 1". If end
1066 * is OFFSET_MAX, end + 1 will become negative. 1069 * is OFFSET_MAX, end + 1 will become negative.
1067 */ 1070 */
1068 if (fl->fl_end < request->fl_start - 1) 1071 if (fl->fl_end < request->fl_start - 1)
1069 goto next_lock; 1072 continue;
1070 /* If the next lock in the list has entirely bigger 1073 /* If the next lock in the list has entirely bigger
1071 * addresses than the new one, insert the lock here. 1074 * addresses than the new one, insert the lock here.
1072 */ 1075 */
@@ -1087,18 +1090,17 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
1087 else 1090 else
1088 request->fl_end = fl->fl_end; 1091 request->fl_end = fl->fl_end;
1089 if (added) { 1092 if (added) {
1090 locks_delete_lock(before, &dispose); 1093 locks_delete_lock_ctx(fl, &dispose);
1091 continue; 1094 continue;
1092 } 1095 }
1093 request = fl; 1096 request = fl;
1094 added = true; 1097 added = true;
1095 } 1098 } else {
1096 else {
1097 /* Processing for different lock types is a bit 1099 /* Processing for different lock types is a bit
1098 * more complex. 1100 * more complex.
1099 */ 1101 */
1100 if (fl->fl_end < request->fl_start) 1102 if (fl->fl_end < request->fl_start)
1101 goto next_lock; 1103 continue;
1102 if (fl->fl_start > request->fl_end) 1104 if (fl->fl_start > request->fl_end)
1103 break; 1105 break;
1104 if (request->fl_type == F_UNLCK) 1106 if (request->fl_type == F_UNLCK)
@@ -1117,7 +1119,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
1117 * one (This may happen several times). 1119 * one (This may happen several times).
1118 */ 1120 */
1119 if (added) { 1121 if (added) {
1120 locks_delete_lock(before, &dispose); 1122 locks_delete_lock_ctx(fl, &dispose);
1121 continue; 1123 continue;
1122 } 1124 }
1123 /* 1125 /*
@@ -1133,15 +1135,11 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
1133 locks_copy_lock(new_fl, request); 1135 locks_copy_lock(new_fl, request);
1134 request = new_fl; 1136 request = new_fl;
1135 new_fl = NULL; 1137 new_fl = NULL;
1136 locks_delete_lock(before, &dispose); 1138 locks_insert_lock_ctx(request, &fl->fl_list);
1137 locks_insert_lock(before, request); 1139 locks_delete_lock_ctx(fl, &dispose);
1138 added = true; 1140 added = true;
1139 } 1141 }
1140 } 1142 }
1141 /* Go on to next lock.
1142 */
1143 next_lock:
1144 before = &fl->fl_next;
1145 } 1143 }
1146 1144
1147 /* 1145 /*
@@ -1166,7 +1164,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
1166 goto out; 1164 goto out;
1167 } 1165 }
1168 locks_copy_lock(new_fl, request); 1166 locks_copy_lock(new_fl, request);
1169 locks_insert_lock(before, new_fl); 1167 locks_insert_lock_ctx(new_fl, &fl->fl_list);
1170 new_fl = NULL; 1168 new_fl = NULL;
1171 } 1169 }
1172 if (right) { 1170 if (right) {
@@ -1177,7 +1175,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
1177 left = new_fl2; 1175 left = new_fl2;
1178 new_fl2 = NULL; 1176 new_fl2 = NULL;
1179 locks_copy_lock(left, right); 1177 locks_copy_lock(left, right);
1180 locks_insert_lock(before, left); 1178 locks_insert_lock_ctx(left, &fl->fl_list);
1181 } 1179 }
1182 right->fl_start = request->fl_end + 1; 1180 right->fl_start = request->fl_end + 1;
1183 locks_wake_up_blocks(right); 1181 locks_wake_up_blocks(right);
@@ -1257,22 +1255,29 @@ EXPORT_SYMBOL(posix_lock_file_wait);
1257 */ 1255 */
1258int locks_mandatory_locked(struct file *file) 1256int locks_mandatory_locked(struct file *file)
1259{ 1257{
1258 int ret;
1260 struct inode *inode = file_inode(file); 1259 struct inode *inode = file_inode(file);
1260 struct file_lock_context *ctx;
1261 struct file_lock *fl; 1261 struct file_lock *fl;
1262 1262
1263 ctx = inode->i_flctx;
1264 if (!ctx || list_empty_careful(&ctx->flc_posix))
1265 return 0;
1266
1263 /* 1267 /*
1264 * Search the lock list for this inode for any POSIX locks. 1268 * Search the lock list for this inode for any POSIX locks.
1265 */ 1269 */
1266 spin_lock(&inode->i_lock); 1270 spin_lock(&inode->i_lock);
1267 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { 1271 ret = 0;
1268 if (!IS_POSIX(fl)) 1272 list_for_each_entry(fl, &ctx->flc_posix, fl_list) {
1269 continue;
1270 if (fl->fl_owner != current->files && 1273 if (fl->fl_owner != current->files &&
1271 fl->fl_owner != file) 1274 fl->fl_owner != file) {
1275 ret = -EAGAIN;
1272 break; 1276 break;
1277 }
1273 } 1278 }
1274 spin_unlock(&inode->i_lock); 1279 spin_unlock(&inode->i_lock);
1275 return fl ? -EAGAIN : 0; 1280 return ret;
1276} 1281}
1277 1282
1278/** 1283/**
@@ -2389,13 +2394,14 @@ out:
2389void locks_remove_posix(struct file *filp, fl_owner_t owner) 2394void locks_remove_posix(struct file *filp, fl_owner_t owner)
2390{ 2395{
2391 struct file_lock lock; 2396 struct file_lock lock;
2397 struct file_lock_context *ctx = file_inode(filp)->i_flctx;
2392 2398
2393 /* 2399 /*
2394 * If there are no locks held on this file, we don't need to call 2400 * If there are no locks held on this file, we don't need to call
2395 * posix_lock_file(). Another process could be setting a lock on this 2401 * posix_lock_file(). Another process could be setting a lock on this
2396 * file at the same time, but we wouldn't remove that lock anyway. 2402 * file at the same time, but we wouldn't remove that lock anyway.
2397 */ 2403 */
2398 if (!file_inode(filp)->i_flock) 2404 if (!ctx || list_empty(&ctx->flc_posix))
2399 return; 2405 return;
2400 2406
2401 lock.fl_type = F_UNLCK; 2407 lock.fl_type = F_UNLCK;
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 9f9f67b17e2b..3fb1caa3874d 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -85,17 +85,17 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
85{ 85{
86 struct inode *inode = state->inode; 86 struct inode *inode = state->inode;
87 struct file_lock *fl; 87 struct file_lock *fl;
88 struct file_lock_context *flctx; 88 struct file_lock_context *flctx = inode->i_flctx;
89 struct list_head *list;
89 int status = 0; 90 int status = 0;
90 91
91 if (inode->i_flock == NULL && inode->i_flctx == NULL) 92 if (flctx == NULL)
92 goto out; 93 goto out;
93 94
94 /* Protect inode->i_flock using the i_lock */ 95 list = &flctx->flc_posix;
95 spin_lock(&inode->i_lock); 96 spin_lock(&inode->i_lock);
96 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { 97restart:
97 if (!(fl->fl_flags & (FL_POSIX))) 98 list_for_each_entry(fl, list, fl_list) {
98 continue;
99 if (nfs_file_open_context(fl->fl_file) != ctx) 99 if (nfs_file_open_context(fl->fl_file) != ctx)
100 continue; 100 continue;
101 spin_unlock(&inode->i_lock); 101 spin_unlock(&inode->i_lock);
@@ -104,19 +104,9 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
104 goto out; 104 goto out;
105 spin_lock(&inode->i_lock); 105 spin_lock(&inode->i_lock);
106 } 106 }
107 107 if (list == &flctx->flc_posix) {
108 flctx = inode->i_flctx; 108 list = &flctx->flc_flock;
109 if (flctx) { 109 goto restart;
110 list_for_each_entry(fl, &flctx->flc_flock, fl_list) {
111 if (nfs_file_open_context(fl->fl_file) != ctx)
112 continue;
113 spin_unlock(&inode->i_lock);
114 status = nfs4_lock_delegation_recall(fl, state,
115 stateid);
116 if (status < 0)
117 goto out;
118 spin_lock(&inode->i_lock);
119 }
120 } 110 }
121 spin_unlock(&inode->i_lock); 111 spin_unlock(&inode->i_lock);
122out: 112out:
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 65c404bf61ae..6084c267f3a0 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1367,53 +1367,18 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
1367 struct file_lock *fl; 1367 struct file_lock *fl;
1368 int status = 0; 1368 int status = 0;
1369 struct file_lock_context *flctx = inode->i_flctx; 1369 struct file_lock_context *flctx = inode->i_flctx;
1370 struct list_head *list;
1370 1371
1371 if (inode->i_flock == NULL && flctx == NULL) 1372 if (flctx == NULL)
1372 return 0; 1373 return 0;
1373 1374
1375 list = &flctx->flc_posix;
1376
1374 /* Guard against delegation returns and new lock/unlock calls */ 1377 /* Guard against delegation returns and new lock/unlock calls */
1375 down_write(&nfsi->rwsem); 1378 down_write(&nfsi->rwsem);
1376 /* Protect inode->i_flock using the BKL */
1377 spin_lock(&inode->i_lock); 1379 spin_lock(&inode->i_lock);
1378 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { 1380restart:
1379 if (!(fl->fl_flags & FL_POSIX)) 1381 list_for_each_entry(fl, list, fl_list) {
1380 continue;
1381 if (nfs_file_open_context(fl->fl_file)->state != state)
1382 continue;
1383 spin_unlock(&inode->i_lock);
1384 status = ops->recover_lock(state, fl);
1385 switch (status) {
1386 case 0:
1387 break;
1388 case -ESTALE:
1389 case -NFS4ERR_ADMIN_REVOKED:
1390 case -NFS4ERR_STALE_STATEID:
1391 case -NFS4ERR_BAD_STATEID:
1392 case -NFS4ERR_EXPIRED:
1393 case -NFS4ERR_NO_GRACE:
1394 case -NFS4ERR_STALE_CLIENTID:
1395 case -NFS4ERR_BADSESSION:
1396 case -NFS4ERR_BADSLOT:
1397 case -NFS4ERR_BAD_HIGH_SLOT:
1398 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
1399 goto out;
1400 default:
1401 printk(KERN_ERR "NFS: %s: unhandled error %d\n",
1402 __func__, status);
1403 case -ENOMEM:
1404 case -NFS4ERR_DENIED:
1405 case -NFS4ERR_RECLAIM_BAD:
1406 case -NFS4ERR_RECLAIM_CONFLICT:
1407 /* kill_proc(fl->fl_pid, SIGLOST, 1); */
1408 status = 0;
1409 }
1410 spin_lock(&inode->i_lock);
1411 }
1412
1413 if (!flctx)
1414 goto out_unlock;
1415
1416 list_for_each_entry(fl, &flctx->flc_flock, fl_list) {
1417 if (nfs_file_open_context(fl->fl_file)->state != state) 1382 if (nfs_file_open_context(fl->fl_file)->state != state)
1418 continue; 1383 continue;
1419 spin_unlock(&inode->i_lock); 1384 spin_unlock(&inode->i_lock);
@@ -1445,7 +1410,10 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
1445 } 1410 }
1446 spin_lock(&inode->i_lock); 1411 spin_lock(&inode->i_lock);
1447 } 1412 }
1448out_unlock: 1413 if (list == &flctx->flc_posix) {
1414 list = &flctx->flc_flock;
1415 goto restart;
1416 }
1449 spin_unlock(&inode->i_lock); 1417 spin_unlock(&inode->i_lock);
1450out: 1418out:
1451 up_write(&nfsi->rwsem); 1419 up_write(&nfsi->rwsem);
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index a3b62e15b444..29c7f33c9cf1 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -831,12 +831,10 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev,
831 if (prev) { 831 if (prev) {
832 if (!nfs_match_open_context(req->wb_context, prev->wb_context)) 832 if (!nfs_match_open_context(req->wb_context, prev->wb_context))
833 return false; 833 return false;
834 if (req->wb_context->dentry->d_inode->i_flock != NULL &&
835 !nfs_match_lock_context(req->wb_lock_context,
836 prev->wb_lock_context))
837 return false;
838 flctx = req->wb_context->dentry->d_inode->i_flctx; 834 flctx = req->wb_context->dentry->d_inode->i_flctx;
839 if (flctx != NULL && !list_empty_careful(&flctx->flc_flock) && 835 if (flctx != NULL &&
836 !(list_empty_careful(&flctx->flc_posix) &&
837 list_empty_careful(&flctx->flc_flock)) &&
840 !nfs_match_lock_context(req->wb_lock_context, 838 !nfs_match_lock_context(req->wb_lock_context,
841 prev->wb_lock_context)) 839 prev->wb_lock_context))
842 return false; 840 return false;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index e072aeb34195..784c13485b3f 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1091,6 +1091,7 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
1091{ 1091{
1092 struct nfs_open_context *ctx = nfs_file_open_context(file); 1092 struct nfs_open_context *ctx = nfs_file_open_context(file);
1093 struct nfs_lock_context *l_ctx; 1093 struct nfs_lock_context *l_ctx;
1094 struct file_lock_context *flctx = file_inode(file)->i_flctx;
1094 struct nfs_page *req; 1095 struct nfs_page *req;
1095 int do_flush, status; 1096 int do_flush, status;
1096 /* 1097 /*
@@ -1109,12 +1110,9 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
1109 do_flush = req->wb_page != page || req->wb_context != ctx; 1110 do_flush = req->wb_page != page || req->wb_context != ctx;
1110 /* for now, flush if more than 1 request in page_group */ 1111 /* for now, flush if more than 1 request in page_group */
1111 do_flush |= req->wb_this_page != req; 1112 do_flush |= req->wb_this_page != req;
1112 if (l_ctx && ctx->dentry->d_inode->i_flock != NULL) { 1113 if (l_ctx && flctx &&
1113 do_flush |= l_ctx->lockowner.l_owner != current->files 1114 !(list_empty_careful(&flctx->flc_posix) &&
1114 || l_ctx->lockowner.l_pid != current->tgid; 1115 list_empty_careful(&flctx->flc_flock))) {
1115 }
1116 if (l_ctx && ctx->dentry->d_inode->i_flctx &&
1117 !list_empty_careful(&ctx->dentry->d_inode->i_flctx->flc_flock)) {
1118 do_flush |= l_ctx->lockowner.l_owner != current->files 1116 do_flush |= l_ctx->lockowner.l_owner != current->files
1119 || l_ctx->lockowner.l_pid != current->tgid; 1117 || l_ctx->lockowner.l_pid != current->tgid;
1120 } 1118 }
@@ -1202,26 +1200,24 @@ static int nfs_can_extend_write(struct file *file, struct page *page, struct ino
1202 return 0; 1200 return 0;
1203 if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) 1201 if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE))
1204 return 1; 1202 return 1;
1205 if (!inode->i_flock && !flctx) 1203 if (!flctx || (list_empty_careful(&flctx->flc_flock) &&
1204 list_empty_careful(&flctx->flc_posix)))
1206 return 0; 1205 return 0;
1207 1206
1208 /* Check to see if there are whole file write locks */ 1207 /* Check to see if there are whole file write locks */
1209 spin_lock(&inode->i_lock);
1210 ret = 0; 1208 ret = 0;
1211 1209 spin_lock(&inode->i_lock);
1212 fl = inode->i_flock; 1210 if (!list_empty(&flctx->flc_posix)) {
1213 if (fl && is_whole_file_wrlock(fl)) { 1211 fl = list_first_entry(&flctx->flc_posix, struct file_lock,
1214 ret = 1; 1212 fl_list);
1215 goto out; 1213 if (is_whole_file_wrlock(fl))
1216 } 1214 ret = 1;
1217 1215 } else if (!list_empty(&flctx->flc_flock)) {
1218 if (!list_empty(&flctx->flc_flock)) {
1219 fl = list_first_entry(&flctx->flc_flock, struct file_lock, 1216 fl = list_first_entry(&flctx->flc_flock, struct file_lock,
1220 fl_list); 1217 fl_list);
1221 if (fl->fl_type == F_WRLCK) 1218 if (fl->fl_type == F_WRLCK)
1222 ret = 1; 1219 ret = 1;
1223 } 1220 }
1224out:
1225 spin_unlock(&inode->i_lock); 1221 spin_unlock(&inode->i_lock);
1226 return ret; 1222 return ret;
1227} 1223}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index c06a1ba80d73..fad821991369 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -5556,10 +5556,11 @@ out_nfserr:
5556static bool 5556static bool
5557check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) 5557check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
5558{ 5558{
5559 struct file_lock **flpp; 5559 struct file_lock *fl;
5560 int status = false; 5560 int status = false;
5561 struct file *filp = find_any_file(fp); 5561 struct file *filp = find_any_file(fp);
5562 struct inode *inode; 5562 struct inode *inode;
5563 struct file_lock_context *flctx;
5563 5564
5564 if (!filp) { 5565 if (!filp) {
5565 /* Any valid lock stateid should have some sort of access */ 5566 /* Any valid lock stateid should have some sort of access */
@@ -5568,15 +5569,18 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
5568 } 5569 }
5569 5570
5570 inode = file_inode(filp); 5571 inode = file_inode(filp);
5572 flctx = inode->i_flctx;
5571 5573
5572 spin_lock(&inode->i_lock); 5574 if (flctx && !list_empty_careful(&flctx->flc_posix)) {
5573 for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) { 5575 spin_lock(&inode->i_lock);
5574 if ((*flpp)->fl_owner == (fl_owner_t)lowner) { 5576 list_for_each_entry(fl, &flctx->flc_posix, fl_list) {
5575 status = true; 5577 if (fl->fl_owner == (fl_owner_t)lowner) {
5576 break; 5578 status = true;
5579 break;
5580 }
5577 } 5581 }
5582 spin_unlock(&inode->i_lock);
5578 } 5583 }
5579 spin_unlock(&inode->i_lock);
5580 fput(filp); 5584 fput(filp);
5581 return status; 5585 return status;
5582} 5586}
diff --git a/fs/read_write.c b/fs/read_write.c
index c0805c93b6fa..4060691e78f7 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -358,7 +358,7 @@ int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t
358 return retval; 358 return retval;
359 } 359 }
360 360
361 if (unlikely(inode->i_flock && mandatory_lock(inode))) { 361 if (unlikely(inode->i_flctx && mandatory_lock(inode))) {
362 retval = locks_mandatory_area( 362 retval = locks_mandatory_area(
363 read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, 363 read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
364 inode, file, pos, count); 364 inode, file, pos, count);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index dec0d38b05de..571f113588e9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -968,6 +968,7 @@ struct file_lock {
968 968
969struct file_lock_context { 969struct file_lock_context {
970 struct list_head flc_flock; 970 struct list_head flc_flock;
971 struct list_head flc_posix;
971}; 972};
972 973
973/* The following constant reflects the upper bound of the file/locking space */ 974/* The following constant reflects the upper bound of the file/locking space */
@@ -1971,7 +1972,7 @@ static inline int locks_verify_truncate(struct inode *inode,
1971 struct file *filp, 1972 struct file *filp,
1972 loff_t size) 1973 loff_t size)
1973{ 1974{
1974 if (inode->i_flock && mandatory_lock(inode)) 1975 if (inode->i_flctx && mandatory_lock(inode))
1975 return locks_mandatory_area( 1976 return locks_mandatory_area(
1976 FLOCK_VERIFY_WRITE, inode, filp, 1977 FLOCK_VERIFY_WRITE, inode, filp,
1977 size < inode->i_size ? size : inode->i_size, 1978 size < inode->i_size ? size : inode->i_size,