+static int ldlm_do_decrement(void)
+{
+ struct ldlm_test_lock *lock_info;
+ struct ldlm_lock *lock;
+ int rc = 0;
+ ENTRY;
+
+ spin_lock(&ctl_lock);
+ if(list_empty(&lock_list)) {
+ CERROR("lock_list is empty\n");
+ spin_unlock(&ctl_lock);
+ RETURN(0);
+ }
+
+ /* delete from list */
+ lock_info = list_entry(lock_list.next,
+ struct ldlm_test_lock, l_link);
+ list_del(lock_list.next);
+ num_locks--;
+ spin_unlock(&ctl_lock);
+
+ /* decrement and free the info */
+ lock = ldlm_handle2lock(&lock_info->l_lockh);
+ ldlm_lock_decref(&lock_info->l_lockh, lock->l_granted_mode);
+ ldlm_lock_put(lock);
+
+ OBD_FREE(lock_info, sizeof(*lock_info));
+
+ RETURN(rc);
+}
+
+static int ldlm_do_enqueue(struct ldlm_test_thread *thread)
+{
+ struct lustre_handle lockh;
+ struct ldlm_res_id res_id = { .name = {0} };
+ __u32 lock_mode;
+ struct ldlm_extent ext;
+ unsigned char random;
+ int flags = 0, rc = 0;
+ ENTRY;
+
+ /* Pick a random resource from 1 to num_resources */
+ get_random_bytes(&random, sizeof(random));
+ res_id.name[0] = random % num_resources;
+
+ /* Pick a random lock mode */
+ get_random_bytes(&random, sizeof(random));
+ lock_mode = random % LCK_NL + 1;
+
+ /* Pick a random extent */
+ get_random_bytes(&random, sizeof(random));
+ ext.start = random % num_extents;
+ get_random_bytes(&random, sizeof(random));
+ ext.end = random %
+ (num_extents - (int)ext.start) + ext.start;
+
+ LDLM_DEBUG_NOLOCK("about to enqueue with resource "LPX64", mode %d,"
+ " extent "LPX64" -> "LPX64, res_id.name[0], lock_mode,
+ ext.start, ext.end);
+
+ rc = ldlm_match_or_enqueue(®ress_connh, NULL,
+ thread->obddev->obd_namespace,
+ NULL, res_id, LDLM_EXTENT, &ext,
+ sizeof(ext), lock_mode, &flags,
+ ldlm_test_completion_ast,
+ ldlm_test_blocking_ast,
+ NULL, 0, &lockh);
+
+ atomic_inc(&locks_requested);
+
+ if (rc < 0) {
+ CERROR("ldlm_cli_enqueue: %d\n", rc);
+ LBUG();
+ }
+
+ RETURN(rc);
+}
+
+static int ldlm_do_convert(void)
+{
+ __u32 lock_mode;
+ unsigned char random;
+ int flags = 0, rc = 0;
+ struct ldlm_test_lock *lock_info;
+ struct ldlm_lock *lock;
+ ENTRY;
+
+ /* delete from list */
+ spin_lock(&ctl_lock);
+ lock_info = list_entry(lock_list.next, struct ldlm_test_lock, l_link);
+ list_del(lock_list.next);
+ num_locks--;
+ spin_unlock(&ctl_lock);
+
+ /* Pick a random lock mode */
+ get_random_bytes(&random, sizeof(random));
+ lock_mode = random % LCK_NL + 1;
+
+ /* do the conversion */
+ rc = ldlm_cli_convert(&lock_info->l_lockh , lock_mode, &flags);
+ atomic_inc(&converts_requested);
+
+ if (rc < 0) {
+ CERROR("ldlm_cli_convert: %d\n", rc);
+ LBUG();
+ }
+
+ /*
+ * Adjust reference counts.
+ * FIXME: This is technically a bit... wrong,
+ * since we don't know when/if the convert succeeded
+ */
+ ldlm_lock_addref(&lock_info->l_lockh, lock_mode);
+ lock = ldlm_handle2lock(&lock_info->l_lockh);
+ ldlm_lock_decref(&lock_info->l_lockh, lock->l_granted_mode);
+ ldlm_lock_put(lock);
+
+ OBD_FREE(lock_info, sizeof(*lock_info));
+
+ RETURN(rc);
+}
+
+
+