1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
3 *
4 * Copyright (C) 1998 Peter J. Braam
5 * Copyright (C) 2001 Cluster File Systems, Inc.
6 * Copyright (C) 2001 Tacit Networks, Inc. <phil@off.net>
7 *
8 * Support for journalling extended attributes
9 * Copyright (C) 2001 Shirish H. Phatak, Tacit Networks, Inc.
10 *
11 * This file is part of InterMezzo, http://www.inter-mezzo.org.
12 *
13 * InterMezzo is free software; you can redistribute it and/or
14 * modify it under the terms of version 2 of the GNU General Public
15 * License as published by the Free Software Foundation.
16 *
17 * InterMezzo is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with InterMezzo; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27 #include <linux/types.h>
28 #include <linux/kernel.h>
29 #include <linux/sched.h>
30 #include <linux/fs.h>
31 #include <linux/slab.h>
32 #include <linux/vmalloc.h>
33 #include <linux/time.h>
34 #include <linux/errno.h>
35 #include <linux/locks.h>
36 #include <asm/segment.h>
37 #include <asm/uaccess.h>
38 #include <linux/string.h>
39 #include <linux/smp_lock.h>
40 #include <linux/intermezzo_fs.h>
41 #include <linux/intermezzo_psdev.h>
42
43 struct presto_reservation_data {
44 unsigned int ri_recno;
45 loff_t ri_offset;
46 loff_t ri_size;
47 struct list_head ri_list;
48 };
49
50 /*
51 * Locking Semantics
52 *
53 * write lock in struct presto_log_fd:
54 * - name: fd_lock
55 * - required for: accessing any field in a presto_log_fd
56 * - may not be held across I/O
57 * -
58 *
59 */
60
61 /*
62 * reserve record space and/or atomically request state of the log
63 * rec will hold the location reserved record upon return
64 * this reservation will be placed in the queue
65 */
presto_reserve_record(struct presto_file_set * fset,struct presto_log_fd * fd,struct rec_info * rec,struct presto_reservation_data * rd)66 static void presto_reserve_record(struct presto_file_set *fset,
67 struct presto_log_fd *fd,
68 struct rec_info *rec,
69 struct presto_reservation_data *rd)
70 {
71 int chunked_record = 0;
72 ENTRY;
73
74 write_lock(&fd->fd_lock);
75 if ( rec->is_kml ) {
76 int chunk = 1 << fset->fset_chunkbits;
77 int chunk_mask = ~(chunk -1);
78 loff_t boundary;
79
80 boundary = (fd->fd_offset + chunk - 1) & chunk_mask;
81 if ( fd->fd_offset + rec->size >= boundary ) {
82 chunked_record = 1;
83 fd->fd_offset = boundary;
84 }
85 }
86
87 fd->fd_recno++;
88
89 /* this moves the fd_offset back after truncation */
90 if ( list_empty(&fd->fd_reservations) &&
91 !chunked_record) {
92 fd->fd_offset = fd->fd_file->f_dentry->d_inode->i_size;
93 }
94
95 rec->offset = fd->fd_offset;
96 if (rec->is_kml)
97 rec->offset += fset->fset_kml_logical_off;
98
99 rec->recno = fd->fd_recno;
100
101 /* add the reservation data to the end of the list */
102 rd->ri_offset = fd->fd_offset;
103 rd->ri_size = rec->size;
104 rd->ri_recno = rec->recno;
105 list_add(&rd->ri_list, fd->fd_reservations.prev);
106
107 fd->fd_offset += rec->size;
108
109 write_unlock(&fd->fd_lock);
110
111 EXIT;
112 }
113
presto_release_record(struct presto_log_fd * fd,struct presto_reservation_data * rd)114 static inline void presto_release_record(struct presto_log_fd *fd,
115 struct presto_reservation_data *rd)
116 {
117 write_lock(&fd->fd_lock);
118 list_del(&rd->ri_list);
119 write_unlock(&fd->fd_lock);
120 }
121
122 /* XXX should we ask for do_truncate to be exported? */
izo_do_truncate(struct presto_file_set * fset,struct dentry * dentry,loff_t length,loff_t size_check)123 int izo_do_truncate(struct presto_file_set *fset, struct dentry *dentry,
124 loff_t length, loff_t size_check)
125 {
126 struct inode *inode = dentry->d_inode;
127 int error;
128 struct iattr newattrs;
129
130 ENTRY;
131
132 if (length < 0) {
133 EXIT;
134 return -EINVAL;
135 }
136
137 down(&inode->i_sem);
138 lock_kernel();
139
140 if (size_check != inode->i_size) {
141 unlock_kernel();
142 up(&inode->i_sem);
143 EXIT;
144 return -EALREADY;
145 }
146
147 newattrs.ia_size = length;
148 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
149
150 if (inode->i_op && inode->i_op->setattr)
151 error = inode->i_op->setattr(dentry, &newattrs);
152 else {
153 inode_setattr(dentry->d_inode, &newattrs);
154 error = 0;
155 }
156
157 unlock_kernel();
158 up(&inode->i_sem);
159 EXIT;
160 return error;
161 }
162
presto_kml_truncate(struct presto_file_set * fset)163 static void presto_kml_truncate(struct presto_file_set *fset)
164 {
165 int rc;
166 ENTRY;
167
168 write_lock(&fset->fset_kml.fd_lock);
169 if (fset->fset_kml.fd_truncating == 1 ) {
170 write_unlock(&fset->fset_kml.fd_lock);
171 EXIT;
172 return;
173 }
174
175 fset->fset_kml.fd_truncating = 1;
176 write_unlock(&fset->fset_kml.fd_lock);
177
178 CERROR("islento: %d, count: %d\n",
179 ISLENTO(presto_i2m(fset->fset_dentry->d_inode)),
180 fset->fset_permit_count);
181
182 rc = izo_upc_kml_truncate(fset->fset_cache->cache_psdev->uc_minor,
183 fset->fset_lento_off, fset->fset_lento_recno,
184 fset->fset_name);
185
186 /* Userspace is the only permitholder now, and will retain an exclusive
187 * hold on the permit until KML truncation completes. */
188 /* FIXME: double check this code path now that the precise semantics of
189 * fset->fset_permit_count have changed. */
190
191 if (rc != 0) {
192 write_lock(&fset->fset_kml.fd_lock);
193 fset->fset_kml.fd_truncating = 0;
194 write_unlock(&fset->fset_kml.fd_lock);
195 }
196
197 EXIT;
198 }
199
presto_trans_start(struct presto_file_set * fset,struct inode * inode,int op)200 void *presto_trans_start(struct presto_file_set *fset, struct inode *inode,
201 int op)
202 {
203 ENTRY;
204 if ( !fset->fset_cache->cache_filter->o_trops ) {
205 EXIT;
206 return NULL;
207 }
208 EXIT;
209 return fset->fset_cache->cache_filter->o_trops->tr_start
210 (fset, inode, op);
211 }
212
presto_trans_commit(struct presto_file_set * fset,void * handle)213 void presto_trans_commit(struct presto_file_set *fset, void *handle)
214 {
215 ENTRY;
216 if (!fset->fset_cache->cache_filter->o_trops ) {
217 EXIT;
218 return;
219 }
220
221 fset->fset_cache->cache_filter->o_trops->tr_commit(fset, handle);
222
223 /* Check to see if the KML needs truncated. */
224 if (fset->kml_truncate_size > 0 &&
225 !fset->fset_kml.fd_truncating &&
226 fset->fset_kml.fd_offset > fset->kml_truncate_size) {
227 CDEBUG(D_JOURNAL, "kml size: %lu; truncating\n",
228 (unsigned long)fset->fset_kml.fd_offset);
229 presto_kml_truncate(fset);
230 }
231 EXIT;
232 }
233
presto_no_journal(struct presto_file_set * fset)234 inline int presto_no_journal(struct presto_file_set *fset)
235 {
236 int minor = fset->fset_cache->cache_psdev->uc_minor;
237 return izo_channels[minor].uc_no_journal;
238 }
239
240 #define size_round(x) (((x)+3) & ~0x3)
241
242 #define BUFF_FREE(buf) PRESTO_FREE(buf, PAGE_SIZE)
243 #define BUFF_ALLOC(newbuf, oldbuf) \
244 PRESTO_ALLOC(newbuf, PAGE_SIZE); \
245 if ( !newbuf ) { \
246 if (oldbuf) \
247 BUFF_FREE(oldbuf); \
248 return -ENOMEM; \
249 }
250
251 /*
252 * "buflen" should be PAGE_SIZE or more.
253 * Give relative path wrt to a fsetroot
254 */
presto_path(struct dentry * dentry,struct dentry * root,char * buffer,int buflen)255 char * presto_path(struct dentry *dentry, struct dentry *root,
256 char *buffer, int buflen)
257 {
258 char * end = buffer+buflen;
259 char * retval;
260
261 *--end = '\0';
262 buflen--;
263 if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) {
264 buflen -= 10;
265 end -= 10;
266 memcpy(end, " (deleted)", 10);
267 }
268
269 /* Get '/' right */
270 retval = end-1;
271 *retval = '/';
272
273 for (;;) {
274 struct dentry * parent;
275 int namelen;
276
277 if (dentry == root)
278 break;
279 parent = dentry->d_parent;
280 if (dentry == parent)
281 break;
282 namelen = dentry->d_name.len;
283 buflen -= namelen + 1;
284 if (buflen < 0)
285 break;
286 end -= namelen;
287 memcpy(end, dentry->d_name.name, namelen);
288 *--end = '/';
289 retval = end;
290 dentry = parent;
291 }
292 return retval;
293 }
294
logit(char * buf,const void * value,int size)295 static inline char *logit(char *buf, const void *value, int size)
296 {
297 char *ptr = (char *)value;
298
299 memcpy(buf, ptr, size);
300 buf += size;
301 return buf;
302 }
303
304
305 static inline char *
journal_log_prefix_with_groups_and_ids(char * buf,int opcode,struct rec_info * rec,__u32 ngroups,gid_t * groups,__u32 fsuid,__u32 fsgid)306 journal_log_prefix_with_groups_and_ids(char *buf, int opcode,
307 struct rec_info *rec,
308 __u32 ngroups, gid_t *groups,
309 __u32 fsuid, __u32 fsgid)
310 {
311 struct kml_prefix_hdr p;
312 u32 loggroups[NGROUPS_MAX];
313
314 int i;
315
316 p.len = cpu_to_le32(rec->size);
317 p.version = KML_MAJOR_VERSION | KML_MINOR_VERSION;
318 p.pid = cpu_to_le32(current->pid);
319 p.auid = cpu_to_le32(current->uid);
320 p.fsuid = cpu_to_le32(fsuid);
321 p.fsgid = cpu_to_le32(fsgid);
322 p.ngroups = cpu_to_le32(ngroups);
323 p.opcode = cpu_to_le32(opcode);
324 for (i=0 ; i < ngroups ; i++)
325 loggroups[i] = cpu_to_le32((__u32) groups[i]);
326
327 buf = logit(buf, &p, sizeof(struct kml_prefix_hdr));
328 buf = logit(buf, &loggroups, sizeof(__u32) * ngroups);
329 return buf;
330 }
331
332 static inline char *
journal_log_prefix(char * buf,int opcode,struct rec_info * rec)333 journal_log_prefix(char *buf, int opcode, struct rec_info *rec)
334 {
335 __u32 groups[NGROUPS_MAX];
336 int i;
337
338 /* convert 16 bit gid's to 32 bit gid's */
339 for (i=0; i<current->ngroups; i++)
340 groups[i] = (__u32) current->groups[i];
341
342 return journal_log_prefix_with_groups_and_ids(buf, opcode, rec,
343 (__u32)current->ngroups,
344 groups,
345 (__u32)current->fsuid,
346 (__u32)current->fsgid);
347 }
348
349 static inline char *
journal_log_prefix_with_groups(char * buf,int opcode,struct rec_info * rec,__u32 ngroups,gid_t * groups)350 journal_log_prefix_with_groups(char *buf, int opcode, struct rec_info *rec,
351 __u32 ngroups, gid_t *groups)
352 {
353 return journal_log_prefix_with_groups_and_ids(buf, opcode, rec,
354 ngroups, groups,
355 (__u32)current->fsuid,
356 (__u32)current->fsgid);
357 }
358
log_dentry_version(char * buf,struct dentry * dentry)359 static inline char *log_dentry_version(char *buf, struct dentry *dentry)
360 {
361 struct presto_version version;
362
363 presto_getversion(&version, dentry->d_inode);
364
365 version.pv_mtime = HTON__u64(version.pv_mtime);
366 version.pv_ctime = HTON__u64(version.pv_ctime);
367 version.pv_size = HTON__u64(version.pv_size);
368
369 return logit(buf, &version, sizeof(version));
370 }
371
log_version(char * buf,struct presto_version * pv)372 static inline char *log_version(char *buf, struct presto_version *pv)
373 {
374 struct presto_version version;
375
376 memcpy(&version, pv, sizeof(version));
377
378 version.pv_mtime = HTON__u64(version.pv_mtime);
379 version.pv_ctime = HTON__u64(version.pv_ctime);
380 version.pv_size = HTON__u64(version.pv_size);
381
382 return logit(buf, &version, sizeof(version));
383 }
384
log_rollback(char * buf,struct izo_rollback_data * rb)385 static inline char *log_rollback(char *buf, struct izo_rollback_data *rb)
386 {
387 struct izo_rollback_data rollback;
388
389 memcpy(&rollback, rb, sizeof(rollback));
390
391 rollback.rb_mode = HTON__u32(rollback.rb_mode);
392 rollback.rb_rdev = HTON__u32(rollback.rb_rdev);
393 rollback.rb_uid = HTON__u64(rollback.rb_uid);
394 rollback.rb_gid = HTON__u64(rollback.rb_gid);
395
396 return logit(buf, &rollback, sizeof(rollback));
397 }
398
journal_log_suffix(char * buf,char * log,struct presto_file_set * fset,struct dentry * dentry,struct rec_info * rec)399 static inline char *journal_log_suffix(char *buf, char *log,
400 struct presto_file_set *fset,
401 struct dentry *dentry,
402 struct rec_info *rec)
403 {
404 struct kml_suffix s;
405 struct kml_prefix_hdr *p = (struct kml_prefix_hdr *)log;
406
407 #if 0
408 /* XXX needs to be done after reservation,
409 disable ths until version 1.2 */
410 if ( dentry ) {
411 s.prevrec = cpu_to_le32(rec->offset -
412 presto_d2d(dentry)->dd_kml_offset);
413 presto_d2d(dentry)->dd_kml_offset = rec->offset;
414 } else {
415 s.prevrec = -1;
416 }
417 #endif
418 s.prevrec = 0;
419
420 /* record number needs to be filled in after reservation
421 s.recno = cpu_to_le32(rec->recno); */
422 s.time = cpu_to_le32(CURRENT_TIME);
423 s.len = p->len;
424 return logit(buf, &s, sizeof(s));
425 }
426
izo_log_close(struct presto_log_fd * logfd)427 int izo_log_close(struct presto_log_fd *logfd)
428 {
429 int rc = 0;
430
431 if (logfd->fd_file) {
432 rc = filp_close(logfd->fd_file, 0);
433 logfd->fd_file = NULL;
434 } else
435 CERROR("InterMezzo: %s: no filp\n", __FUNCTION__);
436 if (rc != 0)
437 CERROR("InterMezzo: close files: filp won't close: %d\n", rc);
438
439 return rc;
440 }
441
presto_fwrite(struct file * file,const char * str,int len,loff_t * off)442 int presto_fwrite(struct file *file, const char *str, int len, loff_t *off)
443 {
444 int rc;
445 mm_segment_t old_fs;
446 ENTRY;
447
448 rc = -EINVAL;
449 if ( !off ) {
450 EXIT;
451 return rc;
452 }
453
454 if ( ! file ) {
455 EXIT;
456 return rc;
457 }
458
459 if ( ! file->f_op ) {
460 EXIT;
461 return rc;
462 }
463
464 if ( ! file->f_op->write ) {
465 EXIT;
466 return rc;
467 }
468
469 old_fs = get_fs();
470 set_fs(get_ds());
471 rc = file->f_op->write(file, str, len, off);
472 if (rc != len) {
473 CERROR("presto_fwrite: wrote %d bytes instead of "
474 "%d at %ld\n", rc, len, (long)*off);
475 rc = -EIO;
476 }
477 set_fs(old_fs);
478 EXIT;
479 return rc;
480 }
481
presto_fread(struct file * file,char * str,int len,loff_t * off)482 int presto_fread(struct file *file, char *str, int len, loff_t *off)
483 {
484 int rc;
485 mm_segment_t old_fs;
486 ENTRY;
487
488 if (len > 512)
489 CERROR("presto_fread: read at %Ld for %d bytes, ino %ld\n",
490 *off, len, file->f_dentry->d_inode->i_ino);
491
492 rc = -EINVAL;
493 if ( !off ) {
494 EXIT;
495 return rc;
496 }
497
498 if ( ! file ) {
499 EXIT;
500 return rc;
501 }
502
503 if ( ! file->f_op ) {
504 EXIT;
505 return rc;
506 }
507
508 if ( ! file->f_op->read ) {
509 EXIT;
510 return rc;
511 }
512
513 old_fs = get_fs();
514 set_fs(get_ds());
515 rc = file->f_op->read(file, str, len, off);
516 if (rc != len) {
517 CDEBUG(D_FILE, "presto_fread: read %d bytes instead of "
518 "%d at %Ld\n", rc, len, *off);
519 rc = -EIO;
520 }
521 set_fs(old_fs);
522 EXIT;
523 return rc;
524 }
525
presto_kml_offset(struct presto_file_set * fset)526 loff_t presto_kml_offset(struct presto_file_set *fset)
527 {
528 unsigned int kml_recno;
529 struct presto_log_fd *fd = &fset->fset_kml;
530 loff_t offset;
531 ENTRY;
532
533 write_lock(&fd->fd_lock);
534
535 /* Determine the largest valid offset, i.e. up until the first
536 * reservation held on the file. */
537 if ( !list_empty(&fd->fd_reservations) ) {
538 struct presto_reservation_data *rd;
539 rd = list_entry(fd->fd_reservations.next,
540 struct presto_reservation_data,
541 ri_list);
542 offset = rd->ri_offset;
543 kml_recno = rd->ri_recno;
544 } else {
545 offset = fd->fd_file->f_dentry->d_inode->i_size;
546 kml_recno = fset->fset_kml.fd_recno;
547 }
548 write_unlock(&fd->fd_lock);
549 return offset;
550 }
551
presto_kml_dispatch(struct presto_file_set * fset)552 static int presto_kml_dispatch(struct presto_file_set *fset)
553 {
554 int rc = 0;
555 unsigned int kml_recno;
556 struct presto_log_fd *fd = &fset->fset_kml;
557 loff_t offset;
558 ENTRY;
559
560 write_lock(&fd->fd_lock);
561
562 /* Determine the largest valid offset, i.e. up until the first
563 * reservation held on the file. */
564 if ( !list_empty(&fd->fd_reservations) ) {
565 struct presto_reservation_data *rd;
566 rd = list_entry(fd->fd_reservations.next,
567 struct presto_reservation_data,
568 ri_list);
569 offset = rd->ri_offset;
570 kml_recno = rd->ri_recno;
571 } else {
572 offset = fd->fd_file->f_dentry->d_inode->i_size;
573 kml_recno = fset->fset_kml.fd_recno;
574 }
575
576 if ( kml_recno < fset->fset_lento_recno ) {
577 CERROR("presto_kml_dispatch: smoke is coming\n");
578 write_unlock(&fd->fd_lock);
579 EXIT;
580 return 0;
581 } else if ( kml_recno == fset->fset_lento_recno ) {
582 write_unlock(&fd->fd_lock);
583 EXIT;
584 return 0;
585 /* XXX add a further "if" here to delay the KML upcall */
586 #if 0
587 } else if ( kml_recno < fset->fset_lento_recno + 100) {
588 write_unlock(&fd->fd_lock);
589 EXIT;
590 return 0;
591 #endif
592 }
593 CDEBUG(D_PIOCTL, "fset: %s\n", fset->fset_name);
594
595 rc = izo_upc_kml(fset->fset_cache->cache_psdev->uc_minor,
596 fset->fset_lento_off, fset->fset_lento_recno,
597 offset + fset->fset_kml_logical_off, kml_recno,
598 fset->fset_name);
599
600 if ( rc ) {
601 write_unlock(&fd->fd_lock);
602 EXIT;
603 return rc;
604 }
605
606 fset->fset_lento_off = offset;
607 fset->fset_lento_recno = kml_recno;
608 write_unlock(&fd->fd_lock);
609 EXIT;
610 return 0;
611 }
612
izo_lookup_file(struct presto_file_set * fset,char * path,struct nameidata * nd)613 int izo_lookup_file(struct presto_file_set *fset, char *path,
614 struct nameidata *nd)
615 {
616 int error = 0;
617
618 CDEBUG(D_CACHE, "looking up: %s\n", path);
619
620 if (path_init(path, LOOKUP_PARENT, nd))
621 error = path_walk(path, nd);
622 if (error) {
623 EXIT;
624 return error;
625 }
626
627 return 0;
628 }
629
630 /* FIXME: this function is a mess of locking and error handling. There's got to
631 * be a better way. */
do_truncate_rename(struct presto_file_set * fset,char * oldname,char * newname)632 static int do_truncate_rename(struct presto_file_set *fset, char *oldname,
633 char *newname)
634 {
635 struct dentry *old_dentry, *new_dentry;
636 struct nameidata oldnd, newnd;
637 char *oldpath, *newpath;
638 int error;
639
640 ENTRY;
641
642 oldpath = izo_make_path(fset, oldname);
643 if (oldpath == NULL) {
644 EXIT;
645 return -ENOENT;
646 }
647
648 newpath = izo_make_path(fset, newname);
649 if (newpath == NULL) {
650 error = -ENOENT;
651 EXIT;
652 goto exit;
653 }
654
655 if ((error = izo_lookup_file(fset, oldpath, &oldnd)) != 0) {
656 EXIT;
657 goto exit1;
658 }
659
660 if ((error = izo_lookup_file(fset, newpath, &newnd)) != 0) {
661 EXIT;
662 goto exit2;
663 }
664
665 double_lock(newnd.dentry, oldnd.dentry);
666 old_dentry = lookup_hash(&oldnd.last, oldnd.dentry);
667 error = PTR_ERR(old_dentry);
668 if (IS_ERR(old_dentry)) {
669 EXIT;
670 goto exit3;
671 }
672 error = -ENOENT;
673 if (!old_dentry->d_inode) {
674 EXIT;
675 goto exit4;
676 }
677 new_dentry = lookup_hash(&newnd.last, newnd.dentry);
678 error = PTR_ERR(new_dentry);
679 if (IS_ERR(new_dentry)) {
680 EXIT;
681 goto exit4;
682 }
683
684 {
685 extern int presto_rename(struct inode *old_dir,struct dentry *old_dentry,
686 struct inode *new_dir,struct dentry *new_dentry);
687 error = presto_rename(old_dentry->d_parent->d_inode, old_dentry,
688 new_dentry->d_parent->d_inode, new_dentry);
689 }
690
691 dput(new_dentry);
692 EXIT;
693 exit4:
694 dput(old_dentry);
695 exit3:
696 double_up(&newnd.dentry->d_inode->i_sem, &oldnd.dentry->d_inode->i_sem);
697 path_release(&newnd);
698 exit2:
699 path_release(&oldnd);
700 exit1:
701 PRESTO_FREE(newpath, strlen(newpath) + 1);
702 exit:
703 PRESTO_FREE(oldpath, strlen(oldpath) + 1);
704 return error;
705 }
706
707 /* This function is called with the fset->fset_kml.fd_lock held */
presto_finish_kml_truncate(struct presto_file_set * fset,unsigned long int offset)708 int presto_finish_kml_truncate(struct presto_file_set *fset,
709 unsigned long int offset)
710 {
711 struct lento_vfs_context info;
712 void *handle;
713 struct file *f;
714 struct dentry *dentry;
715 int error = 0, len;
716 struct nameidata nd;
717 char *kmlpath = NULL, *smlpath = NULL;
718 ENTRY;
719
720 if (offset == 0) {
721 /* Lento couldn't do what it needed to; abort the truncation. */
722 fset->fset_kml.fd_truncating = 0;
723 EXIT;
724 return 0;
725 }
726
727 /* someone is about to write to the end of the KML; try again later. */
728 if ( !list_empty(&fset->fset_kml.fd_reservations) ) {
729 EXIT;
730 return -EAGAIN;
731 }
732
733 f = presto_copy_kml_tail(fset, offset);
734 if (IS_ERR(f)) {
735 EXIT;
736 return PTR_ERR(f);
737 }
738
739 /* In a single transaction:
740 *
741 * - unlink 'kml'
742 * - rename 'kml_tmp' to 'kml'
743 * - unlink 'sml'
744 * - rename 'sml_tmp' to 'sml'
745 * - rewrite the first record of last_rcvd with the new kml
746 * offset.
747 */
748 handle = presto_trans_start(fset, fset->fset_dentry->d_inode,
749 KML_OPCODE_KML_TRUNC);
750 if (IS_ERR(handle)) {
751 presto_release_space(fset->fset_cache, PRESTO_REQLOW);
752 CERROR("ERROR: presto_finish_kml_truncate: no space for transaction\n");
753 EXIT;
754 return -ENOMEM;
755 }
756
757 memset(&info, 0, sizeof(info));
758 info.flags = LENTO_FL_IGNORE_TIME;
759
760 kmlpath = izo_make_path(fset, "kml");
761 if (kmlpath == NULL) {
762 error = -ENOMEM;
763 CERROR("make_path failed: ENOMEM\n");
764 EXIT;
765 goto exit_commit;
766 }
767
768 if ((error = izo_lookup_file(fset, kmlpath, &nd)) != 0) {
769 CERROR("izo_lookup_file(kml) failed: %d.\n", error);
770 EXIT;
771 goto exit_commit;
772 }
773 down(&nd.dentry->d_inode->i_sem);
774 dentry = lookup_hash(&nd.last, nd.dentry);
775 error = PTR_ERR(dentry);
776 if (IS_ERR(dentry)) {
777 up(&nd.dentry->d_inode->i_sem);
778 path_release(&nd);
779 CERROR("lookup_hash failed\n");
780 EXIT;
781 goto exit_commit;
782 }
783 error = presto_do_unlink(fset, dentry->d_parent, dentry, &info);
784 dput(dentry);
785 up(&nd.dentry->d_inode->i_sem);
786 path_release(&nd);
787
788 if (error != 0) {
789 CERROR("presto_do_unlink(kml) failed: %d.\n", error);
790 EXIT;
791 goto exit_commit;
792 }
793
794 smlpath = izo_make_path(fset, "sml");
795 if (smlpath == NULL) {
796 error = -ENOMEM;
797 CERROR("make_path() failed: ENOMEM\n");
798 EXIT;
799 goto exit_commit;
800 }
801
802 if ((error = izo_lookup_file(fset, smlpath, &nd)) != 0) {
803 CERROR("izo_lookup_file(sml) failed: %d.\n", error);
804 EXIT;
805 goto exit_commit;
806 }
807 down(&nd.dentry->d_inode->i_sem);
808 dentry = lookup_hash(&nd.last, nd.dentry);
809 error = PTR_ERR(dentry);
810 if (IS_ERR(dentry)) {
811 up(&nd.dentry->d_inode->i_sem);
812 path_release(&nd);
813 CERROR("lookup_hash failed\n");
814 EXIT;
815 goto exit_commit;
816 }
817 error = presto_do_unlink(fset, dentry->d_parent, dentry, &info);
818 dput(dentry);
819 up(&nd.dentry->d_inode->i_sem);
820 path_release(&nd);
821
822 if (error != 0) {
823 CERROR("presto_do_unlink(sml) failed: %d.\n", error);
824 EXIT;
825 goto exit_commit;
826 }
827
828 error = do_truncate_rename(fset, "kml_tmp", "kml");
829 if (error != 0)
830 CERROR("do_truncate_rename(kml_tmp, kml) failed: %d\n", error);
831 error = do_truncate_rename(fset, "sml_tmp", "sml");
832 if (error != 0)
833 CERROR("do_truncate_rename(sml_tmp, sml) failed: %d\n", error);
834
835 /* Write a new 'last_rcvd' record with the new KML offset */
836 fset->fset_kml_logical_off += offset;
837 CDEBUG(D_CACHE, "new kml_logical_offset: %Lu\n",
838 fset->fset_kml_logical_off);
839 if (presto_write_kml_logical_offset(fset) != 0) {
840 CERROR("presto_write_kml_logical_offset failed\n");
841 }
842
843 presto_trans_commit(fset, handle);
844
845 /* Everything was successful, so swap the KML file descriptors */
846 filp_close(fset->fset_kml.fd_file, NULL);
847 fset->fset_kml.fd_file = f;
848 fset->fset_kml.fd_offset -= offset;
849 fset->fset_kml.fd_truncating = 0;
850
851 EXIT;
852 return 0;
853
854 exit_commit:
855 presto_trans_commit(fset, handle);
856 len = strlen("/.intermezzo/") + strlen(fset->fset_name) +strlen("sml");
857 if (kmlpath != NULL)
858 PRESTO_FREE(kmlpath, len);
859 if (smlpath != NULL)
860 PRESTO_FREE(smlpath, len);
861 return error;
862 }
863
864 /* structure of an extended log record:
865
866 buf-prefix buf-body [string1 [string2 [string3]]] buf-suffix
867
868 note: moves offset forward
869 */
presto_write_record(struct file * f,loff_t * off,const char * buf,size_t size,const char * string1,int len1,const char * string2,int len2,const char * string3,int len3)870 static inline int presto_write_record(struct file *f, loff_t *off,
871 const char *buf, size_t size,
872 const char *string1, int len1,
873 const char *string2, int len2,
874 const char *string3, int len3)
875 {
876 size_t prefix_size;
877 int rc;
878
879 prefix_size = size - sizeof(struct kml_suffix);
880 rc = presto_fwrite(f, buf, prefix_size, off);
881 if ( rc != prefix_size ) {
882 CERROR("Write error!\n");
883 EXIT;
884 return -EIO;
885 }
886
887 if ( string1 && len1 ) {
888 rc = presto_fwrite(f, string1, len1, off);
889 if ( rc != len1 ) {
890 CERROR("Write error!\n");
891 EXIT;
892 return -EIO;
893 }
894 }
895
896 if ( string2 && len2 ) {
897 rc = presto_fwrite(f, string2, len2, off);
898 if ( rc != len2 ) {
899 CERROR("Write error!\n");
900 EXIT;
901 return -EIO;
902 }
903 }
904
905 if ( string3 && len3 ) {
906 rc = presto_fwrite(f, string3, len3, off);
907 if ( rc != len3 ) {
908 CERROR("Write error!\n");
909 EXIT;
910 return -EIO;
911 }
912 }
913
914 rc = presto_fwrite(f, buf + prefix_size,
915 sizeof(struct kml_suffix), off);
916 if ( rc != sizeof(struct kml_suffix) ) {
917 CERROR("Write error!\n");
918 EXIT;
919 return -EIO;
920 }
921 return 0;
922 }
923
924
925 /*
926 * rec->size must be valid prior to calling this function.
927 *
928 * had to export this for branch_reinter in kml_reint.c
929 */
presto_log(struct presto_file_set * fset,struct rec_info * rec,const char * buf,size_t size,const char * string1,int len1,const char * string2,int len2,const char * string3,int len3)930 int presto_log(struct presto_file_set *fset, struct rec_info *rec,
931 const char *buf, size_t size,
932 const char *string1, int len1,
933 const char *string2, int len2,
934 const char *string3, int len3)
935 {
936 int rc;
937 struct presto_reservation_data rd;
938 loff_t offset;
939 struct presto_log_fd *fd;
940 struct kml_suffix *s;
941 int prefix_size;
942
943 ENTRY;
944
945 /* buf is NULL when no_journal is in effect */
946 if (!buf) {
947 EXIT;
948 return -EINVAL;
949 }
950
951 if (rec->is_kml) {
952 fd = &fset->fset_kml;
953 } else {
954 fd = &fset->fset_lml;
955 }
956
957 presto_reserve_record(fset, fd, rec, &rd);
958
959 if (rec->is_kml) {
960 if (rec->offset < fset->fset_kml_logical_off) {
961 CERROR("record with pre-trunc offset. tell phil.\n");
962 BUG();
963 }
964 offset = rec->offset - fset->fset_kml_logical_off;
965 } else {
966 offset = rec->offset;
967 }
968
969 /* now we know the record number */
970 prefix_size = size - sizeof(struct kml_suffix);
971 s = (struct kml_suffix *) (buf + prefix_size);
972 s->recno = cpu_to_le32(rec->recno);
973
974 rc = presto_write_record(fd->fd_file, &offset, buf, size,
975 string1, len1, string2, len2, string3, len3);
976 if (rc) {
977 CERROR("presto: error writing record to %s\n",
978 rec->is_kml ? "KML" : "LML");
979 return rc;
980 }
981 presto_release_record(fd, &rd);
982
983 rc = presto_kml_dispatch(fset);
984
985 EXIT;
986 return rc;
987 }
988
989 /* read from the record at tail */
presto_last_record(struct presto_log_fd * fd,loff_t * size,loff_t * tail_offset,__u32 * recno,loff_t tail)990 static int presto_last_record(struct presto_log_fd *fd, loff_t *size,
991 loff_t *tail_offset, __u32 *recno, loff_t tail)
992 {
993 struct kml_suffix suffix;
994 int rc;
995 loff_t zeroes;
996
997 *recno = 0;
998 *tail_offset = 0;
999 *size = 0;
1000
1001 if (tail < sizeof(struct kml_prefix_hdr) + sizeof(suffix)) {
1002 EXIT;
1003 return 0;
1004 }
1005
1006 zeroes = tail - sizeof(int);
1007 while ( zeroes >= 0 ) {
1008 int data;
1009 rc = presto_fread(fd->fd_file, (char *)&data, sizeof(data),
1010 &zeroes);
1011 if ( rc != sizeof(data) ) {
1012 rc = -EIO;
1013 return rc;
1014 }
1015 if (data)
1016 break;
1017 zeroes -= 2 * sizeof(data);
1018 }
1019
1020 /* zeroes at the begining of file. this is needed to prevent
1021 presto_fread errors -SHP
1022 */
1023 if (zeroes <= 0) return 0;
1024
1025 zeroes -= sizeof(suffix) + sizeof(int);
1026 rc = presto_fread(fd->fd_file, (char *)&suffix, sizeof(suffix), &zeroes);
1027 if ( rc != sizeof(suffix) ) {
1028 EXIT;
1029 return rc;
1030 }
1031 if ( suffix.len > 500 ) {
1032 CERROR("InterMezzo: Warning long record tail at %ld, rec tail_offset at %ld (size %d)\n",
1033 (long) zeroes, (long)*tail_offset, suffix.len);
1034 }
1035
1036 *recno = suffix.recno;
1037 *size = suffix.len;
1038 *tail_offset = zeroes;
1039 return 0;
1040 }
1041
izo_kml_last_recno(struct presto_log_fd * logfd)1042 static int izo_kml_last_recno(struct presto_log_fd *logfd)
1043 {
1044 int rc;
1045 loff_t size;
1046 loff_t tail_offset;
1047 int recno;
1048 loff_t tail = logfd->fd_file->f_dentry->d_inode->i_size;
1049
1050 rc = presto_last_record(logfd, &size, &tail_offset, &recno, tail);
1051 if (rc != 0) {
1052 EXIT;
1053 return rc;
1054 }
1055
1056 logfd->fd_offset = tail_offset;
1057 logfd->fd_recno = recno;
1058 CDEBUG(D_JOURNAL, "setting fset_kml->fd_recno to %d, offset %Ld\n",
1059 recno, tail_offset);
1060 EXIT;
1061 return 0;
1062 }
1063
izo_log_open(struct presto_file_set * fset,char * name,int flags)1064 struct file *izo_log_open(struct presto_file_set *fset, char *name, int flags)
1065 {
1066 struct presto_cache *cache = fset->fset_cache;
1067 struct file *f;
1068 int error;
1069 ENTRY;
1070
1071 f = izo_fset_open(fset, name, flags, 0644);
1072 error = PTR_ERR(f);
1073 if (IS_ERR(f)) {
1074 EXIT;
1075 return f;
1076 }
1077
1078 error = -EINVAL;
1079 if ( cache != presto_get_cache(f->f_dentry->d_inode) ) {
1080 CERROR("InterMezzo: %s cache does not match fset cache!\n",name);
1081 fset->fset_kml.fd_file = NULL;
1082 filp_close(f, NULL);
1083 f = NULL;
1084 EXIT;
1085 return f;
1086 }
1087
1088 if (cache->cache_filter && cache->cache_filter->o_trops &&
1089 cache->cache_filter->o_trops->tr_journal_data) {
1090 cache->cache_filter->o_trops->tr_journal_data
1091 (f->f_dentry->d_inode);
1092 } else {
1093 CERROR("InterMezzo WARNING: no file data logging!\n");
1094 }
1095
1096 EXIT;
1097
1098 return f;
1099 }
1100
izo_init_kml_file(struct presto_file_set * fset,struct presto_log_fd * logfd)1101 int izo_init_kml_file(struct presto_file_set *fset, struct presto_log_fd *logfd)
1102 {
1103 int error = 0;
1104 struct file *f;
1105
1106 ENTRY;
1107 if (logfd->fd_file) {
1108 CDEBUG(D_INODE, "fset already has KML open\n");
1109 EXIT;
1110 return 0;
1111 }
1112
1113 logfd->fd_lock = RW_LOCK_UNLOCKED;
1114 INIT_LIST_HEAD(&logfd->fd_reservations);
1115 f = izo_log_open(fset, "kml", O_RDWR | O_CREAT);
1116 if (IS_ERR(f)) {
1117 error = PTR_ERR(f);
1118 return error;
1119 }
1120
1121 logfd->fd_file = f;
1122 error = izo_kml_last_recno(logfd);
1123
1124 if (error) {
1125 logfd->fd_file = NULL;
1126 filp_close(f, NULL);
1127 CERROR("InterMezzo: IO error in KML of fset %s\n",
1128 fset->fset_name);
1129 EXIT;
1130 return error;
1131 }
1132 fset->fset_lento_off = logfd->fd_offset;
1133 fset->fset_lento_recno = logfd->fd_recno;
1134
1135 EXIT;
1136 return error;
1137 }
1138
izo_init_last_rcvd_file(struct presto_file_set * fset,struct presto_log_fd * logfd)1139 int izo_init_last_rcvd_file(struct presto_file_set *fset, struct presto_log_fd *logfd)
1140 {
1141 int error = 0;
1142 struct file *f;
1143 struct rec_info recinfo;
1144
1145 ENTRY;
1146 if (logfd->fd_file != NULL) {
1147 CDEBUG(D_INODE, "fset already has last_rcvd open\n");
1148 EXIT;
1149 return 0;
1150 }
1151
1152 logfd->fd_lock = RW_LOCK_UNLOCKED;
1153 INIT_LIST_HEAD(&logfd->fd_reservations);
1154 f = izo_log_open(fset, "last_rcvd", O_RDWR | O_CREAT);
1155 if (IS_ERR(f)) {
1156 error = PTR_ERR(f);
1157 return error;
1158 }
1159
1160 logfd->fd_file = f;
1161 logfd->fd_offset = f->f_dentry->d_inode->i_size;
1162
1163 error = izo_rep_cache_init(fset);
1164
1165 if (presto_read_kml_logical_offset(&recinfo, fset) == 0) {
1166 fset->fset_kml_logical_off = recinfo.offset;
1167 } else {
1168 /* The 'last_rcvd' file doesn't contain a kml offset record,
1169 * probably because we just created 'last_rcvd'. Write one. */
1170 fset->fset_kml_logical_off = 0;
1171 presto_write_kml_logical_offset(fset);
1172 }
1173
1174 EXIT;
1175 return error;
1176 }
1177
izo_init_lml_file(struct presto_file_set * fset,struct presto_log_fd * logfd)1178 int izo_init_lml_file(struct presto_file_set *fset, struct presto_log_fd *logfd)
1179 {
1180 int error = 0;
1181 struct file *f;
1182
1183 ENTRY;
1184 if (logfd->fd_file) {
1185 CDEBUG(D_INODE, "fset already has lml open\n");
1186 EXIT;
1187 return 0;
1188 }
1189
1190 logfd->fd_lock = RW_LOCK_UNLOCKED;
1191 INIT_LIST_HEAD(&logfd->fd_reservations);
1192 f = izo_log_open(fset, "lml", O_RDWR | O_CREAT);
1193 if (IS_ERR(f)) {
1194 error = PTR_ERR(f);
1195 return error;
1196 }
1197
1198 logfd->fd_file = f;
1199 logfd->fd_offset = f->f_dentry->d_inode->i_size;
1200
1201 EXIT;
1202 return error;
1203 }
1204
1205 /* Get the KML-offset record from the last_rcvd file */
presto_read_kml_logical_offset(struct rec_info * recinfo,struct presto_file_set * fset)1206 int presto_read_kml_logical_offset(struct rec_info *recinfo,
1207 struct presto_file_set *fset)
1208 {
1209 loff_t off;
1210 struct izo_rcvd_rec rec;
1211 char uuid[16] = {0};
1212
1213 off = izo_rcvd_get(&rec, fset, uuid);
1214 if (off < 0)
1215 return -1;
1216
1217 recinfo->offset = rec.lr_local_offset;
1218 return 0;
1219 }
1220
presto_write_kml_logical_offset(struct presto_file_set * fset)1221 int presto_write_kml_logical_offset(struct presto_file_set *fset)
1222 {
1223 loff_t rc;
1224 struct izo_rcvd_rec rec;
1225 char uuid[16] = {0};
1226
1227 rc = izo_rcvd_get(&rec, fset, uuid);
1228 if (rc < 0)
1229 memset(&rec, 0, sizeof(rec));
1230
1231 rec.lr_local_offset =
1232 cpu_to_le64(fset->fset_kml_logical_off);
1233
1234 return izo_rcvd_write(fset, &rec);
1235 }
1236
presto_copy_kml_tail(struct presto_file_set * fset,unsigned long int start)1237 struct file * presto_copy_kml_tail(struct presto_file_set *fset,
1238 unsigned long int start)
1239 {
1240 struct file *f;
1241 int len;
1242 loff_t read_off, write_off, bytes;
1243
1244 ENTRY;
1245
1246 /* Copy the tail of 'kml' to 'kml_tmp' */
1247 f = izo_log_open(fset, "kml_tmp", O_RDWR);
1248 if (IS_ERR(f)) {
1249 EXIT;
1250 return f;
1251 }
1252
1253 write_off = 0;
1254 read_off = start;
1255 bytes = fset->fset_kml.fd_offset - start;
1256 while (bytes > 0) {
1257 char buf[4096];
1258 int toread;
1259
1260 if (bytes > sizeof(buf))
1261 toread = sizeof(buf);
1262 else
1263 toread = bytes;
1264
1265 len = presto_fread(fset->fset_kml.fd_file, buf, toread,
1266 &read_off);
1267 if (len <= 0)
1268 break;
1269
1270 if (presto_fwrite(f, buf, len, &write_off) != len) {
1271 filp_close(f, NULL);
1272 EXIT;
1273 return ERR_PTR(-EIO);
1274 }
1275
1276 bytes -= len;
1277 }
1278
1279 EXIT;
1280 return f;
1281 }
1282
1283
1284 /* LML records here */
1285 /* this writes an LML record to the LML file (rec->is_kml =0) */
presto_write_lml_close(struct rec_info * rec,struct presto_file_set * fset,struct file * file,__u64 remote_ino,__u64 remote_generation,struct presto_version * remote_version,struct presto_version * new_file_ver)1286 int presto_write_lml_close(struct rec_info *rec,
1287 struct presto_file_set *fset,
1288 struct file *file,
1289 __u64 remote_ino,
1290 __u64 remote_generation,
1291 struct presto_version *remote_version,
1292 struct presto_version *new_file_ver)
1293 {
1294 int opcode = KML_OPCODE_CLOSE;
1295 char *buffer;
1296 struct dentry *dentry = file->f_dentry;
1297 __u64 ino;
1298 __u32 pathlen;
1299 char *path;
1300 __u32 generation;
1301 int size;
1302 char *logrecord;
1303 char record[292];
1304 struct dentry *root;
1305 int error;
1306
1307 ENTRY;
1308
1309 if ( presto_no_journal(fset) ) {
1310 EXIT;
1311 return 0;
1312 }
1313 root = fset->fset_dentry;
1314
1315 BUFF_ALLOC(buffer, NULL);
1316 path = presto_path(dentry, root, buffer, PAGE_SIZE);
1317 CDEBUG(D_INODE, "Path: %s\n", path);
1318 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1319 ino = cpu_to_le64(dentry->d_inode->i_ino);
1320 generation = cpu_to_le32(dentry->d_inode->i_generation);
1321 size = sizeof(__u32) * current->ngroups +
1322 sizeof(struct kml_prefix_hdr) + sizeof(*new_file_ver) +
1323 sizeof(ino) + sizeof(generation) + sizeof(pathlen) +
1324 sizeof(remote_ino) + sizeof(remote_generation) +
1325 sizeof(remote_version) + sizeof(rec->offset) +
1326 sizeof(struct kml_suffix);
1327
1328 if ( size > sizeof(record) )
1329 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1330
1331 rec->is_kml = 0;
1332 rec->size = size + size_round(le32_to_cpu(pathlen));
1333
1334 logrecord = journal_log_prefix(record, opcode, rec);
1335 logrecord = log_version(logrecord, new_file_ver);
1336 logrecord = logit(logrecord, &ino, sizeof(ino));
1337 logrecord = logit(logrecord, &generation, sizeof(generation));
1338 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1339 logrecord = logit(logrecord, &remote_ino, sizeof(remote_ino));
1340 logrecord = logit(logrecord, &remote_generation,
1341 sizeof(remote_generation));
1342 logrecord = log_version(logrecord, remote_version);
1343 logrecord = logit(logrecord, &rec->offset, sizeof(rec->offset));
1344 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
1345
1346 error = presto_log(fset, rec, record, size,
1347 path, size_round(le32_to_cpu(pathlen)),
1348 NULL, 0, NULL, 0);
1349
1350 BUFF_FREE(buffer);
1351
1352 EXIT;
1353 return error;
1354 }
1355
1356 /*
1357 * Check if the given record is at the end of the file. If it is, truncate
1358 * the lml to the record's offset, removing it. Repeat on prior record,
1359 * until we reach an active record or a reserved record (as defined by the
1360 * reservations list).
1361 */
presto_truncate_lml_tail(struct presto_file_set * fset)1362 static int presto_truncate_lml_tail(struct presto_file_set *fset)
1363 {
1364 loff_t lml_tail;
1365 loff_t lml_last_rec;
1366 loff_t lml_last_recsize;
1367 loff_t local_offset;
1368 int recno;
1369 struct kml_prefix_hdr prefix;
1370 struct inode *inode = fset->fset_lml.fd_file->f_dentry->d_inode;
1371 void *handle;
1372 int rc;
1373
1374 ENTRY;
1375 /* If someone else is already truncating the LML, return. */
1376 write_lock(&fset->fset_lml.fd_lock);
1377 if (fset->fset_lml.fd_truncating == 1 ) {
1378 write_unlock(&fset->fset_lml.fd_lock);
1379 EXIT;
1380 return 0;
1381 }
1382 /* someone is about to write to the end of the LML */
1383 if ( !list_empty(&fset->fset_lml.fd_reservations) ) {
1384 write_unlock(&fset->fset_lml.fd_lock);
1385 EXIT;
1386 return 0;
1387 }
1388 lml_tail = fset->fset_lml.fd_file->f_dentry->d_inode->i_size;
1389 /* Nothing to truncate?*/
1390 if (lml_tail == 0) {
1391 write_unlock(&fset->fset_lml.fd_lock);
1392 EXIT;
1393 return 0;
1394 }
1395 fset->fset_lml.fd_truncating = 1;
1396 write_unlock(&fset->fset_lml.fd_lock);
1397
1398 presto_last_record(&fset->fset_lml, &lml_last_recsize,
1399 &lml_last_rec, &recno, lml_tail);
1400 /* Do we have a record to check? If not we have zeroes at the
1401 beginning of the file. -SHP
1402 */
1403 if (lml_last_recsize != 0) {
1404 local_offset = lml_last_rec - lml_last_recsize;
1405 rc = presto_fread(fset->fset_lml.fd_file, (char *)&prefix,
1406 sizeof(prefix), &local_offset);
1407 if (rc != sizeof(prefix)) {
1408 EXIT;
1409 goto tr_out;
1410 }
1411
1412 if ( prefix.opcode != KML_OPCODE_NOOP ) {
1413 EXIT;
1414 rc = 0;
1415 /* We may have zeroes at the end of the file, should
1416 we clear them out? -SHP
1417 */
1418 goto tr_out;
1419 }
1420 } else
1421 lml_last_rec=0;
1422
1423 handle = presto_trans_start(fset, inode, KML_OPCODE_TRUNC);
1424 if ( IS_ERR(handle) ) {
1425 EXIT;
1426 rc = -ENOMEM;
1427 goto tr_out;
1428 }
1429
1430 rc = izo_do_truncate(fset, fset->fset_lml.fd_file->f_dentry,
1431 lml_last_rec - lml_last_recsize, lml_tail);
1432 presto_trans_commit(fset, handle);
1433 if ( rc == 0 ) {
1434 rc = 1;
1435 }
1436 EXIT;
1437
1438 tr_out:
1439 CDEBUG(D_JOURNAL, "rc = %d\n", rc);
1440 write_lock(&fset->fset_lml.fd_lock);
1441 fset->fset_lml.fd_truncating = 0;
1442 write_unlock(&fset->fset_lml.fd_lock);
1443 return rc;
1444 }
1445
presto_truncate_lml(struct presto_file_set * fset)1446 int presto_truncate_lml(struct presto_file_set *fset)
1447 {
1448 int rc;
1449 ENTRY;
1450
1451 while ( (rc = presto_truncate_lml_tail(fset)) > 0);
1452 if ( rc < 0 && rc != -EALREADY) {
1453 CERROR("truncate_lml error %d\n", rc);
1454 }
1455 EXIT;
1456 return rc;
1457 }
1458
presto_clear_lml_close(struct presto_file_set * fset,loff_t lml_offset)1459 int presto_clear_lml_close(struct presto_file_set *fset, loff_t lml_offset)
1460 {
1461 int rc;
1462 struct kml_prefix_hdr record;
1463 loff_t offset = lml_offset;
1464
1465 ENTRY;
1466
1467 if ( presto_no_journal(fset) ) {
1468 EXIT;
1469 return 0;
1470 }
1471
1472 CDEBUG(D_JOURNAL, "reading prefix: off %ld, size %d\n",
1473 (long)lml_offset, sizeof(record));
1474 rc = presto_fread(fset->fset_lml.fd_file, (char *)&record,
1475 sizeof(record), &offset);
1476
1477 if ( rc != sizeof(record) ) {
1478 CERROR("presto: clear_lml io error %d\n", rc);
1479 EXIT;
1480 return -EIO;
1481 }
1482
1483 /* overwrite the prefix */
1484 CDEBUG(D_JOURNAL, "overwriting prefix: off %ld\n", (long)lml_offset);
1485 record.opcode = KML_OPCODE_NOOP;
1486 offset = lml_offset;
1487 /* note: this does just a single transaction in the cache */
1488 rc = presto_fwrite(fset->fset_lml.fd_file, (char *)(&record),
1489 sizeof(record), &offset);
1490 if ( rc != sizeof(record) ) {
1491 EXIT;
1492 return -EIO;
1493 }
1494
1495 EXIT;
1496 return 0;
1497 }
1498
1499
1500
1501 /* now a journal function for every operation */
1502
presto_journal_setattr(struct rec_info * rec,struct presto_file_set * fset,struct dentry * dentry,struct presto_version * old_ver,struct izo_rollback_data * rb,struct iattr * iattr)1503 int presto_journal_setattr(struct rec_info *rec, struct presto_file_set *fset,
1504 struct dentry *dentry, struct presto_version *old_ver,
1505 struct izo_rollback_data *rb, struct iattr *iattr)
1506 {
1507 int opcode = KML_OPCODE_SETATTR;
1508 char *buffer, *path, *logrecord, record[316];
1509 struct dentry *root;
1510 __u32 uid, gid, mode, valid, flags, pathlen;
1511 __u64 fsize, mtime, ctime;
1512 int error, size;
1513
1514 ENTRY;
1515 if ( presto_no_journal(fset) ) {
1516 EXIT;
1517 return 0;
1518 }
1519
1520 if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0)
1521 || ((dentry->d_parent != dentry) && list_empty(&dentry->d_hash))) {
1522 EXIT;
1523 return 0;
1524 }
1525
1526 root = fset->fset_dentry;
1527
1528 BUFF_ALLOC(buffer, NULL);
1529 path = presto_path(dentry, root, buffer, PAGE_SIZE);
1530 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1531 size = sizeof(__u32) * current->ngroups +
1532 sizeof(struct kml_prefix_hdr) + sizeof(*old_ver) +
1533 sizeof(valid) + sizeof(mode) + sizeof(uid) + sizeof(gid) +
1534 sizeof(fsize) + sizeof(mtime) + sizeof(ctime) + sizeof(flags) +
1535 sizeof(pathlen) + sizeof(*rb) + sizeof(struct kml_suffix);
1536
1537 if ( size > sizeof(record) )
1538 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1539
1540 /* Only journal one kind of mtime, and not atime at all. Also don't
1541 * journal bogus data in iattr, to make the journal more compressible.
1542 */
1543 if (iattr->ia_valid & ATTR_MTIME_SET)
1544 iattr->ia_valid = iattr->ia_valid | ATTR_MTIME;
1545 valid = cpu_to_le32(iattr->ia_valid & ~(ATTR_ATIME | ATTR_MTIME_SET |
1546 ATTR_ATIME_SET));
1547 mode = iattr->ia_valid & ATTR_MODE ? cpu_to_le32(iattr->ia_mode): 0;
1548 uid = iattr->ia_valid & ATTR_UID ? cpu_to_le32(iattr->ia_uid): 0;
1549 gid = iattr->ia_valid & ATTR_GID ? cpu_to_le32(iattr->ia_gid): 0;
1550 fsize = iattr->ia_valid & ATTR_SIZE ? cpu_to_le64(iattr->ia_size): 0;
1551 mtime = iattr->ia_valid & ATTR_MTIME ? cpu_to_le64(iattr->ia_mtime): 0;
1552 ctime = iattr->ia_valid & ATTR_CTIME ? cpu_to_le64(iattr->ia_ctime): 0;
1553 flags = iattr->ia_valid & ATTR_ATTR_FLAG ?
1554 cpu_to_le32(iattr->ia_attr_flags): 0;
1555
1556 rec->is_kml = 1;
1557 rec->size = size + size_round(le32_to_cpu(pathlen));
1558
1559 logrecord = journal_log_prefix(record, opcode, rec);
1560 logrecord = log_version(logrecord, old_ver);
1561 logrecord = logit(logrecord, &valid, sizeof(valid));
1562 logrecord = logit(logrecord, &mode, sizeof(mode));
1563 logrecord = logit(logrecord, &uid, sizeof(uid));
1564 logrecord = logit(logrecord, &gid, sizeof(gid));
1565 logrecord = logit(logrecord, &fsize, sizeof(fsize));
1566 logrecord = logit(logrecord, &mtime, sizeof(mtime));
1567 logrecord = logit(logrecord, &ctime, sizeof(ctime));
1568 logrecord = logit(logrecord, &flags, sizeof(flags));
1569 logrecord = log_rollback(logrecord, rb);
1570 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1571 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
1572
1573 error = presto_log(fset, rec, record, size,
1574 path, size_round(le32_to_cpu(pathlen)),
1575 NULL, 0, NULL, 0);
1576
1577 BUFF_FREE(buffer);
1578 EXIT;
1579 return error;
1580 }
1581
presto_get_fileid(int minor,struct presto_file_set * fset,struct dentry * dentry)1582 int presto_get_fileid(int minor, struct presto_file_set *fset,
1583 struct dentry *dentry)
1584 {
1585 int opcode = KML_OPCODE_GET_FILEID;
1586 struct rec_info rec;
1587 char *buffer, *path, *logrecord, record[4096]; /*include path*/
1588 struct dentry *root;
1589 __u32 uid, gid, pathlen;
1590 int error, size;
1591 struct kml_suffix *suffix;
1592
1593 ENTRY;
1594
1595 root = fset->fset_dentry;
1596
1597 uid = cpu_to_le32(dentry->d_inode->i_uid);
1598 gid = cpu_to_le32(dentry->d_inode->i_gid);
1599 BUFF_ALLOC(buffer, NULL);
1600 path = presto_path(dentry, root, buffer, PAGE_SIZE);
1601 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1602 size = sizeof(__u32) * current->ngroups +
1603 sizeof(struct kml_prefix_hdr) + sizeof(pathlen) +
1604 size_round(le32_to_cpu(pathlen)) +
1605 sizeof(struct kml_suffix);
1606
1607 CDEBUG(D_FILE, "kml size: %d\n", size);
1608 if ( size > sizeof(record) )
1609 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1610
1611 memset(&rec, 0, sizeof(rec));
1612 rec.is_kml = 1;
1613 rec.size = size;
1614
1615 logrecord = journal_log_prefix(record, opcode, &rec);
1616 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1617 logrecord = logit(logrecord, path, size_round(le32_to_cpu(pathlen)));
1618 suffix = (struct kml_suffix *)logrecord;
1619 logrecord = journal_log_suffix(logrecord, record, fset, dentry, &rec);
1620 /* journal_log_suffix expects journal_log to set this */
1621 suffix->recno = 0;
1622
1623 CDEBUG(D_FILE, "actual kml size: %d\n", logrecord - record);
1624 CDEBUG(D_FILE, "get fileid: uid %d, gid %d, path: %s\n", uid, gid,path);
1625
1626 error = izo_upc_get_fileid(minor, size, record,
1627 size_round(le32_to_cpu(pathlen)), path,
1628 fset->fset_name);
1629
1630 BUFF_FREE(buffer);
1631 EXIT;
1632 return error;
1633 }
1634
presto_journal_create(struct rec_info * rec,struct presto_file_set * fset,struct dentry * dentry,struct presto_version * tgt_dir_ver,struct presto_version * new_file_ver,int mode)1635 int presto_journal_create(struct rec_info *rec, struct presto_file_set *fset,
1636 struct dentry *dentry,
1637 struct presto_version *tgt_dir_ver,
1638 struct presto_version *new_file_ver, int mode)
1639 {
1640 int opcode = KML_OPCODE_CREATE;
1641 char *buffer, *path, *logrecord, record[292];
1642 struct dentry *root;
1643 __u32 uid, gid, lmode, pathlen;
1644 int error, size;
1645
1646 ENTRY;
1647 if ( presto_no_journal(fset) ) {
1648 EXIT;
1649 return 0;
1650 }
1651
1652 root = fset->fset_dentry;
1653
1654 uid = cpu_to_le32(dentry->d_inode->i_uid);
1655 gid = cpu_to_le32(dentry->d_inode->i_gid);
1656 lmode = cpu_to_le32(mode);
1657
1658 BUFF_ALLOC(buffer, NULL);
1659 path = presto_path(dentry, root, buffer, PAGE_SIZE);
1660 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1661 size = sizeof(__u32) * current->ngroups +
1662 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
1663 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
1664 sizeof(struct kml_suffix);
1665
1666 if ( size > sizeof(record) )
1667 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1668
1669 rec->is_kml = 1;
1670 rec->size = size + size_round(le32_to_cpu(pathlen));
1671
1672 logrecord = journal_log_prefix(record, opcode, rec);
1673 logrecord = log_version(logrecord, tgt_dir_ver);
1674 logrecord = log_dentry_version(logrecord, dentry->d_parent);
1675 logrecord = log_version(logrecord, new_file_ver);
1676 logrecord = logit(logrecord, &lmode, sizeof(lmode));
1677 logrecord = logit(logrecord, &uid, sizeof(uid));
1678 logrecord = logit(logrecord, &gid, sizeof(gid));
1679 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1680 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
1681
1682 error = presto_log(fset, rec, record, size,
1683 path, size_round(le32_to_cpu(pathlen)),
1684 NULL, 0, NULL, 0);
1685
1686 BUFF_FREE(buffer);
1687 EXIT;
1688 return error;
1689 }
1690
presto_journal_symlink(struct rec_info * rec,struct presto_file_set * fset,struct dentry * dentry,const char * target,struct presto_version * tgt_dir_ver,struct presto_version * new_link_ver)1691 int presto_journal_symlink(struct rec_info *rec, struct presto_file_set *fset,
1692 struct dentry *dentry, const char *target,
1693 struct presto_version *tgt_dir_ver,
1694 struct presto_version *new_link_ver)
1695 {
1696 int opcode = KML_OPCODE_SYMLINK;
1697 char *buffer, *path, *logrecord, record[292];
1698 struct dentry *root;
1699 __u32 uid, gid, pathlen;
1700 __u32 targetlen = cpu_to_le32(strlen(target));
1701 int error, size;
1702
1703 ENTRY;
1704 if ( presto_no_journal(fset) ) {
1705 EXIT;
1706 return 0;
1707 }
1708
1709 root = fset->fset_dentry;
1710
1711 uid = cpu_to_le32(dentry->d_inode->i_uid);
1712 gid = cpu_to_le32(dentry->d_inode->i_gid);
1713
1714 BUFF_ALLOC(buffer, NULL);
1715 path = presto_path(dentry, root, buffer, PAGE_SIZE);
1716 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1717 size = sizeof(__u32) * current->ngroups +
1718 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
1719 sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
1720 sizeof(targetlen) + sizeof(struct kml_suffix);
1721
1722 if ( size > sizeof(record) )
1723 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1724
1725 rec->is_kml = 1;
1726 rec->size = size + size_round(le32_to_cpu(pathlen)) +
1727 size_round(le32_to_cpu(targetlen));
1728
1729 logrecord = journal_log_prefix(record, opcode, rec);
1730 logrecord = log_version(logrecord, tgt_dir_ver);
1731 logrecord = log_dentry_version(logrecord, dentry->d_parent);
1732 logrecord = log_version(logrecord, new_link_ver);
1733 logrecord = logit(logrecord, &uid, sizeof(uid));
1734 logrecord = logit(logrecord, &gid, sizeof(gid));
1735 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1736 logrecord = logit(logrecord, &targetlen, sizeof(targetlen));
1737 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
1738
1739 error = presto_log(fset, rec, record, size,
1740 path, size_round(le32_to_cpu(pathlen)),
1741 target, size_round(le32_to_cpu(targetlen)),
1742 NULL, 0);
1743
1744 BUFF_FREE(buffer);
1745 EXIT;
1746 return error;
1747 }
1748
presto_journal_mkdir(struct rec_info * rec,struct presto_file_set * fset,struct dentry * dentry,struct presto_version * tgt_dir_ver,struct presto_version * new_dir_ver,int mode)1749 int presto_journal_mkdir(struct rec_info *rec, struct presto_file_set *fset,
1750 struct dentry *dentry,
1751 struct presto_version *tgt_dir_ver,
1752 struct presto_version *new_dir_ver, int mode)
1753 {
1754 int opcode = KML_OPCODE_MKDIR;
1755 char *buffer, *path, *logrecord, record[292];
1756 struct dentry *root;
1757 __u32 uid, gid, lmode, pathlen;
1758 int error, size;
1759
1760 ENTRY;
1761 if ( presto_no_journal(fset) ) {
1762 EXIT;
1763 return 0;
1764 }
1765
1766 root = fset->fset_dentry;
1767
1768 uid = cpu_to_le32(dentry->d_inode->i_uid);
1769 gid = cpu_to_le32(dentry->d_inode->i_gid);
1770 lmode = cpu_to_le32(mode);
1771
1772 BUFF_ALLOC(buffer, NULL);
1773 path = presto_path(dentry, root, buffer, PAGE_SIZE);
1774 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1775 size = sizeof(__u32) * current->ngroups +
1776 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
1777 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
1778 sizeof(struct kml_suffix);
1779
1780 if ( size > sizeof(record) )
1781 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1782
1783 rec->is_kml = 1;
1784 rec->size = size + size_round(le32_to_cpu(pathlen));
1785 logrecord = journal_log_prefix(record, opcode, rec);
1786
1787 logrecord = log_version(logrecord, tgt_dir_ver);
1788 logrecord = log_dentry_version(logrecord, dentry->d_parent);
1789 logrecord = log_version(logrecord, new_dir_ver);
1790 logrecord = logit(logrecord, &lmode, sizeof(lmode));
1791 logrecord = logit(logrecord, &uid, sizeof(uid));
1792 logrecord = logit(logrecord, &gid, sizeof(gid));
1793 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1794 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
1795
1796 error = presto_log(fset, rec, record, size,
1797 path, size_round(le32_to_cpu(pathlen)),
1798 NULL, 0, NULL, 0);
1799
1800 BUFF_FREE(buffer);
1801 EXIT;
1802 return error;
1803 }
1804
1805
1806 int
presto_journal_rmdir(struct rec_info * rec,struct presto_file_set * fset,struct dentry * dir,struct presto_version * tgt_dir_ver,struct presto_version * old_dir_ver,struct izo_rollback_data * rb,int len,const char * name)1807 presto_journal_rmdir(struct rec_info *rec, struct presto_file_set *fset,
1808 struct dentry *dir, struct presto_version *tgt_dir_ver,
1809 struct presto_version *old_dir_ver,
1810 struct izo_rollback_data *rb, int len, const char *name)
1811 {
1812 int opcode = KML_OPCODE_RMDIR;
1813 char *buffer, *path, *logrecord, record[316];
1814 __u32 pathlen, llen;
1815 struct dentry *root;
1816 int error, size;
1817
1818 ENTRY;
1819 if ( presto_no_journal(fset) ) {
1820 EXIT;
1821 return 0;
1822 }
1823
1824 root = fset->fset_dentry;
1825
1826 llen = cpu_to_le32(len);
1827 BUFF_ALLOC(buffer, NULL);
1828 path = presto_path(dir, root, buffer, PAGE_SIZE);
1829 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1830 size = sizeof(__u32) * current->ngroups +
1831 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
1832 sizeof(pathlen) + sizeof(llen) + sizeof(*rb) +
1833 sizeof(struct kml_suffix);
1834
1835 if ( size > sizeof(record) )
1836 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1837
1838 CDEBUG(D_JOURNAL, "path: %s (%d), name: %s (%d), size %d\n",
1839 path, pathlen, name, len, size);
1840
1841 rec->is_kml = 1;
1842 rec->size = size + size_round(le32_to_cpu(pathlen)) +
1843 size_round(len);
1844
1845 logrecord = journal_log_prefix(record, opcode, rec);
1846 logrecord = log_version(logrecord, tgt_dir_ver);
1847 logrecord = log_dentry_version(logrecord, dir);
1848 logrecord = log_version(logrecord, old_dir_ver);
1849 logrecord = logit(logrecord, rb, sizeof(*rb));
1850 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1851 logrecord = logit(logrecord, &llen, sizeof(llen));
1852 logrecord = journal_log_suffix(logrecord, record, fset, dir, rec);
1853 error = presto_log(fset, rec, record, size,
1854 path, size_round(le32_to_cpu(pathlen)),
1855 name, size_round(len),
1856 NULL, 0);
1857
1858 BUFF_FREE(buffer);
1859 EXIT;
1860 return error;
1861 }
1862
1863
1864 int
presto_journal_mknod(struct rec_info * rec,struct presto_file_set * fset,struct dentry * dentry,struct presto_version * tgt_dir_ver,struct presto_version * new_node_ver,int mode,int dmajor,int dminor)1865 presto_journal_mknod(struct rec_info *rec, struct presto_file_set *fset,
1866 struct dentry *dentry, struct presto_version *tgt_dir_ver,
1867 struct presto_version *new_node_ver, int mode,
1868 int dmajor, int dminor )
1869 {
1870 int opcode = KML_OPCODE_MKNOD;
1871 char *buffer, *path, *logrecord, record[292];
1872 struct dentry *root;
1873 __u32 uid, gid, lmode, lmajor, lminor, pathlen;
1874 int error, size;
1875
1876 ENTRY;
1877 if ( presto_no_journal(fset) ) {
1878 EXIT;
1879 return 0;
1880 }
1881
1882 root = fset->fset_dentry;
1883
1884 uid = cpu_to_le32(dentry->d_inode->i_uid);
1885 gid = cpu_to_le32(dentry->d_inode->i_gid);
1886 lmode = cpu_to_le32(mode);
1887 lmajor = cpu_to_le32(dmajor);
1888 lminor = cpu_to_le32(dminor);
1889
1890 BUFF_ALLOC(buffer, NULL);
1891 path = presto_path(dentry, root, buffer, PAGE_SIZE);
1892 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1893 size = sizeof(__u32) * current->ngroups +
1894 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
1895 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(lmajor) +
1896 sizeof(lminor) + sizeof(pathlen) +
1897 sizeof(struct kml_suffix);
1898
1899 if ( size > sizeof(record) )
1900 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1901
1902 rec->is_kml = 1;
1903 rec->size = size + size_round(le32_to_cpu(pathlen));
1904
1905 logrecord = journal_log_prefix(record, opcode, rec);
1906 logrecord = log_version(logrecord, tgt_dir_ver);
1907 logrecord = log_dentry_version(logrecord, dentry->d_parent);
1908 logrecord = log_version(logrecord, new_node_ver);
1909 logrecord = logit(logrecord, &lmode, sizeof(lmode));
1910 logrecord = logit(logrecord, &uid, sizeof(uid));
1911 logrecord = logit(logrecord, &gid, sizeof(gid));
1912 logrecord = logit(logrecord, &lmajor, sizeof(lmajor));
1913 logrecord = logit(logrecord, &lminor, sizeof(lminor));
1914 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1915 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
1916
1917 error = presto_log(fset, rec, record, size,
1918 path, size_round(le32_to_cpu(pathlen)),
1919 NULL, 0, NULL, 0);
1920
1921 BUFF_FREE(buffer);
1922 EXIT;
1923 return error;
1924 }
1925
1926 int
presto_journal_link(struct rec_info * rec,struct presto_file_set * fset,struct dentry * src,struct dentry * tgt,struct presto_version * tgt_dir_ver,struct presto_version * new_link_ver)1927 presto_journal_link(struct rec_info *rec, struct presto_file_set *fset,
1928 struct dentry *src, struct dentry *tgt,
1929 struct presto_version *tgt_dir_ver,
1930 struct presto_version *new_link_ver)
1931 {
1932 int opcode = KML_OPCODE_LINK;
1933 char *buffer, *srcbuffer, *path, *srcpath, *logrecord, record[292];
1934 __u32 pathlen, srcpathlen;
1935 struct dentry *root;
1936 int error, size;
1937
1938 ENTRY;
1939 if ( presto_no_journal(fset) ) {
1940 EXIT;
1941 return 0;
1942 }
1943
1944 root = fset->fset_dentry;
1945
1946 BUFF_ALLOC(srcbuffer, NULL);
1947 srcpath = presto_path(src, root, srcbuffer, PAGE_SIZE);
1948 srcpathlen = cpu_to_le32(MYPATHLEN(srcbuffer, srcpath));
1949
1950 BUFF_ALLOC(buffer, srcbuffer);
1951 path = presto_path(tgt, root, buffer, PAGE_SIZE);
1952 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
1953 size = sizeof(__u32) * current->ngroups +
1954 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
1955 sizeof(srcpathlen) + sizeof(pathlen) +
1956 sizeof(struct kml_suffix);
1957
1958 if ( size > sizeof(record) )
1959 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
1960
1961 rec->is_kml = 1;
1962 rec->size = size + size_round(le32_to_cpu(pathlen)) +
1963 size_round(le32_to_cpu(srcpathlen));
1964
1965 logrecord = journal_log_prefix(record, opcode, rec);
1966 logrecord = log_version(logrecord, tgt_dir_ver);
1967 logrecord = log_dentry_version(logrecord, tgt->d_parent);
1968 logrecord = log_version(logrecord, new_link_ver);
1969 logrecord = logit(logrecord, &srcpathlen, sizeof(srcpathlen));
1970 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
1971 logrecord = journal_log_suffix(logrecord, record, fset, tgt, rec);
1972
1973 error = presto_log(fset, rec, record, size,
1974 srcpath, size_round(le32_to_cpu(srcpathlen)),
1975 path, size_round(le32_to_cpu(pathlen)),
1976 NULL, 0);
1977
1978 BUFF_FREE(srcbuffer);
1979 BUFF_FREE(buffer);
1980 EXIT;
1981 return error;
1982 }
1983
1984
presto_journal_rename(struct rec_info * rec,struct presto_file_set * fset,struct dentry * src,struct dentry * tgt,struct presto_version * src_dir_ver,struct presto_version * tgt_dir_ver)1985 int presto_journal_rename(struct rec_info *rec, struct presto_file_set *fset,
1986 struct dentry *src, struct dentry *tgt,
1987 struct presto_version *src_dir_ver,
1988 struct presto_version *tgt_dir_ver)
1989 {
1990 int opcode = KML_OPCODE_RENAME;
1991 char *buffer, *srcbuffer, *path, *srcpath, *logrecord, record[292];
1992 __u32 pathlen, srcpathlen;
1993 struct dentry *root;
1994 int error, size;
1995
1996 ENTRY;
1997 if ( presto_no_journal(fset) ) {
1998 EXIT;
1999 return 0;
2000 }
2001
2002 root = fset->fset_dentry;
2003
2004 BUFF_ALLOC(srcbuffer, NULL);
2005 srcpath = presto_path(src, root, srcbuffer, PAGE_SIZE);
2006 srcpathlen = cpu_to_le32(MYPATHLEN(srcbuffer, srcpath));
2007
2008 BUFF_ALLOC(buffer, srcbuffer);
2009 path = presto_path(tgt, root, buffer, PAGE_SIZE);
2010 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
2011 size = sizeof(__u32) * current->ngroups +
2012 sizeof(struct kml_prefix_hdr) + 4 * sizeof(*src_dir_ver) +
2013 sizeof(srcpathlen) + sizeof(pathlen) +
2014 sizeof(struct kml_suffix);
2015
2016 if ( size > sizeof(record) )
2017 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
2018
2019 rec->is_kml = 1;
2020 rec->size = size + size_round(le32_to_cpu(pathlen)) +
2021 size_round(le32_to_cpu(srcpathlen));
2022
2023 logrecord = journal_log_prefix(record, opcode, rec);
2024 logrecord = log_version(logrecord, src_dir_ver);
2025 logrecord = log_dentry_version(logrecord, src->d_parent);
2026 logrecord = log_version(logrecord, tgt_dir_ver);
2027 logrecord = log_dentry_version(logrecord, tgt->d_parent);
2028 logrecord = logit(logrecord, &srcpathlen, sizeof(srcpathlen));
2029 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
2030 logrecord = journal_log_suffix(logrecord, record, fset, tgt, rec);
2031
2032 error = presto_log(fset, rec, record, size,
2033 srcpath, size_round(le32_to_cpu(srcpathlen)),
2034 path, size_round(le32_to_cpu(pathlen)),
2035 NULL, 0);
2036
2037 BUFF_FREE(buffer);
2038 BUFF_FREE(srcbuffer);
2039 EXIT;
2040 return error;
2041 }
2042
presto_journal_unlink(struct rec_info * rec,struct presto_file_set * fset,struct dentry * dir,struct presto_version * tgt_dir_ver,struct presto_version * old_file_ver,struct izo_rollback_data * rb,struct dentry * dentry,char * old_target,int old_targetlen)2043 int presto_journal_unlink(struct rec_info *rec, struct presto_file_set *fset,
2044 struct dentry *dir, struct presto_version *tgt_dir_ver,
2045 struct presto_version *old_file_ver,
2046 struct izo_rollback_data *rb, struct dentry *dentry,
2047 char *old_target, int old_targetlen)
2048 {
2049 int opcode = KML_OPCODE_UNLINK;
2050 char *buffer, *path, *logrecord, record[316];
2051 const char *name;
2052 __u32 pathlen, llen;
2053 struct dentry *root;
2054 int error, size, len;
2055
2056 ENTRY;
2057 if ( presto_no_journal(fset) ) {
2058 EXIT;
2059 return 0;
2060 }
2061
2062 root = fset->fset_dentry;
2063
2064 name = dentry->d_name.name;
2065 len = dentry->d_name.len;
2066
2067 llen = cpu_to_le32(len);
2068 BUFF_ALLOC(buffer, NULL);
2069 path = presto_path(dir, root, buffer, PAGE_SIZE);
2070 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
2071 size = sizeof(__u32) * current->ngroups +
2072 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
2073 sizeof(pathlen) + sizeof(llen) + sizeof(*rb) +
2074 sizeof(old_targetlen) + sizeof(struct kml_suffix);
2075
2076 if ( size > sizeof(record) )
2077 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
2078
2079 rec->is_kml = 1;
2080 rec->size = size + size_round(le32_to_cpu(pathlen)) + size_round(len) +
2081 size_round(old_targetlen);
2082
2083 logrecord = journal_log_prefix(record, opcode, rec);
2084 logrecord = log_version(logrecord, tgt_dir_ver);
2085 logrecord = log_dentry_version(logrecord, dir);
2086 logrecord = log_version(logrecord, old_file_ver);
2087 logrecord = log_rollback(logrecord, rb);
2088 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
2089 logrecord = logit(logrecord, &llen, sizeof(llen));
2090 logrecord = logit(logrecord, &old_targetlen, sizeof(old_targetlen));
2091 logrecord = journal_log_suffix(logrecord, record, fset, dir, rec);
2092
2093 error = presto_log(fset, rec, record, size,
2094 path, size_round(le32_to_cpu(pathlen)),
2095 name, size_round(len),
2096 old_target, size_round(old_targetlen));
2097
2098 BUFF_FREE(buffer);
2099 EXIT;
2100 return error;
2101 }
2102
2103 int
presto_journal_close(struct rec_info * rec,struct presto_file_set * fset,struct file * file,struct dentry * dentry,struct presto_version * old_file_ver,struct presto_version * new_file_ver)2104 presto_journal_close(struct rec_info *rec, struct presto_file_set *fset,
2105 struct file *file, struct dentry *dentry,
2106 struct presto_version *old_file_ver,
2107 struct presto_version *new_file_ver)
2108 {
2109 int opcode = KML_OPCODE_CLOSE;
2110 struct presto_file_data *fd;
2111 char *buffer, *path, *logrecord, record[316];
2112 struct dentry *root;
2113 int error, size, i;
2114 __u32 pathlen, generation;
2115 __u64 ino;
2116 __u32 open_fsuid;
2117 __u32 open_fsgid;
2118 __u32 open_ngroups;
2119 __u32 open_groups[NGROUPS_MAX];
2120 __u32 open_mode;
2121 __u32 open_uid;
2122 __u32 open_gid;
2123
2124 ENTRY;
2125
2126 if ( presto_no_journal(fset) ) {
2127 EXIT;
2128 return 0;
2129 }
2130
2131 if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0)
2132 || ((dentry->d_parent != dentry) && list_empty(&dentry->d_hash))) {
2133 EXIT;
2134 return 0;
2135 }
2136
2137 root = fset->fset_dentry;
2138
2139 fd = (struct presto_file_data *)file->private_data;
2140 if (fd) {
2141 open_ngroups = fd->fd_ngroups;
2142 for (i = 0; i < fd->fd_ngroups; i++)
2143 open_groups[i] = (__u32) fd->fd_groups[i];
2144 open_mode = fd->fd_mode;
2145 open_uid = fd->fd_uid;
2146 open_gid = fd->fd_gid;
2147 open_fsuid = fd->fd_fsuid;
2148 open_fsgid = fd->fd_fsgid;
2149 } else {
2150 open_ngroups = current->ngroups;
2151 for (i=0; i<current->ngroups; i++)
2152 open_groups[i] = (__u32) current->groups[i];
2153 open_mode = dentry->d_inode->i_mode;
2154 open_uid = dentry->d_inode->i_uid;
2155 open_gid = dentry->d_inode->i_gid;
2156 open_fsuid = current->fsuid;
2157 open_fsgid = current->fsgid;
2158 }
2159 BUFF_ALLOC(buffer, NULL);
2160 path = presto_path(dentry, root, buffer, PAGE_SIZE);
2161 pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
2162 ino = cpu_to_le64(dentry->d_inode->i_ino);
2163 generation = cpu_to_le32(dentry->d_inode->i_generation);
2164 size = sizeof(__u32) * open_ngroups +
2165 sizeof(open_mode) + sizeof(open_uid) + sizeof(open_gid) +
2166 sizeof(struct kml_prefix_hdr) + sizeof(*old_file_ver) +
2167 sizeof(*new_file_ver) + sizeof(ino) + sizeof(generation) +
2168 sizeof(pathlen) + sizeof(struct kml_suffix);
2169
2170 if ( size > sizeof(record) )
2171 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
2172
2173 rec->is_kml = 1;
2174 rec->size = size + size_round(le32_to_cpu(pathlen));
2175
2176 logrecord = journal_log_prefix_with_groups_and_ids(
2177 record, opcode, rec, open_ngroups, open_groups,
2178 open_fsuid, open_fsgid);
2179 logrecord = logit(logrecord, &open_mode, sizeof(open_mode));
2180 logrecord = logit(logrecord, &open_uid, sizeof(open_uid));
2181 logrecord = logit(logrecord, &open_gid, sizeof(open_gid));
2182 logrecord = log_version(logrecord, old_file_ver);
2183 logrecord = log_version(logrecord, new_file_ver);
2184 logrecord = logit(logrecord, &ino, sizeof(ino));
2185 logrecord = logit(logrecord, &generation, sizeof(generation));
2186 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
2187 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
2188
2189 error = presto_log(fset, rec, record, size,
2190 path, size_round(le32_to_cpu(pathlen)),
2191 NULL, 0, NULL, 0);
2192 BUFF_FREE(buffer);
2193
2194 EXIT;
2195 return error;
2196 }
2197
presto_rewrite_close(struct rec_info * rec,struct presto_file_set * fset,char * path,__u32 pathlen,int ngroups,__u32 * groups,__u64 ino,__u32 generation,struct presto_version * new_file_ver)2198 int presto_rewrite_close(struct rec_info *rec, struct presto_file_set *fset,
2199 char *path, __u32 pathlen,
2200 int ngroups, __u32 *groups,
2201 __u64 ino, __u32 generation,
2202 struct presto_version *new_file_ver)
2203 {
2204 int opcode = KML_OPCODE_CLOSE;
2205 char *logrecord, record[292];
2206 struct dentry *root;
2207 int error, size;
2208
2209 ENTRY;
2210
2211 if ( presto_no_journal(fset) ) {
2212 EXIT;
2213 return 0;
2214 }
2215
2216 root = fset->fset_dentry;
2217
2218 size = sizeof(__u32) * ngroups +
2219 sizeof(struct kml_prefix_hdr) + sizeof(*new_file_ver) +
2220 sizeof(ino) + sizeof(generation) +
2221 sizeof(le32_to_cpu(pathlen)) +
2222 sizeof(struct kml_suffix);
2223
2224 if ( size > sizeof(record) )
2225 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
2226
2227 rec->is_kml = 1;
2228 rec->size = size + size_round(le32_to_cpu(pathlen));
2229
2230 logrecord = journal_log_prefix_with_groups(record, opcode, rec,
2231 ngroups, groups);
2232 logrecord = log_version(logrecord, new_file_ver);
2233 logrecord = logit(logrecord, &ino, sizeof(ino));
2234 logrecord = logit(logrecord, &generation, sizeof(generation));
2235 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
2236 logrecord = journal_log_suffix(logrecord, record, fset, NULL, rec);
2237
2238 error = presto_log(fset, rec, record, size,
2239 path, size_round(le32_to_cpu(pathlen)),
2240 NULL, 0, NULL, 0);
2241
2242 EXIT;
2243 return error;
2244 }
2245
2246
2247 /* write closes for the local close records in the LML */
presto_complete_lml(struct presto_file_set * fset)2248 int presto_complete_lml(struct presto_file_set *fset)
2249 {
2250 __u32 groups[NGROUPS_MAX];
2251 loff_t lml_offset;
2252 loff_t read_offset;
2253 char *buffer;
2254 void *handle;
2255 struct rec_info rec;
2256 struct close_rec {
2257 struct presto_version new_file_ver;
2258 __u64 ino;
2259 __u32 generation;
2260 __u32 pathlen;
2261 __u64 remote_ino;
2262 __u32 remote_generation;
2263 __u32 remote_version;
2264 __u64 lml_offset;
2265 } close_rec;
2266 struct file *file = fset->fset_lml.fd_file;
2267 struct kml_prefix_hdr prefix;
2268 int rc = 0;
2269 ENTRY;
2270
2271 lml_offset = 0;
2272 again:
2273 if (lml_offset >= file->f_dentry->d_inode->i_size) {
2274 EXIT;
2275 return rc;
2276 }
2277
2278 read_offset = lml_offset;
2279 rc = presto_fread(file, (char *)&prefix,
2280 sizeof(prefix), &read_offset);
2281 if ( rc != sizeof(prefix) ) {
2282 EXIT;
2283 CERROR("presto_complete_lml: ioerror - 1, tell Peter\n");
2284 return -EIO;
2285 }
2286
2287 if ( prefix.opcode == KML_OPCODE_NOOP ) {
2288 lml_offset += prefix.len;
2289 goto again;
2290 }
2291
2292 rc = presto_fread(file, (char *)groups,
2293 prefix.ngroups * sizeof(__u32), &read_offset);
2294 if ( rc != prefix.ngroups * sizeof(__u32) ) {
2295 EXIT;
2296 CERROR("presto_complete_lml: ioerror - 2, tell Peter\n");
2297 return -EIO;
2298 }
2299
2300 rc = presto_fread(file, (char *)&close_rec,
2301 sizeof(close_rec), &read_offset);
2302 if ( rc != sizeof(close_rec) ) {
2303 EXIT;
2304 CERROR("presto_complete_lml: ioerror - 3, tell Peter\n");
2305 return -EIO;
2306 }
2307
2308 /* is this a backfetch or a close record? */
2309 if ( le64_to_cpu(close_rec.remote_ino) != 0 ) {
2310 lml_offset += prefix.len;
2311 goto again;
2312 }
2313
2314 BUFF_ALLOC(buffer, NULL);
2315 rc = presto_fread(file, (char *)buffer,
2316 le32_to_cpu(close_rec.pathlen), &read_offset);
2317 if ( rc != le32_to_cpu(close_rec.pathlen) ) {
2318 EXIT;
2319 CERROR("presto_complete_lml: ioerror - 4, tell Peter\n");
2320 return -EIO;
2321 }
2322
2323 handle = presto_trans_start(fset, file->f_dentry->d_inode,
2324 KML_OPCODE_RELEASE);
2325 if ( IS_ERR(handle) ) {
2326 EXIT;
2327 return -ENOMEM;
2328 }
2329
2330 rc = presto_clear_lml_close(fset, lml_offset);
2331 if ( rc ) {
2332 CERROR("error during clearing: %d\n", rc);
2333 presto_trans_commit(fset, handle);
2334 EXIT;
2335 return rc;
2336 }
2337
2338 rc = presto_rewrite_close(&rec, fset, buffer, close_rec.pathlen,
2339 prefix.ngroups, groups,
2340 close_rec.ino, close_rec.generation,
2341 &close_rec.new_file_ver);
2342 if ( rc ) {
2343 CERROR("error during rewrite close: %d\n", rc);
2344 presto_trans_commit(fset, handle);
2345 EXIT;
2346 return rc;
2347 }
2348
2349 presto_trans_commit(fset, handle);
2350 if ( rc ) {
2351 CERROR("error during truncation: %d\n", rc);
2352 EXIT;
2353 return rc;
2354 }
2355
2356 lml_offset += prefix.len;
2357 CDEBUG(D_JOURNAL, "next LML record at: %ld\n", (long)lml_offset);
2358 goto again;
2359
2360 EXIT;
2361 return -EINVAL;
2362 }
2363
2364
2365 #ifdef CONFIG_FS_EXT_ATTR
2366 /* Journal an ea operation. A NULL buffer implies the attribute is
2367 * getting deleted. In this case we simply change the opcode, but nothing
2368 * else is affected.
2369 */
presto_journal_set_ext_attr(struct rec_info * rec,struct presto_file_set * fset,struct dentry * dentry,struct presto_version * ver,const char * name,const char * buffer,int buffer_len,int flags)2370 int presto_journal_set_ext_attr (struct rec_info *rec,
2371 struct presto_file_set *fset,
2372 struct dentry *dentry,
2373 struct presto_version *ver, const char *name,
2374 const char *buffer, int buffer_len,
2375 int flags)
2376 {
2377 int opcode = (buffer == NULL) ?
2378 KML_OPCODE_DELEXTATTR :
2379 KML_OPCODE_SETEXTATTR ;
2380 char *temp, *path, *logrecord, record[292];
2381 struct dentry *root;
2382 int error, size;
2383 __u32 namelen=cpu_to_le32(strnlen(name,PRESTO_EXT_ATTR_NAME_MAX));
2384 __u32 buflen=(buffer != NULL)? cpu_to_le32(buffer_len): cpu_to_le32(0);
2385 __u32 mode, pathlen;
2386
2387 ENTRY;
2388 if ( presto_no_journal(fset) ) {
2389 EXIT;
2390 return 0;
2391 }
2392
2393 if (!dentry->d_inode || (dentry->d_inode->i_nlink == 0)
2394 || ((dentry->d_parent != dentry) && list_empty(&dentry->d_hash))) {
2395 EXIT;
2396 return 0;
2397 }
2398
2399 root = fset->fset_dentry;
2400
2401 BUFF_ALLOC(temp, NULL);
2402 path = presto_path(dentry, root, temp, PAGE_SIZE);
2403 pathlen = cpu_to_le32(MYPATHLEN(temp, path));
2404
2405 flags=cpu_to_le32(flags);
2406 /* Ugly, but needed. posix ACLs change the mode without using
2407 * setattr, we need to record these changes. The EA code per se
2408 * is not really affected.
2409 */
2410 mode=cpu_to_le32(dentry->d_inode->i_mode);
2411
2412 size = sizeof(__u32) * current->ngroups +
2413 sizeof(struct kml_prefix_hdr) +
2414 2 * sizeof(struct presto_version) +
2415 sizeof(flags) + sizeof(mode) + sizeof(namelen) +
2416 sizeof(buflen) + sizeof(pathlen) +
2417 sizeof(struct kml_suffix);
2418
2419 if ( size > sizeof(record) )
2420 CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
2421
2422 rec->is_kml = 1;
2423 /* Make space for a path, a attr name and value*/
2424 /* We use the buflen instead of buffer_len to make sure that we
2425 * journal the right length. This may be a little paranoid, but
2426 * with 64 bits round the corner, I would rather be safe than sorry!
2427 * Also this handles deletes with non-zero buffer_lengths correctly.
2428 * SHP
2429 */
2430 rec->size = size + size_round(le32_to_cpu(pathlen)) +
2431 size_round(le32_to_cpu(namelen)) +
2432 size_round(le32_to_cpu(buflen));
2433
2434 logrecord = journal_log_prefix(record, opcode, rec);
2435 logrecord = log_version(logrecord, ver);
2436 logrecord = log_dentry_version(logrecord, dentry);
2437 logrecord = logit(logrecord, &flags, sizeof(flags));
2438 logrecord = logit(logrecord, &mode, sizeof(flags));
2439 logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
2440 logrecord = logit(logrecord, &namelen, sizeof(namelen));
2441 logrecord = logit(logrecord, &buflen, sizeof(buflen));
2442 logrecord = journal_log_suffix(logrecord, record, fset, dentry, rec);
2443
2444 error = presto_log(fset, rec, record, size,
2445 path, size_round(le32_to_cpu(pathlen)),
2446 name, size_round(le32_to_cpu(namelen)),
2447 buffer, size_round(le32_to_cpu(buflen)));
2448
2449 BUFF_FREE(temp);
2450 EXIT;
2451 return error;
2452 }
2453 #endif
2454