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