17 #ifdef AFS_FREELANCE_CLIENT
18 #include "cm_freelance.h"
21 int cm_noLocalMountPoints;
23 int cm_fakeDirCallback=0;
24 int cm_fakeGettingCallback=0;
25 int cm_fakeDirVersion = 0x8;
26 cm_localMountPoint_t* cm_localMountPoints;
27 osi_mutex_t cm_Freelance_Lock;
28 int cm_localMountPointChangeFlag = 0;
29 int cm_freelanceEnabled = 0;
31 void cm_InitFakeRootDir();
33 void cm_InitFreelance() {
35 lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock");
37 // yj: first we make a call to cm_initLocalMountPoints
38 // to read all the local mount points from an ini file
39 cm_InitLocalMountPoints();
41 // then we make a call to InitFakeRootDir to create
42 // a fake root directory based on the local mount points
48 /* yj: Initialization of the fake root directory */
49 /* to be called while holding freelance lock unless during init. */
50 void cm_InitFakeRootDir() {
58 // allocate space for the fake info
59 cm_dirHeader_t fakeDirHeader;
60 cm_dirEntry_t fakeEntry;
61 cm_pageHeader_t fakePageHeader;
63 // i'm going to calculate how much space is needed for
64 // this fake root directory. we have these rules:
65 // 1. there are cm_noLocalMountPoints number of entries
66 // 2. each page is CM_DIR_PAGESIZE in size
67 // 3. the first 13 chunks of the first page are used for
69 // 4. the first chunk of all subsequent pages are used
70 // for page header stuff
71 // 5. a max of CM_DIR_EPP entries are allowed per page
72 // 6. each entry takes 1 or more chunks, depending on
73 // the size of the mount point string, as determined
75 // 7. each chunk is CM_DIR_CHUNKSIZE bytes
77 int CPP = CM_DIR_PAGESIZE / CM_DIR_CHUNKSIZE;
78 int curChunk = 13; // chunks 0 - 12 are used for header stuff
79 // of the first page in the directory
82 int curDirEntryInPage = 0;
87 while (curDirEntry!=cm_noLocalMountPoints) {
88 sizeOfCurEntry = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
89 if ((curChunk + sizeOfCurEntry >= CPP) ||
90 (curDirEntryInPage + 1 >= CM_DIR_EPP)) {
92 curDirEntryInPage = 0;
95 curChunk += sizeOfCurEntry;
100 dirSize = (curPage+1) * CM_DIR_PAGESIZE;
101 cm_FakeRootDir = malloc(dirSize);
102 cm_fakeDirSize = dirSize;
106 // yj: when we get here, we've figured out how much memory we need and
107 // allocated the appropriate space for it. we now prceed to fill
108 // it up with entries.
111 curDirEntryInPage = 0;
114 // fields in the directory entry that are unused.
116 fakeEntry.length = 0;
118 fakeEntry.fid.unique = htonl(1);
120 // the first page is special, it uses fakeDirHeader instead of fakePageHeader
121 // we fill up the page with dirEntries that belong there and we make changes
122 // to the fakeDirHeader.header.freeBitmap along the way. Then when we're done
123 // filling up the dirEntries in this page, we copy the fakeDirHeader into
124 // the top of the page.
126 // init the freeBitmap array
128 fakeDirHeader.header.freeBitmap[i]=0;
130 fakeDirHeader.header.freeBitmap[0] = 0xff;
131 fakeDirHeader.header.freeBitmap[1] = 0x7f;
134 // we start counting at 13 because the 0th to 12th chunks are used for header
137 // stick the first 2 entries "." and ".." in
138 fakeEntry.fid.unique = htonl(1);
139 fakeEntry.fid.vnode = htonl(1);
140 strcpy(fakeEntry.name, ".");
141 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
142 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
143 curChunk++; curDirEntryInPage++;
144 strcpy(fakeEntry.name, "..");
145 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
146 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
147 curChunk++; curDirEntryInPage++;
149 // keep putting stuff into page 0 if
150 // 1. we're not done with all entries
151 // 2. we have less than CM_DIR_EPP entries in page 0
152 // 3. we're not out of chunks in page 0
154 while( (curDirEntry!=cm_noLocalMountPoints) &&
155 (curDirEntryInPage < CM_DIR_EPP) &&
156 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
159 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
160 fakeEntry.fid.vnode = htonl(curDirEntry + 2);
161 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
163 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
164 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
167 for (i=0; i<noChunks; i++) {
168 t1 = (curChunk + i) / 8;
169 t2 = curChunk + i - (t1*8);
170 fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
175 // when we get here, we're done with filling in the entries for page 0
176 // copy in the header info
178 memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
182 // ok, page 0's done. Move on to the next page.
183 while (curDirEntry!=cm_noLocalMountPoints) {
185 curChunk = 1; // the zeroth chunk is reserved for page header
186 curDirEntryInPage = 0;
187 for (i=0; i<8; i++) {
188 fakePageHeader.freeBitmap[i]=0;
190 fakePageHeader.freeCount = 0;
191 fakePageHeader.pgcount = 0;
192 fakePageHeader.tag = htons(1234);
194 // while we're on the same page...
195 while ( (curDirEntry!=cm_noLocalMountPoints) &&
196 (curDirEntryInPage < CM_DIR_EPP) &&
197 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
199 // add an entry to this page
201 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
202 fakeEntry.fid.vnode=htonl(curDirEntry+2);
203 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
204 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
205 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
208 for (i=0; i<noChunks; i++) {
209 t1 = (curChunk + i) / 8;
210 t2 = curChunk + i - (t1*8);
211 fakePageHeader.freeBitmap[t1] |= (1 << t2);
215 memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
220 // we know the fakeDir is setup properly, so we claim that we have callback
221 cm_fakeDirCallback=1;
223 // when we get here, we've set up everything! done!
228 int cm_FakeRootFid(cm_fid_t *fidp)
230 fidp->cell = 0x1; /* root cell */
231 fidp->volume = 0x20000001; /* root.afs ? */
236 int cm_getLocalMountPointChange() {
237 return cm_localMountPointChangeFlag;
240 int cm_clearLocalMountPointChange() {
241 cm_localMountPointChangeFlag = 0;
244 /* called directly from ioctl */
245 /* called while not holding freelance lock */
246 int cm_noteLocalMountPointChange() {
247 lock_ObtainMutex(&cm_Freelance_Lock);
249 cm_localMountPointChangeFlag = 1;
250 lock_ReleaseMutex(&cm_Freelance_Lock);
254 int cm_reInitLocalMountPoints() {
257 cm_scache_t *scp, **lscpp, *tscp;
260 printf("\n\n----- reinitialization starts ----- \n");
263 // first we invalidate all the SCPs that were created
264 // for the local mount points
266 printf("Invalidating local mount point scp... ");
269 aFid.volume=0x20000001;
273 lock_ObtainWrite(&cm_scacheLock);
274 lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
275 for (i=0; i<cm_noLocalMountPoints; i++) {
276 hash = CM_SCACHE_HASH(&aFid);
277 for (scp=cm_hashTablep[hash]; scp; scp=scp->nextp) {
278 if (scp->fid.volume == aFid.volume &&
279 scp->fid.vnode == aFid.vnode &&
280 scp->fid.unique == aFid.unique
283 // mark the scp to be reused
284 lock_ReleaseWrite(&cm_scacheLock);
285 lock_ObtainMutex(&scp->mx);
286 cm_DiscardSCache(scp);
287 lock_ReleaseMutex(&scp->mx);
288 cm_CallbackNotifyChange(scp);
289 lock_ObtainWrite(&cm_scacheLock);
292 // take the scp out of the hash
293 lscpp = &cm_hashTablep[hash];
294 for (tscp=*lscpp; tscp; lscpp = &tscp->nextp, tscp = *lscpp) {
295 if (tscp == scp) break;
298 scp->flags &= ~CM_SCACHEFLAG_INHASH;
303 aFid.vnode = aFid.vnode + 1;
305 lock_ReleaseWrite(&cm_scacheLock);
306 printf("\tall old scp cleared!\n");
308 // we must free the memory that was allocated in the prev
309 // cm_InitLocalMountPoints call
310 printf("Removing old localmountpoints... ");
311 free(cm_localMountPoints);
312 printf("\tall old localmountpoints cleared!\n");
314 // now re-init the localmountpoints
315 printf("Creating new localmountpoints... ");
316 cm_InitLocalMountPoints();
317 printf("\tcreated new set of localmountpoints!\n");
320 // now we have to free the memory allocated in cm_initfakerootdir
321 printf("Removing old fakedir... ");
322 free(cm_FakeRootDir);
323 printf("\t\told fakedir removed!\n");
325 // then we re-create that dir
326 printf("Creating new fakedir... ");
327 cm_InitFakeRootDir();
328 printf("\t\tcreated new fakedir!\n");
330 lock_ReleaseMutex(&cm_Freelance_Lock);
332 printf("----- reinit complete -----\n\n");
336 // yj: open up the ini file and read all the local mount
337 // points that are stored there. Part of the initialization
338 // process for the freelance client.
339 /* to be called while holding freelance lock unless during init. */
340 long cm_InitLocalMountPoints() {
346 cm_localMountPoint_t* aLocalMountPoint;
349 cm_GetConfigDir(hdir);
350 strcat(hdir, AFS_FREELANCE_INI);
351 // open the ini file for reading
352 fp = fopen(hdir, "r");
354 // if we fail to open the file, create an empty one
356 fp = fopen(hdir, "w");
359 return 0; /* success */
362 // we successfully opened the file
364 fprintf(stderr, "opened afs_freelance.ini\n");
367 // now we read the first line to see how many entries
369 fgets(line, 200, fp);
371 // if the line is empty at any point when we're reading
372 // we're screwed. report error and return.
374 afsi_log("error occurred while reading afs_freelance.ini");
375 fprintf(stderr, "error occurred while reading afs_freelance.ini");
379 // get the number of entries there are from the first line
381 cm_noLocalMountPoints = atoi(line);
383 // create space to store the local mount points
384 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
385 aLocalMountPoint = cm_localMountPoints;
387 // now we read n lines and parse them into local mount points
388 // where n is the number of local mount points there are, as
390 // Each line in the ini file represents 1 local mount point and
391 // is in the format xxx#yyy:zzz, where xxx is the directory
392 // entry name, yyy is the cell name and zzz is the volume name.
393 // #yyy:zzz together make up the mount point.
394 for (i=0; i<cm_noLocalMountPoints; i++) {
395 fgets(line, 200, fp);
396 // check that the line is not empty
398 afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
399 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
402 // line is not empty, so let's parse it
403 t = strchr(line, '#');
404 // make sure that there is a '#' separator in the line
406 afsi_log("error occurred while parsing entry in %s: no # separator in line %d", AFS_FREELANCE_INI, i);
407 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # separator in line %d", i);
410 aLocalMountPoint->namep=malloc(t-line+1);
411 memcpy(aLocalMountPoint->namep, line, t-line);
412 *(aLocalMountPoint->namep + (t-line)) = 0;
413 aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
414 memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-2);
415 *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-2)) = 0;
417 fprintf(stderr, "found mount point: name %s, string %s\n",
418 aLocalMountPoint->namep,
419 aLocalMountPoint->mountPointStringp);
430 int cm_getNoLocalMountPoints() {
431 return cm_noLocalMountPoints;
434 cm_localMountPoint_t* cm_getLocalMountPoint(int vnode) {
438 long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, cm_fid_t *fidp)
446 /* before adding, verify the cell name; if it is not a valid cell,
447 don't add the mount point */
448 /* major performance issue? */
449 if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
452 if (strcmp(cellname, fullname) != 0) /* no partial matches allowed */
456 lock_ObtainMutex(&cm_Freelance_Lock);
458 cm_GetConfigDir(hfile);
459 strcat(hfile, AFS_FREELANCE_INI);
460 fp = fopen(hfile, "r+");
462 return CM_ERROR_INVAL;
463 fgets(line, 200, fp);
466 fseek(fp, 0, SEEK_SET);
467 fprintf(fp, "%d", n);
468 fseek(fp, 0, SEEK_END);
469 fprintf(fp, "%s#%s:%s\n", filename, fullname, volume);
471 lock_ReleaseMutex(&cm_Freelance_Lock);
473 /*cm_reInitLocalMountPoints(&vnode);*/
476 fidp->vnode = cm_noLocalMountPoints + 1; /* vnode value of last mt pt */
478 cm_noteLocalMountPointChange();
483 long cm_FreelanceRemoveMount(char *toremove)
489 char hfile[120], hfile2[120];
494 lock_ObtainMutex(&cm_Freelance_Lock);
496 cm_GetConfigDir(hfile);
497 strcat(hfile, AFS_FREELANCE_INI);
498 strcpy(hfile2, hfile);
500 fp1=fopen(hfile, "r+");
502 return CM_ERROR_INVAL;
503 fp2=fopen(hfile2, "w+");
506 return CM_ERROR_INVAL;
509 fgets(line, 200, fp1);
511 fprintf(fp2, "%d\n", n-1);
513 for (i=0; i<n; i++) {
514 fgets(line, 200, fp1);
515 cp=strchr(line, '#');
516 memcpy(shortname, line, cp-line);
517 shortname[cp-line]=0;
519 if (strcmp(shortname, toremove)==0) {
530 return CM_ERROR_NOSUCHFILE;
533 rename(hfile2, hfile);
535 lock_ReleaseMutex(&cm_Freelance_Lock);
537 cm_noteLocalMountPointChange();
541 #endif /* AFS_FREELANCE_CLIENT */