Subversion Repositories shark

Rev

Rev 2 | Go to most recent revision | 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: dentry.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/types.h>
46
#include <fs/assert.h>
47
#include "fs.h"
48
#include "super.h"
49
#include "superop.h"
50
#include "dentry.h"
51
#include "dentryop.h"
52
#include "inode.h"
53
#include "inodeop.h"
54
#include "fsconst.h"
55
#include "mutex.h"
56
 
57
#include "debug.h"
58
 
59
/*
60
 * DEBUG
61
 */
62
 
63
/* if defined:
64
 * a short message is printed on console when a task go in/out of
65
 * functions dentry_find() & dentry_unlock()
66
 * (after  and before the lock/unlock of the mutex!)
67
 */
68
#define DEBUGFINDUNLOCK KERN_DEBUG
69
#undef DEBUGFINDUNLOCK
70
 
71
#ifdef DEBUGFINDUNLOCK
72
#define printdd(fmt,pid) kern_printf(fmt,pid)
73
#else
74
#define printdd(fmt,pid)
75
#endif
76
 
77
/* if you modify this you must modify MAXINODE */
78
#define MAXDENTRY 128
79
 
80
static __fs_mutex_t mutex;
81
static __fs_fastmutex_t mutexreq;
82
static struct dentry *freelist;
83
//static struct dentry *leaflist;
84
static struct dentry direntry[MAXDENTRY];
85
 
86
static struct dentry *root_direntry=NULL;
87
 
88
#ifdef FSMUTEXCHECK
89
void debug_dump_dentry_mutex(void)
90
{
91
  //printk(KERN_DEBUG "dentry mutex: %i",(int)mutex);
92
  //printk(KERN_DEBUG "dentry mutex req: %i",(int)mutexreq);
93
}
94
 
95
//static __fs_mutex_t regmutex;
96
//static __fs_mutex_t regmutexreq;
97
 
98
int debug_check_dentry_mutex(void)
99
{
100
  /*
101
  if (mutex!=regmutex) {
102
    printk(KERN_DEBUG "dentry mutex CHANGED! (prev: %i)",regmutex);
103
    return 0;
104
  }
105
  if (mutexreq!=regmutexreq) {
106
    printk(KERN_DEBUG "dentry mutexreq CHANGED! (prev: %i)",regmutexreq);
107
    return 0;
108
  }
109
  */
110
  return -1;
111
}
112
 
113
void debug_save_dentry_mutex(void)
114
{
115
  //regmutex=mutex;
116
  //regmutexreq=mutexreq;
117
}
118
#endif
119
 
120
int dentry_init(void)
121
{
122
  int i;
123
 
124
  __fs_mutex_init(&mutex);
125
  __fs_fastmutex_init(&mutexreq);
126
 
127
#ifdef FSMUTEXCHECK
128
  debug_save_dentry_mutex();
129
#endif
130
 
131
  freelist=direntry;
132
  for (i=0;i<MAXDENTRY;i++) {
133
    memset(direntry+i,0,sizeof(struct dentry));
134
    magic_set(direntry[i].magic,DENTRY_MAGIC);
135
    direntry[i].d_next=direntry+i+1;
136
    direntry[i].d_lock=-1;
137
  }
138
  direntry[MAXDENTRY-1].d_next=NULL;
139
  return 0;
140
}
141
 
142
static __inline__ struct dentry *__get_dentry(void)
143
{
144
  struct dentry *den;
145
  if (freelist==NULL) return NULL;    
146
  den=freelist;
147
  freelist=den->d_next;
148
 
149
  _assert(den->d_lock==-1);
150
  magic_assert(den->magic,DENTRY_MAGIC,"get_dentry: dentry MAGIC failed!");
151
 
152
  den->d_lock=0;
153
  return den;
154
}
155
 
156
/* get a dentry from the free queue */
157
struct dentry *get_dentry(void)
158
{
159
  struct dentry *den;
160
  __fs_fastmutex_lock(&mutexreq);
161
  den=__get_dentry();
162
  __fs_fastmutex_unlock(&mutexreq);
163
  return den;
164
}
165
 
166
static __inline__ void __free_dentry(struct dentry *den)
167
{
168
  _assert(den>=direntry&&den<direntry+MAXDENTRY);
169
  _assert(den->d_lock==0);
170
  magic_assert(den->magic,DENTRY_MAGIC,"free_dentry: dentry MAGIC failed!");
171
 
172
  den->d_lock=-1;
173
  den->d_next=freelist;
174
  freelist=den;
175
}
176
 
177
/* insert dentry into the free queue */
178
void free_dentry(struct dentry *den)
179
{
180
  __fs_fastmutex_lock(&mutexreq);
181
  __free_dentry(den);
182
  __fs_fastmutex_unlock(&mutexreq);
183
}
184
 
185
static void __insert_dentry(struct dentry *den, struct dentry *parent)
186
{
187
  _assert(den>=direntry&&den<direntry+MAXDENTRY);
188
  magic_assert(den->magic,DENTRY_MAGIC,"insert_dentry: dentry MAGIC failed!");
189
 
190
  den->d_acc=gettimek();
191
  den->d_parent=parent;
192
  den->d_child=NULL;
193
  den->d_prev=NULL;
194
  den->d_next=parent->d_child;
195
  if (parent->d_child!=NULL)
196
    parent->d_child->d_prev=den;
197
  parent->d_child=den;
198
}
199
 
200
/* insert a dentry into the tree */
201
void insert_dentry(struct dentry *den, struct dentry *parent)
202
{
203
  __fs_mutex_lock(&mutex);
204
  __insert_dentry(den,parent);
205
  __fs_mutex_unlock(&mutex);
206
}
207
 
208
static void __remove_dentry_only(struct dentry *den)
209
{
210
  _assert(den>=direntry&&den<direntry+MAXDENTRY);
211
  magic_assert(den->magic,DENTRY_MAGIC,"remove_dentry: dentry MAGIC failed!");
212
  _assert(den->d_lock==0);
213
 
214
  if (den->d_prev!=NULL)
215
    den->d_prev->d_next=den->d_next;
216
  else
217
    den->d_parent->d_child=den->d_next;
218
  if (den->d_next!=NULL)
219
    den->d_next->d_prev=den->d_prev;
220
}
221
 
222
static __inline__ void __remove_dentry(struct dentry *den)
223
{
224
  __remove_dentry_only(den);
225
  unlock_inode(den->d_inode);  
226
}
227
 
228
/* remove a dentry from the tree */
229
void remove_dentry(struct dentry *den)
230
{
231
  __fs_mutex_lock(&mutex);
232
  __remove_dentry(den);
233
  __fs_mutex_unlock(&mutex);
234
}
235
 
236
/* find the oldest dentry into the tree */
237
/*
238
 * (potrebbe essere fatto in maniera non ricorsiva usando un
239
 * puntatore alle foglie e scandendo questa lista invece di visitare
240
 * tutto l'albero!)
241
 *
242
 * si potrebbe usare un task NRT periodico per mantenere liberi (se
243
 * possibile l'X% delle dentry libere.
244
 */
245
 
246
static struct dentry *__recurse(struct dentry *den, struct dentry *act)
247
{
248
  while (den!=NULL) {    
249
    if (den->d_child!=NULL) {
250
      act=__recurse(den->d_child,act);
251
    } else {
252
      if (den->d_lock==0) {
253
        if (act==NULL)
254
          act=den;
255
        else {
256
          if (den->d_acc<act->d_acc)
257
            act=den;
258
        }
259
      }      
260
    }
261
    den=den->d_next;
262
  }
263
  return act;
264
}
265
 
266
struct dentry *__purge_dentry(void)
267
{
268
  struct dentry *act;
269
  act=__recurse(root_direntry,NULL);
270
  if (act!=NULL) __remove_dentry(act);
271
  return act;
272
}
273
 
274
/* find & remove the oldest dentry from the tree */
275
struct dentry *purge_dentry(void)
276
{
277
  struct dentry *act;
278
  __fs_mutex_lock(&mutex);
279
  act=__purge_dentry();  
280
  __fs_mutex_unlock(&mutex);
281
  return act;
282
}
283
 
284
struct dentry *__catch_dentry(void)
285
{
286
  struct dentry *den;
287
  den=__get_dentry();
288
  if (den==NULL) den=__purge_dentry();
289
  return den;
290
}
291
 
292
/* get a dentry by searching into the free space or purging an old one */
293
/*
294
static struct dentry *catch_dentry(void)
295
{
296
  struct dentry *den;
297
  __fs_mutex_lock(&mutex);
298
  den=__catch_dentry();  
299
  __fs_mutex_unlock(&mutex);
300
  return den;
301
}
302
*/
303
 
304
/*---------------------*/
305
 
306
int set_root_dentry(struct super_block *sb)
307
{
308
  struct dentry *den;
309
 
310
  __fs_mutex_lock(&mutex);
311
  if (sb==NULL) {
312
    _assert(root_direntry!=NULL);
313
    root_direntry->d_lock--;
314
    _assert(root_direntry->d_lock==1);
315
    root_direntry=NULL;
316
    __fs_mutex_unlock(&mutex);
317
    return 0;
318
  }
319
  _assert(root_direntry==NULL);
320
  __fs_mutex_unlock(&mutex);
321
 
322
  den=get_dentry();
323
  if (den==NULL) return -1;
324
 
325
  den->d_next=NULL;
326
  den->d_prev=NULL;
327
  den->d_parent=NULL;
328
  den->d_child=NULL;
329
 
330
  den->d_acc=0;
331
  den->d_name.nameptr=ROOTDIRNAME;
332
 
333
  den->d_op=sb->sb_dop;
334
  den->d_sb=sb;
335
  den->d_inode=sb->sb_root;
336
 
337
  den->d_lock=1;
338
 
339
  sb->sb_droot=den;
340
  root_direntry=den;
341
 
342
  return 0;
343
}
344
 
345
struct dentry *get_root_dentry(void)
346
{
347
  _assert(root_direntry!=NULL);
348
  return root_direntry;
349
}
350
 
351
#ifdef DEBUG_FIND_DUMP
352
static void dump_dentry(struct dentry *ptr)
353
{
354
  printk7(KERN_DEBUG "dentry dump:");
355
  printk7(KERN_DEBUG "  name : %s",QSTRNAME(&ptr->d_name));
356
  printk7(KERN_DEBUG "  lock : %i",ptr->d_lock);
357
  printk7(KERN_DEBUG "  inode: %i",ptr->d_inode->i_st.st_ino);
358
}
359
#else
360
#define dump_dentry(x)
361
#endif
362
 
363
/*--------------*/
364
 
365
/*
366
 * flags for createflags:
367
 * DENTRY_NOCREATE   -> can't create a new inode
368
 * DENTRY_CANCREATE  -> an inode (only the last) can be created
369
 * DENTRY_MUSTCREATE -> the last inode MUST be created (it must no exist)
370
 *
371
 * return flags for createflags:
372
 * DENTRY_CREATED -> the last inode has been created
373
 * DENTRY_EXIST   -> (error) the last inode already exist
374
 *
375
 * return NULL on error (not found or DENTRY_EXIST)
376
 *
377
 * NB:
378
 * if createflag is NULL a DENTRY_NOCREATE is assumed
379
 * 'act' can be NULL if pathname is an absolute path
380
 */
381
 
382
struct dentry *find_dentry_from_ext(struct dentry *act,
383
                                    char *pathname,
384
                                    int *createflag)
385
{
386
  struct dentry *ptr;
387
  struct dentry *den;
388
  struct inode *ino;
389
  struct qstr str;
390
  char *sp;
391
  char *s;
392
  int  found,created;
393
 
394
  /* too much 'goto' :-( and 'if' */
395
 
396
  sp=pathname;
397
  if (*pathname==DIRDELIMCHAR) {
398
    act=root_direntry;
399
    sp++;
400
  }
401
  if (act==NULL) return NULL;
402
 
403
  printdd("°f<%i>",exec_shadow);
404
  __fs_mutex_lock(&mutex);
405
  printdd("±f<%i>",exec_shadow);
406
 
407
  if (*sp=='\0') goto END0;
408
 
409
  created=0;
410
  found=1;
411
  while (found) {
412
    s=strchr(sp,DIRDELIMCHAR);
413
    if (s!=NULL) *s='\0';
414
 
415
    printk7("dentry find: searching for %s...",sp);
416
 
417
    /* for handle special directory entry "." and ".." */
418
    if (*sp=='.') {
419
      if (*sp=='\0') {
420
        /* found "." special directory */
421
        printk7("dentry find: special directory entry '.'");
422
        found=1;
423
        if (s==NULL) goto END0;
424
        *s=DIRDELIMCHAR;
425
        sp=s+1;
426
        s=strchr(sp,DIRDELIMCHAR);
427
        continue;      
428
      }
429
      if (*sp=='.') {
430
        if (*sp=='\0') {
431
          /* found ".." special directory */
432
          printk7("dentry find: special directory entry '..'");
433
          found=1;
434
          if (act->d_parent!=NULL) act=act->d_parent;
435
          if (s==NULL) goto END0;
436
          *s=DIRDELIMCHAR;
437
          sp=s+1;
438
          s=strchr(sp,DIRDELIMCHAR);
439
          continue;    
440
        }      
441
      }
442
    }
443
 
444
    ptr=act->d_child;
445
    found=0;
446
    str.nameptr=sp;
447
    while (ptr!=NULL) {
448
      if (ptr->d_op->d_compare(ptr,&ptr->d_name,&str)==0) {
449
 
450
        printk7("dentry find: found!");
451
 
452
        found=1;
453
        act=ptr;
454
        if (s==NULL) goto END0;
455
        *s=DIRDELIMCHAR;
456
        sp=s+1;
457
        s=strchr(sp,DIRDELIMCHAR);
458
        break;
459
      }
460
      ptr=ptr->d_next;
461
    }        
462
  }
463
 
464
  printk7("dentry find: NOT found!");
465
 
466
  for (;;) {
467
    den=__catch_dentry();
468
    if (den==NULL) {
469
      if (s!=NULL) *s=DIRDELIMCHAR;
470
      printk7("dentry find: can't have new struct dentry!");
471
      act=NULL;
472
      goto END1;
473
    }
474
 
475
    den->d_acc=0;
476
    den->d_name.nameptr=NULL;
477
    strcpy(den->d_name.name,sp);
478
    den->d_lock=0;
479
    den->d_op=act->d_op;
480
    den->d_sb=act->d_sb;
481
 
482
    printk7("dentry find: looking up for %s....",sp);
483
    dump_dentry(act);
484
 
485
    ino=act->d_inode->i_op->lookup(act->d_inode,den);
486
 
487
    printk7("dentry find: end looking");
488
 
489
    if (ino==NULL) {
490
 
491
      printk7("dentry find: NOT found!");
492
      if (s!=NULL) *s=DIRDELIMCHAR;      
493
 
494
      if (createflag==NULL) {
495
        __free_dentry(den);
496
        act=NULL;
497
        goto END1;
498
      }
499
 
500
      if ((s==NULL)&&(*createflag&DENTRY_CANCREATE)) {
501
 
502
        printk7("dentry find: check for read-only fs");
503
        if (!(act->d_sb->sb_mopts.flags&MOUNT_FLAG_RW)) {
504
          printk7("dentry find: read-only fs.. creating new inode fails");
505
          __free_dentry(den);
506
          act=NULL;
507
          goto END1;
508
        }
509
 
510
        printk7("dentry find: try to create a new inode");
511
        ino=act->d_inode->i_op->create(act->d_inode,den);
512
 
513
        if (ino==NULL) {  
514
          printk7("dentry find: inode creation fail");
515
          __free_dentry(den);
516
          act=NULL;
517
          goto END1;
518
        }
519
        printk7("dentry find: new inode created");
520
        created=1;
521
 
522
      } else {
523
        __free_dentry(den);
524
        act=NULL;
525
        goto END1;
526
      }
527
    }
528
    den->d_inode=ino;
529
 
530
    insert_inode(ino);  
531
    printk7("dentry find: found!");
532
 
533
    __insert_dentry(den,act);
534
    act=den;
535
 
536
    if (s==NULL) goto END2;
537
 
538
    sp=s+1;
539
    *s=DIRDELIMCHAR;    
540
    s=strchr(sp,DIRDELIMCHAR);
541
    if (s!=NULL) *s='\0';
542
  }
543
 
544
  /* for safety */
545
  _assert(0==-1);
546
 
547
END0:
548
  /* 'if found' we are here */
549
  if (createflag!=NULL) {
550
    *createflag&=~DENTRY_CREATEMASK;
551
    if (*createflag&DENTRY_MUSTCREATE) {
552
      _assert(act!=NULL);
553
      *createflag|=DENTRY_EXIST;
554
      act=NULL;
555
    }
556
  }
557
  goto END;
558
 
559
END1:
560
  /* 'if error' we are here */
561
  _assert(act==NULL);
562
  if (createflag!=NULL) *createflag&=~DENTRY_CREATEMASK;
563
  goto END;
564
 
565
END2:
566
  /* 'if ok' (found or created) we are here */
567
  _assert(act!=NULL);
568
  if (createflag!=NULL) {
569
    if (created) {
570
      *createflag&=~DENTRY_CREATEMASK;           
571
      *createflag|=DENTRY_CREATED;
572
    } else if ((*createflag&DENTRY_MUSTCREATE)==DENTRY_MUSTCREATE) {
573
      *createflag&=~DENTRY_CREATEMASK;           
574
      *createflag|=DENTRY_EXIST;
575
      act=NULL;
576
    } else
577
      *createflag&=~DENTRY_CREATEMASK;                   
578
  }
579
  goto END;    
580
 
581
END:
582
  if (act!=NULL) act->d_lock++;
583
 
584
  printdd("²f<%i>",exec_shadow);
585
  __fs_mutex_unlock(&mutex);
586
  printdd("Ûf<%i>",exec_shadow);
587
  return act;
588
 
589
}
590
 
591
void unlock_dentry(struct dentry *den)
592
{
593
  printdd("°u<%i>",exec_shadow);
594
  __fs_mutex_lock(&mutex);
595
  printdd("±u<%i>",exec_shadow);
596
 
597
  _assert(den>=direntry&&den<direntry+MAXDENTRY);
598
  if (den->d_lock<=0) {
599
    printk(KERN_DEBUG "unlock_dentry on %s",QSTRNAME(&den->d_name));
600
  }
601
  _assert(den->d_lock>0);
602
 
603
  den->d_lock--;
604
  //if (den->d_lock==0) {
605
  //  _assert(den->d_inode!=NULL);
606
  //  unlock_inode(den->d_inode);
607
  //}
608
 
609
  printdd("²u<%i>",exec_shadow);
610
  __fs_mutex_unlock(&mutex);
611
  printdd("Ûu<%i>",exec_shadow);
612
}
613
 
614
/*
615
 *
616
 */
617
 
618
static void __print_name(struct dentry *act,char *buffer)
619
{
620
  if (act->d_parent==NULL) return;
621
  __print_name(act->d_parent,buffer);
622
  strcat(buffer,ROOTDIRNAME);
623
  strcat(buffer,QSTRNAME(&act->d_name));
624
  return;
625
}
626
 
627
static char *print_name(struct dentry *act)
628
{
629
  static char buffer[1024];
630
  buffer[0]='\0';
631
  __print_name(act,buffer);
632
  return buffer;
633
}
634
 
635
void getfullname_dentry(struct dentry *act, char *buffer, int size)
636
{
637
  _assert(act>=direntry&&act<direntry+MAXDENTRY);
638
  magic_assert(act->magic,DENTRY_MAGIC,
639
               "getfullname_dentry: dentry MAGIC failed!");
640
 
641
  buffer[0]='\0';
642
  __print_name(act,buffer);
643
  _assert(strlen(buffer)<size);
644
}
645
 
646
static void visit_tree(struct dentry *act)
647
{
648
  struct dentry *ptr;
649
  if (act==root_direntry) printk(KERN_DEBUG "  %s",ROOTDIRNAME);
650
  else { char *s=print_name(act); printk(KERN_DEBUG "  %s",s);}
651
  ptr=act->d_child;
652
  while (ptr!=NULL) {
653
    visit_tree(ptr);
654
    ptr=ptr->d_next;
655
  }
656
  return;
657
}
658
 
659
void dump_dentry_tree(void)
660
{
661
  printk(KERN_DEBUG "DTREE dump");
662
  visit_tree(root_direntry);
663
}
664
 
665
/*
666
 *
667
 */
668
 
669
#ifdef DEBUGPURGECHILD
670
#define dprint(fmt,args...) printk(fmt,##args)
671
#else
672
#define dprint(fmt,args...)
673
#endif
674
 
675
static __inline__ int __purgeallchilds_mg(struct dentry *de)
676
{
677
  int ret;
678
  struct dentry *ptr,*ptr2,*ptr3;
679
 
680
  dprint(KERN_DEBUG "START mg purgechild");
681
 
682
  {
683
#ifdef DEBUGPURGECHILD
684
    char *s=print_name(de);
685
    dprint(KERN_DEBUG "for %s",s);
686
#endif
687
  }
688
 
689
  /*
690
   * Phase 1
691
   * purge all childs (if possible!)
692
   */
693
 
694
  ptr=de->d_child;
695
  ret=0;
696
 
697
  /* why these? I do not want to use recursion... (or goto statement)*/
698
  for (;;) {
699
    /* if there is a child... continue using the child's chain */
700
    if (ptr->d_child!=NULL) {
701
      ptr=ptr->d_child;
702
      continue;      
703
    }    
704
    /* if a child dentry is locked... can't continue! */
705
    if (ptr->d_lock) {
706
      #ifdef DEBUGPURGECHILD
707
      char *s=print_name(ptr);
708
      dprint(KERN_DEBUG "%s is locked!!!",s);
709
      #endif
710
      ret=-1;
711
      break;
712
    }
713
    /* purge this dentry */
714
    ptr2=ptr->d_next;
715
    ptr3=ptr->d_parent;
716
 
717
    dprint(KERN_DEBUG "%s destroy",QSTRNAME(&ptr->d_name));
718
    ret=destroy_inode(ptr->d_inode);
719
    if (ret) break;
720
    __remove_dentry_only(ptr);
721
 
722
    /* if there is not another child... continue with the parent */
723
    if (ptr2==NULL) {
724
      ptr=ptr3;
725
      if (ptr==de) break;
726
      continue;
727
    }
728
    /* continue with next child */
729
    ptr=ptr2;
730
  }
731
 
732
  dprint(KERN_DEBUG "END mg purgechild");  
733
  return ret;
734
}
735
 
736
static __inline__ int __purgeallchilds_pj(struct dentry *x)
737
{
738
  struct dentry *p,*q;
739
 
740
  dprint(KERN_DEBUG "START pj purgechild");
741
 
742
  p = x->d_child;
743
  q = NULL;
744
  for(;;) {
745
    /* scorro i figli */
746
    while(p) {
747
      q = p;
748
      p = p->d_next;
749
    }
750
 
751
    if (q == x) {
752
      dprint(KERN_DEBUG "END pj purgechild");  
753
      return 0; /* finito */
754
    }
755
 
756
    if (q->d_child) {
757
      p = q->d_child;
758
      q = NULL;
759
    }
760
    else {
761
      /* sono su un nodo senza figli */
762
      /* q punta al nodo */
763
      if (q->d_prev)
764
        { /* non e' il primo figlio */
765
          q = q->d_prev;
766
          if (q->d_next->d_lock) {
767
            dprint(KERN_DEBUG "%s is locked",
768
                   QSTRNAME(&q->d_next->d_name));
769
            return -1;
770
          }
771
          if (destroy_inode(q->d_next->d_inode)) {
772
            dprint(KERN_DEBUG "error destroing %s",
773
                   QSTRNAME(&q->d_next->d_name));
774
            return -1;
775
          }
776
          dprint(KERN_DEBUG "removing %s",QSTRNAME(&q->d_next->d_name));
777
          __remove_dentry_only(q->d_next);
778
          q->d_next = NULL;
779
          p = NULL;
780
        }
781
      else {
782
        /* e' il primo figlio */
783
        q = q->d_parent;
784
        if (q->d_child->d_lock) {
785
            dprint(KERN_DEBUG "%s is locked",
786
                   QSTRNAME(&q->d_child->d_name));
787
          return -1;
788
        }
789
        if (destroy_inode(q->d_child->d_inode)) {
790
            dprint(KERN_DEBUG "error destroing %s",
791
                   QSTRNAME(&q->d_child->d_name));
792
          return -1;
793
        }
794
        dprint(KERN_DEBUG "removing %s",QSTRNAME(&q->d_child->d_name));
795
        __remove_dentry_only(q->d_child);
796
        q->d_child = NULL;
797
        p = NULL;
798
      }
799
    }
800
  }
801
 
802
}
803
 
804
#define __purgeallchilds(de) __purgeallchilds_mg(de)
805
 
806
int mount_dentry(struct super_block *sb, struct dentry *de)
807
{
808
  int ret;
809
 
810
  printk9("START mount_dentry()!");
811
  printk9("for %s",QSTRNAME(&de->d_name));
812
 
813
  _assert(de!=NULL);
814
  _assert(sb!=NULL);
815
 
816
  __fs_mutex_lock(&mutex);
817
 
818
  printk9("locked and ready");
819
 
820
  if (de->d_lock>1) {
821
    printk9("LOCKED!");    
822
    /* someone is using this dentry! */
823
    __fs_mutex_unlock(&mutex);    
824
    return -1;    
825
  }
826
 
827
  /*
828
   * Phase 1
829
   */
830
 
831
  /* purge all childs (if possible) */
832
 
833
  if (de->d_child!=NULL) {
834
    ret=__purgeallchilds(de);      
835
    if (ret) {
836
      printk9("PURGECHILD!");      
837
      __fs_mutex_unlock(&mutex);
838
      return ret;
839
    }
840
 
841
  }
842
 
843
  /*
844
   * Phase 2
845
   */
846
 
847
  ret=destroy_inode(de->d_inode);
848
  if (ret) {
849
    printk9("DESTROY INODE!");    
850
    __fs_mutex_unlock(&mutex);
851
    return ret;
852
  }
853
 
854
  de->d_op=sb->sb_dop;
855
  de->d_inode=sb->sb_root;
856
  de->d_sb=sb;
857
 
858
  sb->sb_droot=de;
859
 
860
  __fs_mutex_unlock(&mutex);
861
  printk9("END mount_dentry()!");
862
  return 0;
863
}
864
 
865
int umount_dentry(struct super_block *sb)
866
{
867
  struct dentry *de;
868
  int res;
869
 
870
  printk9("START umount_dentry()");
871
 
872
  __fs_mutex_lock(&mutex);
873
 
874
  _assert(sb!=NULL);
875
  _assert(sb->sb_droot!=NULL);
876
  if (sb->sb_droot->d_child!=NULL) {
877
    res=__purgeallchilds(sb->sb_droot);
878
    if (res) {      
879
      printk9("PURGING CHILD!");    
880
      __fs_mutex_unlock(&mutex);
881
      return res;
882
    }
883
  }
884
 
885
  printk9("umount_dentry: phase 1");
886
 
887
  de=sb->sb_droot;
888
  _assert(de->d_lock>0);
889
  if (de->d_lock!=1) {
890
    printk9("LOCK COUNT! (%i)",de->d_lock);
891
    __fs_mutex_unlock(&mutex);
892
    return -1;
893
  }
894
  de->d_lock--;
895
 
896
  printk9("umount_dentry: phase 2");
897
 
898
  __remove_dentry_only(de);
899
  destroy_inode(de->d_inode);
900
  __free_dentry(de);
901
 
902
  printk9("umount_dentry: phase 3");
903
 
904
  sb->sb_droot=NULL;
905
  sb->sb_root=NULL;
906
 
907
  __fs_mutex_unlock(&mutex);
908
 
909
  printk9("END umount_dentry()!");
910
  return 0;
911
}
912
 
913
int unlink_dentry(struct dentry *d)
914
{
915
  struct inode *in;
916
  int res;
917
 
918
  printkd("unlink_dentry: START");
919
 
920
  __fs_mutex_lock(&mutex);
921
  if (d->d_lock!=1) return EBUSY;
922
 
923
  in=d->d_inode;
924
 
925
  printkd("unlink_dentry: dentry ok");
926
 
927
  __rwlock_wrlock(&in->i_lock);  
928
 
929
  printkd("unlink_dentry: locked inode");
930
 
931
  res=in->i_op->unlink(d);
932
 
933
  printkd("unlink_dentry: inode unlinked from dentry");
934
 
935
  if (res==0&&in->i_st.st_nlink==0) {
936
    printkd("unlink_dentry: no more links erasing inode");
937
    erase_inode(in);    
938
  }
939
 
940
  __rwlock_wrunlock(&in->i_lock);
941
 
942
  printkd("unlink_dentry: unlocked inode");
943
 
944
  if (res==0) {
945
    d->d_lock--;
946
    __remove_dentry_only(d);
947
    printkd("unlink_dentry: dentry unlinked");
948
  }
949
 
950
  __fs_mutex_unlock(&mutex);
951
 
952
  printkd("unlink_dentry: END");
953
  return -res;
954
}