1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2001, 2002 Cluster File Systems, Inc.
5  *  Copyright (C) 2000 Stelias Computing, Inc.
6  *  Copyright (C) 2000 Red Hat, Inc.
7  *
8  *   This file is part of InterMezzo, http://www.inter-mezzo.org.
9  *
10  *   InterMezzo is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   InterMezzo is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with InterMezzo; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  * vfs.c
24  *
25  * This file implements kernel downcalls from lento.
26  *
27  * Author: Rob Simmonds <simmonds@stelias.com>
28  *         Andreas Dilger <adilger@stelias.com>
29  * Copyright (C) 2000 Stelias Computing Inc
30  * Copyright (C) 2000 Red Hat Inc.
31  *
32  * Extended attribute support
33  * Copyright (C) 2001 Shirish H. Phatak, Tacit Networks, Inc.
34  *
35  * This code is based on code from namei.c in the linux file system;
36  * see copyright notice below.
37  */
38 
39 /** namei.c copyright **/
40 
41 /*
42  *  linux/fs/namei.c
43  *
44  *  Copyright (C) 1991, 1992  Linus Torvalds
45  */
46 
47 /*
48  * Some corrections by tytso.
49  */
50 
51 /* [Feb 1997 T. Schoebel-Theuer] Complete rewrite of the pathname
52  * lookup logic.
53  */
54 
55 /** end of namei.c copyright **/
56 
57 #include <linux/mm.h>
58 #include <linux/proc_fs.h>
59 #include <linux/smp_lock.h>
60 #include <linux/quotaops.h>
61 
62 #include <asm/uaccess.h>
63 #include <asm/unaligned.h>
64 #include <asm/semaphore.h>
65 #include <asm/pgtable.h>
66 
67 #include <linux/file.h>
68 #include <linux/fs.h>
69 #include <linux/blk.h>
70 
71 #include <linux/intermezzo_fs.h>
72 #include <linux/intermezzo_psdev.h>
73 
74 #ifdef CONFIG_FS_EXT_ATTR
75 # include <linux/ext_attr.h>
76 
77 # ifdef CONFIG_FS_POSIX_ACL
78 #  include <linux/posix_acl.h>
79 # endif
80 #endif
81 
82 extern struct inode_operations presto_sym_iops;
83 
84 /* Write the last_rcvd values to the last_rcvd file.  We don't know what the
85  * UUID or last_ctime values are, so we have to read from the file first
86  * (sigh).
87  * exported for branch_reinter in kml_reint.c*/
presto_write_last_rcvd(struct rec_info * recinfo,struct presto_file_set * fset,struct lento_vfs_context * info)88 int presto_write_last_rcvd(struct rec_info *recinfo,
89                            struct presto_file_set *fset,
90                            struct lento_vfs_context *info)
91 {
92         int rc;
93         struct izo_rcvd_rec rcvd_rec;
94 
95         ENTRY;
96 
97         memset(&rcvd_rec, 0, sizeof(rcvd_rec));
98         memcpy(rcvd_rec.lr_uuid, info->uuid, sizeof(rcvd_rec.lr_uuid));
99         rcvd_rec.lr_remote_recno = HTON__u64(info->recno);
100         rcvd_rec.lr_remote_offset = HTON__u64(info->kml_offset);
101         rcvd_rec.lr_local_recno = HTON__u64(recinfo->recno);
102         rcvd_rec.lr_local_offset = HTON__u64(recinfo->offset + recinfo->size);
103 
104         rc = izo_rcvd_write(fset, &rcvd_rec);
105         if (rc < 0) {
106                 /* izo_rcvd_write returns negative errors and non-negative
107                  * offsets */
108                 CERROR("InterMezzo: izo_rcvd_write failed: %d\n", rc);
109                 EXIT;
110                 return rc;
111         }
112         EXIT;
113         return 0;
114 }
115 
116 /*
117  * It's inline, so penalty for filesystems that don't use sticky bit is
118  * minimal.
119  */
check_sticky(struct inode * dir,struct inode * inode)120 static inline int check_sticky(struct inode *dir, struct inode *inode)
121 {
122         if (!(dir->i_mode & S_ISVTX))
123                 return 0;
124         if (inode->i_uid == current->fsuid)
125                 return 0;
126         if (dir->i_uid == current->fsuid)
127                 return 0;
128         return !capable(CAP_FOWNER);
129 }
130 
131 /* from linux/fs/namei.c */
may_delete(struct inode * dir,struct dentry * victim,int isdir)132 static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
133 {
134         int error;
135         if (!victim->d_inode || victim->d_parent->d_inode != dir)
136                 return -ENOENT;
137         error = permission(dir,MAY_WRITE | MAY_EXEC);
138         if (error)
139                 return error;
140         if (IS_APPEND(dir))
141                 return -EPERM;
142         if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||
143             IS_IMMUTABLE(victim->d_inode))
144                 return -EPERM;
145         if (isdir) {
146                 if (!S_ISDIR(victim->d_inode->i_mode))
147                         return -ENOTDIR;
148                 if (IS_ROOT(victim))
149                         return -EBUSY;
150         } else if (S_ISDIR(victim->d_inode->i_mode))
151                 return -EISDIR;
152         return 0;
153 }
154 
155 /* from linux/fs/namei.c */
may_create(struct inode * dir,struct dentry * child)156 static inline int may_create(struct inode *dir, struct dentry *child) {
157         if (child->d_inode)
158                 return -EEXIST;
159         if (IS_DEADDIR(dir))
160                 return -ENOENT;
161         return permission(dir,MAY_WRITE | MAY_EXEC);
162 }
163 
164 #ifdef PRESTO_DEBUG
165 /* The loop_discard_io() function is available via a kernel patch to the
166  * loop block device.  It "works" by accepting writes, but throwing them
167  * away, rather than trying to write them to disk.  The old method worked
168  * by setting the underlying device read-only, but that has the problem
169  * that dirty buffers are kept in memory, and ext3 didn't like that at all.
170  */
171 #ifdef CONFIG_LOOP_DISCARD
172 #define BLKDEV_FAIL(dev,fail) loop_discard_io(dev,fail)
173 #else
174 #define BLKDEV_FAIL(dev,fail) set_device_ro(dev, 1)
175 #endif
176 
177 /* If a breakpoint has been set via /proc/sys/intermezzo/intermezzoX/errorval,
178  * that is the same as "value", the underlying device will "fail" now.
179  */
presto_debug_fail_blkdev(struct presto_file_set * fset,unsigned long value)180 inline void presto_debug_fail_blkdev(struct presto_file_set *fset,
181                                      unsigned long value)
182 {
183         int minor = presto_f2m(fset);
184         int errorval = izo_channels[minor].uc_errorval;
185         kdev_t dev = fset->fset_dentry->d_inode->i_dev;
186 
187         if (errorval && errorval == (long)value && !is_read_only(dev)) {
188                 CDEBUG(D_SUPER, "setting device %s read only\n", kdevname(dev));
189                 BLKDEV_FAIL(dev, 1);
190                 izo_channels[minor].uc_errorval = -dev;
191         }
192 }
193 #else
194 #define presto_debug_fail_blkdev(dev,value) do {} while (0)
195 #endif
196 
197 
presto_do_kml(struct lento_vfs_context * info,struct dentry * dentry)198 static inline int presto_do_kml(struct lento_vfs_context *info,
199                                 struct dentry *dentry)
200 {
201         if ( ! (info->flags & LENTO_FL_KML) )
202                 return 0;
203         if ( presto_chk(dentry, PRESTO_DONT_JOURNAL) )
204                 return 0;
205         return 1;
206 }
207 
presto_do_rcvd(struct lento_vfs_context * info,struct dentry * dentry)208 static inline int presto_do_rcvd(struct lento_vfs_context *info,
209                                  struct dentry *dentry)
210 {
211         if ( ! (info->flags & LENTO_FL_EXPECT) )
212                 return 0;
213         if ( presto_chk(dentry, PRESTO_DONT_JOURNAL) )
214                 return 0;
215         return 1;
216 }
217 
218 
219 /* XXX fixme: this should not fail, all these dentries are in memory
220    when _we_ call this */
presto_settime(struct presto_file_set * fset,struct dentry * newobj,struct dentry * parent,struct dentry * target,struct lento_vfs_context * ctx,int valid)221 int presto_settime(struct presto_file_set *fset,
222                    struct dentry *newobj,
223                    struct dentry *parent,
224                    struct dentry *target,
225                    struct lento_vfs_context *ctx,
226                    int valid)
227 {
228         int error = 0;
229         struct dentry *dentry;
230         struct inode *inode;
231         struct inode_operations *iops;
232         struct iattr iattr;
233 
234         ENTRY;
235         if (ctx->flags &  LENTO_FL_IGNORE_TIME ) {
236                 EXIT;
237                 return 0;
238         }
239 
240         iattr.ia_ctime = ctx->updated_time;
241         iattr.ia_mtime = ctx->updated_time;
242         iattr.ia_valid = valid;
243 
244         while (1) {
245                 if (parent && ctx->flags & LENTO_FL_TOUCH_PARENT) {
246                         dentry = parent;
247                         parent = NULL;
248                 } else if (newobj && ctx->flags & LENTO_FL_TOUCH_NEWOBJ) {
249                         dentry = newobj;
250                         newobj = NULL;
251                 } else if (target) {
252                         dentry = target;
253                         target = NULL;
254                 } else
255                         break;
256 
257                 inode = dentry->d_inode;
258 
259                 error = -EROFS;
260                 if (IS_RDONLY(inode)) {
261                         EXIT;
262                         return -EROFS;
263                 }
264 
265                 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
266                         EXIT;
267                         return -EPERM;
268                 }
269 
270                 error = -EPERM;
271                 iops = filter_c2cdiops(fset->fset_cache->cache_filter);
272                 if (!iops) {
273                         EXIT;
274                         return error;
275                 }
276 
277                 if (iops->setattr != NULL)
278                         error = iops->setattr(dentry, &iattr);
279                 else {
280                         error = 0;
281                         inode_setattr(dentry->d_inode, &iattr);
282                 }
283         }
284         EXIT;
285         return error;
286 }
287 
izo_get_rollback_data(struct inode * inode,struct izo_rollback_data * rb)288 void izo_get_rollback_data(struct inode *inode, struct izo_rollback_data *rb)
289 {
290         rb->rb_mode = (__u32)inode->i_mode;
291         rb->rb_rdev = (__u32)inode->i_rdev;
292         rb->rb_uid  = (__u64)inode->i_uid;
293         rb->rb_gid  = (__u64)inode->i_gid;
294 }
295 
296 
presto_do_close(struct presto_file_set * fset,struct file * file)297 int presto_do_close(struct presto_file_set *fset, struct file *file)
298 {
299         struct rec_info rec;
300         int rc = -ENOSPC;
301         void *handle;
302         struct inode *inode = file->f_dentry->d_inode;
303         struct presto_file_data *fdata =
304                 (struct presto_file_data *)file->private_data;
305 
306         ENTRY;
307         presto_getversion(&fdata->fd_info.remote_version, inode);
308 
309         rc = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);
310         if (rc) {
311                 EXIT;
312                 return rc;
313         }
314 
315         handle = presto_trans_start(fset, file->f_dentry->d_inode,
316                                             KML_OPCODE_RELEASE);
317         if ( IS_ERR(handle) ) {
318                 CERROR("presto_release: no space for transaction\n");
319                 return rc;
320         }
321 
322         if (fdata->fd_info.flags & LENTO_FL_KML)
323                 rc = presto_journal_close(&rec, fset, file, file->f_dentry,
324                                           &fdata->fd_version,
325                                           &fdata->fd_info.remote_version);
326         if (rc) {
327                 CERROR("presto_close: cannot journal close\n");
328                 goto out;
329         }
330 
331         if (fdata->fd_info.flags & LENTO_FL_EXPECT)
332                 rc = presto_write_last_rcvd(&rec, fset, &fdata->fd_info);
333 
334         if (rc) {
335                 CERROR("presto_close: cannot journal last_rcvd\n");
336                 goto out;
337         }
338         presto_trans_commit(fset, handle);
339 
340         /* cancel the LML record */
341         handle = presto_trans_start(fset, inode, KML_OPCODE_WRITE);
342         if ( IS_ERR(handle) ) {
343                 CERROR("presto_release: no space for clear\n");
344                 return -ENOSPC;
345         }
346 
347         rc = presto_clear_lml_close(fset, fdata->fd_lml_offset);
348         if (rc < 0 ) {
349                 CERROR("presto_close: cannot journal close\n");
350                 goto out;
351         }
352         presto_truncate_lml(fset);
353 
354  out:
355         presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
356         presto_trans_commit(fset, handle);
357         EXIT;
358         return rc;
359 }
360 
presto_do_setattr(struct presto_file_set * fset,struct dentry * dentry,struct iattr * iattr,struct lento_vfs_context * info)361 int presto_do_setattr(struct presto_file_set *fset, struct dentry *dentry,
362                       struct iattr *iattr, struct lento_vfs_context *info)
363 {
364         struct rec_info rec;
365         struct inode *inode = dentry->d_inode;
366         struct inode_operations *iops;
367         int error;
368         struct presto_version old_ver, new_ver;
369         struct izo_rollback_data rb;
370         void *handle;
371         loff_t old_size=inode->i_size;
372 
373         ENTRY;
374         error = -EROFS;
375         if (IS_RDONLY(inode)) {
376                 EXIT;
377                 return -EROFS;
378         }
379 
380         if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
381                 EXIT;
382                 return -EPERM;
383         }
384 
385         presto_getversion(&old_ver, dentry->d_inode);
386         izo_get_rollback_data(dentry->d_inode, &rb);
387         error = -EPERM;
388         iops = filter_c2cdiops(fset->fset_cache->cache_filter);
389 
390         error = presto_reserve_space(fset->fset_cache, 2*PRESTO_REQHIGH);
391         if (error) {
392                 EXIT;
393                 return error;
394         }
395 
396         if  (iattr->ia_valid & ATTR_SIZE) {
397                 if (izo_mark_dentry(dentry, ~PRESTO_DATA, 0, NULL) != 0)
398                         CERROR("izo_mark_dentry(inode %ld, ~PRESTO_DATA) "
399                                "failed\n", dentry->d_inode->i_ino);
400                 handle = presto_trans_start(fset, dentry->d_inode,
401                                             KML_OPCODE_TRUNC);
402         } else {
403                 handle = presto_trans_start(fset, dentry->d_inode,
404                                             KML_OPCODE_SETATTR);
405         }
406 
407         if ( IS_ERR(handle) ) {
408                 CERROR("presto_do_setattr: no space for transaction\n");
409                 presto_release_space(fset->fset_cache, 2*PRESTO_REQHIGH);
410                 return -ENOSPC;
411         }
412 
413         if (dentry->d_inode && iops && iops->setattr) {
414                 error = iops->setattr(dentry, iattr);
415         } else {
416                 error = inode_change_ok(dentry->d_inode, iattr);
417                 if (!error)
418                         inode_setattr(inode, iattr);
419         }
420 
421         if (!error && (iattr->ia_valid & ATTR_SIZE))
422                 vmtruncate(inode, iattr->ia_size);
423 
424         if (error) {
425                 EXIT;
426                 goto exit;
427         }
428 
429         presto_debug_fail_blkdev(fset, KML_OPCODE_SETATTR | 0x10);
430 
431         if ( presto_do_kml(info, dentry) ) {
432                 if ((iattr->ia_valid & ATTR_SIZE) && (old_size != inode->i_size)) {
433                         struct file file;
434                         /* Journal a close whenever we see a potential truncate
435                         * At the receiving end, lento should explicitly remove
436                         * ATTR_SIZE from the list of valid attributes */
437                         presto_getversion(&new_ver, inode);
438                         file.private_data = NULL;
439                         file.f_dentry = dentry;
440                         error = presto_journal_close(&rec, fset, &file, dentry,
441                                                      &old_ver, &new_ver);
442                 }
443 
444                 if (!error)
445                         error = presto_journal_setattr(&rec, fset, dentry,
446                                                        &old_ver, &rb, iattr);
447         }
448 
449         presto_debug_fail_blkdev(fset, KML_OPCODE_SETATTR | 0x20);
450         if ( presto_do_rcvd(info, dentry) )
451                 error = presto_write_last_rcvd(&rec, fset, info);
452 
453         presto_debug_fail_blkdev(fset, KML_OPCODE_SETATTR | 0x30);
454 
455         EXIT;
456 exit:
457         presto_release_space(fset->fset_cache, 2*PRESTO_REQHIGH);
458         presto_trans_commit(fset, handle);
459         return error;
460 }
461 
lento_setattr(const char * name,struct iattr * iattr,struct lento_vfs_context * info)462 int lento_setattr(const char *name, struct iattr *iattr,
463                   struct lento_vfs_context *info)
464 {
465         struct nameidata nd;
466         struct dentry *dentry;
467         struct presto_file_set *fset;
468         int error;
469 #ifdef  CONFIG_FS_POSIX_ACL
470         int (*set_posix_acl)(struct inode *, int type, posix_acl_t *)=NULL;
471 #endif
472 
473         ENTRY;
474         CDEBUG(D_PIOCTL,"name %s, valid %#x, mode %#o, uid %d, gid %d, size %Ld\n",
475                name, iattr->ia_valid, iattr->ia_mode, iattr->ia_uid,
476                iattr->ia_gid, iattr->ia_size);
477         CDEBUG(D_PIOCTL, "atime %#lx, mtime %#lx, ctime %#lx, attr_flags %#x\n",
478                iattr->ia_atime, iattr->ia_mtime, iattr->ia_ctime,
479                iattr->ia_attr_flags);
480         CDEBUG(D_PIOCTL, "offset %d, recno %d, flags %#x\n",
481                info->slot_offset, info->recno, info->flags);
482 
483         lock_kernel();
484         error = presto_walk(name, &nd);
485         if (error) {
486                 EXIT;
487                 goto exit;
488         }
489         dentry = nd.dentry;
490 
491         fset = presto_fset(dentry);
492         error = -EINVAL;
493         if ( !fset ) {
494                 CERROR("No fileset!\n");
495                 EXIT;
496                 goto exit_lock;
497         }
498 
499         /* NOTE: this prevents us from changing the filetype on setattr,
500          *       as we normally only want to change permission bits.
501          *       If this is not correct, then we need to fix the perl code
502          *       to always send the file type OR'ed with the permission.
503          */
504         if (iattr->ia_valid & ATTR_MODE) {
505                 int set_mode = iattr->ia_mode;
506                 iattr->ia_mode = (iattr->ia_mode & S_IALLUGO) |
507                                  (dentry->d_inode->i_mode & ~S_IALLUGO);
508                 CDEBUG(D_PIOCTL, "chmod: orig %#o, set %#o, result %#o\n",
509                        dentry->d_inode->i_mode, set_mode, iattr->ia_mode);
510 #ifdef CONFIG_FS_POSIX_ACL
511                 /* ACl code interacts badly with setattr
512                  * since it tries to modify the ACL using
513                  * set_ext_attr which recurses back into presto.
514                  * This only happens if ATTR_MODE is set.
515                  * Here we are doing a "forced" mode set
516                  * (initiated by lento), so we disable the
517                  * set_posix_acl operation which
518                  * prevents such recursion.  -SHP
519                  *
520                  * This will probably still be required when native
521                  * acl journalling is in place.
522                  */
523                 set_posix_acl=dentry->d_inode->i_op->set_posix_acl;
524                 dentry->d_inode->i_op->set_posix_acl=NULL;
525 #endif
526         }
527 
528         error = presto_do_setattr(fset, dentry, iattr, info);
529 
530         if (info->flags & LENTO_FL_SET_DDFILEID) {
531                 struct presto_dentry_data *dd = presto_d2d(dentry);
532                 if (dd) {
533                         dd->remote_ino = info->remote_ino;
534                         dd->remote_generation = info->remote_generation;
535                 }
536         }
537 
538 #ifdef CONFIG_FS_POSIX_ACL
539         /* restore the inode_operations if we changed them*/
540         if (iattr->ia_valid & ATTR_MODE)
541                 dentry->d_inode->i_op->set_posix_acl=set_posix_acl;
542 #endif
543 
544 
545         EXIT;
546 exit_lock:
547         path_release(&nd);
548 exit:
549         unlock_kernel();
550         return error;
551 }
552 
presto_do_create(struct presto_file_set * fset,struct dentry * dir,struct dentry * dentry,int mode,struct lento_vfs_context * info)553 int presto_do_create(struct presto_file_set *fset, struct dentry *dir,
554                      struct dentry *dentry, int mode,
555                      struct lento_vfs_context *info)
556 {
557         struct rec_info rec;
558         int error;
559         struct presto_version tgt_dir_ver, new_file_ver;
560         struct inode_operations *iops;
561         void *handle;
562 
563         ENTRY;
564         mode &= S_IALLUGO;
565         mode |= S_IFREG;
566 
567         down(&dir->d_inode->i_zombie);
568         error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);
569         if (error) {
570                 EXIT;
571                 up(&dir->d_inode->i_zombie);
572                 return error;
573         }
574 
575         error = may_create(dir->d_inode, dentry);
576         if (error) {
577                 EXIT;
578                 goto exit_pre_lock;
579         }
580 
581         error = -EPERM;
582         iops = filter_c2cdiops(fset->fset_cache->cache_filter);
583         if (!iops->create) {
584                 EXIT;
585                 goto exit_pre_lock;
586         }
587 
588         presto_getversion(&tgt_dir_ver, dir->d_inode);
589         handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_CREATE);
590         if ( IS_ERR(handle) ) {
591                 EXIT;
592                 presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
593                 CERROR("presto_do_create: no space for transaction\n");
594                 error=-ENOSPC;
595                 goto exit_pre_lock;
596         }
597         DQUOT_INIT(dir->d_inode);
598         lock_kernel();
599         error = iops->create(dir->d_inode, dentry, mode);
600         if (error) {
601                 EXIT;
602                 goto exit_lock;
603         }
604 
605         if (dentry->d_inode) {
606                 struct presto_cache *cache = fset->fset_cache;
607                 /* was this already done? */
608                 presto_set_ops(dentry->d_inode, cache->cache_filter);
609 
610                 filter_setup_dentry_ops(cache->cache_filter,
611                                         dentry->d_op,
612                                         &presto_dentry_ops);
613                 dentry->d_op = filter_c2udops(cache->cache_filter);
614 
615                 /* if Lento creates this file, we won't have data */
616                 if ( ISLENTO(presto_c2m(cache)) ) {
617                         presto_set(dentry, PRESTO_ATTR);
618                 } else {
619                         presto_set(dentry, PRESTO_ATTR | PRESTO_DATA);
620                 }
621         }
622 
623         info->flags |= LENTO_FL_TOUCH_PARENT;
624         error = presto_settime(fset, NULL, dir, dentry,
625                                info, ATTR_CTIME | ATTR_MTIME);
626         if (error) {
627                 EXIT;
628                 goto exit_lock;
629         }
630 
631         presto_debug_fail_blkdev(fset, KML_OPCODE_CREATE | 0x10);
632 
633         if ( presto_do_kml(info, dentry) ) {
634                 presto_getversion(&new_file_ver, dentry->d_inode);
635                 error = presto_journal_create(&rec, fset, dentry, &tgt_dir_ver,
636                                               &new_file_ver,
637                                               dentry->d_inode->i_mode);
638         }
639 
640         presto_debug_fail_blkdev(fset, KML_OPCODE_CREATE | 0x20);
641 
642         if ( presto_do_rcvd(info, dentry) )
643                 error = presto_write_last_rcvd(&rec, fset, info);
644 
645         presto_debug_fail_blkdev(fset, KML_OPCODE_CREATE | 0x30);
646 
647         /* add inode dentry */
648         if (fset->fset_cache->cache_filter->o_trops->tr_add_ilookup ) {
649                 struct dentry *d;
650                 d = fset->fset_cache->cache_filter->o_trops->tr_add_ilookup
651                         (dir->d_inode->i_sb->s_root, dentry);
652         }
653 
654         EXIT;
655 
656  exit_lock:
657         unlock_kernel();
658         presto_trans_commit(fset, handle);
659  exit_pre_lock:
660         presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
661         up(&dir->d_inode->i_zombie);
662         return error;
663 }
664 
665 /* from namei.c */
lookup_create(struct nameidata * nd,int is_dir)666 static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
667 {
668         struct dentry *dentry;
669 
670         down(&nd->dentry->d_inode->i_sem);
671         dentry = ERR_PTR(-EEXIST);
672         if (nd->last_type != LAST_NORM)
673                 goto fail;
674         dentry = lookup_hash(&nd->last, nd->dentry);
675         if (IS_ERR(dentry))
676                 goto fail;
677         if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
678                 goto enoent;
679         return dentry;
680 enoent:
681         dput(dentry);
682         dentry = ERR_PTR(-ENOENT);
683 fail:
684         return dentry;
685 }
686 
lento_create(const char * name,int mode,struct lento_vfs_context * info)687 int lento_create(const char *name, int mode, struct lento_vfs_context *info)
688 {
689         int error;
690         struct nameidata nd;
691         char * pathname;
692         struct dentry *dentry;
693         struct presto_file_set *fset;
694 
695         ENTRY;
696         pathname = getname(name);
697         error = PTR_ERR(pathname);
698         if (IS_ERR(pathname)) {
699                 EXIT;
700                 goto exit;
701         }
702 
703         /* this looks up the parent */
704 //        if (path_init(pathname, LOOKUP_FOLLOW | LOOKUP_POSITIVE, &nd))
705         if (path_init(pathname,  LOOKUP_PARENT, &nd))
706                 error = path_walk(pathname, &nd);
707         if (error) {
708                 EXIT;
709                 goto exit;
710         }
711         dentry = lookup_create(&nd, 0);
712         error = PTR_ERR(dentry);
713         if (IS_ERR(dentry)) {
714                 EXIT;
715                 goto exit_lock;
716         }
717 
718         fset = presto_fset(dentry);
719         error = -EINVAL;
720         if ( !fset ) {
721                 CERROR("No fileset!\n");
722                 EXIT;
723                 goto exit_lock;
724         }
725         error = presto_do_create(fset, dentry->d_parent, dentry, (mode&S_IALLUGO)|S_IFREG,
726                                  info);
727 
728         EXIT;
729 
730  exit_lock:
731         path_release (&nd);
732         dput(dentry);
733         up(&dentry->d_parent->d_inode->i_sem);
734         putname(pathname);
735 exit:
736         return error;
737 }
738 
presto_do_link(struct presto_file_set * fset,struct dentry * old_dentry,struct dentry * dir,struct dentry * new_dentry,struct lento_vfs_context * info)739 int presto_do_link(struct presto_file_set *fset, struct dentry *old_dentry,
740                    struct dentry *dir, struct dentry *new_dentry,
741                    struct lento_vfs_context *info)
742 {
743         struct rec_info rec;
744         struct inode *inode;
745         int error;
746         struct inode_operations *iops;
747         struct presto_version tgt_dir_ver;
748         struct presto_version new_link_ver;
749         void *handle;
750 
751         down(&dir->d_inode->i_zombie);
752         error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);
753         if (error) {
754                 EXIT;
755                 up(&dir->d_inode->i_zombie);
756                 return error;
757         }
758         error = -ENOENT;
759         inode = old_dentry->d_inode;
760         if (!inode)
761                 goto exit_lock;
762 
763         error = may_create(dir->d_inode, new_dentry);
764         if (error)
765                 goto exit_lock;
766 
767         error = -EXDEV;
768         if (dir->d_inode->i_dev != inode->i_dev)
769                 goto exit_lock;
770 
771         /*
772          * A link to an append-only or immutable file cannot be created.
773          */
774         error = -EPERM;
775         if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
776                 EXIT;
777                 goto exit_lock;
778         }
779 
780         iops = filter_c2cdiops(fset->fset_cache->cache_filter);
781         if (!iops->link) {
782                 EXIT;
783                 goto exit_lock;
784         }
785 
786 
787         presto_getversion(&tgt_dir_ver, dir->d_inode);
788         handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_LINK);
789         if ( IS_ERR(handle) ) {
790                 presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
791                 CERROR("presto_do_link: no space for transaction\n");
792                 return -ENOSPC;
793         }
794 
795         DQUOT_INIT(dir->d_inode);
796         lock_kernel();
797         error = iops->link(old_dentry, dir->d_inode, new_dentry);
798         unlock_kernel();
799         if (error) {
800                 EXIT;
801                 goto exit_lock;
802         }
803 
804         /* link dd data to that of existing dentry */
805         old_dentry->d_op->d_release(new_dentry);
806         if (!presto_d2d(old_dentry))
807                 BUG();
808         presto_d2d(old_dentry)->dd_count++;
809 
810         new_dentry->d_fsdata = presto_d2d(old_dentry);
811 
812         info->flags |= LENTO_FL_TOUCH_PARENT;
813         error = presto_settime(fset, NULL, dir, new_dentry,
814                                info, ATTR_CTIME);
815         if (error) {
816                 EXIT;
817                 goto exit_lock;
818         }
819 
820         presto_debug_fail_blkdev(fset, KML_OPCODE_LINK | 0x10);
821         presto_getversion(&new_link_ver, new_dentry->d_inode);
822         if ( presto_do_kml(info, old_dentry) )
823                 error = presto_journal_link(&rec, fset, old_dentry, new_dentry,
824                                             &tgt_dir_ver, &new_link_ver);
825 
826         presto_debug_fail_blkdev(fset, KML_OPCODE_LINK | 0x20);
827         if ( presto_do_rcvd(info, old_dentry) )
828                 error = presto_write_last_rcvd(&rec, fset, info);
829 
830         presto_debug_fail_blkdev(fset, KML_OPCODE_LINK | 0x30);
831         EXIT;
832         presto_trans_commit(fset, handle);
833 exit_lock:
834         presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
835         up(&dir->d_inode->i_zombie);
836         return error;
837 }
838 
839 
lento_link(const char * oldname,const char * newname,struct lento_vfs_context * info)840 int lento_link(const char * oldname, const char * newname,
841                          struct lento_vfs_context *info)
842 {
843         int error;
844         char * from;
845         char * to;
846         struct presto_file_set *fset;
847 
848         from = getname(oldname);
849         if(IS_ERR(from))
850                 return PTR_ERR(from);
851         to = getname(newname);
852         error = PTR_ERR(to);
853         if (!IS_ERR(to)) {
854                 struct dentry *new_dentry;
855                 struct nameidata nd, old_nd;
856 
857                 error = 0;
858                 if (path_init(from, LOOKUP_POSITIVE, &old_nd))
859                         error = path_walk(from, &old_nd);
860                 if (error)
861                         goto exit;
862                 if (path_init(to, LOOKUP_PARENT, &nd))
863                         error = path_walk(to, &nd);
864                 if (error)
865                         goto out;
866                 error = -EXDEV;
867                 if (old_nd.mnt != nd.mnt)
868                         goto out;
869                 new_dentry = lookup_create(&nd, 0);
870                 error = PTR_ERR(new_dentry);
871 
872                 if (!IS_ERR(new_dentry)) {
873                         fset = presto_fset(new_dentry);
874                         error = -EINVAL;
875                         if ( !fset ) {
876                                 CERROR("No fileset!\n");
877                                 EXIT;
878                                 goto out2;
879                         }
880                         error = presto_do_link(fset, old_nd.dentry,
881                                                nd.dentry,
882                                                new_dentry, info);
883                         dput(new_dentry);
884                 }
885         out2:
886                 up(&nd.dentry->d_inode->i_sem);
887                 path_release(&nd);
888         out:
889                 path_release(&old_nd);
890         exit:
891                 putname(to);
892         }
893         putname(from);
894 
895         return error;
896 }
897 
presto_do_unlink(struct presto_file_set * fset,struct dentry * dir,struct dentry * dentry,struct lento_vfs_context * info)898 int presto_do_unlink(struct presto_file_set *fset, struct dentry *dir,
899                      struct dentry *dentry, struct lento_vfs_context *info)
900 {
901         struct rec_info rec;
902         struct inode_operations *iops;
903         struct presto_version tgt_dir_ver, old_file_ver;
904         struct izo_rollback_data rb;
905         void *handle;
906         int do_kml = 0, do_rcvd = 0, linkno = 0, error, old_targetlen = 0;
907         char *old_target = NULL;
908 
909         ENTRY;
910         down(&dir->d_inode->i_zombie);
911         error = may_delete(dir->d_inode, dentry, 0);
912         if (error) {
913                 EXIT;
914                 up(&dir->d_inode->i_zombie);
915                 return error;
916         }
917 
918         error = -EPERM;
919         iops = filter_c2cdiops(fset->fset_cache->cache_filter);
920         if (!iops->unlink) {
921                 EXIT;
922                 up(&dir->d_inode->i_zombie);
923                 return error;
924         }
925 
926         error = presto_reserve_space(fset->fset_cache, PRESTO_REQLOW);
927         if (error) {
928                 EXIT;
929                 up(&dir->d_inode->i_zombie);
930                 return error;
931         }
932 
933 
934         if (presto_d2d(dentry)) {
935                 struct presto_dentry_data *dd = presto_d2d(dentry);
936                 struct dentry *de = dd->dd_inodentry;
937                 if (de && dentry->d_inode->i_nlink == 1) {
938                         dd->dd_count--;
939                         dd->dd_inodentry = NULL;
940                         de->d_fsdata = NULL;
941                         atomic_dec(&de->d_inode->i_count);
942                         de->d_inode = NULL;
943                         dput(de);
944                 }
945         }
946 
947         presto_getversion(&tgt_dir_ver, dir->d_inode);
948         presto_getversion(&old_file_ver, dentry->d_inode);
949         izo_get_rollback_data(dentry->d_inode, &rb);
950         handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_UNLINK);
951         if ( IS_ERR(handle) ) {
952                 presto_release_space(fset->fset_cache, PRESTO_REQLOW);
953                 CERROR("ERROR: presto_do_unlink: no space for transaction. Tell Peter.\n");
954                 up(&dir->d_inode->i_zombie);
955                 return -ENOSPC;
956         }
957         DQUOT_INIT(dir->d_inode);
958         if (d_mountpoint(dentry))
959                 error = -EBUSY;
960         else {
961                 lock_kernel();
962                 linkno = dentry->d_inode->i_nlink;
963                 if (linkno > 1) {
964                         dget(dentry);
965                 }
966 
967                 if (S_ISLNK(dentry->d_inode->i_mode)) {
968                         mm_segment_t old_fs;
969                         struct inode_operations *riops;
970                         riops = filter_c2csiops(fset->fset_cache->cache_filter);
971 
972                         PRESTO_ALLOC(old_target, PATH_MAX);
973                         if (old_target == NULL) {
974                                 error = -ENOMEM;
975                                 EXIT;
976                                 goto exit;
977                         }
978 
979                         old_fs = get_fs();
980                         set_fs(get_ds());
981 
982                         if (riops->readlink == NULL)
983                                 CERROR("InterMezzo %s: no readlink iops.\n",
984                                        __FUNCTION__);
985                         else
986                                 old_targetlen =
987                                         riops->readlink(dentry, old_target,
988                                                         PATH_MAX);
989                         if (old_targetlen < 0) {
990                                 CERROR("InterMezzo: readlink failed: %ld\n",
991                                        PTR_ERR(old_target));
992                                 PRESTO_FREE(old_target, PATH_MAX);
993                                 old_target = NULL;
994                                 old_targetlen = 0;
995                         }
996                         set_fs(old_fs);
997                 }
998 
999                 do_kml = presto_do_kml(info, dir);
1000                 do_rcvd = presto_do_rcvd(info, dir);
1001                 error = iops->unlink(dir->d_inode, dentry);
1002                 unlock_kernel();
1003                 if (!error)
1004                         d_delete(dentry);
1005         }
1006 
1007         if (linkno > 1) {
1008                 /* FIXME: Combine this with the next call? */
1009                 error = presto_settime(fset, NULL, NULL, dentry,
1010                                        info, ATTR_CTIME);
1011                 dput(dentry);
1012                 if (error) {
1013                         EXIT;
1014                         goto exit;
1015                 }
1016         }
1017 
1018         error = presto_settime(fset, NULL, NULL, dir,
1019                                info, ATTR_CTIME | ATTR_MTIME);
1020         if (error) {
1021                 EXIT;
1022                 goto exit;
1023         }
1024 
1025         up(&dir->d_inode->i_zombie);
1026         if (error) {
1027                 EXIT;
1028                 goto exit;
1029         }
1030 
1031         presto_debug_fail_blkdev(fset, KML_OPCODE_UNLINK | 0x10);
1032         if ( do_kml )
1033                 error = presto_journal_unlink(&rec, fset, dir, &tgt_dir_ver,
1034                                               &old_file_ver, &rb, dentry,
1035                                               old_target, old_targetlen);
1036         presto_debug_fail_blkdev(fset, KML_OPCODE_UNLINK | 0x20);
1037         if ( do_rcvd ) {
1038                 error = presto_write_last_rcvd(&rec, fset, info);
1039         }
1040         presto_debug_fail_blkdev(fset, KML_OPCODE_UNLINK | 0x30);
1041         EXIT;
1042 exit:
1043         presto_release_space(fset->fset_cache, PRESTO_REQLOW);
1044         presto_trans_commit(fset, handle);
1045         if (old_target != NULL)
1046                 PRESTO_FREE(old_target, PATH_MAX);
1047         return error;
1048 }
1049 
1050 
lento_unlink(const char * pathname,struct lento_vfs_context * info)1051 int lento_unlink(const char *pathname, struct lento_vfs_context *info)
1052 {
1053         int error = 0;
1054         char * name;
1055         struct dentry *dentry;
1056         struct nameidata nd;
1057         struct presto_file_set *fset;
1058 
1059         ENTRY;
1060 
1061         name = getname(pathname);
1062         if(IS_ERR(name))
1063                 return PTR_ERR(name);
1064 
1065         if (path_init(name, LOOKUP_PARENT, &nd))
1066                 error = path_walk(name, &nd);
1067         if (error)
1068                 goto exit;
1069         error = -EISDIR;
1070         if (nd.last_type != LAST_NORM)
1071                 goto exit1;
1072         down(&nd.dentry->d_inode->i_sem);
1073         dentry = lookup_hash(&nd.last, nd.dentry);
1074         error = PTR_ERR(dentry);
1075         if (!IS_ERR(dentry)) {
1076                 fset = presto_fset(dentry);
1077                 error = -EINVAL;
1078                 if ( !fset ) {
1079                         CERROR("No fileset!\n");
1080                         EXIT;
1081                         goto exit2;
1082                 }
1083                 /* Why not before? Because we want correct error value */
1084                 if (nd.last.name[nd.last.len])
1085                         goto slashes;
1086                 error = presto_do_unlink(fset, nd.dentry, dentry, info);
1087         exit2:
1088                 EXIT;
1089                 dput(dentry);
1090         }
1091         up(&nd.dentry->d_inode->i_sem);
1092 exit1:
1093         path_release(&nd);
1094 exit:
1095         putname(name);
1096 
1097         return error;
1098 
1099 slashes:
1100         error = !dentry->d_inode ? -ENOENT :
1101                 S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR;
1102         goto exit2;
1103 }
1104 
presto_do_symlink(struct presto_file_set * fset,struct dentry * dir,struct dentry * dentry,const char * oldname,struct lento_vfs_context * info)1105 int presto_do_symlink(struct presto_file_set *fset, struct dentry *dir,
1106                       struct dentry *dentry, const char *oldname,
1107                       struct lento_vfs_context *info)
1108 {
1109         struct rec_info rec;
1110         int error;
1111         struct presto_version tgt_dir_ver, new_link_ver;
1112         struct inode_operations *iops;
1113         void *handle;
1114 
1115         ENTRY;
1116         down(&dir->d_inode->i_zombie);
1117         /* record + max path len + space to free */
1118         error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
1119         if (error) {
1120                 EXIT;
1121                 up(&dir->d_inode->i_zombie);
1122                 return error;
1123         }
1124 
1125         error = may_create(dir->d_inode, dentry);
1126         if (error) {
1127                 EXIT;
1128                 goto exit_lock;
1129         }
1130 
1131         error = -EPERM;
1132         iops = filter_c2cdiops(fset->fset_cache->cache_filter);
1133         if (!iops->symlink) {
1134                 EXIT;
1135                 goto exit_lock;
1136         }
1137 
1138         presto_getversion(&tgt_dir_ver, dir->d_inode);
1139         handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_SYMLINK);
1140         if ( IS_ERR(handle) ) {
1141                 presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
1142                 CERROR("ERROR: presto_do_symlink: no space for transaction. Tell Peter.\n");
1143                 EXIT;
1144                 up(&dir->d_inode->i_zombie);
1145                 return -ENOSPC;
1146         }
1147         DQUOT_INIT(dir->d_inode);
1148         lock_kernel();
1149         error = iops->symlink(dir->d_inode, dentry, oldname);
1150         if (error) {
1151                 EXIT;
1152                 goto exit;
1153         }
1154 
1155         if (dentry->d_inode) {
1156                 struct presto_cache *cache = fset->fset_cache;
1157 
1158                 presto_set_ops(dentry->d_inode, cache->cache_filter);
1159 
1160                 filter_setup_dentry_ops(cache->cache_filter, dentry->d_op,
1161                                         &presto_dentry_ops);
1162                 dentry->d_op = filter_c2udops(cache->cache_filter);
1163                 /* XXX ? Cache state ? if Lento creates a symlink */
1164                 if ( ISLENTO(presto_c2m(cache)) ) {
1165                         presto_set(dentry, PRESTO_ATTR);
1166                 } else {
1167                         presto_set(dentry, PRESTO_ATTR | PRESTO_DATA);
1168                 }
1169         }
1170 
1171         info->flags |= LENTO_FL_TOUCH_PARENT;
1172         error = presto_settime(fset, NULL, dir, dentry,
1173                                info, ATTR_CTIME | ATTR_MTIME);
1174         if (error) {
1175                 EXIT;
1176                 goto exit;
1177         }
1178 
1179         presto_debug_fail_blkdev(fset, KML_OPCODE_SYMLINK | 0x10);
1180         presto_getversion(&new_link_ver, dentry->d_inode);
1181         if ( presto_do_kml(info, dentry) )
1182                 error = presto_journal_symlink(&rec, fset, dentry, oldname,
1183                                                &tgt_dir_ver, &new_link_ver);
1184 
1185         presto_debug_fail_blkdev(fset, KML_OPCODE_SYMLINK | 0x20);
1186         if ( presto_do_rcvd(info, dentry) )
1187                 error = presto_write_last_rcvd(&rec, fset, info);
1188 
1189         presto_debug_fail_blkdev(fset, KML_OPCODE_SYMLINK | 0x30);
1190         EXIT;
1191 exit:
1192         unlock_kernel();
1193         presto_trans_commit(fset, handle);
1194  exit_lock:
1195         presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
1196         up(&dir->d_inode->i_zombie);
1197         return error;
1198 }
1199 
lento_symlink(const char * oldname,const char * newname,struct lento_vfs_context * info)1200 int lento_symlink(const char *oldname, const char *newname,
1201                   struct lento_vfs_context *info)
1202 {
1203         int error;
1204         char *from;
1205         char *to;
1206         struct dentry *dentry;
1207         struct presto_file_set *fset;
1208         struct nameidata nd;
1209 
1210         ENTRY;
1211         lock_kernel();
1212         from = getname(oldname);
1213         error = PTR_ERR(from);
1214         if (IS_ERR(from)) {
1215                 EXIT;
1216                 goto exit;
1217         }
1218 
1219         to = getname(newname);
1220         error = PTR_ERR(to);
1221         if (IS_ERR(to)) {
1222                 EXIT;
1223                 goto exit_from;
1224         }
1225 
1226         if (path_init(to, LOOKUP_PARENT, &nd))
1227                 error = path_walk(to, &nd);
1228         if (error) {
1229                 EXIT;
1230                 goto exit_to;
1231         }
1232 
1233         dentry = lookup_create(&nd, 0);
1234         error = PTR_ERR(dentry);
1235         if (IS_ERR(dentry)) {
1236                 path_release(&nd);
1237                 EXIT;
1238                 goto exit_to;
1239         }
1240 
1241         fset = presto_fset(dentry);
1242         error = -EINVAL;
1243         if ( !fset ) {
1244                 CERROR("No fileset!\n");
1245                 path_release(&nd);
1246                 EXIT;
1247                 goto exit_lock;
1248         }
1249         error = presto_do_symlink(fset, nd.dentry,
1250                                   dentry, from, info);
1251         path_release(&nd);
1252         EXIT;
1253  exit_lock:
1254         up(&nd.dentry->d_inode->i_sem);
1255         dput(dentry);
1256  exit_to:
1257         putname(to);
1258  exit_from:
1259         putname(from);
1260  exit:
1261         unlock_kernel();
1262         return error;
1263 }
1264 
presto_do_mkdir(struct presto_file_set * fset,struct dentry * dir,struct dentry * dentry,int mode,struct lento_vfs_context * info)1265 int presto_do_mkdir(struct presto_file_set *fset, struct dentry *dir,
1266                     struct dentry *dentry, int mode,
1267                     struct lento_vfs_context *info)
1268 {
1269         struct rec_info rec;
1270         int error;
1271         struct presto_version tgt_dir_ver, new_dir_ver;
1272         void *handle;
1273 
1274         ENTRY;
1275         down(&dir->d_inode->i_zombie);
1276 
1277         /* one journal record + directory block + room for removals*/
1278         error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
1279         if (error) {
1280                 EXIT;
1281                 up(&dir->d_inode->i_zombie);
1282                 return error;
1283         }
1284 
1285         error = may_create(dir->d_inode, dentry);
1286         if (error) {
1287                 EXIT;
1288                 goto exit_lock;
1289         }
1290 
1291         error = -EPERM;
1292         if (!filter_c2cdiops(fset->fset_cache->cache_filter)->mkdir) {
1293                 EXIT;
1294                 goto exit_lock;
1295         }
1296 
1297         error = -ENOSPC;
1298         presto_getversion(&tgt_dir_ver, dir->d_inode);
1299         handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_MKDIR);
1300         if ( IS_ERR(handle) ) {
1301                 presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
1302                 CERROR("presto_do_mkdir: no space for transaction\n");
1303                 goto exit_lock;
1304         }
1305 
1306         DQUOT_INIT(dir->d_inode);
1307         mode &= (S_IRWXUGO|S_ISVTX);
1308         lock_kernel();
1309         error = filter_c2cdiops(fset->fset_cache->cache_filter)->mkdir(dir->d_inode, dentry, mode);
1310         if (error) {
1311                 EXIT;
1312                 goto exit;
1313         }
1314 
1315         if ( dentry->d_inode && !error) {
1316                 struct presto_cache *cache = fset->fset_cache;
1317 
1318                 presto_set_ops(dentry->d_inode, cache->cache_filter);
1319 
1320                 filter_setup_dentry_ops(cache->cache_filter,
1321                                         dentry->d_op,
1322                                         &presto_dentry_ops);
1323                 dentry->d_op = filter_c2udops(cache->cache_filter);
1324                 /* if Lento does this, we won't have data */
1325                 if ( ISLENTO(presto_c2m(cache)) ) {
1326                         presto_set(dentry, PRESTO_ATTR);
1327                 } else {
1328                         presto_set(dentry, PRESTO_ATTR | PRESTO_DATA);
1329                 }
1330         }
1331 
1332         info->flags |= LENTO_FL_TOUCH_PARENT;
1333         error = presto_settime(fset, NULL, dir, dentry,
1334                              info, ATTR_CTIME | ATTR_MTIME);
1335         if (error) {
1336                 EXIT;
1337                 goto exit;
1338         }
1339 
1340         presto_debug_fail_blkdev(fset, KML_OPCODE_MKDIR | 0x10);
1341         presto_getversion(&new_dir_ver, dentry->d_inode);
1342         if ( presto_do_kml(info, dir) )
1343                 error = presto_journal_mkdir(&rec, fset, dentry, &tgt_dir_ver,
1344                                              &new_dir_ver,
1345                                              dentry->d_inode->i_mode);
1346 
1347         presto_debug_fail_blkdev(fset, KML_OPCODE_MKDIR | 0x20);
1348         if ( presto_do_rcvd(info, dentry) )
1349                 error = presto_write_last_rcvd(&rec, fset, info);
1350 
1351         presto_debug_fail_blkdev(fset, KML_OPCODE_MKDIR | 0x30);
1352         EXIT;
1353 exit:
1354         unlock_kernel();
1355         presto_trans_commit(fset, handle);
1356  exit_lock:
1357         presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
1358         up(&dir->d_inode->i_zombie);
1359         return error;
1360 }
1361 
1362 /*
1363  * Look out: this function may change a normal dentry
1364  * into a directory dentry (different size)..
1365  */
lento_mkdir(const char * name,int mode,struct lento_vfs_context * info)1366 int lento_mkdir(const char *name, int mode, struct lento_vfs_context *info)
1367 {
1368         int error;
1369         char *pathname;
1370         struct dentry *dentry;
1371         struct presto_file_set *fset;
1372         struct nameidata nd;
1373 
1374         ENTRY;
1375         CDEBUG(D_PIOCTL, "name: %s, mode %o, offset %d, recno %d, flags %x\n",
1376                name, mode, info->slot_offset, info->recno, info->flags);
1377         pathname = getname(name);
1378         error = PTR_ERR(pathname);
1379         if (IS_ERR(pathname)) {
1380                 EXIT;
1381                 return error;
1382         }
1383 
1384         if (path_init(pathname, LOOKUP_PARENT, &nd))
1385                 error = path_walk(pathname, &nd);
1386         if (error)
1387                 goto out_name;
1388 
1389         dentry = lookup_create(&nd, 1);
1390         error = PTR_ERR(dentry);
1391         if (!IS_ERR(dentry)) {
1392                 fset = presto_fset(dentry);
1393                 error = -EINVAL;
1394                 if (!fset) {
1395                         CERROR("No fileset!\n");
1396                         EXIT;
1397                         goto out_dput;
1398                 }
1399 
1400                 error = presto_do_mkdir(fset, nd.dentry, dentry,
1401                                         mode & S_IALLUGO, info);
1402 out_dput:
1403                 dput(dentry);
1404         }
1405         up(&nd.dentry->d_inode->i_sem);
1406         path_release(&nd);
1407 out_name:
1408         EXIT;
1409         putname(pathname);
1410         CDEBUG(D_PIOCTL, "error: %d\n", error);
1411         return error;
1412 }
1413 
d_unhash(struct dentry * dentry)1414 static void d_unhash(struct dentry *dentry)
1415 {
1416         dget(dentry);
1417         switch (atomic_read(&dentry->d_count)) {
1418         default:
1419                 shrink_dcache_parent(dentry);
1420                 if (atomic_read(&dentry->d_count) != 2)
1421                         break;
1422         case 2:
1423                 d_drop(dentry);
1424         }
1425 }
1426 
presto_do_rmdir(struct presto_file_set * fset,struct dentry * dir,struct dentry * dentry,struct lento_vfs_context * info)1427 int presto_do_rmdir(struct presto_file_set *fset, struct dentry *dir,
1428                     struct dentry *dentry, struct lento_vfs_context *info)
1429 {
1430         struct rec_info rec;
1431         int error;
1432         struct presto_version tgt_dir_ver, old_dir_ver;
1433         struct izo_rollback_data rb;
1434         struct inode_operations *iops;
1435         void *handle;
1436         int do_kml, do_rcvd;
1437         int size;
1438 
1439         ENTRY;
1440         error = may_delete(dir->d_inode, dentry, 1);
1441         if (error)
1442                 return error;
1443 
1444         error = -EPERM;
1445         iops = filter_c2cdiops(fset->fset_cache->cache_filter);
1446         if (!iops->rmdir) {
1447                 EXIT;
1448                 return error;
1449         }
1450 
1451         size = PRESTO_REQHIGH - dentry->d_inode->i_size;
1452         error = presto_reserve_space(fset->fset_cache, size);
1453         if (error) {
1454                 EXIT;
1455                 return error;
1456         }
1457 
1458         presto_getversion(&tgt_dir_ver, dir->d_inode);
1459         presto_getversion(&old_dir_ver, dentry->d_inode);
1460         izo_get_rollback_data(dentry->d_inode, &rb);
1461         handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_RMDIR);
1462         if ( IS_ERR(handle) ) {
1463                 presto_release_space(fset->fset_cache, size);
1464                 CERROR("ERROR: presto_do_rmdir: no space for transaction. Tell Peter.\n");
1465                 return -ENOSPC;
1466         }
1467 
1468         DQUOT_INIT(dir->d_inode);
1469 
1470         do_kml = presto_do_kml(info, dir);
1471         do_rcvd = presto_do_rcvd(info, dir);
1472 
1473         double_down(&dir->d_inode->i_zombie, &dentry->d_inode->i_zombie);
1474         d_unhash(dentry);
1475         if (IS_DEADDIR(dir->d_inode))
1476                 error = -ENOENT;
1477         else if (d_mountpoint(dentry)) {
1478                 CERROR("foo: d_mountpoint(dentry): ino %ld\n",
1479                        dentry->d_inode->i_ino);
1480                 error = -EBUSY;
1481         } else {
1482                 lock_kernel();
1483                 error = iops->rmdir(dir->d_inode, dentry);
1484                 unlock_kernel();
1485                 if (!error) {
1486                         dentry->d_inode->i_flags |= S_DEAD;
1487                         error = presto_settime(fset, NULL, NULL, dir, info,
1488                                                ATTR_CTIME | ATTR_MTIME);
1489                 }
1490         }
1491         double_up(&dir->d_inode->i_zombie, &dentry->d_inode->i_zombie);
1492         if (!error)
1493                 d_delete(dentry);
1494         dput(dentry);
1495 
1496         presto_debug_fail_blkdev(fset, KML_OPCODE_RMDIR | 0x10);
1497         if ( !error && do_kml )
1498                 error = presto_journal_rmdir(&rec, fset, dir, &tgt_dir_ver,
1499                                              &old_dir_ver, &rb,
1500                                              dentry->d_name.len,
1501                                              dentry->d_name.name);
1502 
1503         presto_debug_fail_blkdev(fset, KML_OPCODE_RMDIR | 0x20);
1504         if ( !error && do_rcvd )
1505                 error = presto_write_last_rcvd(&rec, fset, info);
1506 
1507         presto_debug_fail_blkdev(fset, KML_OPCODE_RMDIR | 0x30);
1508         EXIT;
1509 
1510         presto_trans_commit(fset, handle);
1511         presto_release_space(fset->fset_cache, size);
1512         return error;
1513 }
1514 
lento_rmdir(const char * pathname,struct lento_vfs_context * info)1515 int lento_rmdir(const char *pathname, struct lento_vfs_context *info)
1516 {
1517         int error = 0;
1518         char * name;
1519         struct dentry *dentry;
1520         struct presto_file_set *fset;
1521         struct nameidata nd;
1522 
1523         ENTRY;
1524         name = getname(pathname);
1525         if(IS_ERR(name)) {
1526                 EXIT;
1527                 return PTR_ERR(name);
1528         }
1529 
1530         if (path_init(name, LOOKUP_PARENT, &nd))
1531                 error = path_walk(name, &nd);
1532         if (error) {
1533                 EXIT;
1534                 goto exit;
1535         }
1536         switch(nd.last_type) {
1537         case LAST_DOTDOT:
1538                 error = -ENOTEMPTY;
1539                 EXIT;
1540                 goto exit1;
1541         case LAST_ROOT:
1542         case LAST_DOT:
1543                 error = -EBUSY;
1544                 EXIT;
1545                 goto exit1;
1546         }
1547         down(&nd.dentry->d_inode->i_sem);
1548         dentry = lookup_hash(&nd.last, nd.dentry);
1549         error = PTR_ERR(dentry);
1550         if (!IS_ERR(dentry)) {
1551                 fset = presto_fset(dentry);
1552                 error = -EINVAL;
1553                 if ( !fset ) {
1554                         CERROR("No fileset!\n");
1555                         EXIT;
1556                         goto exit_put;
1557                 }
1558                 error = presto_do_rmdir(fset, nd.dentry, dentry, info);
1559         exit_put:
1560                 dput(dentry);
1561         }
1562         up(&nd.dentry->d_inode->i_sem);
1563 exit1:
1564         path_release(&nd);
1565 exit:
1566         putname(name);
1567         EXIT;
1568         return error;
1569 }
1570 
presto_do_mknod(struct presto_file_set * fset,struct dentry * dir,struct dentry * dentry,int mode,dev_t dev,struct lento_vfs_context * info)1571 int presto_do_mknod(struct presto_file_set *fset, struct dentry *dir,
1572                     struct dentry *dentry, int mode, dev_t dev,
1573                     struct lento_vfs_context *info)
1574 {
1575         struct rec_info rec;
1576         int error = -EPERM;
1577         struct presto_version tgt_dir_ver, new_node_ver;
1578         struct inode_operations *iops;
1579         void *handle;
1580 
1581         ENTRY;
1582 
1583         down(&dir->d_inode->i_zombie);
1584         /* one KML entry */
1585         error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);
1586         if (error) {
1587                 EXIT;
1588                 up(&dir->d_inode->i_zombie);
1589                 return error;
1590         }
1591 
1592         if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) {
1593                 EXIT;
1594                 goto exit_lock;
1595         }
1596 
1597         error = may_create(dir->d_inode, dentry);
1598         if (error) {
1599                 EXIT;
1600                 goto exit_lock;
1601         }
1602 
1603         error = -EPERM;
1604         iops = filter_c2cdiops(fset->fset_cache->cache_filter);
1605         if (!iops->mknod) {
1606                 EXIT;
1607                 goto exit_lock;
1608         }
1609 
1610         DQUOT_INIT(dir->d_inode);
1611         lock_kernel();
1612 
1613         error = -ENOSPC;
1614         presto_getversion(&tgt_dir_ver, dir->d_inode);
1615         handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_MKNOD);
1616         if ( IS_ERR(handle) ) {
1617                 presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
1618                 CERROR("presto_do_mknod: no space for transaction\n");
1619                 goto exit_lock2;
1620         }
1621 
1622         error = iops->mknod(dir->d_inode, dentry, mode, dev);
1623         if (error) {
1624                 EXIT;
1625                 goto exit_commit;
1626         }
1627         if ( dentry->d_inode) {
1628                 struct presto_cache *cache = fset->fset_cache;
1629 
1630                 presto_set_ops(dentry->d_inode, cache->cache_filter);
1631 
1632                 filter_setup_dentry_ops(cache->cache_filter, dentry->d_op,
1633                                         &presto_dentry_ops);
1634                 dentry->d_op = filter_c2udops(cache->cache_filter);
1635 
1636                 /* if Lento does this, we won't have data */
1637                 if ( ISLENTO(presto_c2m(cache)) ) {
1638                         presto_set(dentry, PRESTO_ATTR);
1639                 } else {
1640                         presto_set(dentry, PRESTO_ATTR | PRESTO_DATA);
1641                 }
1642         }
1643 
1644         error = presto_settime(fset, NULL, NULL, dir,
1645                                info, ATTR_MTIME);
1646         if (error) {
1647                 EXIT;
1648         }
1649         error = presto_settime(fset, NULL, NULL, dentry,
1650                                info, ATTR_CTIME | ATTR_MTIME);
1651         if (error) {
1652                 EXIT;
1653         }
1654 
1655         presto_debug_fail_blkdev(fset, KML_OPCODE_MKNOD | 0x10);
1656         presto_getversion(&new_node_ver, dentry->d_inode);
1657         if ( presto_do_kml(info, dentry) )
1658                 error = presto_journal_mknod(&rec, fset, dentry, &tgt_dir_ver,
1659                                              &new_node_ver,
1660                                              dentry->d_inode->i_mode,
1661                                              MAJOR(dev), MINOR(dev) );
1662 
1663         presto_debug_fail_blkdev(fset, KML_OPCODE_MKNOD | 0x20);
1664         if ( presto_do_rcvd(info, dentry) )
1665                 error = presto_write_last_rcvd(&rec, fset, info);
1666 
1667         presto_debug_fail_blkdev(fset, KML_OPCODE_MKNOD | 0x30);
1668         EXIT;
1669  exit_commit:
1670         presto_trans_commit(fset, handle);
1671  exit_lock2:
1672         unlock_kernel();
1673  exit_lock:
1674         presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
1675         up(&dir->d_inode->i_zombie);
1676         return error;
1677 }
1678 
lento_mknod(const char * filename,int mode,dev_t dev,struct lento_vfs_context * info)1679 int lento_mknod(const char *filename, int mode, dev_t dev,
1680                 struct lento_vfs_context *info)
1681 {
1682         int error = 0;
1683         char * tmp;
1684         struct dentry * dentry;
1685         struct nameidata nd;
1686         struct presto_file_set *fset;
1687 
1688         ENTRY;
1689 
1690         if (S_ISDIR(mode))
1691                 return -EPERM;
1692         tmp = getname(filename);
1693         if (IS_ERR(tmp))
1694                 return PTR_ERR(tmp);
1695 
1696         if (path_init(tmp, LOOKUP_PARENT, &nd))
1697                 error = path_walk(tmp, &nd);
1698         if (error)
1699                 goto out;
1700         dentry = lookup_create(&nd, 0);
1701         error = PTR_ERR(dentry);
1702         if (!IS_ERR(dentry)) {
1703                 fset = presto_fset(dentry);
1704                 error = -EINVAL;
1705                 if ( !fset ) {
1706                         CERROR("No fileset!\n");
1707                         EXIT;
1708                         goto exit_put;
1709                 }
1710                 switch (mode & S_IFMT) {
1711                 case 0: case S_IFREG:
1712                         error = -EOPNOTSUPP;
1713                         break;
1714                 case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
1715                         error = presto_do_mknod(fset, nd.dentry, dentry,
1716                                                 mode, dev, info);
1717                         break;
1718                 case S_IFDIR:
1719                         error = -EPERM;
1720                         break;
1721                 default:
1722                         error = -EINVAL;
1723                 }
1724         exit_put:
1725                 dput(dentry);
1726         }
1727         up(&nd.dentry->d_inode->i_sem);
1728         path_release(&nd);
1729 out:
1730         putname(tmp);
1731 
1732         return error;
1733 }
1734 
do_rename(struct presto_file_set * fset,struct dentry * old_parent,struct dentry * old_dentry,struct dentry * new_parent,struct dentry * new_dentry,struct lento_vfs_context * info)1735 int do_rename(struct presto_file_set *fset,
1736                      struct dentry *old_parent, struct dentry *old_dentry,
1737                      struct dentry *new_parent, struct dentry *new_dentry,
1738                      struct lento_vfs_context *info)
1739 {
1740         struct rec_info rec;
1741         int error;
1742         struct inode_operations *iops;
1743         struct presto_version src_dir_ver, tgt_dir_ver;
1744         void *handle;
1745         int new_inode_unlink = 0;
1746         struct inode *old_dir = old_parent->d_inode;
1747         struct inode *new_dir = new_parent->d_inode;
1748 
1749         ENTRY;
1750         presto_getversion(&src_dir_ver, old_dir);
1751         presto_getversion(&tgt_dir_ver, new_dir);
1752 
1753         error = -EPERM;
1754         iops = filter_c2cdiops(fset->fset_cache->cache_filter);
1755         if (!iops || !iops->rename) {
1756                 EXIT;
1757                 return error;
1758         }
1759 
1760         error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);
1761         if (error) {
1762                 EXIT;
1763                 return error;
1764         }
1765         handle = presto_trans_start(fset, old_dir, KML_OPCODE_RENAME);
1766         if ( IS_ERR(handle) ) {
1767                 presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
1768                 CERROR("presto_do_rename: no space for transaction\n");
1769                 return -ENOSPC;
1770         }
1771         if (new_dentry->d_inode && new_dentry->d_inode->i_nlink > 1) {
1772                 dget(new_dentry);
1773                 new_inode_unlink = 1;
1774         }
1775 
1776         error = iops->rename(old_dir, old_dentry, new_dir, new_dentry);
1777 
1778         if (error) {
1779                 EXIT;
1780                 goto exit;
1781         }
1782 
1783         if (new_inode_unlink) {
1784                 error = presto_settime(fset, NULL, NULL, old_dentry,
1785                                        info, ATTR_CTIME);
1786                 dput(old_dentry);
1787                 if (error) {
1788                         EXIT;
1789                         goto exit;
1790                 }
1791         }
1792         info->flags |= LENTO_FL_TOUCH_PARENT;
1793         error = presto_settime(fset, NULL, new_parent, old_parent,
1794                                info, ATTR_CTIME | ATTR_MTIME);
1795         if (error) {
1796                 EXIT;
1797                 goto exit;
1798         }
1799 
1800         /* XXX make a distinction between cross file set
1801          * and intra file set renames here
1802          */
1803         presto_debug_fail_blkdev(fset, KML_OPCODE_RENAME | 0x10);
1804         if ( presto_do_kml(info, old_dentry) )
1805                 error = presto_journal_rename(&rec, fset, old_dentry,
1806                                               new_dentry,
1807                                               &src_dir_ver, &tgt_dir_ver);
1808 
1809         presto_debug_fail_blkdev(fset, KML_OPCODE_RENAME | 0x20);
1810 
1811         if ( presto_do_rcvd(info, old_dentry) )
1812                 error = presto_write_last_rcvd(&rec, fset, info);
1813 
1814         presto_debug_fail_blkdev(fset, KML_OPCODE_RENAME | 0x30);
1815         EXIT;
1816 exit:
1817         presto_trans_commit(fset, handle);
1818         presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
1819         return error;
1820 }
1821 
1822 static
presto_rename_dir(struct presto_file_set * fset,struct dentry * old_parent,struct dentry * old_dentry,struct dentry * new_parent,struct dentry * new_dentry,struct lento_vfs_context * info)1823 int presto_rename_dir(struct presto_file_set *fset, struct dentry *old_parent,
1824                       struct dentry *old_dentry, struct dentry *new_parent,
1825                       struct dentry *new_dentry, struct lento_vfs_context *info)
1826 {
1827         int error;
1828         struct inode *target;
1829         struct inode *old_dir = old_parent->d_inode;
1830         struct inode *new_dir = new_parent->d_inode;
1831 
1832         if (old_dentry->d_inode == new_dentry->d_inode)
1833                 return 0;
1834 
1835         error = may_delete(old_dir, old_dentry, 1);
1836         if (error)
1837                 return error;
1838 
1839         if (new_dir->i_dev != old_dir->i_dev)
1840                 return -EXDEV;
1841 
1842         if (!new_dentry->d_inode)
1843                 error = may_create(new_dir, new_dentry);
1844         else
1845                 error = may_delete(new_dir, new_dentry, 1);
1846         if (error)
1847                 return error;
1848 
1849         if (!old_dir->i_op || !old_dir->i_op->rename)
1850                 return -EPERM;
1851 
1852         /*
1853          * If we are going to change the parent - check write permissions,
1854          * we'll need to flip '..'.
1855          */
1856         if (new_dir != old_dir) {
1857                 error = permission(old_dentry->d_inode, MAY_WRITE);
1858         }
1859         if (error)
1860                 return error;
1861 
1862         DQUOT_INIT(old_dir);
1863         DQUOT_INIT(new_dir);
1864         down(&old_dir->i_sb->s_vfs_rename_sem);
1865         error = -EINVAL;
1866         if (is_subdir(new_dentry, old_dentry))
1867                 goto out_unlock;
1868         target = new_dentry->d_inode;
1869         if (target) { /* Hastur! Hastur! Hastur! */
1870                 triple_down(&old_dir->i_zombie,
1871                             &new_dir->i_zombie,
1872                             &target->i_zombie);
1873                 d_unhash(new_dentry);
1874         } else
1875                 double_down(&old_dir->i_zombie,
1876                             &new_dir->i_zombie);
1877         if (IS_DEADDIR(old_dir)||IS_DEADDIR(new_dir))
1878                 error = -ENOENT;
1879         else if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
1880                 error = -EBUSY;
1881         else
1882                 error = do_rename(fset, old_parent, old_dentry,
1883                                          new_parent, new_dentry, info);
1884         if (target) {
1885                 if (!error)
1886                         target->i_flags |= S_DEAD;
1887                 triple_up(&old_dir->i_zombie,
1888                           &new_dir->i_zombie,
1889                           &target->i_zombie);
1890                 if (d_unhashed(new_dentry))
1891                         d_rehash(new_dentry);
1892                 dput(new_dentry);
1893         } else
1894                 double_up(&old_dir->i_zombie,
1895                           &new_dir->i_zombie);
1896 
1897         if (!error)
1898                 d_move(old_dentry,new_dentry);
1899 out_unlock:
1900         up(&old_dir->i_sb->s_vfs_rename_sem);
1901         return error;
1902 }
1903 
1904 static
presto_rename_other(struct presto_file_set * fset,struct dentry * old_parent,struct dentry * old_dentry,struct dentry * new_parent,struct dentry * new_dentry,struct lento_vfs_context * info)1905 int presto_rename_other(struct presto_file_set *fset, struct dentry *old_parent,
1906                         struct dentry *old_dentry, struct dentry *new_parent,
1907                         struct dentry *new_dentry, struct lento_vfs_context *info)
1908 {
1909         struct inode *old_dir = old_parent->d_inode;
1910         struct inode *new_dir = new_parent->d_inode;
1911         int error;
1912 
1913         if (old_dentry->d_inode == new_dentry->d_inode)
1914                 return 0;
1915 
1916         error = may_delete(old_dir, old_dentry, 0);
1917         if (error)
1918                 return error;
1919 
1920         if (new_dir->i_dev != old_dir->i_dev)
1921                 return -EXDEV;
1922 
1923         if (!new_dentry->d_inode)
1924                 error = may_create(new_dir, new_dentry);
1925         else
1926                 error = may_delete(new_dir, new_dentry, 0);
1927         if (error)
1928                 return error;
1929 
1930         if (!old_dir->i_op || !old_dir->i_op->rename)
1931                 return -EPERM;
1932 
1933         DQUOT_INIT(old_dir);
1934         DQUOT_INIT(new_dir);
1935         double_down(&old_dir->i_zombie, &new_dir->i_zombie);
1936         if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
1937                 error = -EBUSY;
1938         else
1939                 error = do_rename(fset, old_parent, old_dentry,
1940                                   new_parent, new_dentry, info);
1941         double_up(&old_dir->i_zombie, &new_dir->i_zombie);
1942         if (error)
1943                 return error;
1944         /* The following d_move() should become unconditional */
1945         if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME)) {
1946                 d_move(old_dentry, new_dentry);
1947         }
1948         return 0;
1949 }
1950 
presto_do_rename(struct presto_file_set * fset,struct dentry * old_parent,struct dentry * old_dentry,struct dentry * new_parent,struct dentry * new_dentry,struct lento_vfs_context * info)1951 int presto_do_rename(struct presto_file_set *fset,
1952               struct dentry *old_parent, struct dentry *old_dentry,
1953               struct dentry *new_parent, struct dentry *new_dentry,
1954               struct lento_vfs_context *info)
1955 {
1956         if (S_ISDIR(old_dentry->d_inode->i_mode))
1957                 return presto_rename_dir(fset, old_parent,old_dentry,new_parent,
1958                                       new_dentry, info);
1959         else
1960                 return presto_rename_other(fset, old_parent, old_dentry,
1961                                            new_parent,new_dentry, info);
1962 }
1963 
1964 
lento_do_rename(const char * oldname,const char * newname,struct lento_vfs_context * info)1965 int lento_do_rename(const char *oldname, const char *newname,
1966                  struct lento_vfs_context *info)
1967 {
1968         int error = 0;
1969         struct dentry * old_dir, * new_dir;
1970         struct dentry * old_dentry, *new_dentry;
1971         struct nameidata oldnd, newnd;
1972         struct presto_file_set *fset;
1973 
1974         ENTRY;
1975 
1976         if (path_init(oldname, LOOKUP_PARENT, &oldnd))
1977                 error = path_walk(oldname, &oldnd);
1978 
1979         if (error)
1980                 goto exit;
1981 
1982         if (path_init(newname, LOOKUP_PARENT, &newnd))
1983                 error = path_walk(newname, &newnd);
1984         if (error)
1985                 goto exit1;
1986 
1987         error = -EXDEV;
1988         if (oldnd.mnt != newnd.mnt)
1989                 goto exit2;
1990 
1991         old_dir = oldnd.dentry;
1992         error = -EBUSY;
1993         if (oldnd.last_type != LAST_NORM)
1994                 goto exit2;
1995 
1996         new_dir = newnd.dentry;
1997         if (newnd.last_type != LAST_NORM)
1998                 goto exit2;
1999 
2000         double_lock(new_dir, old_dir);
2001 
2002         old_dentry = lookup_hash(&oldnd.last, old_dir);
2003         error = PTR_ERR(old_dentry);
2004         if (IS_ERR(old_dentry))
2005                 goto exit3;
2006         /* source must exist */
2007         error = -ENOENT;
2008         if (!old_dentry->d_inode)
2009                 goto exit4;
2010         fset = presto_fset(old_dentry);
2011         error = -EINVAL;
2012         if ( !fset ) {
2013                 CERROR("No fileset!\n");
2014                 EXIT;
2015                 goto exit4;
2016         }
2017         /* unless the source is a directory trailing slashes give -ENOTDIR */
2018         if (!S_ISDIR(old_dentry->d_inode->i_mode)) {
2019                 error = -ENOTDIR;
2020                 if (oldnd.last.name[oldnd.last.len])
2021                         goto exit4;
2022                 if (newnd.last.name[newnd.last.len])
2023                         goto exit4;
2024         }
2025         new_dentry = lookup_hash(&newnd.last, new_dir);
2026         error = PTR_ERR(new_dentry);
2027         if (IS_ERR(new_dentry))
2028                 goto exit4;
2029 
2030         lock_kernel();
2031         error = presto_do_rename(fset, old_dir, old_dentry,
2032                                    new_dir, new_dentry, info);
2033         unlock_kernel();
2034 
2035         dput(new_dentry);
2036 exit4:
2037         dput(old_dentry);
2038 exit3:
2039         double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem);
2040 exit2:
2041         path_release(&newnd);
2042 exit1:
2043         path_release(&oldnd);
2044 exit:
2045         return error;
2046 }
2047 
lento_rename(const char * oldname,const char * newname,struct lento_vfs_context * info)2048 int  lento_rename(const char * oldname, const char * newname,
2049                   struct lento_vfs_context *info)
2050 {
2051         int error;
2052         char * from;
2053         char * to;
2054 
2055         from = getname(oldname);
2056         if(IS_ERR(from))
2057                 return PTR_ERR(from);
2058         to = getname(newname);
2059         error = PTR_ERR(to);
2060         if (!IS_ERR(to)) {
2061                 error = lento_do_rename(from,to, info);
2062                 putname(to);
2063         }
2064         putname(from);
2065         return error;
2066 }
2067 
presto_iopen(struct dentry * dentry,ino_t ino,unsigned int generation)2068 struct dentry *presto_iopen(struct dentry *dentry,
2069                             ino_t ino, unsigned int generation)
2070 {
2071         struct presto_file_set *fset;
2072         char name[48];
2073         int error;
2074 
2075         ENTRY;
2076         /* see if we already have the dentry we want */
2077         if (dentry->d_inode && dentry->d_inode->i_ino == ino &&
2078             dentry->d_inode->i_generation == generation) {
2079                 EXIT;
2080                 return dentry;
2081         }
2082 
2083         /* Make sure we have a cache beneath us.  We should always find at
2084          * least one dentry inside the cache (if it exists), otherwise not
2085          * even the cache root exists, or we passed in a bad name.
2086          */
2087         fset = presto_fset(dentry);
2088         error = -EINVAL;
2089         if (!fset) {
2090                 CERROR("No fileset for %*s!\n",
2091                        dentry->d_name.len, dentry->d_name.name);
2092                 EXIT;
2093                 dput(dentry);
2094                 return ERR_PTR(error);
2095         }
2096         dput(dentry);
2097 
2098         sprintf(name, "%s%#lx%c%#x",
2099                 PRESTO_ILOOKUP_MAGIC, ino, PRESTO_ILOOKUP_SEP, generation);
2100         CDEBUG(D_PIOCTL, "opening %ld by number (as %s)\n", ino, name);
2101         return lookup_one_len(name, fset->fset_dentry, strlen(name));
2102 }
2103 
presto_filp_dopen(struct dentry * dentry,int flags)2104 static struct file *presto_filp_dopen(struct dentry *dentry, int flags)
2105 {
2106         struct file *f;
2107         struct inode *inode;
2108         int flag, error;
2109 
2110         ENTRY;
2111         error = -ENFILE;
2112         f = get_empty_filp();
2113         if (!f) {
2114                 CDEBUG(D_PIOCTL, "error getting file pointer\n");
2115                 EXIT;
2116                 goto out;
2117         }
2118         f->f_flags = flag = flags;
2119         f->f_mode = (flag+1) & O_ACCMODE;
2120         inode = dentry->d_inode;
2121         if (f->f_mode & FMODE_WRITE) {
2122                 error = get_write_access(inode);
2123                 if (error) {
2124                         CDEBUG(D_PIOCTL, "error getting write access\n");
2125                         EXIT;                        goto cleanup_file;
2126                 }
2127         }
2128 
2129         f->f_dentry = dentry;
2130         f->f_pos = 0;
2131         f->f_reada = 0;
2132         f->f_op = NULL;
2133         if (inode->i_op)
2134                 /* XXX should we set to presto ops, or leave at cache ops? */
2135                 f->f_op = inode->i_fop;
2136         if (f->f_op && f->f_op->open) {
2137                 error = f->f_op->open(inode, f);
2138                 if (error) {
2139                         CDEBUG(D_PIOCTL, "error calling cache 'open'\n");
2140                         EXIT;
2141                         goto cleanup_all;
2142                 }
2143         }
2144         f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
2145 
2146         return f;
2147 
2148 cleanup_all:
2149         if (f->f_mode & FMODE_WRITE)
2150                 put_write_access(inode);
2151 cleanup_file:
2152         put_filp(f);
2153 out:
2154         return ERR_PTR(error);
2155 }
2156 
2157 
2158 /* Open an inode by number.  We pass in the cache root name (or a subdirectory
2159  * from the cache that is guaranteed to exist) to be able to access the cache.
2160  */
lento_iopen(const char * name,ino_t ino,unsigned int generation,int flags)2161 int lento_iopen(const char *name, ino_t ino, unsigned int generation,
2162                 int flags)
2163 {
2164         char * tmp;
2165         struct dentry *dentry;
2166         struct nameidata nd;
2167         int fd;
2168         int error;
2169 
2170         ENTRY;
2171         CDEBUG(D_PIOCTL,
2172                "open %s:inode %#lx (%ld), generation %x (%d), flags %d \n",
2173                name, ino, ino, generation, generation, flags);
2174         /* We don't allow creation of files by number only, as it would
2175          * lead to a dangling files not in any directory.  We could also
2176          * just turn off the flag and ignore it.
2177          */
2178         if (flags & O_CREAT) {
2179                 CERROR("%s: create file by inode number (%ld) not allowed\n",
2180                        __FUNCTION__, ino);
2181                 EXIT;
2182                 return -EACCES;
2183         }
2184 
2185         tmp = getname(name);
2186         if (IS_ERR(tmp)) {
2187                 EXIT;
2188                 return PTR_ERR(tmp);
2189         }
2190 
2191         lock_kernel();
2192 again:  /* look the named file or a parent directory so we can get the cache */
2193         error = presto_walk(tmp, &nd);
2194         if ( error && error != -ENOENT ) {
2195                 EXIT;
2196                 unlock_kernel();
2197                 putname(tmp);
2198                 return error;
2199         }
2200         if (error == -ENOENT)
2201                 dentry = NULL;
2202         else
2203                 dentry = nd.dentry;
2204 
2205         /* we didn't find the named file, so see if a parent exists */
2206         if (!dentry) {
2207                 char *slash;
2208 
2209                 slash = strrchr(tmp, '/');
2210                 if (slash && slash != tmp) {
2211                         *slash = '\0';
2212                         path_release(&nd);
2213                         goto again;
2214                 }
2215                 /* we should never get here... */
2216                 CDEBUG(D_PIOCTL, "no more path components to try!\n");
2217                 fd = -ENOENT;
2218                 goto exit;
2219         }
2220         CDEBUG(D_PIOCTL, "returned dentry %p\n", dentry);
2221 
2222         dentry = presto_iopen(dentry, ino, generation);
2223         fd = PTR_ERR(dentry);
2224         if (IS_ERR(dentry)) {
2225                 EXIT;
2226                 goto exit;
2227         }
2228 
2229         /* XXX start of code that might be replaced by something like:
2230          * if (flags & (O_WRONLY | O_RDWR)) {
2231          *      error = get_write_access(dentry->d_inode);
2232          *      if (error) {
2233          *              EXIT;
2234          *              goto cleanup_dput;
2235          *      }
2236          * }
2237          * fd = open_dentry(dentry, flags);
2238          *
2239          * including the presto_filp_dopen() function (check dget counts!)
2240          */
2241         fd = get_unused_fd();
2242         if (fd < 0) {
2243                 EXIT;
2244                 goto exit;
2245         }
2246 
2247         {
2248                 int error;
2249                 struct file * f = presto_filp_dopen(dentry, flags);
2250                 error = PTR_ERR(f);
2251                 if (IS_ERR(f)) {
2252                         put_unused_fd(fd);
2253                         fd = error;
2254                 } else {
2255                         fd_install(fd, f);
2256                 }
2257         }
2258         /* end of code that might be replaced by open_dentry */
2259 
2260         EXIT;
2261 exit:
2262         unlock_kernel();
2263         path_release(&nd);
2264         putname(tmp);
2265         return fd;
2266 }
2267 
2268 #ifdef CONFIG_FS_EXT_ATTR
2269 
2270 #ifdef CONFIG_FS_POSIX_ACL
2271 /* Posix ACL code changes i_mode without using a notify_change (or
2272  * a mark_inode_dirty!). We need to duplicate this at the reintegrator
2273  * which is done by this function. This function also takes care of
2274  * resetting the cached posix acls in this inode. If we don't reset these
2275  * VFS continues using the old acl information, which by now may be out of
2276  * date.
2277  */
presto_setmode(struct presto_file_set * fset,struct dentry * dentry,mode_t mode)2278 int presto_setmode(struct presto_file_set *fset, struct dentry *dentry,
2279                    mode_t mode)
2280 {
2281         struct inode *inode = dentry->d_inode;
2282 
2283         ENTRY;
2284         /* The extended attributes for this inode were modified.
2285          * At this point we can not be sure if any of the ACL
2286          * information for this inode was updated. So we will
2287          * force VFS to reread the acls. Note that we do this
2288          * only when called from the SETEXTATTR ioctl, which is why we
2289          * do this while setting the mode of the file. Also note
2290          * that mark_inode_dirty is not be needed for i_*acl only
2291          * to force i_mode info to disk, and should be removed once
2292          * we use notify_change to update the mode.
2293          * XXX: is mode setting really needed? Just setting acl's should
2294          * be enough! VFS should change the i_mode as needed? SHP
2295          */
2296         if (inode->i_acl &&
2297             inode->i_acl != POSIX_ACL_NOT_CACHED)
2298             posix_acl_release(inode->i_acl);
2299         if (inode->i_default_acl &&
2300             inode->i_default_acl != POSIX_ACL_NOT_CACHED)
2301             posix_acl_release(inode->i_default_acl);
2302         inode->i_acl = POSIX_ACL_NOT_CACHED;
2303         inode->i_default_acl = POSIX_ACL_NOT_CACHED;
2304         inode->i_mode = mode;
2305         /* inode should already be dirty...but just in case */
2306         mark_inode_dirty(inode);
2307         return 0;
2308 
2309 #if 0
2310         /* XXX: The following code is the preferred way to set mode,
2311          * however, I need to carefully go through possible recursion
2312          * paths back into presto. See comments in presto_do_setattr.
2313          */
2314         {
2315         int error=0;
2316         struct super_operations *sops;
2317         struct iattr iattr;
2318 
2319         iattr.ia_mode = mode;
2320         iattr.ia_valid = ATTR_MODE|ATTR_FORCE;
2321 
2322         error = -EPERM;
2323         sops = filter_c2csops(fset->fset_cache->cache_filter);
2324         if (!sops &&
2325             !sops->notify_change) {
2326                 EXIT;
2327                 return error;
2328         }
2329 
2330         error = sops->notify_change(dentry, &iattr);
2331 
2332         EXIT;
2333         return error;
2334         }
2335 #endif
2336 }
2337 #endif
2338 
2339 /* setextattr Interface to cache filesystem */
presto_do_set_ext_attr(struct presto_file_set * fset,struct dentry * dentry,const char * name,void * buffer,size_t buffer_len,int flags,mode_t * mode,struct lento_vfs_context * info)2340 int presto_do_set_ext_attr(struct presto_file_set *fset,
2341                            struct dentry *dentry,
2342                            const char *name, void *buffer,
2343                            size_t buffer_len, int flags, mode_t *mode,
2344                            struct lento_vfs_context *info)
2345 {
2346         struct rec_info rec;
2347         struct inode *inode = dentry->d_inode;
2348         struct inode_operations *iops;
2349         int error;
2350         struct presto_version ver;
2351         void *handle;
2352         char temp[PRESTO_EXT_ATTR_NAME_MAX+1];
2353 
2354         ENTRY;
2355         error = -EROFS;
2356         if (IS_RDONLY(inode)) {
2357                 EXIT;
2358                 return -EROFS;
2359         }
2360 
2361         if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
2362                 EXIT;
2363                 return -EPERM;
2364         }
2365 
2366         presto_getversion(&ver, inode);
2367         error = -EPERM;
2368         /* We need to invoke different filters based on whether
2369          * this dentry is a regular file, directory or symlink.
2370          */
2371         switch (inode->i_mode & S_IFMT) {
2372                 case S_IFLNK: /* symlink */
2373                     iops = filter_c2csiops(fset->fset_cache->cache_filter);
2374                     break;
2375                 case S_IFDIR: /* directory */
2376                     iops = filter_c2cdiops(fset->fset_cache->cache_filter);
2377                     break;
2378                 case S_IFREG:
2379                 default: /* everything else including regular files */
2380                     iops = filter_c2cfiops(fset->fset_cache->cache_filter);
2381         }
2382 
2383         if (!iops && !iops->set_ext_attr) {
2384                 EXIT;
2385                 return error;
2386         }
2387 
2388         error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);
2389         if (error) {
2390                 EXIT;
2391                 return error;
2392         }
2393 
2394 
2395         handle = presto_trans_start(fset,dentry->d_inode,KML_OPCODE_SETEXTATTR);
2396         if ( IS_ERR(handle) ) {
2397                 CERROR("presto_do_set_ext_attr: no space for transaction\n");
2398                 presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
2399                 return -ENOSPC;
2400         }
2401 
2402         /* We first "truncate" name to the maximum allowable in presto */
2403         /* This simulates the strncpy_from_use code in fs/ext_attr.c */
2404         strncpy(temp,name,sizeof(temp));
2405 
2406         /* Pass down to cache*/
2407         error = iops->set_ext_attr(inode,temp,buffer,buffer_len,flags);
2408         if (error) {
2409                 EXIT;
2410                 goto exit;
2411         }
2412 
2413 #ifdef CONFIG_FS_POSIX_ACL
2414         /* Reset mode if specified*/
2415         /* XXX: when we do native acl support, move this code out! */
2416         if (mode != NULL) {
2417                 error = presto_setmode(fset, dentry, *mode);
2418                 if (error) {
2419                     EXIT;
2420                     goto exit;
2421                 }
2422         }
2423 #endif
2424 
2425         /* Reset ctime. Only inode change time (ctime) is affected */
2426         error = presto_settime(fset, NULL, NULL, dentry, info, ATTR_CTIME);
2427         if (error) {
2428                 EXIT;
2429                 goto exit;
2430         }
2431 
2432         if (flags & EXT_ATTR_FLAG_USER) {
2433                 CERROR(" USER flag passed to presto_do_set_ext_attr!\n");
2434                 BUG();
2435         }
2436 
2437         /* We are here, so set_ext_attr succeeded. We no longer need to keep
2438          * track of EXT_ATTR_FLAG_{EXISTS,CREATE}, instead, we will force
2439          * the attribute value during log replay. -SHP
2440          */
2441         flags &= ~(EXT_ATTR_FLAG_EXISTS | EXT_ATTR_FLAG_CREATE);
2442 
2443         presto_debug_fail_blkdev(fset, KML_OPCODE_SETEXTATTR | 0x10);
2444         if ( presto_do_kml(info, dentry) )
2445                 error = presto_journal_set_ext_attr
2446                         (&rec, fset, dentry, &ver, name, buffer,
2447                          buffer_len, flags);
2448 
2449         presto_debug_fail_blkdev(fset, KML_OPCODE_SETEXTATTR | 0x20);
2450         if ( presto_do_rcvd(info, dentry) )
2451                 error = presto_write_last_rcvd(&rec, fset, info);
2452 
2453         presto_debug_fail_blkdev(fset, KML_OPCODE_SETEXTATTR | 0x30);
2454         EXIT;
2455 exit:
2456         presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
2457         presto_trans_commit(fset, handle);
2458 
2459         return error;
2460 }
2461 #endif
2462