xfile.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <fcall.h>
  12. #include <thread.h>
  13. #include <9p.h>
  14. #include "dat.h"
  15. #include "fns.h"
  16. static Xfs *xhead;
  17. static Xfile *freelist;
  18. static Lock xlock, freelock;
  19. int client;
  20. Xfs *
  21. getxfs(char *name)
  22. {
  23. int fd;
  24. Dir *dir;
  25. Xfs *xf, *fxf;
  26. if(name==0 || name[0]==0)
  27. name = deffile;
  28. if(name == 0){
  29. errno = Enofilsys;
  30. return 0;
  31. }
  32. fd = open(name, rdonly ? OREAD : ORDWR);
  33. if(fd < 0){
  34. errno = Enonexist;
  35. return 0;
  36. }
  37. if((dir = dirfstat(fd)) == 0){
  38. errno = Eio;
  39. close(fd);
  40. return 0;
  41. }
  42. lock(&xlock);
  43. for(fxf=0, xf=xhead; xf; xf=xf->next){
  44. if(xf->ref == 0){
  45. if(fxf == 0)
  46. fxf = xf;
  47. continue;
  48. }
  49. if(xf->qid.path != dir->qid.path || xf->qid.vers != dir->qid.vers)
  50. continue;
  51. if(strcmp(xf->name, name) != 0 || xf->dev < 0)
  52. continue;
  53. chat("incref \"%s\", dev=%d...", xf->name, xf->dev);
  54. ++xf->ref;
  55. unlock(&xlock);
  56. close(fd);
  57. free(dir);
  58. return xf;
  59. }
  60. if(fxf==0){
  61. fxf = malloc(sizeof(Xfs));
  62. if(fxf==0){
  63. unlock(&xlock);
  64. close(fd);
  65. free(dir);
  66. errno = Enomem;
  67. return 0;
  68. }
  69. fxf->next = xhead;
  70. xhead = fxf;
  71. }
  72. chat("alloc \"%s\", dev=%d...", name, fd);
  73. fxf->name = strdup(name);
  74. fxf->ref = 1;
  75. fxf->qid = dir->qid;
  76. fxf->dev = fd;
  77. fxf->fmt = 0;
  78. fxf->ptr = 0;
  79. free(dir);
  80. if( ext2fs(fxf)<0 ){
  81. xhead = fxf->next;
  82. free(fxf);
  83. unlock(&xlock);
  84. return 0;
  85. }
  86. unlock(&xlock);
  87. return fxf;
  88. }
  89. void
  90. refxfs(Xfs *xf, int delta)
  91. {
  92. lock(&xlock);
  93. xf->ref += delta;
  94. if(xf->ref == 0){
  95. /*mchat("free \"%s\", dev=%d...", xf->name, xf->dev);
  96. dumpbuf();*/
  97. CleanSuper(xf);
  98. syncbuf();
  99. free(xf->name);
  100. purgebuf(xf);
  101. if(xf->dev >= 0){
  102. close(xf->dev);
  103. xf->dev = -1;
  104. }
  105. }
  106. unlock(&xlock);
  107. }
  108. Xfile *
  109. xfile(Fid *fid, int flag)
  110. {
  111. Xfile *f;
  112. f = (Xfile*)fid->aux;
  113. switch(flag){
  114. default:
  115. panic("xfile");
  116. case Asis:
  117. return (f && f->xf && f->xf->dev < 0) ? 0 : f;
  118. case Clean:
  119. if (f) chat("Clean and fid->aux already exists\n");
  120. break;
  121. case Clunk:
  122. if(f){
  123. clean(f);
  124. lock(&freelock);
  125. f->next = freelist;
  126. freelist = f;
  127. unlock(&freelock);
  128. fid->aux = 0;
  129. }
  130. return 0;
  131. }
  132. if(f)
  133. return clean(f);
  134. lock(&freelock);
  135. if(f = freelist){ /* assign = */
  136. freelist = f->next;
  137. unlock(&freelock);
  138. } else {
  139. unlock(&freelock);
  140. f = malloc(sizeof(Xfile));
  141. }
  142. fid->aux = f;
  143. f->fid = fid->fid;
  144. f->client = client;
  145. f->xf = 0;
  146. f->ptr = 0;
  147. f->root = 0;
  148. return f;
  149. }
  150. Xfile *
  151. clean(Xfile *f)
  152. {
  153. if(f->xf && f->root){
  154. refxfs(f->xf, -1);
  155. f->xf = 0;
  156. }
  157. f->xf = 0;
  158. f->root = 0;
  159. f->dirindex = 0;
  160. return f;
  161. }