~ubuntu-branches/ubuntu/vivid/cctools/vivid

« back to all changes in this revision

Viewing changes to chirp/src/chirp_alloc.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Hanke
  • Date: 2011-05-07 09:05:00 UTC
  • Revision ID: james.westby@ubuntu.com-20110507090500-lqpmdtwndor6e7os
Tags: upstream-3.3.2
ImportĀ upstreamĀ versionĀ 3.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (C) 2008- The University of Notre Dame
 
3
This software is distributed under the GNU General Public License.
 
4
See the file COPYING for details.
 
5
*/
 
6
 
 
7
#include "macros.h"
 
8
#include "chirp_alloc.h"
 
9
#include "chirp_protocol.h"
 
10
#include "chirp_filesystem.h"
 
11
 
 
12
#include "itable.h"
 
13
#include "hash_table.h"
 
14
#include "xmalloc.h"
 
15
#include "int_sizes.h"
 
16
#include "stringtools.h"
 
17
#include "full_io.h"
 
18
#include "delete_dir.h"
 
19
#include "debug.h"
 
20
 
 
21
#include <assert.h>
 
22
#include <stdlib.h>
 
23
#include <stdio.h>
 
24
#include <errno.h>
 
25
#include <string.h>
 
26
#include <unistd.h>
 
27
#include <sys/stat.h>
 
28
 
 
29
static struct hash_table * alloc_table = 0;
 
30
static struct hash_table * root_table = 0;
 
31
static struct itable * fd_table = 0;
 
32
static int recovery_in_progress = 0;
 
33
static int alloc_enabled = 0;
 
34
 
 
35
struct alloc_state {
 
36
        FILE *file;
 
37
        INT64_T size;
 
38
        INT64_T inuse;
 
39
        INT64_T avail;
 
40
        INT64_T dirty;
 
41
};
 
42
 
 
43
/*
 
44
Note that the space consumed by a file is not the same
 
45
as the filesize.  This function computes the space consumed
 
46
by a file of a given size.  Currently, it rounds up to
 
47
the next blocksize.  A more exact function might take into
 
48
account indirect blocks allocated within the filesystem.
 
49
*/
 
50
 
 
51
static INT64_T space_consumed( INT64_T filesize )
 
52
{
 
53
        INT64_T block_size = 4096;
 
54
        INT64_T blocks = filesize/block_size;
 
55
        if(filesize%block_size) blocks++;
 
56
        return blocks*block_size;
 
57
}
 
58
 
 
59
static void alloc_state_update( struct alloc_state *a, INT64_T change )
 
60
{
 
61
        if(change!=0) {
 
62
                a->inuse += change;
 
63
                if(a->inuse<0) a->inuse=0;
 
64
                a->avail = a->size-a->inuse;
 
65
                a->dirty = 1;   
 
66
        }
 
67
}
 
68
 
 
69
static struct alloc_state * alloc_state_load( const char *path )
 
70
{
 
71
        struct alloc_state *s = xxmalloc(sizeof(*s));
 
72
        char statename[CHIRP_PATH_MAX];
 
73
 
 
74
        debug(D_ALLOC,"locking %s",path);
 
75
 
 
76
        sprintf(statename,"%s/.__alloc",path);
 
77
 
 
78
    /* WARNING chirp_alloc assumes we are using the local filesystem */
 
79
        s->file = fopen(statename,"r+");
 
80
        if(!s->file) {
 
81
                free(s);
 
82
                return 0;
 
83
        }
 
84
 
 
85
        if(lockf(fileno(s->file),F_TLOCK,0)) {
 
86
                debug(D_ALLOC,"lock of %s blocked; flushing outstanding locks",path);
 
87
                chirp_alloc_flush();
 
88
                debug(D_ALLOC,"locking %s (retry)",path);
 
89
 
 
90
                if(lockf(fileno(s->file),F_LOCK,0)) {
 
91
                        debug(D_ALLOC,"lock of %s failed: %s",path,strerror(errno));
 
92
                        fclose(s->file);
 
93
                        free(s);
 
94
                        return 0;
 
95
                }
 
96
        }
 
97
 
 
98
        fscanf(s->file,"%lld %lld",&s->size,&s->inuse);
 
99
 
 
100
        s->dirty = 0;
 
101
 
 
102
        if(recovery_in_progress) {
 
103
                s->inuse = 0;
 
104
                s->dirty = 1;
 
105
        }
 
106
 
 
107
        s->avail = s->size - s->inuse;
 
108
 
 
109
        return s;
 
110
}
 
111
 
 
112
static void alloc_state_save( const char *path, struct alloc_state *s )
 
113
{
 
114
        if(s->dirty) {
 
115
                debug(D_ALLOC,"storing %s",path);
 
116
        } else {
 
117
                debug(D_ALLOC,"freeing %s",path);
 
118
        }
 
119
                
 
120
        if(s->dirty) {
 
121
                ftruncate(fileno(s->file),0);
 
122
                fseek(s->file,0,SEEK_SET);
 
123
                fprintf(s->file,"%lld\n%lld\n",s->size,s->inuse);
 
124
        }
 
125
        fclose(s->file);
 
126
        free(s);
 
127
}
 
128
 
 
129
static int alloc_state_create( const char *path, INT64_T size )
 
130
{
 
131
        char statepath[CHIRP_PATH_MAX];
 
132
        FILE *file;
 
133
        sprintf(statepath,"%s/.__alloc",path);
 
134
        file = fopen(statepath,"w");
 
135
        if(file) {
 
136
                fprintf(file,"%lld 0\n",size);
 
137
                fclose(file);
 
138
                return 1;
 
139
        } else {
 
140
                return 0;
 
141
        }
 
142
}
 
143
 
 
144
static char * alloc_state_root( const char *path )
 
145
{
 
146
        char dirname[CHIRP_PATH_MAX];
 
147
        char statename[CHIRP_PATH_MAX];
 
148
        char *s;
 
149
 
 
150
        strcpy(dirname,path);
 
151
 
 
152
        while(1) {
 
153
                sprintf(statename,"%s/.__alloc",dirname);
 
154
                if(cfs->file_size(statename)>=0) {
 
155
                        return xstrdup(dirname);
 
156
                }
 
157
                s = strrchr(dirname,'/');
 
158
                if(!s) return 0;
 
159
                *s = 0;
 
160
        }
 
161
 
 
162
        return 0;
 
163
}
 
164
 
 
165
static char * alloc_state_root_cached( const char *path )
 
166
{
 
167
        char *result;
 
168
 
 
169
        if(!root_table) root_table = hash_table_create(0,0);
 
170
 
 
171
        result = hash_table_lookup(root_table,path);
 
172
        if(result) return result;
 
173
 
 
174
        result = alloc_state_root(path);
 
175
        if(!result) return 0;
 
176
 
 
177
        hash_table_insert(root_table,path,result);
 
178
 
 
179
        return result;
 
180
}
 
181
 
 
182
static struct alloc_state * alloc_state_cache_exact( const char *path )
 
183
{
 
184
        struct alloc_state *a;
 
185
        char *d;
 
186
        char dirname[CHIRP_PATH_MAX];
 
187
        char statename[CHIRP_PATH_MAX];
 
188
 
 
189
        d = alloc_state_root_cached(path);
 
190
        if(!d) return 0;
 
191
 
 
192
        /*
 
193
        Save a copy of dirname, because the following
 
194
        alloc_table_load_cached may result in a flush of the alloc table root.
 
195
        */
 
196
 
 
197
        strcpy(dirname,d);
 
198
 
 
199
        sprintf(statename,"%s/.__alloc",dirname);
 
200
 
 
201
        if(!alloc_table) alloc_table = hash_table_create(0,0);
 
202
 
 
203
        a = hash_table_lookup(alloc_table,dirname);
 
204
        if(a) return a;
 
205
 
 
206
        a = alloc_state_load(dirname);
 
207
        if(!a) return a;
 
208
                
 
209
        hash_table_insert(alloc_table,dirname,a);
 
210
 
 
211
        return a;
 
212
}
 
213
 
 
214
static struct alloc_state * alloc_state_cache( const char *path )
 
215
{
 
216
        char dirname[CHIRP_PATH_MAX];
 
217
        string_dirname(path,dirname);
 
218
        return alloc_state_cache_exact(dirname);
 
219
}
 
220
 
 
221
static void recover( const char *path )
 
222
{
 
223
        char newpath[CHIRP_PATH_MAX];
 
224
        struct chirp_stat info;
 
225
        struct alloc_state *a, *b;
 
226
        int result;
 
227
        void *dir;
 
228
        char *d;
 
229
 
 
230
        a = alloc_state_cache_exact(path);
 
231
        if(!a) fatal("couldn't open alloc state in %s: %s",path,strerror(errno));
 
232
 
 
233
        dir = cfs->opendir(path);
 
234
        if(!dir) fatal("couldn't open %s: %s\n",path,strerror(errno));
 
235
 
 
236
        while((d=cfs->readdir(dir))) {
 
237
                if(!strcmp(d,".")) continue;
 
238
                if(!strcmp(d,"..")) continue;
 
239
                if(!strncmp(d,".__",3)) continue;
 
240
 
 
241
                sprintf(newpath,"%s/%s",path,d);
 
242
 
 
243
                result = cfs->lstat(newpath,&info);
 
244
                if(result!=0) fatal("couldn't stat %s: %s\n",path,strerror(errno));
 
245
 
 
246
                if(S_ISDIR(info.cst_mode)) {
 
247
                        recover(newpath);
 
248
                        b = alloc_state_cache_exact(newpath);
 
249
                        if(a!=b) alloc_state_update(a,b->size);
 
250
                } else if(S_ISREG(info.cst_mode)) {
 
251
                        alloc_state_update(a,space_consumed(info.cst_size));
 
252
                } else {
 
253
                        debug(D_ALLOC,"warning: unknown file type: %s\n",newpath);
 
254
                }
 
255
        }
 
256
 
 
257
        cfs->closedir(dir);
 
258
 
 
259
        debug(D_ALLOC,"%s (%sB)",path,string_metric(a->inuse,-1,0));
 
260
}
 
261
 
 
262
void chirp_alloc_init( const char *rootpath, INT64_T size )
 
263
{
 
264
        struct alloc_state *a;
 
265
        time_t start, stop;
 
266
        INT64_T inuse, avail;
 
267
 
 
268
#ifdef CCTOOLS_OPSYS_CYGWIN
 
269
        fatal("sorry, CYGWIN cannot employ space allocation because it does not support file locking.");
 
270
#endif
 
271
 
 
272
        alloc_enabled = 1;
 
273
        recovery_in_progress = 1;
 
274
 
 
275
        debug(D_ALLOC,"### begin allocation recovery scan ###");
 
276
 
 
277
        if(!alloc_state_create(rootpath,size))
 
278
                fatal("couldn't create allocation in %s: %s\n",rootpath,strerror(errno));
 
279
 
 
280
        a = alloc_state_cache_exact(rootpath);
 
281
        if(!a) fatal("couldn't find allocation in %s: %s\n",rootpath,strerror(errno));
 
282
 
 
283
 
 
284
        start = time(0);
 
285
        recover(rootpath);
 
286
        size = a->size;
 
287
        inuse = a->inuse;
 
288
        avail = a->avail;
 
289
        chirp_alloc_flush();
 
290
        stop = time(0);
 
291
 
 
292
        debug(D_ALLOC,"### allocation recovery took %d seconds ###",stop-start);
 
293
 
 
294
        debug(D_ALLOC,"%sB total",string_metric(size,-1,0));
 
295
        debug(D_ALLOC,"%sB in use",string_metric(inuse,-1,0));
 
296
        debug(D_ALLOC,"%sB available",string_metric(avail,-1,0));
 
297
 
 
298
        recovery_in_progress = 0;
 
299
}
 
300
 
 
301
static time_t last_flush_time = 0;
 
302
 
 
303
void chirp_alloc_flush()
 
304
{
 
305
        char *path, *root;
 
306
        struct alloc_state *s;
 
307
 
 
308
        if(!alloc_enabled) return;
 
309
 
 
310
        debug(D_ALLOC,"flushing allocation states...");
 
311
 
 
312
        if(!alloc_table) alloc_table = hash_table_create(0,0);
 
313
 
 
314
        hash_table_firstkey(alloc_table);
 
315
        while(hash_table_nextkey(alloc_table,&path,(void**)&s)) {
 
316
                alloc_state_save(path,s);
 
317
                hash_table_remove(alloc_table,path);
 
318
        }
 
319
 
 
320
        if(!root_table) root_table = hash_table_create(0,0);
 
321
 
 
322
        hash_table_firstkey(root_table);
 
323
        while(hash_table_nextkey(root_table,&path,(void**)&root)) {
 
324
                free(root);
 
325
                hash_table_remove(root_table,path);
 
326
        }
 
327
 
 
328
        last_flush_time = time(0);
 
329
}
 
330
 
 
331
int chirp_alloc_flush_needed()
 
332
{
 
333
        if(!alloc_enabled) return 0;
 
334
        return hash_table_size(alloc_table);
 
335
}
 
336
 
 
337
time_t chirp_alloc_last_flush_time()
 
338
{
 
339
        return last_flush_time;
 
340
}
 
341
 
 
342
INT64_T chirp_alloc_open( const char *path, INT64_T flags, INT64_T mode )
 
343
{
 
344
        struct alloc_state *a;
 
345
        int fd = -1;
 
346
 
 
347
        if(!alloc_enabled) return cfs->open(path,flags,mode);
 
348
 
 
349
        a = alloc_state_cache(path);
 
350
        if(a) {
 
351
                INT64_T filesize = cfs->file_size(path);
 
352
                if(filesize<0) filesize = 0;
 
353
 
 
354
                fd = cfs->open(path,flags,mode);
 
355
                if(fd>=0) {
 
356
                        if(!fd_table) fd_table = itable_create(0);
 
357
                        itable_insert(fd_table,fd,xstrdup(path));
 
358
                        if(flags&O_TRUNC) {
 
359
                                alloc_state_update(a,-space_consumed(filesize));
 
360
                        }
 
361
                }
 
362
        } else {
 
363
                fd = -1;
 
364
        }
 
365
        return fd;
 
366
}
 
367
 
 
368
INT64_T chirp_alloc_close( int fd )
 
369
{
 
370
        if(!alloc_enabled) return cfs->close(fd);
 
371
 
 
372
        if(!fd_table) fd_table = itable_create(0);
 
373
        char *path = itable_remove(fd_table,fd);
 
374
        if(path) free(path);
 
375
        cfs->close(fd);
 
376
        return 0;
 
377
}
 
378
 
 
379
INT64_T chirp_alloc_pread( int fd, void *buffer, INT64_T length, INT64_T offset )
 
380
{
 
381
        return cfs->pread(fd,buffer,length,offset);
 
382
}
 
383
 
 
384
INT64_T chirp_alloc_pwrite( int fd, const void *data, INT64_T length, INT64_T offset )
 
385
{
 
386
        struct alloc_state *a;
 
387
        int result;
 
388
 
 
389
        if(!alloc_enabled) return cfs->pwrite(fd,data,length,offset);
 
390
 
 
391
        if(!fd_table) fd_table = itable_create(0);
 
392
 
 
393
        a  = alloc_state_cache(itable_lookup(fd_table,fd));
 
394
        if(a) {
 
395
                INT64_T filesize = cfs->fd_size(fd);
 
396
                if(filesize>=0) {
 
397
                        INT64_T newfilesize = MAX(length+offset,filesize);
 
398
                        INT64_T alloc_change = space_consumed(newfilesize) - space_consumed(filesize);
 
399
                        if(a->avail>=alloc_change) {
 
400
                                result = cfs->pwrite(fd,data,length,offset);
 
401
                                if(result>0) alloc_state_update(a,alloc_change);
 
402
                        } else {
 
403
                                errno = ENOSPC;
 
404
                                result = -1;
 
405
                        }
 
406
                } else {
 
407
                        result = -1;
 
408
                }
 
409
        } else {
 
410
                result = -1;
 
411
        }
 
412
        return result;
 
413
}
 
414
 
 
415
INT64_T chirp_alloc_sread( int fd, void *buffer, INT64_T length, INT64_T stride_length, INT64_T stride_skip, INT64_T offset )
 
416
{
 
417
        return cfs->sread(fd,buffer,length,stride_length,stride_skip,offset);
 
418
}
 
419
 
 
420
INT64_T chirp_alloc_swrite( int fd, const void *buffer, INT64_T length, INT64_T stride_length, INT64_T stride_skip, INT64_T offset )
 
421
{
 
422
        return cfs->swrite(fd,buffer,length,stride_length,stride_skip,offset);
 
423
}
 
424
 
 
425
INT64_T chirp_alloc_fstat( int fd, struct chirp_stat *buf )
 
426
{
 
427
        return cfs->fstat(fd,buf);
 
428
}
 
429
 
 
430
INT64_T chirp_alloc_fstatfs( int fd, struct chirp_statfs *info )
 
431
{
 
432
        struct alloc_state *a;
 
433
        int result;
 
434
 
 
435
        if(!alloc_enabled) return cfs->fstatfs(fd,info);
 
436
 
 
437
        if(!fd_table) fd_table = itable_create(0);
 
438
 
 
439
        a = alloc_state_cache(itable_lookup(fd_table,fd));
 
440
        if(a) {
 
441
                result = cfs->fstatfs(fd,info);
 
442
                if(result==0) {
 
443
                        info->f_blocks = a->size/info->f_bsize;
 
444
                        info->f_bfree = a->avail/info->f_bsize;
 
445
                        info->f_bavail = a->avail/info->f_bsize;
 
446
                }
 
447
        } else {
 
448
                result = -1;
 
449
        }
 
450
 
 
451
        return result;
 
452
}
 
453
 
 
454
 
 
455
INT64_T chirp_alloc_fchown( int fd, INT64_T uid, INT64_T gid )
 
456
{
 
457
        return cfs->fchown(fd,uid,gid);
 
458
}
 
459
 
 
460
INT64_T chirp_alloc_fchmod( int fd, INT64_T mode )
 
461
{
 
462
        return cfs->fchmod(fd,mode);
 
463
}
 
464
 
 
465
INT64_T chirp_alloc_ftruncate( int fd, INT64_T length )
 
466
{
 
467
        struct alloc_state *a;
 
468
        int result;
 
469
 
 
470
        if(!alloc_enabled) return cfs->ftruncate(fd,length);
 
471
 
 
472
        if(!fd_table) fd_table = itable_create(0);
 
473
 
 
474
        a = alloc_state_cache(itable_lookup(fd_table,fd));
 
475
        if(a) {
 
476
                INT64_T filesize = cfs->fd_size(fd);
 
477
                if(filesize>=0) {
 
478
                        INT64_T alloc_change = space_consumed(length)-space_consumed(filesize);
 
479
                        if(a->avail>=alloc_change) {
 
480
                                result = cfs->ftruncate(fd,length);
 
481
                                if(result==0) alloc_state_update(a,alloc_change);
 
482
                        } else {
 
483
                                errno = ENOSPC;
 
484
                                result = -1;
 
485
                        }
 
486
                } else {
 
487
                        result = -1;
 
488
                }
 
489
        } else {
 
490
                result = -1;
 
491
        }
 
492
        return result;
 
493
}
 
494
 
 
495
INT64_T chirp_alloc_fsync( int fd )
 
496
{
 
497
        return cfs->fsync(fd);
 
498
}
 
499
 
 
500
void *  chirp_alloc_opendir( const char *path )
 
501
{
 
502
        return cfs->opendir(path);
 
503
}
 
504
 
 
505
char *  chirp_alloc_readdir( void *dir )
 
506
{
 
507
        return cfs->readdir(dir);
 
508
}
 
509
 
 
510
void    chirp_alloc_closedir( void *dir )
 
511
{
 
512
        return cfs->closedir(dir);
 
513
}
 
514
 
 
515
INT64_T chirp_alloc_getfile( const char *path, struct link *link, time_t stoptime )
 
516
{
 
517
        return cfs->getfile(path,link,stoptime);
 
518
}
 
519
 
 
520
INT64_T chirp_alloc_getstream( const char *path, struct link *l, time_t stoptime )
 
521
{
 
522
        INT64_T fd, result, actual, total = 0;
 
523
        int buffer_size = 65536;
 
524
        char *buffer;
 
525
 
 
526
        fd = chirp_alloc_open(path,O_RDONLY,0700);
 
527
        if(fd<0) return fd;
 
528
 
 
529
        link_putliteral(l,"0\n",stoptime);
 
530
 
 
531
        buffer = malloc(buffer_size);
 
532
 
 
533
        while(1) {
 
534
                result = chirp_alloc_pread(fd,buffer,buffer_size,total);
 
535
                if(result<=0) break;
 
536
 
 
537
                actual = link_putlstring(l,buffer,result,stoptime);
 
538
                if(actual!=result) break;
 
539
 
 
540
                total += actual;
 
541
        }
 
542
 
 
543
        free(buffer);
 
544
 
 
545
        chirp_alloc_close(fd);
 
546
 
 
547
        return total;
 
548
}
 
549
 
 
550
/*
 
551
Note that putfile is given in advance the size of a file.
 
552
It checks the space available, and then guarantees that
 
553
the file will either be delivered whole or not at all.
 
554
*/
 
555
 
 
556
INT64_T chirp_alloc_putfile( const char *path, struct link *link, INT64_T length, INT64_T mode, time_t stoptime )
 
557
{
 
558
        struct alloc_state *a;
 
559
        int result;
 
560
 
 
561
        if(!alloc_enabled) return cfs->putfile(path,link,length,mode,stoptime);
 
562
 
 
563
        result = chirp_alloc_unlink(path);
 
564
        if(result<0 && errno!=ENOENT) return result;
 
565
 
 
566
        a = alloc_state_cache(path);
 
567
        if(a) {
 
568
                if(a->avail>length) {
 
569
                        result = cfs->putfile(path,link,length,mode,stoptime);
 
570
                        if(result>0) {
 
571
                                alloc_state_update(a,space_consumed(result));
 
572
                        } else {
 
573
                                cfs->unlink(path);
 
574
                        }
 
575
                } else {
 
576
                        errno = ENOSPC;
 
577
                        result = -1;
 
578
                }
 
579
        } else {
 
580
                result = -1;
 
581
        }
 
582
        return result;
 
583
}
 
584
 
 
585
/*
 
586
In contrast, putstream does not know the size of the output in advance,
 
587
and simply writes piece by piece, updating the allocation state as it goes.
 
588
*/
 
589
 
 
590
INT64_T chirp_alloc_putstream( const char *path, struct link *l, time_t stoptime )
 
591
{
 
592
        INT64_T fd, result, actual, total = 0;
 
593
        int buffer_size = 65536;
 
594
        char *buffer;
 
595
 
 
596
        fd = chirp_alloc_open(path,O_CREAT|O_TRUNC|O_WRONLY,0700);
 
597
        if(fd<0) return fd;
 
598
 
 
599
        link_putliteral(l,"0\n",stoptime);
 
600
 
 
601
        buffer = malloc(buffer_size);
 
602
 
 
603
        while(1) {
 
604
                result = link_read(l,buffer,buffer_size,stoptime);
 
605
                if(result<=0) break;
 
606
 
 
607
                actual = chirp_alloc_pwrite(fd,buffer,result,total);
 
608
                if(actual!=result) break;
 
609
 
 
610
                total += actual;
 
611
        }
 
612
 
 
613
        free(buffer);
 
614
 
 
615
        chirp_alloc_close(fd);
 
616
 
 
617
        return total;
 
618
}
 
619
 
 
620
INT64_T chirp_alloc_unlink( const char *path )
 
621
{
 
622
        struct alloc_state *a;
 
623
        int result;
 
624
 
 
625
        if(!alloc_enabled) return cfs->unlink(path);
 
626
 
 
627
        a = alloc_state_cache(path);
 
628
        if(a) {
 
629
                INT64_T filesize = cfs->file_size(path);
 
630
                if(filesize>=0) {
 
631
                        result = cfs->unlink(path);
 
632
                        if(result==0) alloc_state_update(a,-space_consumed(filesize));
 
633
                } else {
 
634
                        result = -1;
 
635
                }
 
636
        } else {
 
637
                result = -1;
 
638
        }
 
639
        return result;
 
640
}
 
641
 
 
642
INT64_T chirp_alloc_rename( const char *oldpath, const char *newpath )
 
643
{
 
644
        struct alloc_state *a, *b;
 
645
        int result = -1;
 
646
 
 
647
        if(!alloc_enabled) return cfs->rename(oldpath,newpath);
 
648
 
 
649
        a = alloc_state_cache(oldpath);
 
650
        if(a) {
 
651
                b = alloc_state_cache(newpath);
 
652
                if(b) {
 
653
                        if(a==b) {
 
654
                                result = rename(oldpath,newpath);
 
655
                        } else {
 
656
                                INT64_T filesize = cfs->file_size(oldpath);
 
657
                                if(filesize>=0) {
 
658
                                        if(b->avail>=filesize) {
 
659
                                                result = cfs->rename(oldpath,newpath);
 
660
                                                if(result==0) {
 
661
                                                        alloc_state_update(a,-space_consumed(filesize));
 
662
                                                        alloc_state_update(b,space_consumed(filesize));
 
663
                                                }
 
664
                                                chirp_alloc_flush();
 
665
                                        } else {
 
666
                                                errno = ENOSPC;
 
667
                                                result = -1;
 
668
                                        }
 
669
                                } else {
 
670
                                        result = -1;
 
671
                                }
 
672
                        }
 
673
                } else {
 
674
                        result = -1;
 
675
                }
 
676
        } else {
 
677
                result = -1;
 
678
        }
 
679
        return result;
 
680
}
 
681
 
 
682
INT64_T chirp_alloc_link( const char *path, const char *newpath )
 
683
{
 
684
        if(!alloc_enabled) return cfs->link(path,newpath);
 
685
        errno = EPERM;
 
686
        return -1;
 
687
}
 
688
 
 
689
INT64_T chirp_alloc_symlink( const char *path, const char *newpath )
 
690
{
 
691
        return cfs->symlink(path,newpath);
 
692
}
 
693
 
 
694
INT64_T chirp_alloc_readlink( const char *path, char *buf, INT64_T length )
 
695
{
 
696
        return cfs->readlink(path,buf,length);
 
697
}
 
698
 
 
699
INT64_T chirp_alloc_mkdir( const char *path, INT64_T mode )
 
700
{
 
701
        return cfs->mkdir(path,mode);
 
702
}
 
703
 
 
704
INT64_T chirp_alloc_rmall( const char *path )
 
705
{
 
706
        int result;
 
707
 
 
708
        result = chirp_alloc_unlink(path);
 
709
        if(result==0) {
 
710
                return 0;
 
711
        } else if(errno!=EISDIR) {
 
712
                return -1;
 
713
        } else {
 
714
                void *dir;
 
715
                char *d;
 
716
                char subpath[CHIRP_PATH_MAX];
 
717
 
 
718
                dir = chirp_alloc_opendir(path);
 
719
                if(!dir) return -1;
 
720
 
 
721
                result = 0;
 
722
 
 
723
                while((d=chirp_alloc_readdir(dir))) {
 
724
                        if(!strcmp(d,".")) continue;
 
725
                        if(!strcmp(d,"..")) continue;
 
726
                        if(!strncmp(d,".__      ",3)) continue;
 
727
                        sprintf(subpath,"%s/%s",path,d);
 
728
                        result = chirp_alloc_rmall(subpath);
 
729
                        if(result!=0) break;
 
730
                }
 
731
 
 
732
                chirp_alloc_closedir(dir);
 
733
 
 
734
                if(result==0) {
 
735
                        return chirp_alloc_rmdir(path);
 
736
                } else {
 
737
                        return result;
 
738
                }
 
739
        }
 
740
}
 
741
 
 
742
INT64_T chirp_alloc_rmdir( const char *path )
 
743
{
 
744
        struct alloc_state *a, *d;
 
745
        int result=-1;
 
746
 
 
747
        if(!alloc_enabled) return cfs->rmdir(path);
 
748
 
 
749
        d = alloc_state_cache_exact(path);
 
750
        if(d) {
 
751
                a = alloc_state_cache(path);
 
752
                if(a) {
 
753
                        if(cfs->rmdir(path)==0) {
 
754
                                if(d!=a) {
 
755
                                        alloc_state_update(a,-d->size);
 
756
                                        debug(D_ALLOC,"rmalloc %s %lld",path,d->size);
 
757
                                }
 
758
                                chirp_alloc_flush();
 
759
                                result = 0;
 
760
                        } else {
 
761
                                result = -1;
 
762
                        }
 
763
                }
 
764
        }
 
765
        return result;
 
766
}
 
767
 
 
768
INT64_T chirp_alloc_stat( const char *path, struct chirp_stat *buf )
 
769
{
 
770
        return cfs->stat(path,buf);
 
771
}
 
772
 
 
773
INT64_T chirp_alloc_lstat( const char *path, struct chirp_stat *buf )
 
774
{
 
775
        return cfs->lstat(path,buf);
 
776
}
 
777
 
 
778
INT64_T chirp_alloc_statfs( const char *path, struct chirp_statfs *info )
 
779
{
 
780
        struct alloc_state *a;
 
781
        int result;
 
782
 
 
783
        if(!alloc_enabled) return cfs->statfs(path,info);
 
784
 
 
785
        a = alloc_state_cache(path);
 
786
        if(a) {
 
787
                result = cfs->statfs(path,info);
 
788
                if(result==0) {
 
789
                        info->f_blocks = a->size/info->f_bsize;
 
790
                        info->f_bavail = a->avail/info->f_bsize;
 
791
                        info->f_bfree = a->avail/info->f_bsize;
 
792
                        if(a->avail<0) {
 
793
                                info->f_bavail = 0;
 
794
                                info->f_bfree = 0;
 
795
                        }
 
796
                }
 
797
        } else {
 
798
                result = -1;
 
799
        }
 
800
 
 
801
        return result;
 
802
}
 
803
 
 
804
INT64_T chirp_alloc_mkfifo( const char *path )
 
805
{
 
806
        return cfs->mkfifo(path);
 
807
}
 
808
 
 
809
INT64_T chirp_alloc_access( const char *path, INT64_T mode )
 
810
{
 
811
        return cfs->access(path,mode);
 
812
}
 
813
 
 
814
INT64_T chirp_alloc_chmod( const char *path, INT64_T mode )
 
815
{
 
816
        return cfs->chmod(path,mode);
 
817
}
 
818
 
 
819
INT64_T chirp_alloc_chown( const char *path, INT64_T uid, INT64_T gid )
 
820
{
 
821
        return cfs->chown(path,uid,gid);
 
822
}
 
823
 
 
824
INT64_T chirp_alloc_lchown( const char *path, INT64_T uid, INT64_T gid )
 
825
{
 
826
        return cfs->lchown(path,uid,gid);
 
827
}
 
828
 
 
829
INT64_T chirp_alloc_truncate( const char *path, INT64_T newsize )
 
830
{
 
831
        struct alloc_state *a;
 
832
        int result;
 
833
 
 
834
        if(!alloc_enabled) return cfs->truncate(path,newsize);
 
835
 
 
836
        a = alloc_state_cache(path);
 
837
        if(a) {
 
838
                INT64_T filesize = cfs->file_size(path);
 
839
                if(filesize>=0) {
 
840
                        INT64_T alloc_change = space_consumed(newsize)-space_consumed(filesize);
 
841
                        if(a->avail>=alloc_change) {
 
842
                                result = cfs->truncate(path,newsize);
 
843
                                if(result==0) alloc_state_update(a,alloc_change);
 
844
                        } else {
 
845
                                errno = ENOSPC;
 
846
                                result = -1;
 
847
                        }
 
848
                } else {
 
849
                        result = -1;
 
850
                }
 
851
        } else {
 
852
                result = -1;
 
853
        }
 
854
        return result;
 
855
}
 
856
 
 
857
INT64_T chirp_alloc_utime( const char *path, time_t actime, time_t modtime )
 
858
{
 
859
        return cfs->utime(path,actime,modtime);
 
860
}
 
861
 
 
862
INT64_T chirp_alloc_md5( const char *path, unsigned char digest[16] )
 
863
{
 
864
        return cfs->md5(path,digest);
 
865
}
 
866
 
 
867
INT64_T chirp_alloc_lsalloc( const char *path, char *alloc_path, INT64_T *total, INT64_T *inuse )
 
868
{
 
869
        char *name;
 
870
        struct alloc_state *a;
 
871
        int result=-1;
 
872
 
 
873
        if(!alloc_enabled) {
 
874
                errno = ENOSYS;
 
875
                return -1;
 
876
        }
 
877
 
 
878
        name = alloc_state_root_cached(path);
 
879
        if(name) {
 
880
                a = alloc_state_cache_exact(name);
 
881
                if(a) {
 
882
                        strcpy(alloc_path,name);
 
883
                        *total = a->size;
 
884
                        *inuse = a->inuse;
 
885
                        result = 0;
 
886
                } else {
 
887
                        result = -1;
 
888
                }
 
889
        } else {
 
890
                result = -1;
 
891
        }
 
892
        return result;
 
893
}
 
894
 
 
895
INT64_T chirp_alloc_mkalloc( const char *path, INT64_T size, INT64_T mode )
 
896
{
 
897
        struct alloc_state *a;
 
898
        int result=-1;
 
899
 
 
900
        if(!alloc_enabled) {
 
901
                errno = ENOSYS;
 
902
                return -1;
 
903
        }
 
904
 
 
905
        a = alloc_state_cache(path);
 
906
        if(a) {
 
907
                if(a->avail>size) {
 
908
                        result = cfs->mkdir(path,mode);
 
909
                        if(result==0) {
 
910
                                if(alloc_state_create(path,size)) {
 
911
                                        alloc_state_update(a,size);
 
912
                                        debug(D_ALLOC,"mkalloc %s %lld",path,size);
 
913
                                        chirp_alloc_flush();
 
914
                                } else {
 
915
                                        result = -1;
 
916
                                }
 
917
                        }
 
918
                } else {
 
919
                        errno = ENOSPC;
 
920
                        return -1;
 
921
                }
 
922
        } else {
 
923
                return -1;
 
924
        }
 
925
 
 
926
        return result;
 
927
}
 
928
 
 
929
INT64_T chirp_alloc_file_size( const char *path )
 
930
{
 
931
        return cfs->file_size(path);
 
932
}
 
933
 
 
934
INT64_T chirp_alloc_fd_size( int fd )
 
935
{
 
936
        return cfs->fd_size(fd);
 
937
}