Subversion Repositories shark

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 * Project: HARTIK (HA-rd R-eal TI-me K-ernel)
3
 *
4
 * Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
5
 *               Gerardo Lamastra <gerardo@sssup.it>
6
 *
7
 * Authors     : Massimiliano Giorgi <massy@hartik.sssup.it>
8
 * (see authors.txt for full list of hartik's authors)
9
 *
10
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
11
 *
12
 * http://www.sssup.it
13
 * http://retis.sssup.it
14
 * http://hartik.sssup.it
15
 */
16
 
17
/*
18
 * Copyright (C) 1999 Massimiliano Giorgi
19
 *
20
 * This program is free software; you can redistribute it and/or modify
21
 * it under the terms of the GNU General Public License as published by
22
 * the Free Software Foundation; either version 2 of the License, or
23
 * (at your option) any later version.
24
 *
25
 * This program is distributed in the hope that it will be useful,
26
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28
 * GNU General Public License for more details.
29
 *
30
 * You should have received a copy of the GNU General Public License
31
 * along with this program; if not, write to the Free Software
32
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
33
 *
34
 */
35
 
36
/*
37
 * CVS :        $Id: inode.c,v 1.1.1.1 2002-03-29 14:12:50 pj Exp $
38
 *
39
 * File:        $File$
40
 * Revision:    $Revision: 1.1.1.1 $
41
 * Last update: $Date: 2002-03-29 14:12:50 $
42
 */
43
 
44
#include <fs/util.h>
45
#include <fs/magic.h>
46
#include <fs/assert.h>
47
 
48
#include "fs.h"
49
#include "dentry.h"
50
#include "inode.h"
51
#include "inodeop.h"
52
#include "mutex.h"
53
#include "super.h"
54
#include "superop.h"
55
 
56
#include "debug.h"
57
 
58
#define MAXHASH     64
59
#define MAXHASHMASK 0x3f
60
 
61
static struct inode *ihash[MAXHASH];
62
static __fs_mutex_t hashmutex;
63
 
64
/* WARNING: must be greather than MAXDENTRY */
65
#define MAXINODES 256
66
 
67
static __fs_mutex_t mutex;
68
static struct inode *freeinode;
69
static struct inode ino[MAXINODES];
70
 
71
#ifdef FSMUTEXCHECK
72
 
73
void debug_dump_inode_mutex(void)
74
{
75
  //printk(KERN_DEBUG "inode mutex: %i",(int)mutex);
76
  //printk(KERN_DEBUG "inode mutex hasm: %i",(int)hashmutex);
77
}
78
 
79
static __fs_mutex_t regmutex;
80
static __fs_mutex_t reghashmutex;
81
 
82
int debug_check_inode_mutex(void)
83
{
84
  /*
85
  if (mutex!=regmutex) {
86
    printk(KERN_DEBUG "inode mutex CHANGED!");
87
    return 0;
88
  }
89
  if (hashmutex!=reghashmutex) {
90
    printk(KERN_DEBUG "inode hasmmutex CHANGED!");
91
    return 0;
92
  }
93
  */
94
  return -1;
95
}
96
 
97
void debug_save_inode_mutex(void)
98
{
99
  regmutex=mutex;
100
  reghashmutex=hashmutex;
101
}
102
 
103
#endif
104
 
105
/* WARNIG: if you want to aquire "mutex" and "hashmutex" you MUST
106
 * aquire first "hashmutex" and then "mutex" (if you do not want
107
 * a deadlock)
108
 */
109
 
110
void inode_stats(void)
111
{
112
  struct inode *ptr;
113
  int c,i,l,d;
114
 
115
  __fs_mutex_lock(&hashmutex);
116
  __fs_mutex_lock(&mutex);
117
 
118
  printk(KERN_INFO "max inodes:        %4i",MAXINODES);
119
 
120
  c=0;
121
  ptr=freeinode;
122
  while (ptr!=NULL) {
123
    c++;
124
    ptr=ptr->i_next;
125
  }
126
  printk(KERN_INFO "  free inodes:     %4i",c);
127
 
128
  for (i=0,l=0,c=0,d=0;i<MAXHASH;i++) {
129
    ptr=ihash[i];
130
    while (ptr!=NULL) {
131
      c++;
132
      if (ptr->i_dlink!=0) l++;
133
      if (ptr->i_dirty) d++;
134
      ptr=ptr->i_next;
135
    }
136
  }
137
  printk(KERN_INFO "  cached inodes:   %4i",c);
138
  printk(KERN_INFO "    linked inodes: %4i",l);
139
  printk(KERN_INFO "    dirty inodes:  %4i",d);
140
 
141
  __fs_mutex_unlock(&mutex);
142
  __fs_mutex_unlock(&hashmutex);
143
}
144
 
145
int inode_init(void)
146
{
147
  int i;
148
 
149
  __fs_mutex_init(&mutex);
150
  __fs_mutex_init(&hashmutex);
151
 
152
#ifdef FSMUTEXCHECK
153
  debug_save_inode_mutex();
154
#endif
155
 
156
  for (i=0;i<MAXINODES;i++) {
157
 
158
    /* for safety */
159
    memset(ino+i,0,sizeof(struct inode));
160
    magic_clr(ino[i].magic);
161
 
162
    __rwlock_init(&ino[i].i_lock);
163
    ino[i].i_next=&ino[i+1];    
164
  }
165
  freeinode=&ino[0];
166
  ino[MAXINODES-1].i_next=NULL;
167
 
168
  for (i=0;i<MAXHASH;i++)
169
    ihash[i]=NULL;
170
 
171
  return 0;
172
}
173
 
174
static struct inode *__get_inode(void)
175
{
176
  struct inode *ptr;
177
 
178
  //if (debug_info) cprintf("__get_inode start\n");
179
 
180
  ptr=freeinode;
181
  if (freeinode!=NULL) freeinode=freeinode->i_next;
182
 
183
  //if (debug_info) cprintf("__get_inode middle\n");
184
 
185
  if (ptr!=NULL) {
186
 
187
    //if (debug_info) cprintf("__get_inode assert\n");
188
 
189
    magic_assert_ext(ptr->magic,ZERO_MAGIC,inode_stats,
190
                 "inode_get: inode MAGIC number failed!\n");
191
    //magic_assert(ptr->magic,ZERO_MAGIC,
192
    //                  "inode_get: inode MAGIC number failed!\n");
193
 
194
    //if (debug_info) cprintf("__get_inode assert ok\n");
195
 
196
    magic_set(ptr->magic,INODE_MAGIC);
197
 
198
    //if (debug_info) cprintf("__get_inode magic setted\n");
199
 
200
  }
201
 
202
  //if (debug_info) cprintf("__get_inode end\n");
203
 
204
  return ptr;
205
}
206
 
207
struct inode *get_inode(void)
208
{
209
  struct inode *ptr;
210
 
211
  __fs_mutex_lock(&mutex);
212
  ptr=__get_inode();
213
  __fs_mutex_unlock(&mutex);  
214
 
215
  return ptr;
216
}
217
 
218
void free_inode(struct inode *ptr)
219
{
220
  magic_assert_ext(ptr->magic,INODE_MAGIC,inode_stats,
221
               "inode_free: inode MAGIC number failed!\n");
222
  magic_clr(ptr->magic);
223
 
224
  __fs_mutex_lock(&mutex);
225
  ptr->i_next=freeinode;
226
  freeinode=ptr;
227
  __fs_mutex_unlock(&mutex);
228
}
229
 
230
/*-------*/
231
 
232
static int hash_fun(__dev_t device, __ino_t inode)
233
{
234
  static __uint32_t table[8]={3,5,7,11,13,17,19,23};
235
  return (table[device&0x07]*(inode+1))&MAXHASHMASK;
236
}
237
 
238
void __insert_inode(struct inode *ptr)
239
{
240
  int h;
241
 
242
  magic_assert_ext(ptr->magic,INODE_MAGIC,inode_stats,
243
               "inode_insert: inode MAGIC number failed!\n");
244
 
245
  /* these could be done with no mutex syncronization */
246
  h=hash_fun(ptr->i_st.st_dev,ptr->i_st.st_ino);
247
  ptr->i_hash=h;
248
  ptr->i_prev=NULL;
249
 
250
  /* these NO */
251
  ptr->i_next=ihash[h];
252
  if (ihash[h]!=NULL) ihash[h]->i_prev=ptr;
253
  ihash[h]=ptr;
254
  ptr->i_dlink=1;
255
 
256
}
257
 
258
void insert_inode(struct inode *ptr)
259
{  
260
  __fs_mutex_lock(&hashmutex);
261
  __insert_inode(ptr);
262
  __fs_mutex_unlock(&hashmutex);
263
}
264
 
265
static void __remove_inode(struct inode *ptr)
266
{
267
  magic_assert_ext(ptr->magic,INODE_MAGIC,inode_stats,
268
               "inode_remove: inode MAGIC number failed!\n");
269
 
270
  if (ptr->i_next!=NULL) ptr->i_next->i_prev=ptr->i_prev;
271
  if (ptr->i_prev!=NULL) ptr->i_prev->i_next=ptr->i_next;
272
  else ihash[ptr->i_hash]=ptr->i_next;
273
}
274
 
275
void remove_inode(struct inode *ptr)
276
{  
277
  __fs_mutex_lock(&hashmutex);
278
  _assert(ptr->i_dlink==0);
279
  __remove_inode(ptr);
280
  __fs_mutex_unlock(&hashmutex);
281
 
282
}
283
 
284
static struct inode *__purge_inode(void)
285
{
286
  struct inode *ptr;
287
  int i;
288
 
289
  /* Well, this can be implemented better; actually a scan for the
290
   * unused inode into the buckets is done.
291
   * (for examples the unused inodes can be mantained into an unused
292
   * queue)
293
   */
294
  for (i=0;i<MAXHASH;i++) {
295
    ptr=ihash[i];
296
    while (ptr!=NULL) {
297
      if (ptr->i_dlink==0) {
298
        __remove_inode(ptr);
299
        return ptr;
300
      }
301
      ptr=ptr->i_next;
302
    }
303
  }
304
 
305
  return NULL;
306
}
307
 
308
/* find & remove the oldest dentry from the tree */
309
/*
310
static struct inode *purge_inode(void)
311
{
312
  struct inode *act;
313
  __fs_mutex_lock(&hashmutex);
314
  act=__purge_inode();  
315
  __fs_mutex_unlock(&hashmutex);
316
  return act;
317
}
318
*/
319
 
320
static struct inode *__catch_inode(void)
321
{
322
  struct inode *ptr;
323
 
324
 
325
  //if (debug_info) cprintf("get\n");
326
 
327
 
328
  ptr=get_inode(); /* aquiring "mutex" is required!! don't call __get_inode */
329
  if (ptr==NULL) {
330
    //if (debug_info) cprintf("get FAIL\n");
331
 
332
    ptr=__purge_inode();
333
 
334
    //if (debug_info) cprintf("catch\n");
335
 
336
    if (ptr==NULL) {
337
      //if (debug_info) cprintf("catch FAIL\n");
338
    }
339
  }
340
 
341
  return ptr;
342
}
343
 
344
/* get an inode by searching into the free space or purging an old one */
345
struct inode *catch_inode(void)
346
{
347
  struct inode *ptr;
348
 
349
  //if (debug_info) cprintf("catch called\n");
350
 
351
  __fs_mutex_lock(&hashmutex);
352
 
353
  //if (debug_info) cprintf("calling __catch...\n");
354
 
355
  ptr=__catch_inode();
356
 
357
  //if (debug_info) cprintf("__catch exiting\n");
358
 
359
  __fs_mutex_unlock(&hashmutex);
360
 
361
  return ptr;
362
}
363
 
364
struct inode *find_inode(__dev_t device, __ino_t ino)
365
{
366
  struct inode *ptr;
367
  int h;
368
 
369
  //h=hash_fun(ptr->i_st.st_dev,ptr->i_st.st_ino);
370
  h=hash_fun(device,ino);
371
  __fs_mutex_lock(&hashmutex);
372
  ptr=ihash[h];
373
  while (ptr!=NULL) {
374
    if (ptr->i_st.st_dev==device&&ptr->i_st.st_ino==ino) {
375
      ptr->i_dlink++;
376
      break;
377
    }
378
    ptr=ptr->i_next;
379
  }
380
 
381
  if (ptr==NULL) {
382
    ptr=__catch_inode();
383
    if (ptr!=NULL) {
384
      ptr->i_st.st_dev=device;
385
      ptr->i_st.st_ino=ino;
386
      __insert_inode(ptr);      
387
    }
388
  } else
389
    magic_assert_ext(ptr->magic,INODE_MAGIC,inode_stats,
390
                 "find_inode: inode MAGIC number failed!\n");
391
 
392
  __fs_mutex_unlock(&hashmutex);
393
 
394
  return ptr;  
395
}
396
 
397
/* unlock inode */
398
void unlock_inode(struct inode *ptr)
399
{
400
  magic_assert_ext(ptr->magic,INODE_MAGIC,inode_stats,
401
               "unlock_inode: inode MAGIC number failed!\n");
402
 
403
  __fs_mutex_lock(&hashmutex);
404
  _assert(ptr->i_dlink>0);  
405
  ptr->i_dlink--;
406
  __fs_mutex_unlock(&hashmutex);
407
}
408
 
409
/* unlock & remove inode from hash table */
410
int destroy_inode(struct inode *ptr)
411
{
412
  int ret;
413
  magic_assert_ext(ptr->magic,INODE_MAGIC,inode_stats,
414
                   "unlock_inode: inode MAGIC number failed!\n");
415
 
416
  __fs_mutex_lock(&hashmutex);
417
  _assert(ptr->i_dlink>0);  
418
  if (ptr->i_dlink!=1) {
419
    __fs_mutex_unlock(&hashmutex);
420
    return -1;
421
  }
422
 
423
  if (ptr->i_dirty) {
424
    ret=ptr->i_sb->sb_op->write_inode(ptr);
425
    if (ret!=0) {
426
      __fs_mutex_unlock(&hashmutex);
427
      return -1;
428
    }
429
  }
430
 
431
  ptr->i_dlink--;
432
  __remove_inode(ptr);
433
  __fs_mutex_unlock(&hashmutex);
434
  return 0;
435
}
436
 
437
/* unlock, remove the inode from the hast table
438
 * erase inode on disk
439
 */
440
int erase_inode(struct inode *ptr)
441
{
442
  int ret;
443
  magic_assert_ext(ptr->magic,INODE_MAGIC,inode_stats,
444
                   "erase_inode: inode MAGIC number failed!\n");
445
 
446
  __fs_mutex_lock(&hashmutex);
447
  _assert(ptr->i_dlink>0);
448
 
449
  if (ptr->i_dlink!=1) {
450
    __fs_mutex_unlock(&hashmutex);
451
    return -1;
452
  }
453
 
454
  ptr->i_op->destroy(ptr);
455
  ret=ptr->i_sb->sb_op->delete_inode(ptr);
456
  if (ret==0) {
457
    ptr->i_dlink--;
458
    __remove_inode(ptr);
459
  }
460
 
461
  __fs_mutex_unlock(&hashmutex);
462
  return ret;
463
}