17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7a5aac98SJerry Jelinek * Copyright 2015 Joyent, Inc. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #ifndef _SYS_FLOCK_IMPL_H 297c478bd9Sstevel@tonic-gate #define _SYS_FLOCK_IMPL_H 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <sys/types.h> 327c478bd9Sstevel@tonic-gate #include <sys/fcntl.h> /* flock definition */ 337c478bd9Sstevel@tonic-gate #include <sys/file.h> /* FREAD etc */ 347c478bd9Sstevel@tonic-gate #include <sys/flock.h> /* RCMD etc */ 357c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 367c478bd9Sstevel@tonic-gate #include <sys/user.h> 377c478bd9Sstevel@tonic-gate #include <sys/thread.h> 387c478bd9Sstevel@tonic-gate #include <sys/proc.h> 397c478bd9Sstevel@tonic-gate #include <sys/cred.h> 407c478bd9Sstevel@tonic-gate #include <sys/debug.h> 417c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 427c478bd9Sstevel@tonic-gate #include <sys/errno.h> 437c478bd9Sstevel@tonic-gate #include <sys/systm.h> 447c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 457c478bd9Sstevel@tonic-gate #include <sys/share.h> /* just to get GETSYSID def */ 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate #ifdef __cplusplus 487c478bd9Sstevel@tonic-gate extern "C" { 497c478bd9Sstevel@tonic-gate #endif 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate struct edge { 527c478bd9Sstevel@tonic-gate struct edge *edge_adj_next; /* adjacency list next */ 537c478bd9Sstevel@tonic-gate struct edge *edge_adj_prev; /* adjacency list prev */ 547c478bd9Sstevel@tonic-gate struct edge *edge_in_next; /* incoming edges list next */ 557c478bd9Sstevel@tonic-gate struct edge *edge_in_prev; /* incoming edges list prev */ 567c478bd9Sstevel@tonic-gate struct lock_descriptor *from_vertex; /* edge emanating from lock */ 577c478bd9Sstevel@tonic-gate struct lock_descriptor *to_vertex; /* edge pointing to lock */ 587c478bd9Sstevel@tonic-gate }; 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate typedef struct edge edge_t; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate struct lock_descriptor { 637c478bd9Sstevel@tonic-gate struct lock_descriptor *l_next; /* next active/sleep lock */ 647c478bd9Sstevel@tonic-gate struct lock_descriptor *l_prev; /* previous active/sleep lock */ 657c478bd9Sstevel@tonic-gate struct edge l_edge; /* edge for adj and in lists */ 667c478bd9Sstevel@tonic-gate struct lock_descriptor *l_stack; /* for stack operations */ 677c478bd9Sstevel@tonic-gate struct lock_descriptor *l_stack1; /* for stack operations */ 687c478bd9Sstevel@tonic-gate struct lock_descriptor *l_dstack; /* stack for debug functions */ 697c478bd9Sstevel@tonic-gate struct edge *l_sedge; /* start edge for graph alg. */ 707c478bd9Sstevel@tonic-gate int l_index; /* used for barrier count */ 717c478bd9Sstevel@tonic-gate struct graph *l_graph; /* graph this belongs to */ 727c478bd9Sstevel@tonic-gate vnode_t *l_vnode; /* vnode being locked */ 737c478bd9Sstevel@tonic-gate int l_type; /* type of lock */ 747c478bd9Sstevel@tonic-gate int l_state; /* state described below */ 757c478bd9Sstevel@tonic-gate u_offset_t l_start; /* start offset */ 767c478bd9Sstevel@tonic-gate u_offset_t l_end; /* end offset */ 777c478bd9Sstevel@tonic-gate flock64_t l_flock; /* original flock request */ 787c478bd9Sstevel@tonic-gate int l_color; /* color used for graph alg */ 797c478bd9Sstevel@tonic-gate kcondvar_t l_cv; /* wait condition for lock */ 807c478bd9Sstevel@tonic-gate int pvertex; /* index to proc vertex */ 817c478bd9Sstevel@tonic-gate int l_status; /* status described below */ 827c478bd9Sstevel@tonic-gate flk_nlm_status_t l_nlm_state; /* state of NLM server */ 837c478bd9Sstevel@tonic-gate flk_callback_t *l_callbacks; /* callbacks, or NULL */ 847c478bd9Sstevel@tonic-gate zoneid_t l_zoneid; /* zone of request */ 85*7a5aac98SJerry Jelinek file_t *l_ofd; /* OFD-style reference */ 867c478bd9Sstevel@tonic-gate }; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate typedef struct lock_descriptor lock_descriptor_t; 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate /* 917c478bd9Sstevel@tonic-gate * Each graph holds locking information for some number of vnodes. The 927c478bd9Sstevel@tonic-gate * active and sleeping lists are circular, with a dummy head element. 937c478bd9Sstevel@tonic-gate */ 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate struct graph { 967c478bd9Sstevel@tonic-gate kmutex_t gp_mutex; /* mutex for this graph */ 977c478bd9Sstevel@tonic-gate struct lock_descriptor active_locks; 987c478bd9Sstevel@tonic-gate struct lock_descriptor sleeping_locks; 997c478bd9Sstevel@tonic-gate int index; /* index of this graph into the hash table */ 1007c478bd9Sstevel@tonic-gate int mark; /* used for coloring the graph */ 1017c478bd9Sstevel@tonic-gate }; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate typedef struct graph graph_t; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * The possible states a lock can be in. These states are stored in the 1077c478bd9Sstevel@tonic-gate * 'l_status' member of the 'lock_descriptor_t' structure. All locks start 1087c478bd9Sstevel@tonic-gate * life in the INITIAL state, and end up in the DEAD state. Possible state 1097c478bd9Sstevel@tonic-gate * transitions are : 1107c478bd9Sstevel@tonic-gate * 1117c478bd9Sstevel@tonic-gate * INITIAL--> START --> ACTIVE --> DEAD 1127c478bd9Sstevel@tonic-gate * 1137c478bd9Sstevel@tonic-gate * --> DEAD 1147c478bd9Sstevel@tonic-gate * 1157c478bd9Sstevel@tonic-gate * --> ACTIVE --> DEAD (new locks from flk_relation) 1167c478bd9Sstevel@tonic-gate * 1177c478bd9Sstevel@tonic-gate * --> SLEEPING --> GRANTED --> START --> ACTIVE --> DEAD 1187c478bd9Sstevel@tonic-gate * 1197c478bd9Sstevel@tonic-gate * --> INTR --> DEAD 1207c478bd9Sstevel@tonic-gate * 1217c478bd9Sstevel@tonic-gate * --> CANCELLED --> DEAD 1227c478bd9Sstevel@tonic-gate * 1237c478bd9Sstevel@tonic-gate * --> INTR --> DEAD 1247c478bd9Sstevel@tonic-gate * 1257c478bd9Sstevel@tonic-gate * --> INTR --> DEAD 1267c478bd9Sstevel@tonic-gate * 1277c478bd9Sstevel@tonic-gate * --> CANCELLED --> DEAD 1287c478bd9Sstevel@tonic-gate * 1297c478bd9Sstevel@tonic-gate * --> INTR --> DEAD 1307c478bd9Sstevel@tonic-gate * 1317c478bd9Sstevel@tonic-gate * Lock transitions are done in the following functions: 1327c478bd9Sstevel@tonic-gate * --> INITIAL flk_get_lock(), reclock() 1337c478bd9Sstevel@tonic-gate * --> START flk_execute_request() 1347c478bd9Sstevel@tonic-gate * --> ACTIVE flk_insert_active_lock() 1357c478bd9Sstevel@tonic-gate * --> SLEEPING flk_insert_sleeping_lock() 1367c478bd9Sstevel@tonic-gate * --> GRANTED GRANT_WAKEUP 1377c478bd9Sstevel@tonic-gate * --> INTERRUPTED INTERRUPT_WAKEUP 1387c478bd9Sstevel@tonic-gate * --> CANCELLED CANCEL_WAKEUP 1397c478bd9Sstevel@tonic-gate * --> DEAD reclock(), flk_delete_active_lock(), and 1407c478bd9Sstevel@tonic-gate * flk_cancel_sleeping_lock() 1417c478bd9Sstevel@tonic-gate */ 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate #define FLK_INITIAL_STATE 1 /* Initial state of all requests */ 1447c478bd9Sstevel@tonic-gate #define FLK_START_STATE 2 /* Request has started execution */ 1457c478bd9Sstevel@tonic-gate #define FLK_ACTIVE_STATE 3 /* In active queue */ 1467c478bd9Sstevel@tonic-gate #define FLK_SLEEPING_STATE 4 /* Request is blocked */ 1477c478bd9Sstevel@tonic-gate #define FLK_GRANTED_STATE 5 /* Request is granted */ 1487c478bd9Sstevel@tonic-gate #define FLK_INTERRUPTED_STATE 6 /* Request is interrupted */ 1497c478bd9Sstevel@tonic-gate #define FLK_CANCELLED_STATE 7 /* Request is cancelled */ 1507c478bd9Sstevel@tonic-gate #define FLK_DEAD_STATE 8 /* Request is done - will be deleted */ 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate /* flags defining state of locks */ 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate /* 1557c478bd9Sstevel@tonic-gate * The LLM design has been modified so that lock states are now stored 1567c478bd9Sstevel@tonic-gate * in the l_status field of lock_descriptor_t. The l_state field is 1577c478bd9Sstevel@tonic-gate * currently preserved for binary compatibility, but may be modified or 1587c478bd9Sstevel@tonic-gate * removed in a minor release of Solaris. Note that both of these 1597c478bd9Sstevel@tonic-gate * fields (and the rest of the lock_descriptor_t structure) are private 1607c478bd9Sstevel@tonic-gate * to the implementation of the lock manager and should not be used 1617c478bd9Sstevel@tonic-gate * externally. 1627c478bd9Sstevel@tonic-gate */ 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate #define ACTIVE_LOCK 0x0001 /* in active queue */ 1657c478bd9Sstevel@tonic-gate #define SLEEPING_LOCK 0x0002 /* in sleep queue */ 1667c478bd9Sstevel@tonic-gate #define IO_LOCK 0x0004 /* is an IO lock */ 1677c478bd9Sstevel@tonic-gate #define REFERENCED_LOCK 0x0008 /* referenced some where */ 1687c478bd9Sstevel@tonic-gate #define QUERY_LOCK 0x0010 /* querying about lock */ 1697c478bd9Sstevel@tonic-gate #define WILLING_TO_SLEEP_LOCK 0x0020 /* lock can be put in sleep queue */ 1707c478bd9Sstevel@tonic-gate #define RECOMPUTE_LOCK 0x0040 /* used for recomputing dependencies */ 1717c478bd9Sstevel@tonic-gate #define RECOMPUTE_DONE 0x0080 /* used for recomputing dependencies */ 1727c478bd9Sstevel@tonic-gate #define BARRIER_LOCK 0x0100 /* used for recomputing dependencies */ 1737c478bd9Sstevel@tonic-gate #define GRANTED_LOCK 0x0200 /* granted but still in sleep queue */ 1747c478bd9Sstevel@tonic-gate #define CANCELLED_LOCK 0x0400 /* cancelled will be thrown out */ 1757c478bd9Sstevel@tonic-gate #define DELETED_LOCK 0x0800 /* deleted - free at earliest */ 1767c478bd9Sstevel@tonic-gate #define INTERRUPTED_LOCK 0x1000 /* pretend signal */ 1777c478bd9Sstevel@tonic-gate #define LOCKMGR_LOCK 0x2000 /* remote lock (server-side) */ 1787c478bd9Sstevel@tonic-gate /* Clustering: flag for PXFS locks */ 1797c478bd9Sstevel@tonic-gate #define PXFS_LOCK 0x4000 /* lock created by PXFS file system */ 1807c478bd9Sstevel@tonic-gate #define NBMAND_LOCK 0x8000 /* non-blocking mandatory locking */ 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate #define HASH_SIZE 32 1837c478bd9Sstevel@tonic-gate #define HASH_SHIFT (HASH_SIZE - 1) 1847c478bd9Sstevel@tonic-gate #define HASH_INDEX(vp) (((uintptr_t)vp >> 7) & HASH_SHIFT) 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* extern definitions */ 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate extern struct graph *lock_graph[HASH_SIZE]; 1897c478bd9Sstevel@tonic-gate extern struct kmem_cache *flk_edge_cache; 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* Clustering: functions called by PXFS */ 1927c478bd9Sstevel@tonic-gate int flk_execute_request(lock_descriptor_t *); 1937c478bd9Sstevel@tonic-gate void flk_cancel_sleeping_lock(lock_descriptor_t *, int); 1947c478bd9Sstevel@tonic-gate void flk_set_state(lock_descriptor_t *, int); 1957c478bd9Sstevel@tonic-gate graph_t *flk_get_lock_graph(vnode_t *, int); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate /* flags used for readability in flock.c */ 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate #define FLK_USE_GRAPH 0 /* don't initialize the lock_graph */ 2007c478bd9Sstevel@tonic-gate #define FLK_INIT_GRAPH 1 /* initialize the lock graph */ 2017c478bd9Sstevel@tonic-gate #define NO_COLOR 0 /* vertex is not colored */ 2027c478bd9Sstevel@tonic-gate #define NO_CHECK_CYCLE 0 /* don't mark vertex's in flk_add_edge */ 2037c478bd9Sstevel@tonic-gate #define CHECK_CYCLE 1 /* mark vertex's in flk_add_edge */ 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate #define SAME_OWNER(lock1, lock2) \ 2067c478bd9Sstevel@tonic-gate (((lock1)->l_flock.l_pid == (lock2)->l_flock.l_pid) && \ 207*7a5aac98SJerry Jelinek ((lock1)->l_flock.l_sysid == (lock2)->l_flock.l_sysid) && \ 208*7a5aac98SJerry Jelinek ((lock1)->l_ofd == (lock2)->l_ofd)) 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate #define COLORED(vertex) ((vertex)->l_color == (vertex)->l_graph->mark) 2117c478bd9Sstevel@tonic-gate #define COLOR(vertex) ((vertex)->l_color = (vertex)->l_graph->mark) 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate /* 2147c478bd9Sstevel@tonic-gate * stack data structure and operations 2157c478bd9Sstevel@tonic-gate */ 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate #define STACK_INIT(stack) ((stack) = NULL) 2187c478bd9Sstevel@tonic-gate #define STACK_PUSH(stack, ptr, stack_link) (ptr)->stack_link = (stack),\ 2197c478bd9Sstevel@tonic-gate (stack) = (ptr) 2207c478bd9Sstevel@tonic-gate #define STACK_POP(stack, stack_link) (stack) = (stack)->stack_link 2217c478bd9Sstevel@tonic-gate #define STACK_TOP(stack) (stack) 2227c478bd9Sstevel@tonic-gate #define STACK_EMPTY(stack) ((stack) == NULL) 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate #define ACTIVE_HEAD(gp) (&(gp)->active_locks) 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate #define SLEEPING_HEAD(gp) (&(gp)->sleeping_locks) 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate #define SET_LOCK_TO_FIRST_ACTIVE_VP(gp, lock, vp) \ 2307c478bd9Sstevel@tonic-gate { \ 2317c478bd9Sstevel@tonic-gate (lock) = (lock_descriptor_t *)vp->v_filocks; \ 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate #define SET_LOCK_TO_FIRST_SLEEP_VP(gp, lock, vp) \ 2357c478bd9Sstevel@tonic-gate { \ 2367c478bd9Sstevel@tonic-gate for ((lock) = SLEEPING_HEAD((gp))->l_next; ((lock) != SLEEPING_HEAD((gp)) && \ 2377c478bd9Sstevel@tonic-gate (lock)->l_vnode != (vp)); (lock) = (lock)->l_next) \ 2387c478bd9Sstevel@tonic-gate ; \ 2397c478bd9Sstevel@tonic-gate (lock) = ((lock) == SLEEPING_HEAD((gp))) ? NULL : (lock); \ 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate #define OVERLAP(lock1, lock2) \ 2437c478bd9Sstevel@tonic-gate (((lock1)->l_start <= (lock2)->l_start && \ 2447c478bd9Sstevel@tonic-gate (lock2)->l_start <= (lock1)->l_end) || \ 2457c478bd9Sstevel@tonic-gate ((lock2)->l_start <= (lock1)->l_start && \ 2467c478bd9Sstevel@tonic-gate (lock1)->l_start <= (lock2)->l_end)) 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate #define IS_INITIAL(lock) ((lock)->l_status == FLK_INITIAL_STATE) 2497c478bd9Sstevel@tonic-gate #define IS_ACTIVE(lock) ((lock)->l_status == FLK_ACTIVE_STATE) 2507c478bd9Sstevel@tonic-gate #define IS_SLEEPING(lock) ((lock)->l_status == FLK_SLEEPING_STATE) 2517c478bd9Sstevel@tonic-gate #define IS_GRANTED(lock) ((lock)->l_status == FLK_GRANTED_STATE) 2527c478bd9Sstevel@tonic-gate #define IS_INTERRUPTED(lock) ((lock)->l_status == FLK_INTERRUPTED_STATE) 2537c478bd9Sstevel@tonic-gate #define IS_CANCELLED(lock) ((lock)->l_status == FLK_CANCELLED_STATE) 2547c478bd9Sstevel@tonic-gate #define IS_DEAD(lock) ((lock)->l_status == FLK_DEAD_STATE) 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate #define IS_QUERY_LOCK(lock) ((lock)->l_state & QUERY_LOCK) 2577c478bd9Sstevel@tonic-gate #define IS_RECOMPUTE(lock) ((lock)->l_state & RECOMPUTE_LOCK) 2587c478bd9Sstevel@tonic-gate #define IS_BARRIER(lock) ((lock)->l_state & BARRIER_LOCK) 2597c478bd9Sstevel@tonic-gate #define IS_DELETED(lock) ((lock)->l_state & DELETED_LOCK) 2607c478bd9Sstevel@tonic-gate #define IS_REFERENCED(lock) ((lock)->l_state & REFERENCED_LOCK) 2617c478bd9Sstevel@tonic-gate #define IS_IO_LOCK(lock) ((lock)->l_state & IO_LOCK) 2627c478bd9Sstevel@tonic-gate #define IS_WILLING_TO_SLEEP(lock) \ 2637c478bd9Sstevel@tonic-gate ((lock)->l_state & WILLING_TO_SLEEP_LOCK) 2647c478bd9Sstevel@tonic-gate #define IS_LOCKMGR(lock) ((lock)->l_state & LOCKMGR_LOCK) 2657c478bd9Sstevel@tonic-gate #define IS_NLM_UP(lock) ((lock)->l_nlm_state == FLK_NLM_UP) 2667c478bd9Sstevel@tonic-gate /* Clustering: Macro for PXFS locks */ 2677c478bd9Sstevel@tonic-gate #define IS_PXFS(lock) ((lock)->l_state & PXFS_LOCK) 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate /* 2707c478bd9Sstevel@tonic-gate * "local" requests don't involve the NFS lock manager in any way. 2717c478bd9Sstevel@tonic-gate * "remote" requests can be on the server (requests from a remote client), 2727c478bd9Sstevel@tonic-gate * in which case they should be associated with a local vnode (UFS, tmpfs, 2737c478bd9Sstevel@tonic-gate * etc.). These requests are flagged with LOCKMGR_LOCK and are made using 2747c478bd9Sstevel@tonic-gate * kernel service threads. Remote requests can also be on an NFS client, 2757c478bd9Sstevel@tonic-gate * because the NFS lock manager uses local locking for some of its 2767c478bd9Sstevel@tonic-gate * bookkeeping. These requests are made by regular user processes. 2777c478bd9Sstevel@tonic-gate */ 2787c478bd9Sstevel@tonic-gate #define IS_LOCAL(lock) (GETSYSID((lock)->l_flock.l_sysid) == 0) 2797c478bd9Sstevel@tonic-gate #define IS_REMOTE(lock) (! IS_LOCAL(lock)) 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* Clustering: Return value for blocking PXFS locks */ 2827c478bd9Sstevel@tonic-gate /* 2837c478bd9Sstevel@tonic-gate * For PXFS locks, reclock() will return this error code for requests that 2847c478bd9Sstevel@tonic-gate * need to block 2857c478bd9Sstevel@tonic-gate */ 2867c478bd9Sstevel@tonic-gate #define PXFS_LOCK_BLOCKED -1 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate /* Clustering: PXFS callback function */ 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * This function is a callback from the LLM into the PXFS server module. It 2917c478bd9Sstevel@tonic-gate * is initialized as a weak stub, and is functional when the pxfs server module 2927c478bd9Sstevel@tonic-gate * is loaded. 2937c478bd9Sstevel@tonic-gate */ 2947c478bd9Sstevel@tonic-gate extern void cl_flk_state_transition_notify(lock_descriptor_t *lock, 2957c478bd9Sstevel@tonic-gate int old_state, int new_state); 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate #define BLOCKS(lock1, lock2) (!SAME_OWNER((lock1), (lock2)) && \ 2987c478bd9Sstevel@tonic-gate (((lock1)->l_type == F_WRLCK) || \ 2997c478bd9Sstevel@tonic-gate ((lock2)->l_type == F_WRLCK)) && \ 3007c478bd9Sstevel@tonic-gate OVERLAP((lock1), (lock2))) 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate #define COVERS(lock1, lock2) \ 3037c478bd9Sstevel@tonic-gate (((lock1)->l_start <= (lock2)->l_start) && \ 3047c478bd9Sstevel@tonic-gate ((lock1)->l_end >= (lock2)->l_end)) 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate #define IN_LIST_REMOVE(ep) \ 3077c478bd9Sstevel@tonic-gate { \ 3087c478bd9Sstevel@tonic-gate (ep)->edge_in_next->edge_in_prev = (ep)->edge_in_prev; \ 3097c478bd9Sstevel@tonic-gate (ep)->edge_in_prev->edge_in_next = (ep)->edge_in_next; \ 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate #define ADJ_LIST_REMOVE(ep) \ 3137c478bd9Sstevel@tonic-gate { \ 3147c478bd9Sstevel@tonic-gate (ep)->edge_adj_next->edge_adj_prev = (ep)->edge_adj_prev; \ 3157c478bd9Sstevel@tonic-gate (ep)->edge_adj_prev->edge_adj_next = (ep)->edge_adj_next; \ 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate #define NOT_BLOCKED(lock) \ 3197c478bd9Sstevel@tonic-gate ((lock)->l_edge.edge_adj_next == &(lock)->l_edge && !IS_GRANTED(lock)) 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate #define GRANT_WAKEUP(lock) \ 3227c478bd9Sstevel@tonic-gate { \ 3237c478bd9Sstevel@tonic-gate flk_set_state(lock, FLK_GRANTED_STATE); \ 3247c478bd9Sstevel@tonic-gate (lock)->l_state |= GRANTED_LOCK; \ 3257c478bd9Sstevel@tonic-gate /* \ 3267c478bd9Sstevel@tonic-gate * Clustering: PXFS locks do not sleep in the LLM, \ 3277c478bd9Sstevel@tonic-gate * so there is no need to signal them \ 3287c478bd9Sstevel@tonic-gate */ \ 3297c478bd9Sstevel@tonic-gate if (!IS_PXFS(lock)) { \ 3307c478bd9Sstevel@tonic-gate cv_signal(&(lock)->l_cv); \ 3317c478bd9Sstevel@tonic-gate } \ 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate #define CANCEL_WAKEUP(lock) \ 3357c478bd9Sstevel@tonic-gate { \ 3367c478bd9Sstevel@tonic-gate flk_set_state(lock, FLK_CANCELLED_STATE); \ 3377c478bd9Sstevel@tonic-gate (lock)->l_state |= CANCELLED_LOCK; \ 3387c478bd9Sstevel@tonic-gate /* \ 3397c478bd9Sstevel@tonic-gate * Clustering: PXFS locks do not sleep in the LLM, \ 3407c478bd9Sstevel@tonic-gate * so there is no need to signal them \ 3417c478bd9Sstevel@tonic-gate */ \ 3427c478bd9Sstevel@tonic-gate if (!IS_PXFS(lock)) { \ 3437c478bd9Sstevel@tonic-gate cv_signal(&(lock)->l_cv); \ 3447c478bd9Sstevel@tonic-gate } \ 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate #define INTERRUPT_WAKEUP(lock) \ 3487c478bd9Sstevel@tonic-gate { \ 3497c478bd9Sstevel@tonic-gate flk_set_state(lock, FLK_INTERRUPTED_STATE); \ 3507c478bd9Sstevel@tonic-gate (lock)->l_state |= INTERRUPTED_LOCK; \ 3517c478bd9Sstevel@tonic-gate /* \ 3527c478bd9Sstevel@tonic-gate * Clustering: PXFS locks do not sleep in the LLM, \ 3537c478bd9Sstevel@tonic-gate * so there is no need to signal them \ 3547c478bd9Sstevel@tonic-gate */ \ 3557c478bd9Sstevel@tonic-gate if (!IS_PXFS(lock)) { \ 3567c478bd9Sstevel@tonic-gate cv_signal(&(lock)->l_cv); \ 3577c478bd9Sstevel@tonic-gate } \ 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate #define REMOVE_SLEEP_QUEUE(lock) \ 3617c478bd9Sstevel@tonic-gate { \ 3627c478bd9Sstevel@tonic-gate ASSERT(IS_SLEEPING(lock) || IS_GRANTED(lock) || \ 3637c478bd9Sstevel@tonic-gate IS_INTERRUPTED(lock) || IS_CANCELLED(lock)); \ 3647c478bd9Sstevel@tonic-gate (lock)->l_state &= ~SLEEPING_LOCK; \ 3657c478bd9Sstevel@tonic-gate (lock)->l_next->l_prev = (lock)->l_prev; \ 3667c478bd9Sstevel@tonic-gate (lock)->l_prev->l_next = (lock)->l_next; \ 3677c478bd9Sstevel@tonic-gate (lock)->l_next = (lock)->l_prev = (lock_descriptor_t *)NULL; \ 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate #define NO_DEPENDENTS(lock) \ 3717c478bd9Sstevel@tonic-gate ((lock)->l_edge.edge_in_next == &(lock)->l_edge) 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate #define GRANT(lock) \ 3747c478bd9Sstevel@tonic-gate { \ 3757c478bd9Sstevel@tonic-gate (lock)->l_state |= GRANTED_LOCK; \ 3767c478bd9Sstevel@tonic-gate flk_set_state(lock, FLK_GRANTED_STATE); \ 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate #define FIRST_IN(lock) ((lock)->l_edge.edge_in_next) 3807c478bd9Sstevel@tonic-gate #define FIRST_ADJ(lock) ((lock)->l_edge.edge_adj_next) 3817c478bd9Sstevel@tonic-gate #define HEAD(lock) (&(lock)->l_edge) 3827c478bd9Sstevel@tonic-gate #define NEXT_ADJ(ep) ((ep)->edge_adj_next) 3837c478bd9Sstevel@tonic-gate #define NEXT_IN(ep) ((ep)->edge_in_next) 3847c478bd9Sstevel@tonic-gate #define IN_ADJ_INIT(lock) \ 3857c478bd9Sstevel@tonic-gate { \ 3867c478bd9Sstevel@tonic-gate (lock)->l_edge.edge_adj_next = (lock)->l_edge.edge_adj_prev = &(lock)->l_edge; \ 3877c478bd9Sstevel@tonic-gate (lock)->l_edge.edge_in_next = (lock)->l_edge.edge_in_prev = &(lock)->l_edge; \ 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate #define COPY(lock1, lock2) \ 3917c478bd9Sstevel@tonic-gate { \ 3927c478bd9Sstevel@tonic-gate (lock1)->l_graph = (lock2)->l_graph; \ 3937c478bd9Sstevel@tonic-gate (lock1)->l_vnode = (lock2)->l_vnode; \ 3947c478bd9Sstevel@tonic-gate (lock1)->l_type = (lock2)->l_type; \ 3957c478bd9Sstevel@tonic-gate (lock1)->l_state = (lock2)->l_state; \ 3967c478bd9Sstevel@tonic-gate (lock1)->l_start = (lock2)->l_start; \ 3977c478bd9Sstevel@tonic-gate (lock1)->l_end = (lock2)->l_end; \ 3987c478bd9Sstevel@tonic-gate (lock1)->l_flock = (lock2)->l_flock; \ 3997c478bd9Sstevel@tonic-gate (lock1)->l_zoneid = (lock2)->l_zoneid; \ 4007c478bd9Sstevel@tonic-gate (lock1)->pvertex = (lock2)->pvertex; \ 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate /* 4047c478bd9Sstevel@tonic-gate * Clustering 4057c478bd9Sstevel@tonic-gate */ 4067c478bd9Sstevel@tonic-gate /* Routines to set and get the NLM state in a lock request */ 4077c478bd9Sstevel@tonic-gate #define SET_NLM_STATE(lock, nlm_state) ((lock)->l_nlm_state = nlm_state) 4087c478bd9Sstevel@tonic-gate #define GET_NLM_STATE(lock) ((lock)->l_nlm_state) 4097c478bd9Sstevel@tonic-gate /* 4107c478bd9Sstevel@tonic-gate * NLM registry abstraction: 4117c478bd9Sstevel@tonic-gate * Abstraction overview: 4127c478bd9Sstevel@tonic-gate * This registry keeps track of the NLM servers via their nlmids 4137c478bd9Sstevel@tonic-gate * that have requested locks at the LLM this registry is associated 4147c478bd9Sstevel@tonic-gate * with. 4157c478bd9Sstevel@tonic-gate */ 4167c478bd9Sstevel@tonic-gate /* Routines to manipulate the NLM registry object state */ 4177c478bd9Sstevel@tonic-gate #define FLK_REGISTRY_IS_NLM_UNKNOWN(nlmreg, nlmid) \ 4187c478bd9Sstevel@tonic-gate ((nlmreg)[nlmid] == FLK_NLM_UNKNOWN) 4197c478bd9Sstevel@tonic-gate #define FLK_REGISTRY_IS_NLM_UP(nlmreg, nlmid) \ 4207c478bd9Sstevel@tonic-gate ((nlmreg)[nlmid] == FLK_NLM_UP) 4217c478bd9Sstevel@tonic-gate #define FLK_REGISTRY_ADD_NLMID(nlmreg, nlmid) \ 4227c478bd9Sstevel@tonic-gate ((nlmreg)[nlmid] = FLK_NLM_UP) 4237c478bd9Sstevel@tonic-gate #define FLK_REGISTRY_CHANGE_NLM_STATE(nlmreg, nlmid, state) \ 4247c478bd9Sstevel@tonic-gate ((nlmreg)[nlmid] = state) 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate /* Indicates the effect of executing a request on the existing locks */ 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate #define FLK_UNLOCK 0x1 /* request unlocks the existing lock */ 4297c478bd9Sstevel@tonic-gate #define FLK_DOWNGRADE 0x2 /* request downgrades the existing lock */ 4307c478bd9Sstevel@tonic-gate #define FLK_UPGRADE 0x3 /* request upgrades the existing lock */ 4317c478bd9Sstevel@tonic-gate #define FLK_STAY_SAME 0x4 /* request type is same as existing lock */ 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate /* proc graph definitions */ 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate /* 4377c478bd9Sstevel@tonic-gate * Proc graph is the global process graph that maintains information 4387c478bd9Sstevel@tonic-gate * about the dependencies between processes. An edge is added between two 4397c478bd9Sstevel@tonic-gate * processes represented by proc_vertex's A and B, iff there exists l1 4407c478bd9Sstevel@tonic-gate * owned by process A in any of the lock_graph's dependent on l2 4417c478bd9Sstevel@tonic-gate * (thus having an edge to l2) owned by process B. 4427c478bd9Sstevel@tonic-gate */ 4437c478bd9Sstevel@tonic-gate struct proc_vertex { 4447c478bd9Sstevel@tonic-gate pid_t pid; /* pid of the process */ 4457c478bd9Sstevel@tonic-gate long sysid; /* sysid of the process */ 4467c478bd9Sstevel@tonic-gate struct proc_edge *edge; /* adajcent edges of this process */ 4477c478bd9Sstevel@tonic-gate int incount; /* Number of inedges to this process */ 4487c478bd9Sstevel@tonic-gate struct proc_edge *p_sedge; /* used for implementing stack alg. */ 4497c478bd9Sstevel@tonic-gate struct proc_vertex *p_stack; /* used for stack alg. */ 4507c478bd9Sstevel@tonic-gate int atime; /* used for cycle detection algorithm */ 4517c478bd9Sstevel@tonic-gate int dtime; /* used for cycle detection algorithm */ 4527c478bd9Sstevel@tonic-gate int index; /* index into the array of proc_graph vertices */ 4537c478bd9Sstevel@tonic-gate }; 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate typedef struct proc_vertex proc_vertex_t; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate struct proc_edge { 4587c478bd9Sstevel@tonic-gate struct proc_edge *next; /* next edge in adjacency list */ 4597c478bd9Sstevel@tonic-gate int refcount; /* reference count of this edge */ 4607c478bd9Sstevel@tonic-gate struct proc_vertex *to_proc; /* process this points to */ 4617c478bd9Sstevel@tonic-gate }; 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate typedef struct proc_edge proc_edge_t; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate #define PROC_CHUNK 100 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate struct proc_graph { 4697c478bd9Sstevel@tonic-gate struct proc_vertex **proc; /* list of proc_vertexes */ 4707c478bd9Sstevel@tonic-gate int gcount; /* list size */ 4717c478bd9Sstevel@tonic-gate int free; /* number of free slots in the list */ 4727c478bd9Sstevel@tonic-gate int mark; /* used for graph coloring */ 4737c478bd9Sstevel@tonic-gate }; 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate typedef struct proc_graph proc_graph_t; 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate extern struct proc_graph pgraph; 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate #define PROC_SAME_OWNER(lock, pvertex) \ 4807c478bd9Sstevel@tonic-gate (((lock)->l_flock.l_pid == (pvertex)->pid) && \ 4817c478bd9Sstevel@tonic-gate ((lock)->l_flock.l_sysid == (pvertex)->sysid)) 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate #define PROC_ARRIVE(pvertex) ((pvertex)->atime = pgraph.mark) 4847c478bd9Sstevel@tonic-gate #define PROC_DEPART(pvertex) ((pvertex)->dtime = pgraph.mark) 4857c478bd9Sstevel@tonic-gate #define PROC_ARRIVED(pvertex) ((pvertex)->atime == pgraph.mark) 4867c478bd9Sstevel@tonic-gate #define PROC_DEPARTED(pvertex) ((pvertex)->dtime == pgraph.mark) 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate #ifdef __cplusplus 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate #endif 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate #endif /* _SYS_FLOCK_IMPL_H */ 493