OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [intermezzo/] [kml_reint.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2
 * vim:expandtab:shiftwidth=8:tabstop=8:
3
 *
4
 *  Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
5
 *
6
 *   This file is part of InterMezzo, http://www.inter-mezzo.org.
7
 *
8
 *   InterMezzo is free software; you can redistribute it and/or
9
 *   modify it under the terms of version 2 of the GNU General Public
10
 *   License as published by the Free Software Foundation.
11
 *
12
 *   InterMezzo is distributed in the hope that it will be useful,
13
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *   GNU General Public License for more details.
16
 *
17
 *   You should have received a copy of the GNU General Public License
18
 *   along with InterMezzo; if not, write to the Free Software
19
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
 *
21
 * Reintegration of KML records
22
 *
23
 */
24
 
25
#define __NO_VERSION__
26
#include <linux/module.h>
27
#include <linux/errno.h>
28
#include <linux/fs.h>
29
#include <linux/kernel.h>
30
#include <linux/major.h>
31
#include <linux/slab.h>
32
#include <linux/vmalloc.h>
33
#include <linux/mm.h>
34
#include <asm/uaccess.h>
35
#include <asm/pgtable.h>
36
#include <asm/mmu_context.h>
37
#include <linux/intermezzo_fs.h>
38
#include <linux/intermezzo_psdev.h>
39
 
40
static void kmlreint_pre_secure(struct kml_rec *rec, struct file *dir,
41
                                struct run_ctxt *saved)
42
{
43
        struct run_ctxt ctxt;
44
        struct presto_dentry_data *dd = presto_d2d(dir->f_dentry);
45
        int i;
46
 
47
        ctxt.fsuid = rec->prefix.hdr->fsuid;
48
        ctxt.fsgid = rec->prefix.hdr->fsgid;
49
        ctxt.fs = KERNEL_DS;
50
        ctxt.pwd = dd->dd_fset->fset_dentry;
51
        ctxt.pwdmnt = dd->dd_fset->fset_mnt;
52
 
53
        ctxt.root = ctxt.pwd;
54
        ctxt.rootmnt = ctxt.pwdmnt;
55
        if (rec->prefix.hdr->ngroups > 0) {
56
                ctxt.ngroups = rec->prefix.hdr->ngroups;
57
                for (i = 0; i< ctxt.ngroups; i++)
58
                        ctxt.groups[i] = rec->prefix.groups[i];
59
        } else
60
                ctxt.ngroups = 0;
61
 
62
        push_ctxt(saved, &ctxt);
63
}
64
 
65
 
66
/* Append two strings in a less-retarded fashion. */
67
static char * path_join(char *p1, int p1len, char *p2, int p2len)
68
{
69
        int size = p1len + p2len + 2; /* possibly one extra /, one NULL */
70
        char *path;
71
 
72
        path = kmalloc(size, GFP_KERNEL);
73
        if (path == NULL)
74
                return NULL;
75
 
76
        memcpy(path, p1, p1len);
77
        if (path[p1len - 1] != '/') {
78
                path[p1len] = '/';
79
                p1len++;
80
        }
81
        memcpy(path + p1len, p2, p2len);
82
        path[p1len + p2len] = '\0';
83
 
84
        return path;
85
}
86
 
87
static inline int kml_recno_equal(struct kml_rec *rec,
88
                                  struct presto_file_set *fset)
89
{
90
        return (rec->suffix->recno == fset->fset_lento_recno + 1);
91
}
92
 
93
static inline int version_equal(struct presto_version *a, struct inode *inode)
94
{
95
        if (a == NULL)
96
                return 1;
97
 
98
        if (inode == NULL) {
99
                CERROR("InterMezzo: NULL inode in version_equal()\n");
100
                return 0;
101
        }
102
 
103
        if (inode->i_mtime == a->pv_mtime &&
104
            (S_ISDIR(inode->i_mode) || inode->i_size == a->pv_size))
105
                return 1;
106
 
107
        return 0;
108
}
109
 
110
static int reint_close(struct kml_rec *rec, struct file *file,
111
                       struct lento_vfs_context *given_info)
112
{
113
        struct run_ctxt saved_ctxt;
114
        int error;
115
        struct presto_file_set *fset;
116
        struct lento_vfs_context info;
117
        ENTRY;
118
 
119
        memcpy(&info, given_info, sizeof(*given_info));
120
 
121
 
122
        CDEBUG (D_KML, "=====REINT_CLOSE::%s\n", rec->path);
123
 
124
        fset = presto_fset(file->f_dentry);
125
        if (fset->fset_flags & FSET_DATA_ON_DEMAND) {
126
                struct iattr iattr;
127
 
128
                iattr.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_SIZE;
129
                iattr.ia_mtime = (time_t)rec->new_objectv->pv_mtime;
130
                iattr.ia_ctime = (time_t)rec->new_objectv->pv_ctime;
131
                iattr.ia_size = (time_t)rec->new_objectv->pv_size;
132
 
133
                /* no kml record, but update last rcvd */
134
                /* save fileid in dentry for later backfetch */
135
                info.flags |= LENTO_FL_EXPECT | LENTO_FL_SET_DDFILEID;
136
                info.remote_ino = rec->ino;
137
                info.remote_generation = rec->generation;
138
                info.flags &= ~LENTO_FL_KML;
139
                kmlreint_pre_secure(rec, file, &saved_ctxt);
140
                error = lento_setattr(rec->path, &iattr, &info);
141
                pop_ctxt(&saved_ctxt);
142
 
143
                presto_d2d(file->f_dentry)->dd_flags &= ~PRESTO_DATA;
144
        } else {
145
                int minor = presto_f2m(fset);
146
 
147
                info.updated_time = rec->new_objectv->pv_mtime;
148
                memcpy(&info.remote_version, rec->old_objectv,
149
                       sizeof(*rec->old_objectv));
150
                info.remote_ino = rec->ino;
151
                info.remote_generation = rec->generation;
152
                error = izo_upc_backfetch(minor, rec->path, fset->fset_name,
153
                                          &info);
154
                if (error) {
155
                        CERROR("backfetch error %d\n", error);
156
                        /* if file doesn't exist anymore,  then ignore the CLOSE
157
                         * and just update the last_rcvd.
158
                         */
159
                        if (error == ENOENT) {
160
                                CDEBUG(D_KML, "manually updating remote offset uuid %s"
161
                                       "recno %d offset %Lu\n", info.uuid, info.recno, info.kml_offset);
162
                                error = izo_rcvd_upd_remote(fset, info.uuid, info.recno, info.kml_offset);
163
                                if(error)
164
                                        CERROR("izo_rcvd_upd_remote error %d\n", error);
165
 
166
                        }
167
                }
168
 
169
                /* propagate error to avoid further reint */
170
        }
171
 
172
        EXIT;
173
        return error;
174
}
175
 
176
static int reint_create(struct kml_rec *rec, struct file *dir,
177
                        struct lento_vfs_context *info)
178
{
179
        struct run_ctxt saved_ctxt;
180
        int     error;        ENTRY;
181
 
182
        CDEBUG (D_KML, "=====REINT_CREATE::%s\n", rec->path);
183
        info->updated_time = rec->new_objectv->pv_ctime;
184
        kmlreint_pre_secure(rec, dir, &saved_ctxt);
185
        error = lento_create(rec->path, rec->mode, info);
186
        pop_ctxt(&saved_ctxt);
187
 
188
        EXIT;
189
        return error;
190
}
191
 
192
static int reint_link(struct kml_rec *rec, struct file *dir,
193
                      struct lento_vfs_context *info)
194
{
195
        struct run_ctxt saved_ctxt;
196
        int     error;
197
 
198
        ENTRY;
199
 
200
        CDEBUG (D_KML, "=====REINT_LINK::%s -> %s\n", rec->path, rec->target);
201
        info->updated_time = rec->new_objectv->pv_mtime;
202
        kmlreint_pre_secure(rec, dir, &saved_ctxt);
203
        error = lento_link(rec->path, rec->target, info);
204
        pop_ctxt(&saved_ctxt);
205
 
206
        EXIT;
207
        return error;
208
}
209
 
210
static int reint_mkdir(struct kml_rec *rec, struct file *dir,
211
                       struct lento_vfs_context *info)
212
{
213
        struct run_ctxt saved_ctxt;
214
        int     error;
215
 
216
        ENTRY;
217
 
218
        CDEBUG (D_KML, "=====REINT_MKDIR::%s\n", rec->path);
219
        info->updated_time = rec->new_objectv->pv_ctime;
220
        kmlreint_pre_secure(rec, dir, &saved_ctxt);
221
        error = lento_mkdir(rec->path, rec->mode, info);
222
        pop_ctxt(&saved_ctxt);
223
 
224
        EXIT;
225
        return error;
226
}
227
 
228
static int reint_mknod(struct kml_rec *rec, struct file *dir,
229
                       struct lento_vfs_context *info)
230
{
231
        struct run_ctxt saved_ctxt;
232
        int     error, dev;
233
 
234
        ENTRY;
235
 
236
        CDEBUG (D_KML, "=====REINT_MKNOD::%s\n", rec->path);
237
        info->updated_time = rec->new_objectv->pv_ctime;
238
        kmlreint_pre_secure(rec, dir, &saved_ctxt);
239
 
240
        dev = rec->rdev ?: MKDEV(rec->major, rec->minor);
241
 
242
        error = lento_mknod(rec->path, rec->mode, dev, info);
243
        pop_ctxt(&saved_ctxt);
244
 
245
        EXIT;
246
        return error;
247
}
248
 
249
 
250
static int reint_noop(struct kml_rec *rec, struct file *dir,
251
                      struct lento_vfs_context *info)
252
{
253
        return 0;
254
}
255
 
256
static int reint_rename(struct kml_rec *rec, struct file *dir,
257
                        struct lento_vfs_context *info)
258
{
259
        struct run_ctxt saved_ctxt;
260
        int     error;
261
 
262
        ENTRY;
263
 
264
        CDEBUG (D_KML, "=====REINT_RENAME::%s -> %s\n", rec->path, rec->target);
265
        info->updated_time = rec->new_objectv->pv_mtime;
266
        kmlreint_pre_secure(rec, dir, &saved_ctxt);
267
        error = lento_rename(rec->path, rec->target, info);
268
        pop_ctxt(&saved_ctxt);
269
 
270
        EXIT;
271
        return error;
272
}
273
 
274
static int reint_rmdir(struct kml_rec *rec, struct file *dir,
275
                       struct lento_vfs_context *info)
276
{
277
        struct run_ctxt saved_ctxt;
278
        int     error;
279
        char *path;
280
 
281
        ENTRY;
282
 
283
        path = path_join(rec->path, rec->pathlen - 1, rec->target, rec->targetlen);
284
        if (path == NULL) {
285
                EXIT;
286
                return -ENOMEM;
287
        }
288
 
289
        CDEBUG (D_KML, "=====REINT_RMDIR::%s\n", path);
290
        info->updated_time = rec->new_parentv->pv_mtime;
291
        kmlreint_pre_secure(rec, dir, &saved_ctxt);
292
        error = lento_rmdir(path, info);
293
        pop_ctxt(&saved_ctxt);
294
 
295
        kfree(path);
296
        EXIT;
297
        return error;
298
}
299
 
300
static int reint_setattr(struct kml_rec *rec, struct file *dir,
301
                         struct lento_vfs_context *info)
302
{
303
        struct run_ctxt saved_ctxt;
304
        struct iattr iattr;
305
        int     error;
306
 
307
        ENTRY;
308
 
309
        iattr.ia_valid = rec->valid;
310
        iattr.ia_mode  = (umode_t)rec->mode;
311
        iattr.ia_uid   = (uid_t)rec->uid;
312
        iattr.ia_gid   = (gid_t)rec->gid;
313
        iattr.ia_size  = (off_t)rec->size;
314
        iattr.ia_ctime = (time_t)rec->ctime;
315
        iattr.ia_mtime = (time_t)rec->mtime;
316
        iattr.ia_atime = iattr.ia_mtime; /* We don't track atimes. */
317
        iattr.ia_attr_flags = rec->flags;
318
 
319
        CDEBUG (D_KML, "=====REINT_SETATTR::%s (%d)\n", rec->path, rec->valid);
320
        kmlreint_pre_secure(rec, dir, &saved_ctxt);
321
        error = lento_setattr(rec->path, &iattr, info);
322
        pop_ctxt(&saved_ctxt);
323
 
324
        EXIT;
325
        return error;
326
}
327
 
328
static int reint_symlink(struct kml_rec *rec, struct file *dir,
329
                         struct lento_vfs_context *info)
330
{
331
        struct run_ctxt saved_ctxt;
332
        int     error;
333
 
334
        ENTRY;
335
 
336
        CDEBUG (D_KML, "=====REINT_SYMLINK::%s -> %s\n", rec->path, rec->target);
337
        info->updated_time = rec->new_objectv->pv_ctime;
338
        kmlreint_pre_secure(rec, dir, &saved_ctxt);
339
        error = lento_symlink(rec->target, rec->path, info);
340
        pop_ctxt(&saved_ctxt);
341
 
342
        EXIT;
343
        return error;
344
}
345
 
346
static int reint_unlink(struct kml_rec *rec, struct file *dir,
347
                        struct lento_vfs_context *info)
348
{
349
        struct run_ctxt saved_ctxt;
350
        int     error;
351
        char *path;
352
 
353
        ENTRY;
354
 
355
        path = path_join(rec->path, rec->pathlen - 1, rec->target, rec->targetlen);
356
        if (path == NULL) {
357
                EXIT;
358
                return -ENOMEM;
359
        }
360
 
361
        CDEBUG (D_KML, "=====REINT_UNLINK::%s\n", path);
362
        info->updated_time = rec->new_parentv->pv_mtime;
363
        kmlreint_pre_secure(rec, dir, &saved_ctxt);
364
        error = lento_unlink(path, info);
365
        pop_ctxt(&saved_ctxt);
366
 
367
        kfree(path);
368
        EXIT;
369
        return error;
370
}
371
 
372
static int branch_reint_rename(struct presto_file_set *fset, struct kml_rec *rec,
373
                   struct file *dir, struct lento_vfs_context *info,
374
                   char * kml_data, __u64 kml_size)
375
{
376
        int     error;
377
 
378
        ENTRY;
379
 
380
        error = reint_rename(rec, dir, info);
381
        if (error == -ENOENT) {
382
                /* normal reint failed because path was not found */
383
                struct rec_info rec;
384
 
385
                CDEBUG(D_KML, "saving branch rename kml\n");
386
                rec.is_kml = 1;
387
                rec.size = kml_size;
388
                error = presto_log(fset, &rec, kml_data, kml_size,
389
                           NULL, 0, NULL, 0,  NULL, 0);
390
                if (error == 0)
391
                        error = presto_write_last_rcvd(&rec, fset, info);
392
        }
393
 
394
        EXIT;
395
        return error;
396
}
397
 
398
int branch_reinter(struct presto_file_set *fset, struct kml_rec *rec,
399
                   struct file *dir, struct lento_vfs_context *info,
400
                   char * kml_data, __u64 kml_size)
401
{
402
        int error = 0;
403
        int op = rec->prefix.hdr->opcode;
404
 
405
        if (op == KML_OPCODE_CLOSE) {
406
                /* regular close and backfetch */
407
                error = reint_close(rec, dir, info);
408
        } else if  (op == KML_OPCODE_RENAME) {
409
                /* rename only if name already exists  */
410
                error = branch_reint_rename(fset, rec, dir, info,
411
                                            kml_data, kml_size);
412
        } else {
413
                /* just rewrite kml into branch/kml and update last_rcvd */
414
                struct rec_info rec;
415
 
416
                CDEBUG(D_KML, "Saving branch kml\n");
417
                rec.is_kml = 1;
418
                rec.size = kml_size;
419
                error = presto_log(fset, &rec, kml_data, kml_size,
420
                           NULL, 0, NULL, 0,  NULL, 0);
421
                if (error == 0)
422
                        error = presto_write_last_rcvd(&rec, fset, info);
423
        }
424
 
425
        return error;
426
}
427
 
428
typedef int (*reinter_t)(struct kml_rec *rec, struct file *basedir,
429
                         struct lento_vfs_context *info);
430
 
431
static reinter_t presto_reinters[KML_OPCODE_NUM] =
432
{
433
        [KML_OPCODE_CLOSE] = reint_close,
434
        [KML_OPCODE_CREATE] = reint_create,
435
        [KML_OPCODE_LINK] = reint_link,
436
        [KML_OPCODE_MKDIR] = reint_mkdir,
437
        [KML_OPCODE_MKNOD] = reint_mknod,
438
        [KML_OPCODE_NOOP] = reint_noop,
439
        [KML_OPCODE_RENAME] = reint_rename,
440
        [KML_OPCODE_RMDIR] = reint_rmdir,
441
        [KML_OPCODE_SETATTR] = reint_setattr,
442
        [KML_OPCODE_SYMLINK] = reint_symlink,
443
        [KML_OPCODE_UNLINK] = reint_unlink,
444
};
445
 
446
static inline reinter_t get_reinter(int op)
447
{
448
        if (op < 0 || op >= sizeof(presto_reinters) / sizeof(reinter_t))
449
                return NULL;
450
        else
451
                return  presto_reinters[op];
452
}
453
 
454
int kml_reint_rec(struct file *dir, struct izo_ioctl_data *data)
455
{
456
        char *ptr;
457
        char *end;
458
        struct kml_rec rec;
459
        int error = 0;
460
        struct lento_vfs_context info;
461
        struct presto_cache *cache;
462
        struct presto_file_set *fset;
463
        struct presto_dentry_data *dd = presto_d2d(dir->f_dentry);
464
        int op;
465
        reinter_t reinter;
466
 
467
        struct izo_rcvd_rec lr_rec;
468
        int off;
469
 
470
        ENTRY;
471
 
472
        error = presto_prep(dir->f_dentry, &cache, &fset);
473
        if ( error  ) {
474
                CERROR("intermezzo: Reintegration on invalid file\n");
475
                return error;
476
        }
477
 
478
        if (!dd || !dd->dd_fset || dd->dd_fset->fset_dentry != dir->f_dentry) {
479
                CERROR("intermezzo: reintegration on non-fset root (ino %ld)\n",
480
                       dir->f_dentry->d_inode->i_ino);
481
 
482
                return -EINVAL;
483
        }
484
 
485
        if (data->ioc_plen1 > 64 * 1024) {
486
                EXIT;
487
                return -ENOSPC;
488
        }
489
 
490
        ptr = fset->fset_reint_buf;
491
        end = ptr + data->ioc_plen1;
492
 
493
        if (copy_from_user(ptr, data->ioc_pbuf1, data->ioc_plen1)) {
494
                EXIT;
495
                error = -EFAULT;
496
                goto out;
497
        }
498
 
499
        error = kml_unpack(&rec, &ptr, end);
500
        if (error) {
501
                EXIT;
502
                error = -EFAULT;
503
                goto out;
504
        }
505
 
506
        off = izo_rcvd_get(&lr_rec, fset, data->ioc_uuid);
507
        if (off < 0) {
508
                CERROR("No last_rcvd record, setting to 0\n");
509
                memset(&lr_rec, 0, sizeof(lr_rec));
510
        }
511
 
512
        data->ioc_kmlsize = ptr - fset->fset_reint_buf;
513
 
514
        if (rec.suffix->recno != lr_rec.lr_remote_recno + 1) {
515
                CERROR("KML record number %Lu expected, not %d\n",
516
                       lr_rec.lr_remote_recno + 1,
517
                       rec.suffix->recno);
518
 
519
#if 0
520
                if (!version_check(&rec, dd->dd_fset, &info)) {
521
                        /* FIXME: do an upcall to resolve conflicts */
522
                        CERROR("intermezzo: would be a conflict!\n");
523
                        error = -EINVAL;
524
                        EXIT;
525
                        goto out;
526
                }
527
#endif
528
        }
529
 
530
        op = rec.prefix.hdr->opcode;
531
 
532
        reinter = get_reinter(op);
533
        if (!reinter) {
534
                CERROR("%s: Unrecognized KML opcode %d\n", __FUNCTION__, op);
535
                error = -EINVAL;
536
                EXIT;
537
                goto out;
538
        }
539
 
540
        info.kml_offset = data->ioc_offset + data->ioc_kmlsize;
541
        info.recno = rec.suffix->recno;
542
        info.flags = LENTO_FL_EXPECT;
543
        if (data->ioc_flags)
544
                info.flags |= LENTO_FL_KML;
545
 
546
        memcpy(info.uuid, data->ioc_uuid, sizeof(info.uuid));
547
 
548
        if (fset->fset_flags & FSET_IS_BRANCH && data->ioc_flags)
549
                error = branch_reinter(fset, &rec, dir, &info, fset->fset_reint_buf,
550
                                       data->ioc_kmlsize);
551
        else
552
                error = reinter(&rec, dir, &info);
553
 out:
554
        EXIT;
555
        return error;
556
}
557
 
558
int izo_get_fileid(struct file *dir, struct izo_ioctl_data *data)
559
{
560
        char *buf = NULL;
561
        char *ptr;
562
        char *end;
563
        struct kml_rec rec;
564
        struct file *file;
565
        struct presto_cache *cache;
566
        struct presto_file_set *fset;
567
        struct presto_dentry_data *dd = presto_d2d(dir->f_dentry);
568
        struct run_ctxt saved_ctxt;
569
        int     error;
570
 
571
        ENTRY;
572
 
573
        error = presto_prep(dir->f_dentry, &cache, &fset);
574
        if ( error  ) {
575
                CERROR("intermezzo: Reintegration on invalid file\n");
576
                return error;
577
        }
578
 
579
        if (!dd || !dd->dd_fset || dd->dd_fset->fset_dentry != dir->f_dentry) {
580
                CERROR("intermezzo: reintegration on non-fset root (ino %ld)\n",
581
                       dir->f_dentry->d_inode->i_ino);
582
 
583
                return -EINVAL;
584
        }
585
 
586
 
587
        PRESTO_ALLOC(buf, data->ioc_plen1);
588
        if (!buf) {
589
                EXIT;
590
                return -ENOMEM;
591
        }
592
        ptr = buf;
593
        end = buf + data->ioc_plen1;
594
 
595
        if (copy_from_user(buf, data->ioc_pbuf1, data->ioc_plen1)) {
596
                EXIT;
597
                PRESTO_FREE(buf, data->ioc_plen1);
598
                return -EFAULT;
599
        }
600
 
601
        error = kml_unpack(&rec, &ptr, end);
602
        if (error) {
603
                EXIT;
604
                PRESTO_FREE(buf, data->ioc_plen1);
605
                return -EFAULT;
606
        }
607
 
608
        kmlreint_pre_secure(&rec, dir, &saved_ctxt);
609
 
610
        file = filp_open(rec.path, O_RDONLY, 0);
611
        if (!file || IS_ERR(file)) {
612
                error = PTR_ERR(file);
613
                goto out;
614
        }
615
        data->ioc_ino = file->f_dentry->d_inode->i_ino;
616
        data->ioc_generation = file->f_dentry->d_inode->i_generation;
617
        filp_close(file, 0);
618
 
619
        CDEBUG(D_FILE, "%s ino %Lx, gen %Lx\n", rec.path,
620
               data->ioc_ino, data->ioc_generation);
621
 
622
 out:
623
        if (buf)
624
                PRESTO_FREE(buf, data->ioc_plen1);
625
        pop_ctxt(&saved_ctxt);
626
        EXIT;
627
        return error;
628
}
629
 
630
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.