at v4.18 12 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * linux/include/linux/lockd/lockd.h 4 * 5 * General-purpose lockd include file. 6 * 7 * Copyright (C) 1996 Olaf Kirch <okir@monad.swb.de> 8 */ 9 10#ifndef LINUX_LOCKD_LOCKD_H 11#define LINUX_LOCKD_LOCKD_H 12 13#ifdef __KERNEL__ 14 15#include <linux/in.h> 16#include <linux/in6.h> 17#include <net/ipv6.h> 18#include <linux/fs.h> 19#include <linux/kref.h> 20#include <linux/refcount.h> 21#include <linux/utsname.h> 22#include <linux/lockd/bind.h> 23#include <linux/lockd/xdr.h> 24#ifdef CONFIG_LOCKD_V4 25#include <linux/lockd/xdr4.h> 26#endif 27#include <linux/lockd/debug.h> 28#include <linux/sunrpc/svc.h> 29 30/* 31 * Version string 32 */ 33#define LOCKD_VERSION "0.5" 34 35/* 36 * Default timeout for RPC calls (seconds) 37 */ 38#define LOCKD_DFLT_TIMEO 10 39 40/* 41 * Lockd host handle (used both by the client and server personality). 42 */ 43struct nlm_host { 44 struct hlist_node h_hash; /* doubly linked list */ 45 struct sockaddr_storage h_addr; /* peer address */ 46 size_t h_addrlen; 47 struct sockaddr_storage h_srcaddr; /* our address (optional) */ 48 size_t h_srcaddrlen; 49 struct rpc_clnt *h_rpcclnt; /* RPC client to talk to peer */ 50 char *h_name; /* remote hostname */ 51 u32 h_version; /* interface version */ 52 unsigned short h_proto; /* transport proto */ 53 unsigned short h_reclaiming : 1, 54 h_server : 1, /* server side, not client side */ 55 h_noresvport : 1, 56 h_inuse : 1; 57 wait_queue_head_t h_gracewait; /* wait while reclaiming */ 58 struct rw_semaphore h_rwsem; /* Reboot recovery lock */ 59 u32 h_state; /* pseudo-state counter */ 60 u32 h_nsmstate; /* true remote NSM state */ 61 u32 h_pidcount; /* Pseudopids */ 62 refcount_t h_count; /* reference count */ 63 struct mutex h_mutex; /* mutex for pmap binding */ 64 unsigned long h_nextrebind; /* next portmap call */ 65 unsigned long h_expires; /* eligible for GC */ 66 struct list_head h_lockowners; /* Lockowners for the client */ 67 spinlock_t h_lock; 68 struct list_head h_granted; /* Locks in GRANTED state */ 69 struct list_head h_reclaim; /* Locks in RECLAIM state */ 70 struct nsm_handle *h_nsmhandle; /* NSM status handle */ 71 char *h_addrbuf; /* address eyecatcher */ 72 struct net *net; /* host net */ 73 char nodename[UNX_MAXNODENAME + 1]; 74 const struct nlmclnt_operations *h_nlmclnt_ops; /* Callback ops for NLM users */ 75}; 76 77/* 78 * The largest string sm_addrbuf should hold is a full-size IPv6 address 79 * (no "::" anywhere) with a scope ID. The buffer size is computed to 80 * hold eight groups of colon-separated four-hex-digit numbers, a 81 * percent sign, a scope id (at most 32 bits, in decimal), and NUL. 82 */ 83#define NSM_ADDRBUF ((8 * 4 + 7) + (1 + 10) + 1) 84 85struct nsm_handle { 86 struct list_head sm_link; 87 refcount_t sm_count; 88 char *sm_mon_name; 89 char *sm_name; 90 struct sockaddr_storage sm_addr; 91 size_t sm_addrlen; 92 unsigned int sm_monitored : 1, 93 sm_sticky : 1; /* don't unmonitor */ 94 struct nsm_private sm_priv; 95 char sm_addrbuf[NSM_ADDRBUF]; 96}; 97 98/* 99 * Rigorous type checking on sockaddr type conversions 100 */ 101static inline struct sockaddr_in *nlm_addr_in(const struct nlm_host *host) 102{ 103 return (struct sockaddr_in *)&host->h_addr; 104} 105 106static inline struct sockaddr *nlm_addr(const struct nlm_host *host) 107{ 108 return (struct sockaddr *)&host->h_addr; 109} 110 111static inline struct sockaddr_in *nlm_srcaddr_in(const struct nlm_host *host) 112{ 113 return (struct sockaddr_in *)&host->h_srcaddr; 114} 115 116static inline struct sockaddr *nlm_srcaddr(const struct nlm_host *host) 117{ 118 return (struct sockaddr *)&host->h_srcaddr; 119} 120 121/* 122 * Map an fl_owner_t into a unique 32-bit "pid" 123 */ 124struct nlm_lockowner { 125 struct list_head list; 126 refcount_t count; 127 128 struct nlm_host *host; 129 fl_owner_t owner; 130 uint32_t pid; 131}; 132 133struct nlm_wait; 134 135/* 136 * Memory chunk for NLM client RPC request. 137 */ 138#define NLMCLNT_OHSIZE ((__NEW_UTS_LEN) + 10u) 139struct nlm_rqst { 140 refcount_t a_count; 141 unsigned int a_flags; /* initial RPC task flags */ 142 struct nlm_host * a_host; /* host handle */ 143 struct nlm_args a_args; /* arguments */ 144 struct nlm_res a_res; /* result */ 145 struct nlm_block * a_block; 146 unsigned int a_retries; /* Retry count */ 147 u8 a_owner[NLMCLNT_OHSIZE]; 148 void * a_callback_data; /* sent to nlmclnt_operations callbacks */ 149}; 150 151/* 152 * This struct describes a file held open by lockd on behalf of 153 * an NFS client. 154 */ 155struct nlm_file { 156 struct hlist_node f_list; /* linked list */ 157 struct nfs_fh f_handle; /* NFS file handle */ 158 struct file * f_file; /* VFS file pointer */ 159 struct nlm_share * f_shares; /* DOS shares */ 160 struct list_head f_blocks; /* blocked locks */ 161 unsigned int f_locks; /* guesstimate # of locks */ 162 unsigned int f_count; /* reference count */ 163 struct mutex f_mutex; /* avoid concurrent access */ 164}; 165 166/* 167 * This is a server block (i.e. a lock requested by some client which 168 * couldn't be granted because of a conflicting lock). 169 */ 170#define NLM_NEVER (~(unsigned long) 0) 171/* timeout on non-blocking call: */ 172#define NLM_TIMEOUT (7 * HZ) 173 174struct nlm_block { 175 struct kref b_count; /* Reference count */ 176 struct list_head b_list; /* linked list of all blocks */ 177 struct list_head b_flist; /* linked list (per file) */ 178 struct nlm_rqst * b_call; /* RPC args & callback info */ 179 struct svc_serv * b_daemon; /* NLM service */ 180 struct nlm_host * b_host; /* host handle for RPC clnt */ 181 unsigned long b_when; /* next re-xmit */ 182 unsigned int b_id; /* block id */ 183 unsigned char b_granted; /* VFS granted lock */ 184 struct nlm_file * b_file; /* file in question */ 185 struct cache_req * b_cache_req; /* deferred request handling */ 186 struct cache_deferred_req * b_deferred_req; 187 unsigned int b_flags; /* block flags */ 188#define B_QUEUED 1 /* lock queued */ 189#define B_GOT_CALLBACK 2 /* got lock or conflicting lock */ 190#define B_TIMED_OUT 4 /* filesystem too slow to respond */ 191}; 192 193/* 194 * Global variables 195 */ 196extern const struct rpc_program nlm_program; 197extern const struct svc_procedure nlmsvc_procedures[]; 198#ifdef CONFIG_LOCKD_V4 199extern const struct svc_procedure nlmsvc_procedures4[]; 200#endif 201extern int nlmsvc_grace_period; 202extern unsigned long nlmsvc_timeout; 203extern bool nsm_use_hostnames; 204extern u32 nsm_local_state; 205 206/* 207 * Lockd client functions 208 */ 209struct nlm_rqst * nlm_alloc_call(struct nlm_host *host); 210int nlm_async_call(struct nlm_rqst *, u32, const struct rpc_call_ops *); 211int nlm_async_reply(struct nlm_rqst *, u32, const struct rpc_call_ops *); 212void nlmclnt_release_call(struct nlm_rqst *); 213struct nlm_wait * nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl); 214void nlmclnt_finish_block(struct nlm_wait *block); 215int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout); 216__be32 nlmclnt_grant(const struct sockaddr *addr, 217 const struct nlm_lock *lock); 218void nlmclnt_recovery(struct nlm_host *); 219int nlmclnt_reclaim(struct nlm_host *, struct file_lock *, 220 struct nlm_rqst *); 221void nlmclnt_next_cookie(struct nlm_cookie *); 222 223/* 224 * Host cache 225 */ 226struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap, 227 const size_t salen, 228 const unsigned short protocol, 229 const u32 version, 230 const char *hostname, 231 int noresvport, 232 struct net *net); 233void nlmclnt_release_host(struct nlm_host *); 234struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, 235 const char *hostname, 236 const size_t hostname_len); 237void nlmsvc_release_host(struct nlm_host *); 238struct rpc_clnt * nlm_bind_host(struct nlm_host *); 239void nlm_rebind_host(struct nlm_host *); 240struct nlm_host * nlm_get_host(struct nlm_host *); 241void nlm_shutdown_hosts(void); 242void nlm_shutdown_hosts_net(struct net *net); 243void nlm_host_rebooted(const struct net *net, 244 const struct nlm_reboot *); 245 246/* 247 * Host monitoring 248 */ 249int nsm_monitor(const struct nlm_host *host); 250void nsm_unmonitor(const struct nlm_host *host); 251 252struct nsm_handle *nsm_get_handle(const struct net *net, 253 const struct sockaddr *sap, 254 const size_t salen, 255 const char *hostname, 256 const size_t hostname_len); 257struct nsm_handle *nsm_reboot_lookup(const struct net *net, 258 const struct nlm_reboot *info); 259void nsm_release(struct nsm_handle *nsm); 260 261/* 262 * This is used in garbage collection and resource reclaim 263 * A return value != 0 means destroy the lock/block/share 264 */ 265typedef int (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref); 266 267/* 268 * Server-side lock handling 269 */ 270__be32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, 271 struct nlm_host *, struct nlm_lock *, int, 272 struct nlm_cookie *, int); 273__be32 nlmsvc_unlock(struct net *net, struct nlm_file *, struct nlm_lock *); 274__be32 nlmsvc_testlock(struct svc_rqst *, struct nlm_file *, 275 struct nlm_host *, struct nlm_lock *, 276 struct nlm_lock *, struct nlm_cookie *); 277__be32 nlmsvc_cancel_blocked(struct net *net, struct nlm_file *, struct nlm_lock *); 278unsigned long nlmsvc_retry_blocked(void); 279void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *, 280 nlm_host_match_fn_t match); 281void nlmsvc_grant_reply(struct nlm_cookie *, __be32); 282void nlmsvc_release_call(struct nlm_rqst *); 283 284/* 285 * File handling for the server personality 286 */ 287__be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **, 288 struct nfs_fh *); 289void nlm_release_file(struct nlm_file *); 290void nlmsvc_mark_resources(struct net *); 291void nlmsvc_free_host_resources(struct nlm_host *); 292void nlmsvc_invalidate_all(void); 293 294/* 295 * Cluster failover support 296 */ 297int nlmsvc_unlock_all_by_sb(struct super_block *sb); 298int nlmsvc_unlock_all_by_ip(struct sockaddr *server_addr); 299 300static inline struct inode *nlmsvc_file_inode(struct nlm_file *file) 301{ 302 return file_inode(file->f_file); 303} 304 305static inline int __nlm_privileged_request4(const struct sockaddr *sap) 306{ 307 const struct sockaddr_in *sin = (struct sockaddr_in *)sap; 308 309 if (ntohs(sin->sin_port) > 1023) 310 return 0; 311 312 return ipv4_is_loopback(sin->sin_addr.s_addr); 313} 314 315#if IS_ENABLED(CONFIG_IPV6) 316static inline int __nlm_privileged_request6(const struct sockaddr *sap) 317{ 318 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; 319 320 if (ntohs(sin6->sin6_port) > 1023) 321 return 0; 322 323 if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) 324 return ipv4_is_loopback(sin6->sin6_addr.s6_addr32[3]); 325 326 return ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LOOPBACK; 327} 328#else /* IS_ENABLED(CONFIG_IPV6) */ 329static inline int __nlm_privileged_request6(const struct sockaddr *sap) 330{ 331 return 0; 332} 333#endif /* IS_ENABLED(CONFIG_IPV6) */ 334 335/* 336 * Ensure incoming requests are from local privileged callers. 337 * 338 * Return TRUE if sender is local and is connecting via a privileged port; 339 * otherwise return FALSE. 340 */ 341static inline int nlm_privileged_requester(const struct svc_rqst *rqstp) 342{ 343 const struct sockaddr *sap = svc_addr(rqstp); 344 345 switch (sap->sa_family) { 346 case AF_INET: 347 return __nlm_privileged_request4(sap); 348 case AF_INET6: 349 return __nlm_privileged_request6(sap); 350 default: 351 return 0; 352 } 353} 354 355/* 356 * Compare two NLM locks. 357 * When the second lock is of type F_UNLCK, this acts like a wildcard. 358 */ 359static inline int nlm_compare_locks(const struct file_lock *fl1, 360 const struct file_lock *fl2) 361{ 362 return file_inode(fl1->fl_file) == file_inode(fl2->fl_file) 363 && fl1->fl_pid == fl2->fl_pid 364 && fl1->fl_owner == fl2->fl_owner 365 && fl1->fl_start == fl2->fl_start 366 && fl1->fl_end == fl2->fl_end 367 &&(fl1->fl_type == fl2->fl_type || fl2->fl_type == F_UNLCK); 368} 369 370extern const struct lock_manager_operations nlmsvc_lock_operations; 371 372#endif /* __KERNEL__ */ 373 374#endif /* LINUX_LOCKD_LOCKD_H */