-struct ll_lock_tree_node * ll_node_from_inode(struct inode *inode, __u64 start,
- __u64 end, ldlm_mode_t mode)
-{
- struct ll_lock_tree_node *node;
-
- OBD_ALLOC(node, sizeof(*node));
- if (node == NULL)
- RETURN(ERR_PTR(-ENOMEM));
-
- node->lt_inode = inode;
- node->lt_oid = ll_i2info(inode)->lli_smd->lsm_object_id;
- node->lt_policy.l_extent.start = start;
- node->lt_policy.l_extent.end = end;
- memset(&node->lt_lockh, 0, sizeof(node->lt_lockh));
- INIT_LIST_HEAD(&node->lt_locked_item);
- node->lt_mode = mode;
-
- return node;
-}
-
-int lt_compare(struct ll_lock_tree_node *one, struct ll_lock_tree_node *two)
-{
- /* To avoid multiple fs deadlock */
- if (one->lt_inode->i_sb->s_dev < two->lt_inode->i_sb->s_dev)
- return -1;
- if (one->lt_inode->i_sb->s_dev > two->lt_inode->i_sb->s_dev)
- return 1;
-
- if (one->lt_oid < two->lt_oid)
- return -1;
- if (one->lt_oid > two->lt_oid)
- return 1;
-
- if (one->lt_policy.l_extent.end < two->lt_policy.l_extent.start)
- return -1;
- if (one->lt_policy.l_extent.start > two->lt_policy.l_extent.end)
- return 1;
-
- return 0; /* they are the same object and overlap */
-}
-
-static void lt_merge(struct ll_lock_tree_node *dst,
- struct ll_lock_tree_node *src)
-{
- dst->lt_policy.l_extent.start = min(dst->lt_policy.l_extent.start,
- src->lt_policy.l_extent.start);
- dst->lt_policy.l_extent.end = max(dst->lt_policy.l_extent.end,
- src->lt_policy.l_extent.end);
-
- /* XXX could be a real call to the dlm to find superset modes */
- if (src->lt_mode == LCK_PW && dst->lt_mode != LCK_PW)
- dst->lt_mode = LCK_PW;
-}
-
-static void lt_insert(struct ll_lock_tree *tree,
- struct ll_lock_tree_node *node)
-{
- struct ll_lock_tree_node *walk;
- rb_node_t **p, *parent;
- ENTRY;
-
-restart:
- p = &tree->lt_root.rb_node;
- parent = NULL;
- while (*p) {
- parent = *p;
- walk = rb_entry(parent, struct ll_lock_tree_node, lt_node);
- switch (lt_compare(node, walk)) {
- case -1:
- p = &(*p)->rb_left;
- break;
- case 1:
- p = &(*p)->rb_right;
- break;
- case 0:
- lt_merge(node, walk);
- rb_erase(&walk->lt_node, &tree->lt_root);
- OBD_FREE(walk, sizeof(*walk));
- goto restart;
- break;
- default:
- LBUG();
- break;
- }
- }
- rb_link_node(&node->lt_node, parent, p);
- rb_insert_color(&node->lt_node, &tree->lt_root);
- EXIT;
-}
-
-static struct ll_lock_tree_node *lt_least_node(struct ll_lock_tree *tree)
-{
- rb_node_t *rbnode;
- struct ll_lock_tree_node *node = NULL;
-
- for ( rbnode = tree->lt_root.rb_node; rbnode != NULL;
- rbnode = rbnode->rb_left) {
- if (rbnode->rb_left == NULL) {
- node = rb_entry(rbnode, struct ll_lock_tree_node,
- lt_node);
- break;
- }
- }
- RETURN(node);
-}
-
-int ll_tree_unlock(struct ll_lock_tree *tree)
-{
- struct ll_lock_tree_node *node;
- struct list_head *pos, *n;
- struct inode *inode;
- int rc = 0;
- ENTRY;
-
- list_for_each_safe(pos, n, &tree->lt_locked_list) {
- node = list_entry(pos, struct ll_lock_tree_node,
- lt_locked_item);
-
- inode = node->lt_inode;
- rc = ll_extent_unlock(tree->lt_fd, inode,
- ll_i2info(inode)->lli_smd, node->lt_mode,
- &node->lt_lockh);
- if (rc != 0) {
- /* XXX better message */
- CERROR("couldn't unlock %d\n", rc);
- }
- list_del(&node->lt_locked_item);
- OBD_FREE(node, sizeof(*node));
- }
-
- while ((node = lt_least_node(tree))) {
- rb_erase(&node->lt_node, &tree->lt_root);
- OBD_FREE(node, sizeof(*node));
- }
-
- RETURN(rc);
-}
-
-int ll_tree_lock(struct ll_lock_tree *tree,
- struct ll_lock_tree_node *first_node,
- const char *buf, size_t count, int ast_flags)
-{
- struct ll_lock_tree_node *node;
- int rc = 0;
- ENTRY;
-
- tree->lt_root.rb_node = NULL;
- INIT_LIST_HEAD(&tree->lt_locked_list);
- if (first_node != NULL)
- lt_insert(tree, first_node);
-
- /* To avoid such subtle deadlock case: client1 try to read file1 to
- * mmapped file2, on the same time, client2 try to read file2 to
- * mmapped file1.*/
- rc = lt_get_mmap_locks(tree, (unsigned long)buf, count);
- if (rc)
- GOTO(out, rc);
-
- while ((node = lt_least_node(tree))) {
- struct inode *inode = node->lt_inode;
- rc = ll_extent_lock(tree->lt_fd, inode,
- ll_i2info(inode)->lli_smd, node->lt_mode,
- &node->lt_policy, &node->lt_lockh,
- ast_flags);
- if (rc != 0)
- GOTO(out, rc);
-
- rb_erase(&node->lt_node, &tree->lt_root);
- list_add_tail(&node->lt_locked_item, &tree->lt_locked_list);
- }
- RETURN(rc);
-out:
- ll_tree_unlock(tree);
- RETURN(rc);
-}
-
-static ldlm_mode_t mode_from_vma(struct vm_area_struct *vma)
-{
- /* we only want to hold PW locks if the mmap() can generate
- * writes back to the file and that only happens in shared
- * writable vmas */
- if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE))
- return LCK_PW;
- return LCK_PR;
-}
-
-static void policy_from_vma(ldlm_policy_data_t *policy,