/* * This is somewhat different from trylock. It will take the * spinlock but if it finds the lock is set to blocking, it will * return without the lock held. * * returns 1 if it was able to take the lock and zero otherwise * * After this call, scheduling is not safe without first calling * btrfs_set_lock_blocking() */ int btrfs_try_spin_lock(struct extent_buffer *eb) { #ifndef CONFIG_PREEMPT_RT int i; if (btrfs_spin_on_block(eb)) { spin_nested(eb); if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) return 1; spin_unlock(&eb->lock); } /* spin for a bit on the BLOCKING flag */ for (i = 0; i < 2; i++) { cpu_relax(); if (!btrfs_spin_on_block(eb)) break; spin_nested(eb); if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) return 1; spin_unlock(&eb->lock); } #endif return 0; }
/* * returns with the extent buffer spinlocked. * * This will spin and/or wait as required to take the lock, and then * return with the spinlock held. * * After this call, scheduling is not safe without first calling * btrfs_set_lock_blocking() */ int btrfs_tree_lock(struct extent_buffer *eb) { DEFINE_WAIT(wait); wait.func = btrfs_wake_function; while(1) { spin_nested(eb); /* nobody is blocking, exit with the spinlock held */ if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) return 0; /* * we have the spinlock, but the real owner is blocking. * wait for them */ spin_unlock(&eb->lock); /* * spin for a bit, and if the blocking flag goes away, * loop around */ if (btrfs_spin_on_block(eb)) continue; prepare_to_wait_exclusive(&eb->lock_wq, &wait, TASK_UNINTERRUPTIBLE); if (test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) schedule(); finish_wait(&eb->lock_wq, &wait); } return 0; }
/* * This is somewhat different from trylock. It will take the * spinlock but if it finds the lock is set to blocking, it will * return without the lock held. * * returns 1 if it was able to take the lock and zero otherwise * * After this call, scheduling is not safe without first calling * btrfs_set_lock_blocking() */ int btrfs_try_spin_lock(struct extent_buffer *eb) { int i; spin_nested(eb); if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) return 1; spin_unlock(&eb->lock); /* spin for a bit on the BLOCKING flag */ for (i = 0; i < 2; i++) { if (!btrfs_spin_on_block(eb)) break; spin_nested(eb); if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) return 1; spin_unlock(&eb->lock); } return 0; }