diff options
author | Greg Farnum <gregf@hq.newdream.net> | 2010-09-17 13:24:02 -0400 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2010-10-20 18:38:17 -0400 |
commit | fca4451acfdcf894154e4809529ca28a09db88ff (patch) | |
tree | 446381c8e8c7b592b47c2e50c32b1e40817fcfe1 /fs/ceph/mds_client.c | |
parent | ac0b74d8a1ced8ea86147467daf06b15b130dd94 (diff) |
ceph: preallocate flock state without locks held
When the lock_kernel() turns into lock_flocks() and a spinlock, we won't
be able to do allocations with the lock held. Preallocate space without
the lock, and retry if the lock state changes out from underneath us.
Signed-off-by: Greg Farnum <gregf@hq.newdream.net>
Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/mds_client.c')
-rw-r--r-- | fs/ceph/mds_client.c | 42 |
1 files changed, 29 insertions, 13 deletions
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 | } |