Fork me on GitHub

root/fs/locks.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_new_flock
  2. release_flock
  3. get_flock_file
  4. posix_lock
  5. flock_release_inode
  6. flock_inode
  7. flock_init

   1 /*
   2  * fiwix/fs/locks.c
   3  *
   4  * Copyright 2018-2021, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/errno.h>
   9 #include <fiwix/types.h>
  10 #include <fiwix/locks.h>
  11 #include <fiwix/fs.h>
  12 #include <fiwix/sleep.h>
  13 #include <fiwix/sched.h>
  14 #include <fiwix/stdio.h>
  15 #include <fiwix/string.h>
  16 
  17 static struct resource flock_resource = { NULL, NULL };
  18 
  19 static struct flock_file * get_new_flock(struct inode *i)
  20 {
  21         int n;
  22         struct flock_file *ff;
  23 
  24         lock_resource(&flock_resource);
  25 
  26         for(n = 0; n < NR_FLOCKS; n++) {
  27                 ff = &flock_file_table[n];
  28                 if(!ff->inode) {
  29                         ff->inode = i;  /* mark it as busy */
  30                         unlock_resource(&flock_resource);
  31                         return ff;
  32                 }
  33         }
  34 
  35         printk("WARNING: %s(): no more free slots in flock file table.\n");
  36         unlock_resource(&flock_resource);
  37         return NULL;
  38 }
  39 
  40 static void release_flock(struct flock_file *ff)
  41 {
  42         memset_b(ff, 0, sizeof(struct flock_file));
  43 }
  44 
  45 static struct flock_file * get_flock_file(struct inode *i, int op, struct proc *p)
  46 {
  47         int n;
  48         struct flock_file *ff;
  49 
  50         lock_resource(&flock_resource);
  51 
  52         ff = NULL;
  53         for(n = 0; n < NR_FLOCKS; n++) {
  54                 ff = &flock_file_table[n];
  55                 if(ff->inode != i) {
  56                         continue;
  57                 }
  58                 if(p && p != ff->proc) {
  59                         continue;
  60                 }
  61                 break;
  62         }
  63         unlock_resource(&flock_resource);
  64         return ff;
  65 }
  66 
  67 int posix_lock(int ufd, int cmd, struct flock *fl)
  68 {
  69         int n;
  70         struct flock_file *ff;
  71         struct inode *i;
  72         unsigned char type;
  73 
  74         lock_resource(&flock_resource);
  75         i = fd_table[current->fd[ufd]].inode;
  76         for(n = 0; n < NR_FLOCKS; n++) {
  77                 ff = &flock_file_table[n];
  78                 if(ff->inode != i) {
  79                         continue;
  80                 }
  81                 break;
  82         }
  83         unlock_resource(&flock_resource);
  84         if(cmd == F_GETLK) {
  85                 if(ff->inode == i) {
  86                         fl->l_type = (ff->type & LOCK_SH) ? F_RDLCK : F_WRLCK;
  87                         fl->l_whence = SEEK_SET;
  88                         fl->l_start = 0;
  89                         fl->l_len = 0;
  90                         fl->l_pid = ff->proc->pid;
  91                 } else {
  92                         fl->l_type = F_UNLCK;
  93                 }
  94         }
  95 
  96         switch(fl->l_type) {
  97                 case F_RDLCK:
  98                         type = LOCK_SH;
  99                         break;
 100                 case F_WRLCK:
 101                         type = LOCK_EX;
 102                         break;
 103                 case F_UNLCK:
 104                         type = LOCK_UN;
 105                         break;
 106                 default:
 107                         return -EINVAL;
 108         }
 109         if(cmd == F_SETLK) {
 110                 return flock_inode(i, type);
 111         }
 112         if(cmd == F_SETLKW) {
 113                 return flock_inode(i, type | LOCK_NB);
 114         }
 115         return 0;
 116 }
 117 
 118 void flock_release_inode(struct inode *i)
 119 {
 120         int n;
 121         struct flock_file *ff;
 122 
 123         lock_resource(&flock_resource);
 124         for(n = 0; n < NR_FLOCKS; n++) {
 125                 ff = &flock_file_table[n];
 126                 if(ff->inode != i) {
 127                         continue;
 128                 }
 129                 if(ff->proc != current) {
 130                         continue;
 131                 }
 132                 wakeup(ff);
 133                 release_flock(ff);
 134         }
 135         unlock_resource(&flock_resource);
 136 }
 137 
 138 int flock_inode(struct inode *i, int op)
 139 {
 140         int n;
 141         struct flock_file *ff, *new;
 142 
 143         if(op & LOCK_UN) {
 144                 if((ff = get_flock_file(i, op, current))) {
 145                         wakeup(ff);
 146                         release_flock(ff);
 147                 }
 148                 return 0;
 149         }
 150 
 151 loop:
 152         lock_resource(&flock_resource);
 153         new = NULL;
 154         for(n = 0; n < NR_FLOCKS; n++) {
 155                 ff = &flock_file_table[n];
 156                 if(ff->inode != i) {
 157                         continue;
 158                 }
 159                 if(op & LOCK_SH) {
 160                         if(ff->type & LOCK_EX) {
 161                                 if(ff->proc == current) {
 162                                         new = ff;
 163                                         wakeup(ff);
 164                                         break;
 165                                 }
 166                                 unlock_resource(&flock_resource);
 167                                 if(op & LOCK_NB) {
 168                                         return -EWOULDBLOCK;
 169                                 }
 170                                 if(sleep(ff, PROC_INTERRUPTIBLE)) {
 171                                         return -EINTR;
 172                                 }
 173                                 goto loop;
 174                         }
 175                 }
 176                 if(op & LOCK_EX) {
 177                         if(ff->proc == current) {
 178                                 new = ff;
 179                                 continue;
 180                         }
 181                         unlock_resource(&flock_resource);
 182                         if(op & LOCK_NB) {
 183                                 return -EWOULDBLOCK;
 184                         }
 185                         if(sleep(ff, PROC_INTERRUPTIBLE)) {
 186                                 return -EINTR;
 187                         }
 188                         goto loop;
 189                 }
 190         }
 191         unlock_resource(&flock_resource);
 192 
 193         if(!new) {
 194                 if(!(new = get_new_flock(i))) {
 195                         return -ENOLCK;
 196                 }
 197         }
 198         new->inode = i;
 199         new->type = op;
 200         new->proc = current;
 201 
 202         return 0;
 203 }
 204 
 205 void flock_init(void)
 206 {
 207         memset_b(flock_file_table, NULL, sizeof(flock_file_table));
 208 }

/* [previous][next][first][last][top][bottom][index][help] */