diff options
| -rw-r--r-- | fs/ceph/locks.c | 17 | ||||
| -rw-r--r-- | fs/ceph/mds_client.c | 42 |
2 files changed, 44 insertions, 15 deletions
diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c index 087afe9ca367..40abde93c345 100644 --- a/fs/ceph/locks.c +++ b/fs/ceph/locks.c | |||
| @@ -181,8 +181,9 @@ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count) | |||
| 181 | * Encode the flock and fcntl locks for the given inode into the pagelist. | 181 | * Encode the flock and fcntl locks for the given inode into the pagelist. |
| 182 | * Format is: #fcntl locks, sequential fcntl locks, #flock locks, | 182 | * Format is: #fcntl locks, sequential fcntl locks, #flock locks, |
| 183 | * sequential flock locks. | 183 | * sequential flock locks. |
| 184 | * Must be called with BLK already held, and the lock numbers should have | 184 | * Must be called with lock_flocks() already held. |
| 185 | * been gathered under the same lock holding window. | 185 | * If we encounter more of a specific lock type than expected, |
| 186 | * we return the value 1. | ||
| 186 | */ | 187 | */ |
| 187 | int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist, | 188 | int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist, |
| 188 | int num_fcntl_locks, int num_flock_locks) | 189 | int num_fcntl_locks, int num_flock_locks) |
| @@ -190,6 +191,8 @@ int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist, | |||
| 190 | struct file_lock *lock; | 191 | struct file_lock *lock; |
| 191 | struct ceph_filelock cephlock; | 192 | struct ceph_filelock cephlock; |
| 192 | int err = 0; | 193 | int err = 0; |
| 194 | int seen_fcntl = 0; | ||
| 195 | int seen_flock = 0; | ||
| 193 | 196 | ||
| 194 | dout("encoding %d flock and %d fcntl locks", num_flock_locks, | 197 | dout("encoding %d flock and %d fcntl locks", num_flock_locks, |
| 195 | num_fcntl_locks); | 198 | num_fcntl_locks); |
| @@ -198,6 +201,11 @@ int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist, | |||
| 198 | goto fail; | 201 | goto fail; |
| 199 | for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { | 202 | for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { |
| 200 | if (lock->fl_flags & FL_POSIX) { | 203 | if (lock->fl_flags & FL_POSIX) { |
| 204 | ++seen_fcntl; | ||
| 205 | if (seen_fcntl > num_fcntl_locks) { | ||
| 206 | err = -ENOSPC; | ||
| 207 | goto fail; | ||
| 208 | } | ||
| 201 | err = lock_to_ceph_filelock(lock, &cephlock); | 209 | err = lock_to_ceph_filelock(lock, &cephlock); |
| 202 | if (err) | 210 | if (err) |
| 203 | goto fail; | 211 | goto fail; |
| @@ -213,6 +221,11 @@ int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist, | |||
| 213 | goto fail; | 221 | goto fail; |
| 214 | for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { | 222 | for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { |
| 215 | if (lock->fl_flags & FL_FLOCK) { | 223 | if (lock->fl_flags & FL_FLOCK) { |
| 224 | ++seen_flock; | ||
| 225 | if (seen_flock > num_flock_locks) { | ||
| 226 | err = -ENOSPC; | ||
| 227 | goto fail; | ||
| 228 | } | ||
| 216 | err = lock_to_ceph_filelock(lock, &cephlock); | 229 | err = lock_to_ceph_filelock(lock, &cephlock); |
| 217 | if (err) | 230 | if (err) |
| 218 | goto fail; | 231 | goto fail; |
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 33568239a08e..fbfc298ac55b 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
| @@ -2365,19 +2365,35 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap, | |||
| 2365 | 2365 | ||
| 2366 | if (recon_state->flock) { | 2366 | if (recon_state->flock) { |
| 2367 | int num_fcntl_locks, num_flock_locks; | 2367 | int num_fcntl_locks, num_flock_locks; |
| 2368 | 2368 | struct ceph_pagelist_cursor trunc_point; | |
| 2369 | lock_kernel(); | 2369 | |
| 2370 | ceph_count_locks(inode, &num_fcntl_locks, &num_flock_locks); | 2370 | ceph_pagelist_set_cursor(pagelist, &trunc_point); |
| 2371 | rec.v2.flock_len = (2*sizeof(u32) + | 2371 | do { |
| 2372 | (num_fcntl_locks+num_flock_locks) * | 2372 | lock_kernel(); |
| 2373 | sizeof(struct ceph_filelock)); | 2373 | ceph_count_locks(inode, &num_fcntl_locks, |
| 2374 | 2374 | &num_flock_locks); | |
| 2375 | err = ceph_pagelist_append(pagelist, &rec, reclen); | 2375 | rec.v2.flock_len = (2*sizeof(u32) + |
| 2376 | if (!err) | 2376 | (num_fcntl_locks+num_flock_locks) * |
| 2377 | err = ceph_encode_locks(inode, pagelist, | 2377 | sizeof(struct ceph_filelock)); |
| 2378 | num_fcntl_locks, | 2378 | unlock_kernel(); |
| 2379 | num_flock_locks); | 2379 | |
| 2380 | unlock_kernel(); | 2380 | /* pre-alloc pagelist */ |
| 2381 | ceph_pagelist_truncate(pagelist, &trunc_point); | ||
| 2382 | err = ceph_pagelist_append(pagelist, &rec, reclen); | ||
| 2383 | if (!err) | ||
| 2384 | err = ceph_pagelist_reserve(pagelist, | ||
| 2385 | rec.v2.flock_len); | ||
| 2386 | |||
| 2387 | /* encode locks */ | ||
| 2388 | if (!err) { | ||
| 2389 | lock_kernel(); | ||
| 2390 | err = ceph_encode_locks(inode, | ||
| 2391 | pagelist, | ||
| 2392 | num_fcntl_locks, | ||
| 2393 | num_flock_locks); | ||
| 2394 | unlock_kernel(); | ||
| 2395 | } | ||
| 2396 | } while (err == -ENOSPC); | ||
| 2381 | } else { | 2397 | } else { |
| 2382 | err = ceph_pagelist_append(pagelist, &rec, reclen); | 2398 | err = ceph_pagelist_append(pagelist, &rec, reclen); |
| 2383 | } | 2399 | } |
