| Start/ | End/ | |||
| True | False | - | Line | Source |
| 1 | /* | |||
| 2 | * linux/fs/lockd/clntproc.c | |||
| 3 | * | |||
| 4 | * RPC procedures for the client side NLM implementation | |||
| 5 | * | |||
| 6 | * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> | |||
| 7 | */ | |||
| 8 | ||||
| 9 | #include <linux/config.h> | |||
| 10 | #include <linux/module.h> | |||
| 11 | #include <linux/types.h> | |||
| 12 | #include <linux/errno.h> | |||
| 13 | #include <linux/fs.h> | |||
| 14 | #include <linux/nfs_fs.h> | |||
| 15 | #include <linux/utsname.h> | |||
| 16 | #include <linux/smp_lock.h> | |||
| 17 | #include <linux/sunrpc/clnt.h> | |||
| 18 | #include <linux/sunrpc/svc.h> | |||
| 19 | #include <linux/lockd/lockd.h> | |||
| 20 | #include <linux/lockd/sm_inter.h> | |||
| 21 | ||||
| 22 | #define NLMDBG_FACILITY NLMDBG_CLIENT | |||
| 23 | #define NLMCLNT_GRACE_WAIT (5*HZ) | |||
| 24 | #define NLMCLNT_POLL_TIMEOUT (30*HZ) | |||
| 25 | #define NLMCLNT_MAX_RETRIES 3 | |||
| 26 | ||||
| 27 | static int nlmclnt_test(struct nlm_rqst *, struct file_lock *); | |||
| 28 | static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *); | |||
| 29 | static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *); | |||
| 30 | static int nlm_stat_to_errno(u32 stat); | |||
| 31 | static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host); | |||
| 32 | static int nlmclnt_cancel(struct nlm_host *, int , struct file_lock *); | |||
| 33 | ||||
| 34 | static const struct rpc_call_ops nlmclnt_unlock_ops; | |||
| 35 | static const struct rpc_call_ops nlmclnt_cancel_ops; | |||
| 36 | ||||
| 37 | /* | |||
| 38 | * Cookie counter for NLM requests | |||
| 39 | */ | |||
| 40 | static u32 nlm_cookie = 0x1234; | |||
| 41 | ||||
| 0 | 0 | - | 42 | static inline void nlmclnt_next_cookie(struct nlm_cookie *c) |
| 43 | { | |||
| 44 | memcpy(c->data, &nlm_cookie, 4); | |||
| 45 | memset(c->data+4, 0, 4); | |||
| 46 | c->len=4; | |||
| 47 | nlm_cookie++; | |||
| 48 | } | |||
| 49 | ||||
| 0 | 0 | - | 50 | static struct nlm_lockowner *nlm_get_lockowner(struct nlm_lockowner *lockowner) |
| 51 | { | |||
| 52 | atomic_inc(&lockowner->count); | |||
| 0 | - | 53 | return lockowner; | |
| 54 | } | |||
| 55 | ||||
| 0 | 0 | - | 56 | static void nlm_put_lockowner(struct nlm_lockowner *lockowner) |
| 57 | { | |||
| 0 | 0 | - | 58 | if (!atomic_dec_and_lock(&lockowner->count, &lockowner->host->h_lock)) |
| 0 | - | 59 | return; | |
| 60 | list_del(&lockowner->list); | |||
| 61 | spin_unlock(&lockowner->host->h_lock); | |||
| 61 | do | |||
| 0 | 0 | - | 61 | do-while (0) |
| 0 | 0 | - | 61 | do-while (0) |
| 62 | nlm_release_host(lockowner->host); | |||
| 63 | kfree(lockowner); | |||
| 64 | } | |||
| 65 | ||||
| 0 | 0 | - | 66 | static inline int nlm_pidbusy(struct nlm_host *host, uint32_t pid) |
| 67 | { | |||
| 68 | struct nlm_lockowner *lockowner; | |||
| 0 | 0 | - | 69 | list_for_each_entry(lockowner, &host->h_lockowners, list) { |
| 0 | 0 | - | 70 | if (lockowner->pid == pid) |
| 0 | - | 71 | return -EBUSY; | |
| 72 | } | |||
| 0 | - | 73 | return 0; | |
| 74 | } | |||
| 75 | ||||
| 0 | 0 | - | 76 | static inline uint32_t __nlm_alloc_pid(struct nlm_host *host) |
| 77 | { | |||
| 78 | uint32_t res; | |||
| 79 | do { | |||
| 80 | res = host->h_pidcount++; | |||
| 0 | 0 | - | 81 | } while (nlm_pidbusy(host, res) < 0); |
| 0 | - | 82 | return res; | |
| 83 | } | |||
| 84 | ||||
| 0 | 0 | - | 85 | static struct nlm_lockowner *__nlm_find_lockowner(struct nlm_host *host, fl_owner_t owner) |
| 86 | { | |||
| 87 | struct nlm_lockowner *lockowner; | |||
| 0 | 0 | - | 88 | list_for_each_entry(lockowner, &host->h_lockowners, list) { |
| 0 | 0 | - | 89 | if (lockowner->owner != owner) |
| 0 | - | 90 | continue; | |
| 0 | - | 91 | return nlm_get_lockowner(lockowner); | |
| 92 | } | |||
| 0 | - | 93 | return NULL; | |
| 94 | } | |||
| 95 | ||||
| 0 | 0 | - | 96 | static struct nlm_lockowner *nlm_find_lockowner(struct nlm_host *host, fl_owner_t owner) |
| 97 | { | |||
| 98 | struct nlm_lockowner *res, *new = NULL; | |||
| 99 | ||||
| 100 | spin_lock(&host->h_lock); | |||
| 100 | do | |||
| 0 | 0 | - | 100 | do-while (0) |
| 0 | 0 | - | 100 | do-while (0) |
| 101 | res = __nlm_find_lockowner(host, owner); | |||
| 0 | 0 | - | 102 | if (res == NULL) { |
| 103 | spin_unlock(&host->h_lock); | |||
| 103 | do | |||
| 0 | 0 | - | 103 | do-while (0) |
| 0 | 0 | - | 103 | do-while (0) |
| 104 | new = (struct nlm_lockowner *)kmalloc(sizeof(*new), GFP_KERNEL); | |||
| 105 | spin_lock(&host->h_lock); | |||
| 105 | do | |||
| 0 | 0 | - | 105 | do-while (0) |
| 0 | 0 | - | 105 | do-while (0) |
| 106 | res = __nlm_find_lockowner(host, owner); | |||
| 0 | 0 | - | 107 | if (res == NULL && new != NULL) { |
| 0 | - | 107 | T && T | |
| 0 | - | 107 | T && F | |
| 0 | - | 107 | F && _ | |
| 108 | res = new; | |||
| 109 | atomic_set(&new->count, 1); | |||
| 110 | new->owner = owner; | |||
| 111 | new->pid = __nlm_alloc_pid(host); | |||
| 112 | new->host = nlm_get_host(host); | |||
| 113 | list_add(&new->list, &host->h_lockowners); | |||
| 114 | new = NULL; | |||
| 115 | } | |||
| 116 | } | |||
| 117 | spin_unlock(&host->h_lock); | |||
| 117 | do | |||
| 0 | 0 | - | 117 | do-while (0) |
| 0 | 0 | - | 117 | do-while (0) |
| 118 | kfree(new); | |||
| 0 | - | 119 | return res; | |
| 120 | } | |||
| 121 | ||||
| 122 | /* | |||
| 123 | * Initialize arguments for TEST/LOCK/UNLOCK/CANCEL calls | |||
| 124 | */ | |||
| 0 | 0 | - | 125 | static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl) |
| 126 | { | |||
| 127 | struct nlm_args *argp = &req->a_args; | |||
| 128 | struct nlm_lock *lock = &argp->lock; | |||
| 129 | ||||
| 130 | nlmclnt_next_cookie(&argp->cookie); | |||
| 131 | argp->state = nsm_local_state; | |||
| 132 | memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry->d_inode), sizeof(struct nfs_fh)); | |||
| 133 | lock->caller = system_utsname.nodename; | |||
| 134 | lock->oh.data = req->a_owner; | |||
| 135 | lock->oh.len = sprintf(req->a_owner, "%d@%s", | |||
| 136 | current->pid, system_utsname.nodename); | |||
| 137 | locks_copy_lock(&lock->fl, fl); | |||
| 138 | } | |||
| 139 | ||||
| 0 | 0 | - | 140 | static void nlmclnt_release_lockargs(struct nlm_rqst *req) |
| 141 | { | |||
| 142 | struct file_lock *fl = &req->a_args.lock.fl; | |||
| 143 | ||||
| 0 | 0 | - | 144 | if (fl->fl_ops && fl->fl_ops->fl_release_private) |
| 0 | - | 144 | T && T | |
| 0 | - | 144 | T && F | |
| 0 | - | 144 | F && _ | |
| 145 | fl->fl_ops->fl_release_private(fl); | |||
| 146 | } | |||
| 147 | ||||
| 148 | /* | |||
| 149 | * Initialize arguments for GRANTED call. The nlm_rqst structure | |||
| 150 | * has been cleared already. | |||
| 151 | */ | |||
| 152 | int | |||
| 0 | 0 | - | 153 | nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock) |
| 154 | { | |||
| 155 | locks_copy_lock(&call->a_args.lock.fl, &lock->fl); | |||
| 156 | memcpy(&call->a_args.lock.fh, &lock->fh, sizeof(call->a_args.lock.fh)); | |||
| 157 | call->a_args.lock.caller = system_utsname.nodename; | |||
| 158 | call->a_args.lock.oh.len = lock->oh.len; | |||
| 159 | ||||
| 160 | /* set default data area */ | |||
| 161 | call->a_args.lock.oh.data = call->a_owner; | |||
| 162 | ||||
| 0 | 0 | - | 163 | if (lock->oh.len > NLMCLNT_OHSIZE) { |
| 164 | void *data = kmalloc(lock->oh.len, GFP_KERNEL); | |||
| 0 | 0 | - | 165 | if (!data) { |
| 166 | nlmclnt_freegrantargs(call); | |||
| 0 | - | 167 | return 0; | |
| 168 | } | |||
| 169 | call->a_args.lock.oh.data = (u8 *) data; | |||
| 170 | } | |||
| 171 | ||||
| 172 | memcpy(call->a_args.lock.oh.data, lock->oh.data, lock->oh.len); | |||
| 0 | - | 173 | return 1; | |
| 174 | } | |||
| 175 | ||||
| 176 | void | |||
| 0 | 0 | - | 177 | nlmclnt_freegrantargs(struct nlm_rqst *call) |
| 178 | { | |||
| 179 | struct file_lock *fl = &call->a_args.lock.fl; | |||
| 180 | /* | |||
| 181 | * Check whether we allocated memory for the owner. | |||
| 182 | */ | |||
| 0 | 0 | - | 183 | if (call->a_args.lock.oh.data != (u8 *) call->a_owner) { |
| 184 | kfree(call->a_args.lock.oh.data); | |||
| 185 | } | |||
| 0 | 0 | - | 186 | if (fl->fl_ops && fl->fl_ops->fl_release_private) |
| 0 | - | 186 | T && T | |
| 0 | - | 186 | T && F | |
| 0 | - | 186 | F && _ | |
| 187 | fl->fl_ops->fl_release_private(fl); | |||
| 188 | } | |||
| 189 | ||||
| 190 | /* | |||
| 191 | * This is the main entry point for the NLM client. | |||
| 192 | */ | |||
| 193 | int | |||
| 0 | 0 | - | 194 | nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) |
| 195 | { | |||
| 196 | struct nfs_server *nfssrv = NFS_SERVER(inode); | |||
| 197 | struct nlm_host *host; | |||
| 198 | struct nlm_rqst reqst, *call = &reqst; | |||
| 199 | sigset_t oldset; | |||
| 200 | unsigned long flags; | |||
| 201 | int status, proto, vers; | |||
| 202 | ||||
| 203 | vers = (NFS_PROTO(inode)->version == 3) ? 4 : 1; | |||
| 0 | 0 | - | 203 | ternary-?: ( ( ( ( ( struct nfs_server * ) ( i.. |
| 0 | 0 | - | 204 | if (NFS_PROTO(inode)->version > 3) { |
| 205 | printk(KERN_NOTICE "NFSv4 file locking not implemented!\n"); | |||
| 0 | - | 206 | return -ENOLCK; | |
| 207 | } | |||
| 208 | ||||
| 209 | /* Retrieve transport protocol from NFS client */ | |||
| 210 | proto = NFS_CLIENT(inode)->cl_xprt->prot; | |||
| 211 | ||||
| 0 | 0 | - | 212 | if (!(host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers))) |
| 0 | - | 213 | return -ENOLCK; | |
| 214 | ||||
| 215 | /* Create RPC client handle if not there, and copy soft | |||
| 216 | * and intr flags from NFS client. */ | |||
| 0 | 0 | - | 217 | if (host->h_rpcclnt == NULL) { |
| 218 | struct rpc_clnt *clnt; | |||
| 219 | ||||
| 220 | /* Bind an rpc client to this host handle (does not | |||
| 221 | * perform a portmapper lookup) */ | |||
| 0 | 0 | - | 222 | if (!(clnt = nlm_bind_host(host))) { |
| 223 | status = -ENOLCK; | |||
| 0 | - | 224 | goto done; | |
| 225 | } | |||
| 226 | clnt->cl_softrtry = nfssrv->client->cl_softrtry; | |||
| 227 | clnt->cl_intr = nfssrv->client->cl_intr; | |||
| 228 | } | |||
| 229 | ||||
| 230 | /* Keep the old signal mask */ | |||
| 231 | spin_lock_irqsave(¤t->sighand->siglock, flags); | |||
| 231 | do | |||
| 231 | do | |||
| 0 | 0 | - | 231 | do-while (0) |
| 0 | 0 | - | 231 | do-while (0) |
| 231 | do | |||
| 231 | do | |||
| 0 | 0 | - | 231 | do-while (0) |
| 0 | 0 | - | 231 | do-while (0) |
| 0 | 0 | - | 231 | do-while (0) |
| 232 | oldset = current->blocked; | |||
| 233 | ||||
| 234 | /* If we're cleaning up locks because the process is exiting, | |||
| 235 | * perform the RPC call asynchronously. */ | |||
| 236 | if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) | |||
| 237 | && fl->fl_type == F_UNLCK | |||
| 0 | 0 | - | 238 | && (current->flags & PF_EXITING)) { |
| 0 | - | 238 | (((T) || (_)) || ((_) || (_))) && T && (T) | |
| 0 | - | 238 | (((F) || (T)) || ((_) || (_))) && T && (T) | |
| 0 | - | 238 | (((F) || (F)) || ((T) || (_))) && T && (T) | |
| 0 | - | 238 | (((F) || (F)) || ((F) || (T))) && T && (T) | |
| 0 | - | 238 | (((T) || (_)) || ((_) || (_))) && T && (F) | |
| 0 | - | 238 | (((T) || (_)) || ((_) || (_))) && F && (_) | |
| 0 | - | 238 | (((F) || (T)) || ((_) || (_))) && T && (F) | |
| 0 | - | 238 | (((F) || (T)) || ((_) || (_))) && F && (_) | |
| 0 | - | 238 | (((F) || (F)) || ((T) || (_))) && T && (F) | |
| 0 | - | 238 | (((F) || (F)) || ((T) || (_))) && F && (_) | |
| 0 | - | 238 | (((F) || (F)) || ((F) || (T))) && T && (F) | |
| 0 | - | 238 | (((F) || (F)) || ((F) || (T))) && F && (_) | |
| 0 | - | 238 | (((F) || (F)) || ((F) || (F))) && _ && (_) | |
| 239 | sigfillset(¤t->blocked); /* Mask all signals */ | |||
| 240 | recalc_sigpending(); | |||
| 241 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | |||
| 241 | do | |||
| 241 | do | |||
| 0 | 0 | - | 241 | do-while (0) |
| 0 | 0 | - | 241 | do-while (0) |
| 0 | 0 | - | 241 | do-while (0) |
| 242 | ||||
| 243 | call = nlmclnt_alloc_call(); | |||
| 0 | 0 | - | 244 | if (!call) { |
| 245 | status = -ENOMEM; | |||
| 0 | - | 246 | goto out_restore; | |
| 247 | } | |||
| 248 | call->a_flags = RPC_TASK_ASYNC; | |||
| 249 | } else { | |||
| 250 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | |||
| 250 | do | |||
| 250 | do | |||
| 0 | 0 | - | 250 | do-while (0) |
| 0 | 0 | - | 250 | do-while (0) |
| 0 | 0 | - | 250 | do-while (0) |
| 251 | memset(call, 0, sizeof(*call)); | |||
| 252 | locks_init_lock(&call->a_args.lock.fl); | |||
| 253 | locks_init_lock(&call->a_res.lock.fl); | |||
| 254 | } | |||
| 255 | call->a_host = host; | |||
| 256 | ||||
| 257 | nlmclnt_locks_init_private(fl, host); | |||
| 258 | ||||
| 259 | /* Set up the argument struct */ | |||
| 260 | nlmclnt_setlockargs(call, fl); | |||
| 261 | ||||
| 0 | 0 | - | 262 | if (IS_SETLK(cmd) || IS_SETLKW(cmd)) { |
| 0 | - | 262 | ((T) || (_)) || ((_) || (_)) | |
| 0 | - | 262 | ((F) || (T)) || ((_) || (_)) | |
| 0 | - | 262 | ((F) || (F)) || ((T) || (_)) | |
| 0 | - | 262 | ((F) || (F)) || ((F) || (T)) | |
| 0 | - | 262 | ((F) || (F)) || ((F) || (F)) | |
| 0 | 0 | - | 263 | if (fl->fl_type != F_UNLCK) { |
| 264 | call->a_args.block = IS_SETLKW(cmd) ? 1 : 0; | |||
| 0 | 0 | - | 264 | ternary-?: ( ( 0 ) || ( ( cmd ) == 7 ) ) |
| 265 | status = nlmclnt_lock(call, fl); | |||
| 266 | } else | |||
| 267 | status = nlmclnt_unlock(call, fl); | |||
| 0 | 0 | - | 268 | } else if (IS_GETLK(cmd)) |
| 0 | - | 268 | ((T) || (_)) | |
| 0 | - | 268 | ((F) || (T)) | |
| 0 | - | 268 | ((F) || (F)) | |
| 269 | status = nlmclnt_test(call, fl); | |||
| 270 | else | |||
| 271 | status = -EINVAL; | |||
| 272 | ||||
| 273 | out_restore: | |||
| 274 | spin_lock_irqsave(¤t->sighand->siglock, flags); | |||
| 274 | do | |||
| 274 | do | |||
| 0 | 0 | - | 274 | do-while (0) |
| 0 | 0 | - | 274 | do-while (0) |
| 274 | do | |||
| 274 | do | |||
| 0 | 0 | - | 274 | do-while (0) |
| 0 | 0 | - | 274 | do-while (0) |
| 0 | 0 | - | 274 | do-while (0) |
| 275 | current->blocked = oldset; | |||
| 276 | recalc_sigpending(); | |||
| 277 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | |||
| 277 | do | |||
| 277 | do | |||
| 0 | 0 | - | 277 | do-while (0) |
| 0 | 0 | - | 277 | do-while (0) |
| 0 | 0 | - | 277 | do-while (0) |
| 278 | ||||
| 279 | done: | |||
| 280 | dprintk("lockd: clnt proc returns %d\n", status); | |||
| 0 | 0 | - | 280 | if (__builtin_expect ( ! ! ( nlm_debug & 0x0.. |
| 0 | 0 | - | 280 | do-while (0) |
| 281 | nlm_release_host(host); | |||
| 0 | - | 282 | return status; | |
| 283 | } | |||
| 284 | EXPORT_SYMBOL(nlmclnt_proc); | |||
| 285 | ||||
| 286 | /* | |||
| 287 | * Allocate an NLM RPC call struct | |||
| 288 | */ | |||
| 289 | struct nlm_rqst * | |||
| 0 | 0 | - | 290 | nlmclnt_alloc_call(void) |
| 291 | { | |||
| 292 | struct nlm_rqst *call; | |||
| 293 | ||||
| 0 | 0 | - | 294 | while (!signalled()) { |
| 295 | call = (struct nlm_rqst *) kmalloc(sizeof(struct nlm_rqst), GFP_KERNEL); | |||
| 0 | 0 | - | 296 | if (call) { |
| 297 | memset(call, 0, sizeof(*call)); | |||
| 298 | locks_init_lock(&call->a_args.lock.fl); | |||
| 299 | locks_init_lock(&call->a_res.lock.fl); | |||
| 0 | - | 300 | return call; | |
| 301 | } | |||
| 302 | printk("nlmclnt_alloc_call: failed, waiting for memory\n"); | |||
| 303 | schedule_timeout_interruptible(5*HZ); | |||
| 304 | } | |||
| 0 | - | 305 | return NULL; | |
| 306 | } | |||
| 307 | ||||
| 0 | 0 | - | 308 | static int nlm_wait_on_grace(wait_queue_head_t *queue) |
| 309 | { | |||
| 310 | DEFINE_WAIT(wait); | |||
| 311 | int status = -EINTR; | |||
| 312 | ||||
| 313 | prepare_to_wait(queue, &wait, TASK_INTERRUPTIBLE); | |||
| 0 | 0 | - | 314 | if (!signalled ()) { |
| 315 | schedule_timeout(NLMCLNT_GRACE_WAIT); | |||
| 316 | try_to_freeze(); | |||
| 0 | 0 | - | 317 | if (!signalled ()) |
| 318 | status = 0; | |||
| 319 | } | |||
| 320 | finish_wait(queue, &wait); | |||
| 0 | - | 321 | return status; | |
| 322 | } | |||
| 323 | ||||
| 324 | /* | |||
| 325 | * Generic NLM call | |||
| 326 | */ | |||
| 327 | static int | |||
| 0 | 0 | - | 328 | nlmclnt_call(struct nlm_rqst *req, u32 proc) |
| 329 | { | |||
| 330 | struct nlm_host *host = req->a_host; | |||
| 331 | struct rpc_clnt *clnt; | |||
| 332 | struct nlm_args *argp = &req->a_args; | |||
| 333 | struct nlm_res *resp = &req->a_res; | |||
| 334 | struct rpc_message msg = { | |||
| 335 | .rpc_argp = argp, | |||
| 336 | .rpc_resp = resp, | |||
| 337 | }; | |||
| 338 | int status; | |||
| 339 | ||||
| 340 | dprintk("lockd: call procedure %d on %s\n", | |||
| 0 | 0 | - | 340 | if (__builtin_expect ( ! ! ( nlm_debug & 0x0.. |
| 0 | 0 | - | 340 | do-while (0) |
| 341 | (int)proc, host->h_name); | |||
| 342 | ||||
| 343 | do { | |||
| 0 | 0 | - | 344 | if (host->h_reclaiming && !argp->reclaim) |
| 0 | - | 344 | T && T | |
| 0 | - | 344 | T && F | |
| 0 | - | 344 | F && _ | |
| 0 | - | 345 | goto in_grace_period; | |
| 346 | ||||
| 347 | /* If we have no RPC client yet, create one. */ | |||
| 0 | 0 | - | 348 | if ((clnt = nlm_bind_host(host)) == NULL) |
| 0 | - | 349 | return -ENOLCK; | |
| 350 | msg.rpc_proc = &clnt->cl_procinfo[proc]; | |||
| 351 | ||||
| 352 | /* Perform the RPC call. If an error occurs, try again */ | |||
| 0 | 0 | - | 353 | if ((status = rpc_call_sync(clnt, &msg, 0)) < 0) { |
| 354 | dprintk("lockd: rpc_call returned error %d\n", -status); | |||
| 0 | 0 | - | 354 | if (__builtin_expect ( ! ! ( nlm_debug &.. |
| 0 | 0 | - | 354 | do-while (0) |
| 355 | switch (status) { | |||
| 0 | - | 356 | case -EPROTONOSUPPORT: | |
| 357 | status = -EINVAL; | |||
| 0 | - | 358 | break; | |
| 0 | - | 359 | case -ECONNREFUSED: | |
| 0 | - | 360 | case -ETIMEDOUT: | |
| 0 | - | 361 | case -ENOTCONN: | |
| 362 | nlm_rebind_host(host); | |||
| 363 | status = -EAGAIN; | |||
| 0 | - | 364 | break; | |
| 0 | - | 365 | case -ERESTARTSYS: | |
| 366 | return signalled () ? -EINTR : status; | |||
| 0 | 0 | - | 366 | ternary-?: ( signal_pending ( get_curren.. |
| 0 | - | 366 | return ( signal_pending ( get_current ( .. | |
| 0 | - | 367 | default: | |
| 0 | - | 368 | break; | |
| 369 | } | |||
| 0 | - | 370 | break; | |
| 371 | } else | |||
| 0 | 0 | - | 372 | if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) { |
| 373 | dprintk("lockd: server in grace period\n"); | |||
| 0 | 0 | - | 373 | if (__builtin_expect ( ! ! ( nlm_debug &.. |
| 0 | 0 | - | 373 | do-while (0) |
| 0 | 0 | - | 374 | if (argp->reclaim) { |
| 375 | printk(KERN_WARNING | |||
| 376 | "lockd: spurious grace period reject?!\n"); | |||
| 0 | - | 377 | return -ENOLCK; | |
| 378 | } | |||
| 379 | } else { | |||
| 0 | 0 | - | 380 | if (!argp->reclaim) { |
| 381 | /* We appear to be out of the grace period */ | |||
| 382 | wake_up_all(&host->h_gracewait); | |||
| 383 | } | |||
| 384 | dprintk("lockd: server returns status %d\n", resp->status); | |||
| 0 | 0 | - | 384 | if (__builtin_expect ( ! ! ( nlm_debug &.. |
| 0 | 0 | - | 384 | do-while (0) |
| 0 | - | 385 | return 0; /* Okay, call complete */ | |
| 386 | } | |||
| 387 | ||||
| 388 | in_grace_period: | |||
| 389 | /* | |||
| 390 | * The server has rebooted and appears to be in the grace | |||
| 391 | * period during which locks are only allowed to be | |||
| 392 | * reclaimed. | |||
| 393 | * We can only back off and try again later. | |||
| 394 | */ | |||
| 395 | status = nlm_wait_on_grace(&host->h_gracewait); | |||
| 0 | 0 | - | 396 | } while (status == 0); |
| 397 | ||||
| 0 | - | 398 | return status; | |
| 399 | } | |||
| 400 | ||||