17 #ifdef AFS_FREELANCE_CLIENT
18 #include "cm_freelance.h"
21 extern void afsi_log(char *pattern, ...);
23 int cm_noLocalMountPoints;
25 int cm_fakeDirCallback=0;
26 int cm_fakeGettingCallback=0;
27 int cm_fakeDirVersion = 0x8;
28 cm_localMountPoint_t* cm_localMountPoints;
29 osi_mutex_t cm_Freelance_Lock;
30 int cm_localMountPointChangeFlag = 0;
31 int cm_freelanceEnabled = 0;
33 void cm_InitFakeRootDir();
35 void cm_InitFreelance() {
37 lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock");
39 // yj: first we make a call to cm_initLocalMountPoints
40 // to read all the local mount points from an ini file
41 cm_InitLocalMountPoints();
43 // then we make a call to InitFakeRootDir to create
44 // a fake root directory based on the local mount points
50 /* yj: Initialization of the fake root directory */
51 /* to be called while holding freelance lock unless during init. */
52 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;
86 /* Reserve 2 directory chunks for "." and ".." */
89 while (curDirEntry!=cm_noLocalMountPoints) {
90 sizeOfCurEntry = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
91 if ((curChunk + sizeOfCurEntry >= CPP) ||
92 (curDirEntryInPage + 1 >= CM_DIR_EPP)) {
94 curDirEntryInPage = 0;
97 curChunk += sizeOfCurEntry;
102 dirSize = (curPage+1) * CM_DIR_PAGESIZE;
103 cm_FakeRootDir = malloc(dirSize);
104 cm_fakeDirSize = dirSize;
108 // yj: when we get here, we've figured out how much memory we need and
109 // allocated the appropriate space for it. we now prceed to fill
110 // it up with entries.
113 curDirEntryInPage = 0;
116 // fields in the directory entry that are unused.
118 fakeEntry.length = 0;
120 fakeEntry.fid.unique = htonl(1);
122 // the first page is special, it uses fakeDirHeader instead of fakePageHeader
123 // we fill up the page with dirEntries that belong there and we make changes
124 // to the fakeDirHeader.header.freeBitmap along the way. Then when we're done
125 // filling up the dirEntries in this page, we copy the fakeDirHeader into
126 // the top of the page.
128 // init the freeBitmap array
130 fakeDirHeader.header.freeBitmap[i]=0;
132 fakeDirHeader.header.freeBitmap[0] = 0xff;
133 fakeDirHeader.header.freeBitmap[1] = 0x7f;
136 // we start counting at 13 because the 0th to 12th chunks are used for header
139 // stick the first 2 entries "." and ".." in
140 fakeEntry.fid.unique = htonl(1);
141 fakeEntry.fid.vnode = htonl(1);
142 strcpy(fakeEntry.name, ".");
143 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
144 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
145 curChunk++; curDirEntryInPage++;
146 strcpy(fakeEntry.name, "..");
147 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
148 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
149 curChunk++; curDirEntryInPage++;
151 // keep putting stuff into page 0 if
152 // 1. we're not done with all entries
153 // 2. we have less than CM_DIR_EPP entries in page 0
154 // 3. we're not out of chunks in page 0
156 while( (curDirEntry!=cm_noLocalMountPoints) &&
157 (curDirEntryInPage < CM_DIR_EPP) &&
158 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
161 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
162 fakeEntry.fid.vnode = htonl(curDirEntry + 2);
163 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
165 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
166 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
169 for (i=0; i<noChunks; i++) {
170 t1 = (curChunk + i) / 8;
171 t2 = curChunk + i - (t1*8);
172 fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
177 // when we get here, we're done with filling in the entries for page 0
178 // copy in the header info
180 memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
184 // ok, page 0's done. Move on to the next page.
185 while (curDirEntry!=cm_noLocalMountPoints) {
187 curChunk = 1; // the zeroth chunk is reserved for page header
188 curDirEntryInPage = 0;
189 for (i=0; i<8; i++) {
190 fakePageHeader.freeBitmap[i]=0;
192 fakePageHeader.freeCount = 0;
193 fakePageHeader.pgcount = 0;
194 fakePageHeader.tag = htons(1234);
196 // while we're on the same page...
197 while ( (curDirEntry!=cm_noLocalMountPoints) &&
198 (curDirEntryInPage < CM_DIR_EPP) &&
199 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
201 // add an entry to this page
203 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
204 fakeEntry.fid.vnode=htonl(curDirEntry+2);
205 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
206 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
207 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
210 for (i=0; i<noChunks; i++) {
211 t1 = (curChunk + i) / 8;
212 t2 = curChunk + i - (t1*8);
213 fakePageHeader.freeBitmap[t1] |= (1 << t2);
217 memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
222 // we know the fakeDir is setup properly, so we claim that we have callback
223 cm_fakeDirCallback=1;
225 // when we get here, we've set up everything! done!
230 int cm_FakeRootFid(cm_fid_t *fidp)
232 fidp->cell = 0x1; /* root cell */
233 fidp->volume = 0x20000001; /* root.afs ? */
239 int cm_getLocalMountPointChange() {
240 return cm_localMountPointChangeFlag;
243 int cm_clearLocalMountPointChange() {
244 cm_localMountPointChangeFlag = 0;
247 /* called directly from ioctl */
248 /* called while not holding freelance lock */
249 int cm_noteLocalMountPointChange() {
250 lock_ObtainMutex(&cm_Freelance_Lock);
252 cm_localMountPointChangeFlag = 1;
253 lock_ReleaseMutex(&cm_Freelance_Lock);
257 int cm_reInitLocalMountPoints() {
260 cm_scache_t *scp, **lscpp, *tscp;
263 printf("\n\n----- reinitialization starts ----- \n");
266 // first we invalidate all the SCPs that were created
267 // for the local mount points
269 printf("Invalidating local mount point scp... ");
272 aFid.volume=0x20000001;
276 lock_ObtainWrite(&cm_scacheLock);
277 lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
278 for (i=0; i<cm_noLocalMountPoints; i++) {
279 hash = CM_SCACHE_HASH(&aFid);
280 for (scp=cm_hashTablep[hash]; scp; scp=scp->nextp) {
281 if (scp->fid.volume == aFid.volume &&
282 scp->fid.vnode == aFid.vnode &&
283 scp->fid.unique == aFid.unique
286 // mark the scp to be reused
287 lock_ReleaseWrite(&cm_scacheLock);
288 lock_ObtainMutex(&scp->mx);
289 cm_DiscardSCache(scp);
290 lock_ReleaseMutex(&scp->mx);
291 cm_CallbackNotifyChange(scp);
292 lock_ObtainWrite(&cm_scacheLock);
295 // take the scp out of the hash
296 lscpp = &cm_hashTablep[hash];
297 for (tscp=*lscpp; tscp; lscpp = &tscp->nextp, tscp = *lscpp) {
298 if (tscp == scp) break;
301 scp->flags &= ~CM_SCACHEFLAG_INHASH;
306 aFid.vnode = aFid.vnode + 1;
308 lock_ReleaseWrite(&cm_scacheLock);
309 printf("\tall old scp cleared!\n");
311 // we must free the memory that was allocated in the prev
312 // cm_InitLocalMountPoints call
313 printf("Removing old localmountpoints... ");
314 free(cm_localMountPoints);
315 printf("\tall old localmountpoints cleared!\n");
317 // now re-init the localmountpoints
318 printf("Creating new localmountpoints... ");
319 cm_InitLocalMountPoints();
320 printf("\tcreated new set of localmountpoints!\n");
323 // now we have to free the memory allocated in cm_initfakerootdir
324 printf("Removing old fakedir... ");
325 free(cm_FakeRootDir);
326 printf("\t\told fakedir removed!\n");
328 // then we re-create that dir
329 printf("Creating new fakedir... ");
330 cm_InitFakeRootDir();
331 printf("\t\tcreated new fakedir!\n");
333 lock_ReleaseMutex(&cm_Freelance_Lock);
335 printf("----- reinit complete -----\n\n");
340 // yj: open up the ini file and read all the local mount
341 // points that are stored there. Part of the initialization
342 // process for the freelance client.
343 /* to be called while holding freelance lock unless during init. */
344 long cm_InitLocalMountPoints() {
350 cm_localMountPoint_t* aLocalMountPoint;
353 cm_GetConfigDir(hdir);
354 strcat(hdir, AFS_FREELANCE_INI);
355 // open the ini file for reading
356 fp = fopen(hdir, "r");
358 // if we fail to open the file, create an empty one
360 fp = fopen(hdir, "w");
363 return 0; /* success */
366 // we successfully opened the file
368 fprintf(stderr, "opened afs_freelance.ini\n");
371 // now we read the first line to see how many entries
373 fgets(line, 200, fp);
375 // if the line is empty at any point when we're reading
376 // we're screwed. report error and return.
378 afsi_log("error occurred while reading afs_freelance.ini");
379 fprintf(stderr, "error occurred while reading afs_freelance.ini");
383 // get the number of entries there are from the first line
385 cm_noLocalMountPoints = atoi(line);
387 // create space to store the local mount points
388 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
389 aLocalMountPoint = cm_localMountPoints;
391 // now we read n lines and parse them into local mount points
392 // where n is the number of local mount points there are, as
394 // Each line in the ini file represents 1 local mount point and
395 // is in the format xxx#yyy:zzz, where xxx is the directory
396 // entry name, yyy is the cell name and zzz is the volume name.
397 // #yyy:zzz together make up the mount point.
398 for (i=0; i<cm_noLocalMountPoints; i++) {
399 fgets(line, 200, fp);
400 // check that the line is not empty
402 afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
403 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
406 // line is not empty, so let's parse it
407 t = strchr(line, '#');
408 // make sure that there is a '#' separator in the line
410 afsi_log("error occurred while parsing entry in %s: no # separator in line %d", AFS_FREELANCE_INI, i);
411 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # separator in line %d", i);
414 aLocalMountPoint->namep=malloc(t-line+1);
415 memcpy(aLocalMountPoint->namep, line, t-line);
416 *(aLocalMountPoint->namep + (t-line)) = 0;
417 aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
418 memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-2);
419 *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-2)) = 0;
421 fprintf(stderr, "found mount point: name %s, string %s\n",
422 aLocalMountPoint->namep,
423 aLocalMountPoint->mountPointStringp);
434 int cm_getNoLocalMountPoints() {
435 return cm_noLocalMountPoints;
438 cm_localMountPoint_t* cm_getLocalMountPoint(int vnode) {
442 long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, cm_fid_t *fidp)
450 /* before adding, verify the cell name; if it is not a valid cell,
451 don't add the mount point */
452 /* major performance issue? */
453 if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
456 if (strcmp(cellname, fullname) != 0) /* no partial matches allowed */
460 lock_ObtainMutex(&cm_Freelance_Lock);
462 cm_GetConfigDir(hfile);
463 strcat(hfile, AFS_FREELANCE_INI);
464 fp = fopen(hfile, "r+");
466 return CM_ERROR_INVAL;
467 fgets(line, 200, fp);
470 fseek(fp, 0, SEEK_SET);
471 fprintf(fp, "%d", n);
472 fseek(fp, 0, SEEK_END);
473 fprintf(fp, "%s#%s:%s\n", filename, fullname, volume);
475 lock_ReleaseMutex(&cm_Freelance_Lock);
477 /*cm_reInitLocalMountPoints(&vnode);*/
480 fidp->vnode = cm_noLocalMountPoints + 1; /* vnode value of last mt pt */
482 cm_noteLocalMountPointChange();
487 long cm_FreelanceRemoveMount(char *toremove)
493 char hfile[120], hfile2[120];
497 lock_ObtainMutex(&cm_Freelance_Lock);
499 cm_GetConfigDir(hfile);
500 strcat(hfile, AFS_FREELANCE_INI);
501 strcpy(hfile2, hfile);
503 fp1=fopen(hfile, "r+");
505 return CM_ERROR_INVAL;
506 fp2=fopen(hfile2, "w+");
509 return CM_ERROR_INVAL;
512 fgets(line, 200, fp1);
514 fprintf(fp2, "%d\n", n-1);
516 for (i=0; i<n; i++) {
517 fgets(line, 200, fp1);
518 cp=strchr(line, '#');
519 memcpy(shortname, line, cp-line);
520 shortname[cp-line]=0;
522 if (strcmp(shortname, toremove)==0) {
533 return CM_ERROR_NOSUCHFILE;
536 rename(hfile2, hfile);
538 lock_ReleaseMutex(&cm_Freelance_Lock);
540 cm_noteLocalMountPointChange();
544 #endif /* AFS_FREELANCE_CLIENT */