1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
6 * This file is part of InterMezzo, http://www.inter-mezzo.org.
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.
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.
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.
21 * Reintegration of KML records
25 #include <linux/module.h>
26 #include <linux/errno.h>
28 #include <linux/kernel.h>
29 #include <linux/major.h>
30 #include <linux/slab.h>
31 #include <linux/vmalloc.h>
33 #include <asm/uaccess.h>
34 #include <asm/pgtable.h>
35 #include <asm/mmu_context.h>
37 #include "intermezzo_fs.h"
38 #include "intermezzo_psdev.h"
40 static void kmlreint_pre_secure(struct kml_rec *rec, struct file *dir,
41 struct run_ctxt *saved)
44 struct presto_dentry_data *dd = presto_d2d(dir->f_dentry);
47 ctxt.fsuid = rec->prefix.hdr->fsuid;
48 ctxt.fsgid = rec->prefix.hdr->fsgid;
50 ctxt.pwd = dd->dd_fset->fset_dentry;
51 ctxt.pwdmnt = dd->dd_fset->fset_mnt;
54 ctxt.rootmnt = ctxt.pwdmnt;
55 if (rec->prefix.hdr->ngroups > 0) {
56 ctxt.group_info = groups_alloc(rec->prefix.hdr->ngroups);
57 for (i = 0; i< ctxt.group_info->ngroups; i++)
58 GROUP_AT(ctxt.group_info,i)= rec->prefix.groups[i];
60 ctxt.group_info = groups_alloc(0);
62 push_ctxt(saved, &ctxt);
66 /* Append two strings in a less-retarded fashion. */
67 static char * path_join(char *p1, int p1len, char *p2, int p2len)
69 int size = p1len + p2len + 2; /* possibly one extra /, one NULL */
72 path = kmalloc(size, GFP_KERNEL);
76 memcpy(path, p1, p1len);
77 if (path[p1len - 1] != '/') {
81 memcpy(path + p1len, p2, p2len);
82 path[p1len + p2len] = '\0';
87 static inline int kml_recno_equal(struct kml_rec *rec,
88 struct presto_file_set *fset)
90 return (rec->suffix->recno == fset->fset_lento_recno + 1);
93 static inline int version_equal(struct presto_version *a, struct inode *inode)
99 CERROR("InterMezzo: NULL inode in version_equal()\n");
103 if (inode->i_mtime.tv_sec == a->pv_mtime_sec &&
104 inode->i_mtime.tv_nsec == a->pv_mtime_nsec &&
105 (S_ISDIR(inode->i_mode) || inode->i_size == a->pv_size))
111 static int reint_close(struct kml_rec *rec, struct file *file,
112 struct lento_vfs_context *given_info)
114 struct run_ctxt saved_ctxt;
116 struct presto_file_set *fset;
117 struct lento_vfs_context info;
120 memcpy(&info, given_info, sizeof(*given_info));
123 CDEBUG (D_KML, "=====REINT_CLOSE::%s\n", rec->path);
125 fset = presto_fset(file->f_dentry);
126 if (fset->fset_flags & FSET_DATA_ON_DEMAND) {
129 iattr.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_SIZE;
130 iattr.ia_mtime.tv_sec = (time_t)rec->new_objectv->pv_mtime_sec;
131 iattr.ia_mtime.tv_nsec = (time_t)rec->new_objectv->pv_mtime_nsec;
132 iattr.ia_ctime.tv_sec = (time_t)rec->new_objectv->pv_ctime_sec;
133 iattr.ia_ctime.tv_nsec = (time_t)rec->new_objectv->pv_ctime_nsec;
134 iattr.ia_size = (time_t)rec->new_objectv->pv_size;
136 /* no kml record, but update last rcvd */
137 /* save fileid in dentry for later backfetch */
138 info.flags |= LENTO_FL_EXPECT | LENTO_FL_SET_DDFILEID;
139 info.remote_ino = rec->ino;
140 info.remote_generation = rec->generation;
141 info.flags &= ~LENTO_FL_KML;
142 kmlreint_pre_secure(rec, file, &saved_ctxt);
143 error = lento_setattr(rec->path, &iattr, &info);
144 pop_ctxt(&saved_ctxt);
146 presto_d2d(file->f_dentry)->dd_flags &= ~PRESTO_DATA;
148 int minor = presto_f2m(fset);
150 info.updated_time.tv_sec = rec->new_objectv->pv_mtime_sec;
151 info.updated_time.tv_nsec = rec->new_objectv->pv_mtime_nsec;
152 memcpy(&info.remote_version, rec->old_objectv,
153 sizeof(*rec->old_objectv));
154 info.remote_ino = rec->ino;
155 info.remote_generation = rec->generation;
156 error = izo_upc_backfetch(minor, rec->path, fset->fset_name,
159 CERROR("backfetch error %d\n", error);
160 /* if file doesn't exist anymore, then ignore the CLOSE
161 * and just update the last_rcvd.
163 if (error == ENOENT) {
164 CDEBUG(D_KML, "manually updating remote offset uuid %s"
165 "recno %d offset %Lu\n", info.uuid, info.recno,
166 (unsigned long long) info.kml_offset);
167 error = izo_rcvd_upd_remote(fset, info.uuid, info.recno, info.kml_offset);
169 CERROR("izo_rcvd_upd_remote error %d\n", error);
174 /* propagate error to avoid further reint */
181 static int reint_create(struct kml_rec *rec, struct file *dir,
182 struct lento_vfs_context *info)
184 struct run_ctxt saved_ctxt;
187 CDEBUG (D_KML, "=====REINT_CREATE::%s\n", rec->path);
188 info->updated_time.tv_sec = rec->new_objectv->pv_ctime_sec;
189 info->updated_time.tv_nsec = rec->new_objectv->pv_ctime_nsec;
190 kmlreint_pre_secure(rec, dir, &saved_ctxt);
191 error = lento_create(rec->path, rec->mode, info);
192 pop_ctxt(&saved_ctxt);
198 static int reint_link(struct kml_rec *rec, struct file *dir,
199 struct lento_vfs_context *info)
201 struct run_ctxt saved_ctxt;
206 CDEBUG (D_KML, "=====REINT_LINK::%s -> %s\n", rec->path, rec->target);
207 info->updated_time.tv_sec = rec->new_objectv->pv_mtime_sec;
208 info->updated_time.tv_nsec = rec->new_objectv->pv_mtime_nsec;
209 kmlreint_pre_secure(rec, dir, &saved_ctxt);
210 error = lento_link(rec->path, rec->target, info);
211 pop_ctxt(&saved_ctxt);
217 static int reint_mkdir(struct kml_rec *rec, struct file *dir,
218 struct lento_vfs_context *info)
220 struct run_ctxt saved_ctxt;
225 CDEBUG (D_KML, "=====REINT_MKDIR::%s\n", rec->path);
226 info->updated_time.tv_sec = rec->new_objectv->pv_ctime_sec;
227 info->updated_time.tv_nsec = rec->new_objectv->pv_ctime_nsec;
228 kmlreint_pre_secure(rec, dir, &saved_ctxt);
229 error = lento_mkdir(rec->path, rec->mode, info);
230 pop_ctxt(&saved_ctxt);
236 static int reint_mknod(struct kml_rec *rec, struct file *dir,
237 struct lento_vfs_context *info)
239 struct run_ctxt saved_ctxt;
245 CDEBUG (D_KML, "=====REINT_MKNOD::%s\n", rec->path);
246 info->updated_time.tv_sec = rec->new_objectv->pv_ctime_sec;
247 info->updated_time.tv_nsec = rec->new_objectv->pv_ctime_nsec;
248 kmlreint_pre_secure(rec, dir, &saved_ctxt);
250 dev = rec->rdev ? old_decode_dev(rec->rdev) : MKDEV(rec->major, rec->minor);
252 error = lento_mknod(rec->path, rec->mode, dev, info);
253 pop_ctxt(&saved_ctxt);
260 static int reint_noop(struct kml_rec *rec, struct file *dir,
261 struct lento_vfs_context *info)
266 static int reint_rename(struct kml_rec *rec, struct file *dir,
267 struct lento_vfs_context *info)
269 struct run_ctxt saved_ctxt;
274 CDEBUG (D_KML, "=====REINT_RENAME::%s -> %s\n", rec->path, rec->target);
275 info->updated_time.tv_sec = rec->new_objectv->pv_mtime_sec;
276 info->updated_time.tv_nsec = rec->new_objectv->pv_mtime_nsec;
277 kmlreint_pre_secure(rec, dir, &saved_ctxt);
278 error = lento_rename(rec->path, rec->target, info);
279 pop_ctxt(&saved_ctxt);
285 static int reint_rmdir(struct kml_rec *rec, struct file *dir,
286 struct lento_vfs_context *info)
288 struct run_ctxt saved_ctxt;
294 path = path_join(rec->path, rec->pathlen - 1, rec->target, rec->targetlen);
300 CDEBUG (D_KML, "=====REINT_RMDIR::%s\n", path);
301 info->updated_time.tv_sec = rec->new_parentv->pv_mtime_sec;
302 info->updated_time.tv_nsec = rec->new_parentv->pv_mtime_nsec;
303 kmlreint_pre_secure(rec, dir, &saved_ctxt);
304 error = lento_rmdir(path, info);
305 pop_ctxt(&saved_ctxt);
312 static int reint_setattr(struct kml_rec *rec, struct file *dir,
313 struct lento_vfs_context *info)
315 struct run_ctxt saved_ctxt;
321 iattr.ia_valid = rec->valid;
322 iattr.ia_mode = (umode_t)rec->mode;
323 iattr.ia_uid = (uid_t)rec->uid;
324 iattr.ia_gid = (gid_t)rec->gid;
325 iattr.ia_size = (off_t)rec->size;
326 iattr.ia_ctime.tv_sec = rec->ctime_sec;
327 iattr.ia_ctime.tv_nsec = rec->ctime_nsec;
328 iattr.ia_mtime.tv_sec = rec->mtime_sec;
329 iattr.ia_mtime.tv_nsec = rec->mtime_nsec;
330 iattr.ia_atime = iattr.ia_mtime; /* We don't track atimes. */
331 iattr.ia_attr_flags = rec->flags;
333 CDEBUG (D_KML, "=====REINT_SETATTR::%s (%d)\n", rec->path, rec->valid);
334 kmlreint_pre_secure(rec, dir, &saved_ctxt);
335 error = lento_setattr(rec->path, &iattr, info);
336 pop_ctxt(&saved_ctxt);
342 static int reint_symlink(struct kml_rec *rec, struct file *dir,
343 struct lento_vfs_context *info)
345 struct run_ctxt saved_ctxt;
350 CDEBUG (D_KML, "=====REINT_SYMLINK::%s -> %s\n", rec->path, rec->target);
351 info->updated_time.tv_sec = rec->new_objectv->pv_ctime_sec;
352 info->updated_time.tv_nsec = rec->new_objectv->pv_ctime_nsec;
353 kmlreint_pre_secure(rec, dir, &saved_ctxt);
354 error = lento_symlink(rec->target, rec->path, info);
355 pop_ctxt(&saved_ctxt);
361 static int reint_unlink(struct kml_rec *rec, struct file *dir,
362 struct lento_vfs_context *info)
364 struct run_ctxt saved_ctxt;
370 path = path_join(rec->path, rec->pathlen - 1, rec->target, rec->targetlen);
376 CDEBUG (D_KML, "=====REINT_UNLINK::%s\n", path);
377 info->updated_time.tv_sec = rec->new_parentv->pv_mtime_sec;
378 info->updated_time.tv_nsec = rec->new_parentv->pv_mtime_nsec;
379 kmlreint_pre_secure(rec, dir, &saved_ctxt);
380 error = lento_unlink(path, info);
381 pop_ctxt(&saved_ctxt);
388 static int branch_reint_rename(struct presto_file_set *fset, struct kml_rec *rec,
389 struct file *dir, struct lento_vfs_context *info,
390 char * kml_data, __u64 kml_size)
396 error = reint_rename(rec, dir, info);
397 if (error == -ENOENT) {
398 /* normal reint failed because path was not found */
401 CDEBUG(D_KML, "saving branch rename kml\n");
404 error = presto_log(fset, &rec, kml_data, kml_size,
405 NULL, 0, NULL, 0, NULL, 0);
407 error = presto_write_last_rcvd(&rec, fset, info);
414 int branch_reinter(struct presto_file_set *fset, struct kml_rec *rec,
415 struct file *dir, struct lento_vfs_context *info,
416 char * kml_data, __u64 kml_size)
419 int op = rec->prefix.hdr->opcode;
421 if (op == KML_OPCODE_CLOSE) {
422 /* regular close and backfetch */
423 error = reint_close(rec, dir, info);
424 } else if (op == KML_OPCODE_RENAME) {
425 /* rename only if name already exists */
426 error = branch_reint_rename(fset, rec, dir, info,
429 /* just rewrite kml into branch/kml and update last_rcvd */
432 CDEBUG(D_KML, "Saving branch kml\n");
435 error = presto_log(fset, &rec, kml_data, kml_size,
436 NULL, 0, NULL, 0, NULL, 0);
438 error = presto_write_last_rcvd(&rec, fset, info);
444 typedef int (*reinter_t)(struct kml_rec *rec, struct file *basedir,
445 struct lento_vfs_context *info);
447 static reinter_t presto_reinters[KML_OPCODE_NUM] =
449 [KML_OPCODE_CLOSE] = reint_close,
450 [KML_OPCODE_CREATE] = reint_create,
451 [KML_OPCODE_LINK] = reint_link,
452 [KML_OPCODE_MKDIR] = reint_mkdir,
453 [KML_OPCODE_MKNOD] = reint_mknod,
454 [KML_OPCODE_NOOP] = reint_noop,
455 [KML_OPCODE_RENAME] = reint_rename,
456 [KML_OPCODE_RMDIR] = reint_rmdir,
457 [KML_OPCODE_SETATTR] = reint_setattr,
458 [KML_OPCODE_SYMLINK] = reint_symlink,
459 [KML_OPCODE_UNLINK] = reint_unlink,
462 static inline reinter_t get_reinter(int op)
464 if (op < 0 || op >= sizeof(presto_reinters) / sizeof(reinter_t))
467 return presto_reinters[op];
470 int kml_reint_rec(struct file *dir, struct izo_ioctl_data *data)
476 struct lento_vfs_context info;
477 struct presto_cache *cache;
478 struct presto_file_set *fset;
479 struct presto_dentry_data *dd = presto_d2d(dir->f_dentry);
483 struct izo_rcvd_rec lr_rec;
488 error = presto_prep(dir->f_dentry, &cache, &fset);
490 CERROR("intermezzo: Reintegration on invalid file\n");
494 if (!dd || !dd->dd_fset || dd->dd_fset->fset_dentry != dir->f_dentry) {
495 CERROR("intermezzo: reintegration on non-fset root (ino %ld)\n",
496 dir->f_dentry->d_inode->i_ino);
501 if (data->ioc_plen1 > 64 * 1024) {
506 ptr = fset->fset_reint_buf;
507 end = ptr + data->ioc_plen1;
509 if (copy_from_user(ptr, data->ioc_pbuf1, data->ioc_plen1)) {
515 error = kml_unpack(&rec, &ptr, end);
522 off = izo_rcvd_get(&lr_rec, fset, data->ioc_uuid);
524 CERROR("No last_rcvd record, setting to 0\n");
525 memset(&lr_rec, 0, sizeof(lr_rec));
528 data->ioc_kmlsize = ptr - fset->fset_reint_buf;
530 if (rec.suffix->recno != lr_rec.lr_remote_recno + 1) {
531 CERROR("KML record number %Lu expected, not %d\n",
532 (unsigned long long) (lr_rec.lr_remote_recno + 1),
536 if (!version_check(&rec, dd->dd_fset, &info)) {
537 /* FIXME: do an upcall to resolve conflicts */
538 CERROR("intermezzo: would be a conflict!\n");
546 op = rec.prefix.hdr->opcode;
548 reinter = get_reinter(op);
550 CERROR("%s: Unrecognized KML opcode %d\n", __FUNCTION__, op);
556 info.kml_offset = data->ioc_offset + data->ioc_kmlsize;
557 info.recno = rec.suffix->recno;
558 info.flags = LENTO_FL_EXPECT;
560 info.flags |= LENTO_FL_KML;
562 memcpy(info.uuid, data->ioc_uuid, sizeof(info.uuid));
564 if (fset->fset_flags & FSET_IS_BRANCH && data->ioc_flags)
565 error = branch_reinter(fset, &rec, dir, &info, fset->fset_reint_buf,
568 error = reinter(&rec, dir, &info);
574 int izo_get_fileid(struct file *dir, struct izo_ioctl_data *data)
581 struct presto_cache *cache;
582 struct presto_file_set *fset;
583 struct presto_dentry_data *dd = presto_d2d(dir->f_dentry);
584 struct run_ctxt saved_ctxt;
589 error = presto_prep(dir->f_dentry, &cache, &fset);
591 CERROR("intermezzo: Reintegration on invalid file\n");
595 if (!dd || !dd->dd_fset || dd->dd_fset->fset_dentry != dir->f_dentry) {
596 CERROR("intermezzo: reintegration on non-fset root (ino %ld)\n",
597 dir->f_dentry->d_inode->i_ino);
603 PRESTO_ALLOC(buf, data->ioc_plen1);
609 end = buf + data->ioc_plen1;
611 if (copy_from_user(buf, data->ioc_pbuf1, data->ioc_plen1)) {
613 PRESTO_FREE(buf, data->ioc_plen1);
617 error = kml_unpack(&rec, &ptr, end);
620 PRESTO_FREE(buf, data->ioc_plen1);
624 kmlreint_pre_secure(&rec, dir, &saved_ctxt);
626 file = filp_open(rec.path, O_RDONLY, 0);
627 if (!file || IS_ERR(file)) {
628 error = PTR_ERR(file);
631 data->ioc_ino = file->f_dentry->d_inode->i_ino;
632 data->ioc_generation = file->f_dentry->d_inode->i_generation;
635 CDEBUG(D_FILE, "%s ino %Lx, gen %Lx\n", rec.path,
636 (unsigned long long) data->ioc_ino,
637 (unsigned long long) data->ioc_generation);
641 PRESTO_FREE(buf, data->ioc_plen1);
642 pop_ctxt(&saved_ctxt);