Merge with Linux 2.5.48.
[linux-2.6/linux-mips.git] / fs / intermezzo / vfs.c
blobfb3791b4a82ac551dd04eecf6026b684564cbdf1
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
5 * Copyright (C) 2000 Stelias Computing, Inc.
6 * Copyright (C) 2000 Red Hat, Inc.
8 * This file is part of InterMezzo, http://www.inter-mezzo.org.
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.
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.
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.
23 * vfs.c
25 * This file implements kernel downcalls from lento.
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.
32 * Extended attribute support
33 * Copyright (C) 2001 Shirish H. Phatak, Tacit Networks, Inc.
35 * This code is based on code from namei.c in the linux file system;
36 * see copyright notice below.
39 /** namei.c copyright **/
42 * linux/fs/namei.c
44 * Copyright (C) 1991, 1992 Linus Torvalds
47 * Some corrections by tytso.
50 /* [Feb 1997 T. Schoebel-Theuer] Complete rewrite of the pathname
51 * lookup logic.
54 /** end of namei.c copyright **/
56 #include <linux/mm.h>
57 #include <linux/proc_fs.h>
58 #include <linux/smp_lock.h>
59 #include <linux/quotaops.h>
61 #include <asm/uaccess.h>
62 #include <asm/unaligned.h>
63 #include <asm/semaphore.h>
64 #include <asm/pgtable.h>
66 #include <linux/file.h>
67 #include <linux/fs.h>
68 #include <linux/namei.h>
69 #include <linux/blk.h>
71 #include <linux/intermezzo_fs.h>
72 #include <linux/intermezzo_psdev.h>
74 #ifdef CONFIG_FS_EXT_ATTR
75 # include <linux/ext_attr.h>
77 # if 0 /* was a broken check for Posix ACLs */
78 # include <linux/posix_acl.h>
79 # endif
80 #endif
82 extern struct inode_operations presto_sym_iops;
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*/
88 int presto_write_last_rcvd(struct rec_info *recinfo,
89 struct presto_file_set *fset,
90 struct lento_vfs_context *info)
92 int rc;
93 struct izo_rcvd_rec rcvd_rec;
95 ENTRY;
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);
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;
112 EXIT;
113 return 0;
117 * It's inline, so penalty for filesystems that don't use sticky bit is
118 * minimal.
120 static inline int check_sticky(struct inode *dir, struct inode *inode)
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);
131 /* from linux/fs/namei.c */
132 static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
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;
155 /* from linux/fs/namei.c */
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);
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.
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
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.
180 inline void presto_debug_fail_blkdev(struct presto_file_set *fset,
181 unsigned long value)
183 int minor = presto_f2m(fset);
184 int errorval = izo_channels[minor].uc_errorval;
185 kdev_t dev = to_kdev_t(fset->fset_dentry->d_inode->i_dev);
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 = -kdev_val(dev);
193 #else
194 #define presto_debug_fail_blkdev(dev,value) do {} while (0)
195 #endif
198 static inline int presto_do_kml(struct lento_vfs_context *info,
199 struct dentry *dentry)
201 if ( ! (info->flags & LENTO_FL_KML) )
202 return 0;
203 if ( presto_chk(dentry, PRESTO_DONT_JOURNAL) )
204 return 0;
205 return 1;
208 static inline int presto_do_rcvd(struct lento_vfs_context *info,
209 struct dentry *dentry)
211 if ( ! (info->flags & LENTO_FL_EXPECT) )
212 return 0;
213 if ( presto_chk(dentry, PRESTO_DONT_JOURNAL) )
214 return 0;
215 return 1;
219 /* XXX fixme: this should not fail, all these dentries are in memory
220 when _we_ call this */
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)
228 int error = 0;
229 struct dentry *dentry;
230 struct inode *inode;
231 struct inode_operations *iops;
232 struct iattr iattr;
234 ENTRY;
235 if (ctx->flags & LENTO_FL_IGNORE_TIME ) {
236 EXIT;
237 return 0;
240 iattr.ia_ctime = ctx->updated_time;
241 iattr.ia_mtime = ctx->updated_time;
242 iattr.ia_valid = valid;
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;
257 inode = dentry->d_inode;
259 error = -EROFS;
260 if (IS_RDONLY(inode)) {
261 EXIT;
262 return -EROFS;
265 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
266 EXIT;
267 return -EPERM;
270 error = -EPERM;
271 iops = filter_c2cdiops(fset->fset_cache->cache_filter);
272 if (!iops) {
273 EXIT;
274 return error;
277 if (iops->setattr != NULL)
278 error = iops->setattr(dentry, &iattr);
279 else {
280 error = 0;
281 inode_setattr(dentry->d_inode, &iattr);
284 EXIT;
285 return error;
288 void izo_get_rollback_data(struct inode *inode, struct izo_rollback_data *rb)
290 rb->rb_mode = (__u32)inode->i_mode;
291 rb->rb_rdev = (__u32)kdev_t_to_nr(inode->i_rdev);
292 rb->rb_uid = (__u64)inode->i_uid;
293 rb->rb_gid = (__u64)inode->i_gid;
297 int presto_do_close(struct presto_file_set *fset, struct file *file)
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;
306 ENTRY;
307 presto_getversion(&fdata->fd_info.remote_version, inode);
309 rc = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);
310 if (rc) {
311 EXIT;
312 return rc;
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;
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;
331 if (fdata->fd_info.flags & LENTO_FL_EXPECT)
332 rc = presto_write_last_rcvd(&rec, fset, &fdata->fd_info);
334 if (rc) {
335 CERROR("presto_close: cannot journal last_rcvd\n");
336 goto out;
338 presto_trans_commit(fset, handle);
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;
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;
352 presto_truncate_lml(fset);
354 out:
355 presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
356 presto_trans_commit(fset, handle);
357 EXIT;
358 return rc;
361 int presto_do_setattr(struct presto_file_set *fset, struct dentry *dentry,
362 struct iattr *iattr, struct lento_vfs_context *info)
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;
373 ENTRY;
374 error = -EROFS;
375 if (IS_RDONLY(inode)) {
376 EXIT;
377 return -EROFS;
380 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
381 EXIT;
382 return -EPERM;
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);
390 error = presto_reserve_space(fset->fset_cache, 2*PRESTO_REQHIGH);
391 if (error) {
392 EXIT;
393 return error;
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);
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;
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);
421 if (!error && (iattr->ia_valid & ATTR_SIZE))
422 vmtruncate(inode, iattr->ia_size);
424 if (error) {
425 EXIT;
426 goto exit;
429 presto_debug_fail_blkdev(fset, KML_OPCODE_SETATTR | 0x10);
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);
444 if (!error)
445 error = presto_journal_setattr(&rec, fset, dentry,
446 &old_ver, &rb, iattr);
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);
453 presto_debug_fail_blkdev(fset, KML_OPCODE_SETATTR | 0x30);
455 EXIT;
456 exit:
457 presto_release_space(fset->fset_cache, 2*PRESTO_REQHIGH);
458 presto_trans_commit(fset, handle);
459 return error;
462 int lento_setattr(const char *name, struct iattr *iattr,
463 struct lento_vfs_context *info)
465 struct nameidata nd;
466 struct dentry *dentry;
467 struct presto_file_set *fset;
468 int error;
469 #if 0 /* was a broken check for Posix ACLs */
470 int (*set_posix_acl)(struct inode *, int type, posix_acl_t *)=NULL;
471 #endif
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.tv_sec, iattr->ia_ctime.tv_sec,
479 iattr->ia_attr_flags);
480 CDEBUG(D_PIOCTL, "offset %d, recno %d, flags %#x\n",
481 info->slot_offset, info->recno, info->flags);
483 lock_kernel();
484 error = presto_walk(name, &nd);
485 if (error) {
486 EXIT;
487 goto exit;
489 dentry = nd.dentry;
491 fset = presto_fset(dentry);
492 error = -EINVAL;
493 if ( !fset ) {
494 CERROR("No fileset!\n");
495 EXIT;
496 goto exit_lock;
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.
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 #if 0 /* was a broken check for Posix ACLs */
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
520 * This will probably still be required when native
521 * acl journalling is in place.
523 set_posix_acl=dentry->d_inode->i_op->set_posix_acl;
524 dentry->d_inode->i_op->set_posix_acl=NULL;
525 #endif
528 error = presto_do_setattr(fset, dentry, iattr, info);
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;
538 #if 0 /* was a broken check for Posix ACLs */
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
545 EXIT;
546 exit_lock:
547 path_release(&nd);
548 exit:
549 unlock_kernel();
550 return error;
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)
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;
563 ENTRY;
564 mode &= S_IALLUGO;
565 mode |= S_IFREG;
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;
575 error = may_create(dir->d_inode, dentry);
576 if (error) {
577 EXIT;
578 goto exit_pre_lock;
581 error = -EPERM;
582 iops = filter_c2cdiops(fset->fset_cache->cache_filter);
583 if (!iops->create) {
584 EXIT;
585 goto exit_pre_lock;
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;
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;
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);
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);
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);
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;
631 presto_debug_fail_blkdev(fset, KML_OPCODE_CREATE | 0x10);
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);
640 presto_debug_fail_blkdev(fset, KML_OPCODE_CREATE | 0x20);
642 if ( presto_do_rcvd(info, dentry) )
643 error = presto_write_last_rcvd(&rec, fset, info);
645 presto_debug_fail_blkdev(fset, KML_OPCODE_CREATE | 0x30);
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);
654 EXIT;
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;
665 /* from namei.c */
666 static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
668 struct dentry *dentry;
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;
687 int lento_create(const char *name, int mode, struct lento_vfs_context *info)
689 int error;
690 struct nameidata nd;
691 char * pathname;
692 struct dentry *dentry;
693 struct presto_file_set *fset;
695 ENTRY;
696 pathname = getname(name);
697 error = PTR_ERR(pathname);
698 if (IS_ERR(pathname)) {
699 EXIT;
700 goto exit;
703 /* this looks up the parent */
704 error = path_lookup(pathname, LOOKUP_PARENT, &nd);
705 if (error) {
706 EXIT;
707 goto exit;
709 dentry = lookup_create(&nd, 0);
710 error = PTR_ERR(dentry);
711 if (IS_ERR(dentry)) {
712 EXIT;
713 goto exit_lock;
716 fset = presto_fset(dentry);
717 error = -EINVAL;
718 if ( !fset ) {
719 CERROR("No fileset!\n");
720 EXIT;
721 goto exit_lock;
723 error = presto_do_create(fset, dentry->d_parent, dentry, (mode&S_IALLUGO)|S_IFREG,
724 info);
726 EXIT;
728 exit_lock:
729 path_release (&nd);
730 dput(dentry);
731 up(&dentry->d_parent->d_inode->i_sem);
732 putname(pathname);
733 exit:
734 return error;
737 int presto_do_link(struct presto_file_set *fset, struct dentry *old_dentry,
738 struct dentry *dir, struct dentry *new_dentry,
739 struct lento_vfs_context *info)
741 struct rec_info rec;
742 struct inode *inode;
743 int error;
744 struct inode_operations *iops;
745 struct presto_version tgt_dir_ver;
746 struct presto_version new_link_ver;
747 void *handle;
749 // down(&dir->d_inode->i_zombie);
750 error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);
751 if (error) {
752 EXIT;
753 // up(&dir->d_inode->i_zombie);
754 return error;
756 error = -ENOENT;
757 inode = old_dentry->d_inode;
758 if (!inode)
759 goto exit_lock;
761 error = may_create(dir->d_inode, new_dentry);
762 if (error)
763 goto exit_lock;
765 error = -EXDEV;
766 if (dir->d_inode->i_dev != inode->i_dev)
767 goto exit_lock;
770 * A link to an append-only or immutable file cannot be created.
772 error = -EPERM;
773 if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
774 EXIT;
775 goto exit_lock;
778 iops = filter_c2cdiops(fset->fset_cache->cache_filter);
779 if (!iops->link) {
780 EXIT;
781 goto exit_lock;
785 presto_getversion(&tgt_dir_ver, dir->d_inode);
786 handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_LINK);
787 if ( IS_ERR(handle) ) {
788 presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
789 CERROR("presto_do_link: no space for transaction\n");
790 return -ENOSPC;
793 DQUOT_INIT(dir->d_inode);
794 lock_kernel();
795 error = iops->link(old_dentry, dir->d_inode, new_dentry);
796 unlock_kernel();
797 if (error) {
798 EXIT;
799 goto exit_lock;
802 /* link dd data to that of existing dentry */
803 old_dentry->d_op->d_release(new_dentry);
804 if (!presto_d2d(old_dentry))
805 BUG();
806 presto_d2d(old_dentry)->dd_count++;
808 new_dentry->d_fsdata = presto_d2d(old_dentry);
810 info->flags |= LENTO_FL_TOUCH_PARENT;
811 error = presto_settime(fset, NULL, dir, new_dentry,
812 info, ATTR_CTIME);
813 if (error) {
814 EXIT;
815 goto exit_lock;
818 presto_debug_fail_blkdev(fset, KML_OPCODE_LINK | 0x10);
819 presto_getversion(&new_link_ver, new_dentry->d_inode);
820 if ( presto_do_kml(info, old_dentry) )
821 error = presto_journal_link(&rec, fset, old_dentry, new_dentry,
822 &tgt_dir_ver, &new_link_ver);
824 presto_debug_fail_blkdev(fset, KML_OPCODE_LINK | 0x20);
825 if ( presto_do_rcvd(info, old_dentry) )
826 error = presto_write_last_rcvd(&rec, fset, info);
828 presto_debug_fail_blkdev(fset, KML_OPCODE_LINK | 0x30);
829 EXIT;
830 presto_trans_commit(fset, handle);
831 exit_lock:
832 presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
833 // up(&dir->d_inode->i_zombie);
834 return error;
838 int lento_link(const char * oldname, const char * newname,
839 struct lento_vfs_context *info)
841 int error;
842 char * to;
843 struct presto_file_set *fset;
845 to = getname(newname);
846 error = PTR_ERR(to);
847 if (!IS_ERR(to)) {
848 struct dentry *new_dentry;
849 struct nameidata nd, old_nd;
851 error = __user_walk(oldname, 0, &old_nd);
852 if (error)
853 goto exit;
854 error = path_lookup(to, LOOKUP_PARENT, &nd);
855 if (error)
856 goto out;
857 error = -EXDEV;
858 if (old_nd.mnt != nd.mnt)
859 goto out;
860 new_dentry = lookup_create(&nd, 0);
861 error = PTR_ERR(new_dentry);
863 if (!IS_ERR(new_dentry)) {
864 fset = presto_fset(new_dentry);
865 error = -EINVAL;
866 if ( !fset ) {
867 CERROR("No fileset!\n");
868 EXIT;
869 goto out2;
871 error = presto_do_link(fset, old_nd.dentry,
872 nd.dentry,
873 new_dentry, info);
874 dput(new_dentry);
876 out2:
877 up(&nd.dentry->d_inode->i_sem);
878 path_release(&nd);
879 out:
880 path_release(&old_nd);
881 exit:
882 putname(to);
884 return error;
887 int presto_do_unlink(struct presto_file_set *fset, struct dentry *dir,
888 struct dentry *dentry, struct lento_vfs_context *info)
890 struct rec_info rec;
891 struct inode_operations *iops;
892 struct presto_version tgt_dir_ver, old_file_ver;
893 struct izo_rollback_data rb;
894 void *handle;
895 int do_kml = 0, do_rcvd = 0, linkno = 0, error, old_targetlen = 0;
896 char *old_target = NULL;
898 ENTRY;
899 // down(&dir->d_inode->i_zombie);
900 error = may_delete(dir->d_inode, dentry, 0);
901 if (error) {
902 EXIT;
903 // up(&dir->d_inode->i_zombie);
904 return error;
907 error = -EPERM;
908 iops = filter_c2cdiops(fset->fset_cache->cache_filter);
909 if (!iops->unlink) {
910 EXIT;
911 // up(&dir->d_inode->i_zombie);
912 return error;
915 error = presto_reserve_space(fset->fset_cache, PRESTO_REQLOW);
916 if (error) {
917 EXIT;
918 // up(&dir->d_inode->i_zombie);
919 return error;
923 if (presto_d2d(dentry)) {
924 struct presto_dentry_data *dd = presto_d2d(dentry);
925 struct dentry *de = dd->dd_inodentry;
926 if (de && dentry->d_inode->i_nlink == 1) {
927 dd->dd_count--;
928 dd->dd_inodentry = NULL;
929 de->d_fsdata = NULL;
930 atomic_dec(&de->d_inode->i_count);
931 de->d_inode = NULL;
932 dput(de);
936 presto_getversion(&tgt_dir_ver, dir->d_inode);
937 presto_getversion(&old_file_ver, dentry->d_inode);
938 izo_get_rollback_data(dentry->d_inode, &rb);
939 handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_UNLINK);
940 if ( IS_ERR(handle) ) {
941 presto_release_space(fset->fset_cache, PRESTO_REQLOW);
942 CERROR("ERROR: presto_do_unlink: no space for transaction. Tell Peter.\n");
943 // up(&dir->d_inode->i_zombie);
944 return -ENOSPC;
946 DQUOT_INIT(dir->d_inode);
947 if (d_mountpoint(dentry))
948 error = -EBUSY;
949 else {
950 lock_kernel();
951 linkno = dentry->d_inode->i_nlink;
952 if (linkno > 1) {
953 dget(dentry);
956 if (S_ISLNK(dentry->d_inode->i_mode)) {
957 mm_segment_t old_fs;
958 struct inode_operations *riops;
959 riops = filter_c2csiops(fset->fset_cache->cache_filter);
961 PRESTO_ALLOC(old_target, PATH_MAX);
962 if (old_target == NULL) {
963 error = -ENOMEM;
964 EXIT;
965 goto exit;
968 old_fs = get_fs();
969 set_fs(get_ds());
971 if (riops->readlink == NULL)
972 CERROR("InterMezzo %s: no readlink iops.\n",
973 __FUNCTION__);
974 else
975 old_targetlen =
976 riops->readlink(dentry, old_target,
977 PATH_MAX);
978 if (old_targetlen < 0) {
979 CERROR("InterMezzo: readlink failed: %ld\n",
980 PTR_ERR(old_target));
981 PRESTO_FREE(old_target, PATH_MAX);
982 old_target = NULL;
983 old_targetlen = 0;
985 set_fs(old_fs);
988 do_kml = presto_do_kml(info, dir);
989 do_rcvd = presto_do_rcvd(info, dir);
990 error = iops->unlink(dir->d_inode, dentry);
991 unlock_kernel();
992 if (!error)
993 d_delete(dentry);
996 if (linkno > 1) {
997 /* FIXME: Combine this with the next call? */
998 error = presto_settime(fset, NULL, NULL, dentry,
999 info, ATTR_CTIME);
1000 dput(dentry);
1001 if (error) {
1002 EXIT;
1003 goto exit;
1007 error = presto_settime(fset, NULL, NULL, dir,
1008 info, ATTR_CTIME | ATTR_MTIME);
1009 if (error) {
1010 EXIT;
1011 goto exit;
1014 // up(&dir->d_inode->i_zombie);
1015 if (error) {
1016 EXIT;
1017 goto exit;
1020 presto_debug_fail_blkdev(fset, KML_OPCODE_UNLINK | 0x10);
1021 if ( do_kml )
1022 error = presto_journal_unlink(&rec, fset, dir, &tgt_dir_ver,
1023 &old_file_ver, &rb, dentry,
1024 old_target, old_targetlen);
1025 presto_debug_fail_blkdev(fset, KML_OPCODE_UNLINK | 0x20);
1026 if ( do_rcvd ) {
1027 error = presto_write_last_rcvd(&rec, fset, info);
1029 presto_debug_fail_blkdev(fset, KML_OPCODE_UNLINK | 0x30);
1030 EXIT;
1031 exit:
1032 presto_release_space(fset->fset_cache, PRESTO_REQLOW);
1033 presto_trans_commit(fset, handle);
1034 if (old_target != NULL)
1035 PRESTO_FREE(old_target, PATH_MAX);
1036 return error;
1040 int lento_unlink(const char *pathname, struct lento_vfs_context *info)
1042 int error = 0;
1043 char * name;
1044 struct dentry *dentry;
1045 struct nameidata nd;
1046 struct presto_file_set *fset;
1048 ENTRY;
1050 name = getname(pathname);
1051 if(IS_ERR(name))
1052 return PTR_ERR(name);
1054 error = path_lookup(name, LOOKUP_PARENT, &nd);
1055 if (error)
1056 goto exit;
1057 error = -EISDIR;
1058 if (nd.last_type != LAST_NORM)
1059 goto exit1;
1060 down(&nd.dentry->d_inode->i_sem);
1061 dentry = lookup_hash(&nd.last, nd.dentry);
1062 error = PTR_ERR(dentry);
1063 if (!IS_ERR(dentry)) {
1064 fset = presto_fset(dentry);
1065 error = -EINVAL;
1066 if ( !fset ) {
1067 CERROR("No fileset!\n");
1068 EXIT;
1069 goto exit2;
1071 /* Why not before? Because we want correct error value */
1072 if (nd.last.name[nd.last.len])
1073 goto slashes;
1074 error = presto_do_unlink(fset, nd.dentry, dentry, info);
1075 exit2:
1076 EXIT;
1077 dput(dentry);
1079 up(&nd.dentry->d_inode->i_sem);
1080 exit1:
1081 path_release(&nd);
1082 exit:
1083 putname(name);
1085 return error;
1087 slashes:
1088 error = !dentry->d_inode ? -ENOENT :
1089 S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR;
1090 goto exit2;
1093 int presto_do_symlink(struct presto_file_set *fset, struct dentry *dir,
1094 struct dentry *dentry, const char *oldname,
1095 struct lento_vfs_context *info)
1097 struct rec_info rec;
1098 int error;
1099 struct presto_version tgt_dir_ver, new_link_ver;
1100 struct inode_operations *iops;
1101 void *handle;
1103 ENTRY;
1104 // down(&dir->d_inode->i_zombie);
1105 /* record + max path len + space to free */
1106 error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
1107 if (error) {
1108 EXIT;
1109 // up(&dir->d_inode->i_zombie);
1110 return error;
1113 error = may_create(dir->d_inode, dentry);
1114 if (error) {
1115 EXIT;
1116 goto exit_lock;
1119 error = -EPERM;
1120 iops = filter_c2cdiops(fset->fset_cache->cache_filter);
1121 if (!iops->symlink) {
1122 EXIT;
1123 goto exit_lock;
1126 presto_getversion(&tgt_dir_ver, dir->d_inode);
1127 handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_SYMLINK);
1128 if ( IS_ERR(handle) ) {
1129 presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
1130 CERROR("ERROR: presto_do_symlink: no space for transaction. Tell Peter.\n");
1131 EXIT;
1132 // up(&dir->d_inode->i_zombie);
1133 return -ENOSPC;
1135 DQUOT_INIT(dir->d_inode);
1136 lock_kernel();
1137 error = iops->symlink(dir->d_inode, dentry, oldname);
1138 if (error) {
1139 EXIT;
1140 goto exit;
1143 if (dentry->d_inode) {
1144 struct presto_cache *cache = fset->fset_cache;
1146 presto_set_ops(dentry->d_inode, cache->cache_filter);
1148 filter_setup_dentry_ops(cache->cache_filter, dentry->d_op,
1149 &presto_dentry_ops);
1150 dentry->d_op = filter_c2udops(cache->cache_filter);
1151 /* XXX ? Cache state ? if Lento creates a symlink */
1152 if ( ISLENTO(presto_c2m(cache)) ) {
1153 presto_set(dentry, PRESTO_ATTR);
1154 } else {
1155 presto_set(dentry, PRESTO_ATTR | PRESTO_DATA);
1159 info->flags |= LENTO_FL_TOUCH_PARENT;
1160 error = presto_settime(fset, NULL, dir, dentry,
1161 info, ATTR_CTIME | ATTR_MTIME);
1162 if (error) {
1163 EXIT;
1164 goto exit;
1167 presto_debug_fail_blkdev(fset, KML_OPCODE_SYMLINK | 0x10);
1168 presto_getversion(&new_link_ver, dentry->d_inode);
1169 if ( presto_do_kml(info, dentry) )
1170 error = presto_journal_symlink(&rec, fset, dentry, oldname,
1171 &tgt_dir_ver, &new_link_ver);
1173 presto_debug_fail_blkdev(fset, KML_OPCODE_SYMLINK | 0x20);
1174 if ( presto_do_rcvd(info, dentry) )
1175 error = presto_write_last_rcvd(&rec, fset, info);
1177 presto_debug_fail_blkdev(fset, KML_OPCODE_SYMLINK | 0x30);
1178 EXIT;
1179 exit:
1180 unlock_kernel();
1181 presto_trans_commit(fset, handle);
1182 exit_lock:
1183 presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
1184 // up(&dir->d_inode->i_zombie);
1185 return error;
1188 int lento_symlink(const char *oldname, const char *newname,
1189 struct lento_vfs_context *info)
1191 int error;
1192 char *from;
1193 char *to;
1194 struct dentry *dentry;
1195 struct presto_file_set *fset;
1196 struct nameidata nd;
1198 ENTRY;
1199 lock_kernel();
1200 from = getname(oldname);
1201 error = PTR_ERR(from);
1202 if (IS_ERR(from)) {
1203 EXIT;
1204 goto exit;
1207 to = getname(newname);
1208 error = PTR_ERR(to);
1209 if (IS_ERR(to)) {
1210 EXIT;
1211 goto exit_from;
1214 error = path_lookup(to, LOOKUP_PARENT, &nd);
1215 if (error) {
1216 EXIT;
1217 goto exit_to;
1220 dentry = lookup_create(&nd, 0);
1221 error = PTR_ERR(dentry);
1222 if (IS_ERR(dentry)) {
1223 path_release(&nd);
1224 EXIT;
1225 goto exit_to;
1228 fset = presto_fset(dentry);
1229 error = -EINVAL;
1230 if ( !fset ) {
1231 CERROR("No fileset!\n");
1232 path_release(&nd);
1233 EXIT;
1234 goto exit_lock;
1236 error = presto_do_symlink(fset, nd.dentry,
1237 dentry, oldname, info);
1238 path_release(&nd);
1239 EXIT;
1240 exit_lock:
1241 up(&nd.dentry->d_inode->i_sem);
1242 dput(dentry);
1243 exit_to:
1244 putname(to);
1245 exit_from:
1246 putname(from);
1247 exit:
1248 unlock_kernel();
1249 return error;
1252 int presto_do_mkdir(struct presto_file_set *fset, struct dentry *dir,
1253 struct dentry *dentry, int mode,
1254 struct lento_vfs_context *info)
1256 struct rec_info rec;
1257 int error;
1258 struct presto_version tgt_dir_ver, new_dir_ver;
1259 void *handle;
1261 ENTRY;
1262 // down(&dir->d_inode->i_zombie);
1264 /* one journal record + directory block + room for removals*/
1265 error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
1266 if (error) {
1267 EXIT;
1268 // up(&dir->d_inode->i_zombie);
1269 return error;
1272 error = may_create(dir->d_inode, dentry);
1273 if (error) {
1274 EXIT;
1275 goto exit_lock;
1278 error = -EPERM;
1279 if (!filter_c2cdiops(fset->fset_cache->cache_filter)->mkdir) {
1280 EXIT;
1281 goto exit_lock;
1284 error = -ENOSPC;
1285 presto_getversion(&tgt_dir_ver, dir->d_inode);
1286 handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_MKDIR);
1287 if ( IS_ERR(handle) ) {
1288 presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
1289 CERROR("presto_do_mkdir: no space for transaction\n");
1290 goto exit_lock;
1293 DQUOT_INIT(dir->d_inode);
1294 mode &= (S_IRWXUGO|S_ISVTX);
1295 lock_kernel();
1296 error = filter_c2cdiops(fset->fset_cache->cache_filter)->mkdir(dir->d_inode, dentry, mode);
1297 if (error) {
1298 EXIT;
1299 goto exit;
1302 if ( dentry->d_inode && !error) {
1303 struct presto_cache *cache = fset->fset_cache;
1305 presto_set_ops(dentry->d_inode, cache->cache_filter);
1307 filter_setup_dentry_ops(cache->cache_filter,
1308 dentry->d_op,
1309 &presto_dentry_ops);
1310 dentry->d_op = filter_c2udops(cache->cache_filter);
1311 /* if Lento does this, we won't have data */
1312 if ( ISLENTO(presto_c2m(cache)) ) {
1313 presto_set(dentry, PRESTO_ATTR);
1314 } else {
1315 presto_set(dentry, PRESTO_ATTR | PRESTO_DATA);
1319 info->flags |= LENTO_FL_TOUCH_PARENT;
1320 error = presto_settime(fset, NULL, dir, dentry,
1321 info, ATTR_CTIME | ATTR_MTIME);
1322 if (error) {
1323 EXIT;
1324 goto exit;
1327 presto_debug_fail_blkdev(fset, KML_OPCODE_MKDIR | 0x10);
1328 presto_getversion(&new_dir_ver, dentry->d_inode);
1329 if ( presto_do_kml(info, dir) )
1330 error = presto_journal_mkdir(&rec, fset, dentry, &tgt_dir_ver,
1331 &new_dir_ver,
1332 dentry->d_inode->i_mode);
1334 presto_debug_fail_blkdev(fset, KML_OPCODE_MKDIR | 0x20);
1335 if ( presto_do_rcvd(info, dentry) )
1336 error = presto_write_last_rcvd(&rec, fset, info);
1338 presto_debug_fail_blkdev(fset, KML_OPCODE_MKDIR | 0x30);
1339 EXIT;
1340 exit:
1341 unlock_kernel();
1342 presto_trans_commit(fset, handle);
1343 exit_lock:
1344 presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096);
1345 // up(&dir->d_inode->i_zombie);
1346 return error;
1350 * Look out: this function may change a normal dentry
1351 * into a directory dentry (different size)..
1353 int lento_mkdir(const char *name, int mode, struct lento_vfs_context *info)
1355 int error;
1356 char *pathname;
1357 struct dentry *dentry;
1358 struct presto_file_set *fset;
1359 struct nameidata nd;
1361 ENTRY;
1362 CDEBUG(D_PIOCTL, "name: %s, mode %o, offset %d, recno %d, flags %x\n",
1363 name, mode, info->slot_offset, info->recno, info->flags);
1364 pathname = getname(name);
1365 error = PTR_ERR(pathname);
1366 if (IS_ERR(pathname)) {
1367 EXIT;
1368 return error;
1371 error = path_lookup(pathname, LOOKUP_PARENT, &nd);
1372 if (error)
1373 goto out_name;
1375 dentry = lookup_create(&nd, 1);
1376 error = PTR_ERR(dentry);
1377 if (!IS_ERR(dentry)) {
1378 fset = presto_fset(dentry);
1379 error = -EINVAL;
1380 if (!fset) {
1381 CERROR("No fileset!\n");
1382 EXIT;
1383 goto out_dput;
1386 error = presto_do_mkdir(fset, nd.dentry, dentry,
1387 mode & S_IALLUGO, info);
1388 out_dput:
1389 dput(dentry);
1391 up(&nd.dentry->d_inode->i_sem);
1392 path_release(&nd);
1393 out_name:
1394 EXIT;
1395 putname(pathname);
1396 CDEBUG(D_PIOCTL, "error: %d\n", error);
1397 return error;
1400 static void d_unhash(struct dentry *dentry)
1402 dget(dentry);
1403 switch (atomic_read(&dentry->d_count)) {
1404 default:
1405 shrink_dcache_parent(dentry);
1406 if (atomic_read(&dentry->d_count) != 2)
1407 break;
1408 case 2:
1409 d_drop(dentry);
1413 int presto_do_rmdir(struct presto_file_set *fset, struct dentry *dir,
1414 struct dentry *dentry, struct lento_vfs_context *info)
1416 struct rec_info rec;
1417 int error;
1418 struct presto_version tgt_dir_ver, old_dir_ver;
1419 struct izo_rollback_data rb;
1420 struct inode_operations *iops;
1421 void *handle;
1422 int do_kml, do_rcvd;
1423 int size;
1425 ENTRY;
1426 error = may_delete(dir->d_inode, dentry, 1);
1427 if (error)
1428 return error;
1430 error = -EPERM;
1431 iops = filter_c2cdiops(fset->fset_cache->cache_filter);
1432 if (!iops->rmdir) {
1433 EXIT;
1434 return error;
1437 size = PRESTO_REQHIGH - dentry->d_inode->i_size;
1438 error = presto_reserve_space(fset->fset_cache, size);
1439 if (error) {
1440 EXIT;
1441 return error;
1444 presto_getversion(&tgt_dir_ver, dir->d_inode);
1445 presto_getversion(&old_dir_ver, dentry->d_inode);
1446 izo_get_rollback_data(dentry->d_inode, &rb);
1447 handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_RMDIR);
1448 if ( IS_ERR(handle) ) {
1449 presto_release_space(fset->fset_cache, size);
1450 CERROR("ERROR: presto_do_rmdir: no space for transaction. Tell Peter.\n");
1451 return -ENOSPC;
1454 DQUOT_INIT(dir->d_inode);
1456 do_kml = presto_do_kml(info, dir);
1457 do_rcvd = presto_do_rcvd(info, dir);
1459 // double_down(&dir->d_inode->i_zombie, &dentry->d_inode->i_zombie);
1460 d_unhash(dentry);
1461 if (IS_DEADDIR(dir->d_inode))
1462 error = -ENOENT;
1463 else if (d_mountpoint(dentry)) {
1464 CERROR("foo: d_mountpoint(dentry): ino %ld\n",
1465 dentry->d_inode->i_ino);
1466 error = -EBUSY;
1467 } else {
1468 lock_kernel();
1469 error = iops->rmdir(dir->d_inode, dentry);
1470 unlock_kernel();
1471 if (!error) {
1472 dentry->d_inode->i_flags |= S_DEAD;
1473 error = presto_settime(fset, NULL, NULL, dir, info,
1474 ATTR_CTIME | ATTR_MTIME);
1477 // double_up(&dir->d_inode->i_zombie, &dentry->d_inode->i_zombie);
1478 if (!error)
1479 d_delete(dentry);
1480 dput(dentry);
1482 presto_debug_fail_blkdev(fset, KML_OPCODE_RMDIR | 0x10);
1483 if ( !error && do_kml )
1484 error = presto_journal_rmdir(&rec, fset, dir, &tgt_dir_ver,
1485 &old_dir_ver, &rb,
1486 dentry->d_name.len,
1487 dentry->d_name.name);
1489 presto_debug_fail_blkdev(fset, KML_OPCODE_RMDIR | 0x20);
1490 if ( !error && do_rcvd )
1491 error = presto_write_last_rcvd(&rec, fset, info);
1493 presto_debug_fail_blkdev(fset, KML_OPCODE_RMDIR | 0x30);
1494 EXIT;
1496 presto_trans_commit(fset, handle);
1497 presto_release_space(fset->fset_cache, size);
1498 return error;
1501 int lento_rmdir(const char *pathname, struct lento_vfs_context *info)
1503 int error = 0;
1504 char * name;
1505 struct dentry *dentry;
1506 struct presto_file_set *fset;
1507 struct nameidata nd;
1509 ENTRY;
1510 name = getname(pathname);
1511 if(IS_ERR(name)) {
1512 EXIT;
1513 return PTR_ERR(name);
1516 error = path_lookup(name, LOOKUP_PARENT, &nd);
1517 if (error) {
1518 EXIT;
1519 goto exit;
1521 switch(nd.last_type) {
1522 case LAST_DOTDOT:
1523 error = -ENOTEMPTY;
1524 EXIT;
1525 goto exit1;
1526 case LAST_ROOT:
1527 case LAST_DOT:
1528 error = -EBUSY;
1529 EXIT;
1530 goto exit1;
1532 down(&nd.dentry->d_inode->i_sem);
1533 dentry = lookup_hash(&nd.last, nd.dentry);
1534 error = PTR_ERR(dentry);
1535 if (!IS_ERR(dentry)) {
1536 fset = presto_fset(dentry);
1537 error = -EINVAL;
1538 if ( !fset ) {
1539 CERROR("No fileset!\n");
1540 EXIT;
1541 goto exit_put;
1543 error = presto_do_rmdir(fset, nd.dentry, dentry, info);
1544 exit_put:
1545 dput(dentry);
1547 up(&nd.dentry->d_inode->i_sem);
1548 exit1:
1549 path_release(&nd);
1550 exit:
1551 putname(name);
1552 EXIT;
1553 return error;
1556 int presto_do_mknod(struct presto_file_set *fset, struct dentry *dir,
1557 struct dentry *dentry, int mode, dev_t dev,
1558 struct lento_vfs_context *info)
1560 struct rec_info rec;
1561 int error = -EPERM;
1562 struct presto_version tgt_dir_ver, new_node_ver;
1563 struct inode_operations *iops;
1564 void *handle;
1566 ENTRY;
1568 // down(&dir->d_inode->i_zombie);
1569 /* one KML entry */
1570 error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);
1571 if (error) {
1572 EXIT;
1573 // up(&dir->d_inode->i_zombie);
1574 return error;
1577 if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) {
1578 EXIT;
1579 goto exit_lock;
1582 error = may_create(dir->d_inode, dentry);
1583 if (error) {
1584 EXIT;
1585 goto exit_lock;
1588 error = -EPERM;
1589 iops = filter_c2cdiops(fset->fset_cache->cache_filter);
1590 if (!iops->mknod) {
1591 EXIT;
1592 goto exit_lock;
1595 DQUOT_INIT(dir->d_inode);
1596 lock_kernel();
1598 error = -ENOSPC;
1599 presto_getversion(&tgt_dir_ver, dir->d_inode);
1600 handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_MKNOD);
1601 if ( IS_ERR(handle) ) {
1602 presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
1603 CERROR("presto_do_mknod: no space for transaction\n");
1604 goto exit_lock2;
1607 error = iops->mknod(dir->d_inode, dentry, mode, dev);
1608 if (error) {
1609 EXIT;
1610 goto exit_commit;
1612 if ( dentry->d_inode) {
1613 struct presto_cache *cache = fset->fset_cache;
1615 presto_set_ops(dentry->d_inode, cache->cache_filter);
1617 filter_setup_dentry_ops(cache->cache_filter, dentry->d_op,
1618 &presto_dentry_ops);
1619 dentry->d_op = filter_c2udops(cache->cache_filter);
1621 /* if Lento does this, we won't have data */
1622 if ( ISLENTO(presto_c2m(cache)) ) {
1623 presto_set(dentry, PRESTO_ATTR);
1624 } else {
1625 presto_set(dentry, PRESTO_ATTR | PRESTO_DATA);
1629 error = presto_settime(fset, NULL, NULL, dir,
1630 info, ATTR_MTIME);
1631 if (error) {
1632 EXIT;
1634 error = presto_settime(fset, NULL, NULL, dentry,
1635 info, ATTR_CTIME | ATTR_MTIME);
1636 if (error) {
1637 EXIT;
1640 presto_debug_fail_blkdev(fset, KML_OPCODE_MKNOD | 0x10);
1641 presto_getversion(&new_node_ver, dentry->d_inode);
1642 if ( presto_do_kml(info, dentry) )
1643 error = presto_journal_mknod(&rec, fset, dentry, &tgt_dir_ver,
1644 &new_node_ver,
1645 dentry->d_inode->i_mode,
1646 MAJOR(dev), MINOR(dev) );
1648 presto_debug_fail_blkdev(fset, KML_OPCODE_MKNOD | 0x20);
1649 if ( presto_do_rcvd(info, dentry) )
1650 error = presto_write_last_rcvd(&rec, fset, info);
1652 presto_debug_fail_blkdev(fset, KML_OPCODE_MKNOD | 0x30);
1653 EXIT;
1654 exit_commit:
1655 presto_trans_commit(fset, handle);
1656 exit_lock2:
1657 unlock_kernel();
1658 exit_lock:
1659 presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
1660 // up(&dir->d_inode->i_zombie);
1661 return error;
1664 int lento_mknod(const char *filename, int mode, dev_t dev,
1665 struct lento_vfs_context *info)
1667 int error = 0;
1668 char * tmp;
1669 struct dentry * dentry;
1670 struct nameidata nd;
1671 struct presto_file_set *fset;
1673 ENTRY;
1675 if (S_ISDIR(mode))
1676 return -EPERM;
1677 tmp = getname(filename);
1678 if (IS_ERR(tmp))
1679 return PTR_ERR(tmp);
1681 error = path_lookup(tmp, LOOKUP_PARENT, &nd);
1682 if (error)
1683 goto out;
1684 dentry = lookup_create(&nd, 0);
1685 error = PTR_ERR(dentry);
1686 if (!IS_ERR(dentry)) {
1687 fset = presto_fset(dentry);
1688 error = -EINVAL;
1689 if ( !fset ) {
1690 CERROR("No fileset!\n");
1691 EXIT;
1692 goto exit_put;
1694 switch (mode & S_IFMT) {
1695 case 0: case S_IFREG:
1696 error = -EOPNOTSUPP;
1697 break;
1698 case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
1699 error = presto_do_mknod(fset, nd.dentry, dentry,
1700 mode, dev, info);
1701 break;
1702 case S_IFDIR:
1703 error = -EPERM;
1704 break;
1705 default:
1706 error = -EINVAL;
1708 exit_put:
1709 dput(dentry);
1711 up(&nd.dentry->d_inode->i_sem);
1712 path_release(&nd);
1713 out:
1714 putname(tmp);
1716 return error;
1719 int do_rename(struct presto_file_set *fset,
1720 struct dentry *old_parent, struct dentry *old_dentry,
1721 struct dentry *new_parent, struct dentry *new_dentry,
1722 struct lento_vfs_context *info)
1724 struct rec_info rec;
1725 int error;
1726 struct inode_operations *iops;
1727 struct presto_version src_dir_ver, tgt_dir_ver;
1728 void *handle;
1729 int new_inode_unlink = 0;
1730 struct inode *old_dir = old_parent->d_inode;
1731 struct inode *new_dir = new_parent->d_inode;
1733 ENTRY;
1734 presto_getversion(&src_dir_ver, old_dir);
1735 presto_getversion(&tgt_dir_ver, new_dir);
1737 error = -EPERM;
1738 iops = filter_c2cdiops(fset->fset_cache->cache_filter);
1739 if (!iops || !iops->rename) {
1740 EXIT;
1741 return error;
1744 error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);
1745 if (error) {
1746 EXIT;
1747 return error;
1749 handle = presto_trans_start(fset, old_dir, KML_OPCODE_RENAME);
1750 if ( IS_ERR(handle) ) {
1751 presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
1752 CERROR("presto_do_rename: no space for transaction\n");
1753 return -ENOSPC;
1755 if (new_dentry->d_inode && new_dentry->d_inode->i_nlink > 1) {
1756 dget(new_dentry);
1757 new_inode_unlink = 1;
1760 error = iops->rename(old_dir, old_dentry, new_dir, new_dentry);
1762 if (error) {
1763 EXIT;
1764 goto exit;
1767 if (new_inode_unlink) {
1768 error = presto_settime(fset, NULL, NULL, old_dentry,
1769 info, ATTR_CTIME);
1770 dput(old_dentry);
1771 if (error) {
1772 EXIT;
1773 goto exit;
1776 info->flags |= LENTO_FL_TOUCH_PARENT;
1777 error = presto_settime(fset, NULL, new_parent, old_parent,
1778 info, ATTR_CTIME | ATTR_MTIME);
1779 if (error) {
1780 EXIT;
1781 goto exit;
1784 /* XXX make a distinction between cross file set
1785 * and intra file set renames here
1787 presto_debug_fail_blkdev(fset, KML_OPCODE_RENAME | 0x10);
1788 if ( presto_do_kml(info, old_dentry) )
1789 error = presto_journal_rename(&rec, fset, old_dentry,
1790 new_dentry,
1791 &src_dir_ver, &tgt_dir_ver);
1793 presto_debug_fail_blkdev(fset, KML_OPCODE_RENAME | 0x20);
1795 if ( presto_do_rcvd(info, old_dentry) )
1796 error = presto_write_last_rcvd(&rec, fset, info);
1798 presto_debug_fail_blkdev(fset, KML_OPCODE_RENAME | 0x30);
1799 EXIT;
1800 exit:
1801 presto_trans_commit(fset, handle);
1802 presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
1803 return error;
1806 static
1807 int presto_rename_dir(struct presto_file_set *fset, struct dentry *old_parent,
1808 struct dentry *old_dentry, struct dentry *new_parent,
1809 struct dentry *new_dentry, struct lento_vfs_context *info)
1811 int error;
1812 struct inode *target;
1813 struct inode *old_dir = old_parent->d_inode;
1814 struct inode *new_dir = new_parent->d_inode;
1816 if (old_dentry->d_inode == new_dentry->d_inode)
1817 return 0;
1819 error = may_delete(old_dir, old_dentry, 1);
1820 if (error)
1821 return error;
1823 if (new_dir->i_dev != old_dir->i_dev)
1824 return -EXDEV;
1826 if (!new_dentry->d_inode)
1827 error = may_create(new_dir, new_dentry);
1828 else
1829 error = may_delete(new_dir, new_dentry, 1);
1830 if (error)
1831 return error;
1833 if (!old_dir->i_op || !old_dir->i_op->rename)
1834 return -EPERM;
1837 * If we are going to change the parent - check write permissions,
1838 * we'll need to flip '..'.
1840 if (new_dir != old_dir) {
1841 error = permission(old_dentry->d_inode, MAY_WRITE);
1843 if (error)
1844 return error;
1846 DQUOT_INIT(old_dir);
1847 DQUOT_INIT(new_dir);
1848 down(&old_dir->i_sb->s_vfs_rename_sem);
1849 error = -EINVAL;
1850 if (is_subdir(new_dentry, old_dentry))
1851 goto out_unlock;
1852 target = new_dentry->d_inode;
1853 if (target) { /* Hastur! Hastur! Hastur! */
1854 // triple_down(&old_dir->i_zombie,
1855 // &new_dir->i_zombie,
1856 // &target->i_zombie);
1857 d_unhash(new_dentry);
1858 } else
1859 // double_down(&old_dir->i_zombie,
1860 // &new_dir->i_zombie);
1861 if (IS_DEADDIR(old_dir)||IS_DEADDIR(new_dir))
1862 error = -ENOENT;
1863 else if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
1864 error = -EBUSY;
1865 else
1866 error = do_rename(fset, old_parent, old_dentry,
1867 new_parent, new_dentry, info);
1868 if (target) {
1869 if (!error)
1870 target->i_flags |= S_DEAD;
1871 // triple_up(&old_dir->i_zombie,
1872 // &new_dir->i_zombie,
1873 // &target->i_zombie);
1874 if (d_unhashed(new_dentry))
1875 d_rehash(new_dentry);
1876 dput(new_dentry);
1877 } else
1878 // double_up(&old_dir->i_zombie,
1879 // &new_dir->i_zombie);
1881 if (!error)
1882 d_move(old_dentry,new_dentry);
1883 out_unlock:
1884 up(&old_dir->i_sb->s_vfs_rename_sem);
1885 return error;
1888 static
1889 int presto_rename_other(struct presto_file_set *fset, struct dentry *old_parent,
1890 struct dentry *old_dentry, struct dentry *new_parent,
1891 struct dentry *new_dentry, struct lento_vfs_context *info)
1893 struct inode *old_dir = old_parent->d_inode;
1894 struct inode *new_dir = new_parent->d_inode;
1895 int error;
1897 if (old_dentry->d_inode == new_dentry->d_inode)
1898 return 0;
1900 error = may_delete(old_dir, old_dentry, 0);
1901 if (error)
1902 return error;
1904 if (new_dir->i_dev != old_dir->i_dev)
1905 return -EXDEV;
1907 if (!new_dentry->d_inode)
1908 error = may_create(new_dir, new_dentry);
1909 else
1910 error = may_delete(new_dir, new_dentry, 0);
1911 if (error)
1912 return error;
1914 if (!old_dir->i_op || !old_dir->i_op->rename)
1915 return -EPERM;
1917 DQUOT_INIT(old_dir);
1918 DQUOT_INIT(new_dir);
1919 // double_down(&old_dir->i_zombie, &new_dir->i_zombie);
1920 if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
1921 error = -EBUSY;
1922 else
1923 error = do_rename(fset, old_parent, old_dentry,
1924 new_parent, new_dentry, info);
1925 // double_up(&old_dir->i_zombie, &new_dir->i_zombie);
1926 if (error)
1927 return error;
1928 /* The following d_move() should become unconditional */
1929 if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME)) {
1930 d_move(old_dentry, new_dentry);
1932 return 0;
1935 int presto_do_rename(struct presto_file_set *fset,
1936 struct dentry *old_parent, struct dentry *old_dentry,
1937 struct dentry *new_parent, struct dentry *new_dentry,
1938 struct lento_vfs_context *info)
1940 if (S_ISDIR(old_dentry->d_inode->i_mode))
1941 return presto_rename_dir(fset, old_parent,old_dentry,new_parent,
1942 new_dentry, info);
1943 else
1944 return presto_rename_other(fset, old_parent, old_dentry,
1945 new_parent,new_dentry, info);
1949 int lento_do_rename(const char *oldname, const char *newname,
1950 struct lento_vfs_context *info)
1952 int error = 0;
1953 struct dentry * old_dir, * new_dir;
1954 struct dentry * old_dentry, *new_dentry;
1955 struct nameidata oldnd, newnd;
1956 struct presto_file_set *fset;
1958 ENTRY;
1960 error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
1961 if (error)
1962 goto exit;
1964 error = path_lookup(newname, LOOKUP_PARENT, &newnd);
1965 if (error)
1966 goto exit1;
1968 error = -EXDEV;
1969 if (oldnd.mnt != newnd.mnt)
1970 goto exit2;
1972 old_dir = oldnd.dentry;
1973 error = -EBUSY;
1974 if (oldnd.last_type != LAST_NORM)
1975 goto exit2;
1977 new_dir = newnd.dentry;
1978 if (newnd.last_type != LAST_NORM)
1979 goto exit2;
1981 lock_rename(new_dir, old_dir);
1983 old_dentry = lookup_hash(&oldnd.last, old_dir);
1984 error = PTR_ERR(old_dentry);
1985 if (IS_ERR(old_dentry))
1986 goto exit3;
1987 /* source must exist */
1988 error = -ENOENT;
1989 if (!old_dentry->d_inode)
1990 goto exit4;
1991 fset = presto_fset(old_dentry);
1992 error = -EINVAL;
1993 if ( !fset ) {
1994 CERROR("No fileset!\n");
1995 EXIT;
1996 goto exit4;
1998 /* unless the source is a directory trailing slashes give -ENOTDIR */
1999 if (!S_ISDIR(old_dentry->d_inode->i_mode)) {
2000 error = -ENOTDIR;
2001 if (oldnd.last.name[oldnd.last.len])
2002 goto exit4;
2003 if (newnd.last.name[newnd.last.len])
2004 goto exit4;
2006 new_dentry = lookup_hash(&newnd.last, new_dir);
2007 error = PTR_ERR(new_dentry);
2008 if (IS_ERR(new_dentry))
2009 goto exit4;
2011 lock_kernel();
2012 error = presto_do_rename(fset, old_dir, old_dentry,
2013 new_dir, new_dentry, info);
2014 unlock_kernel();
2016 dput(new_dentry);
2017 exit4:
2018 dput(old_dentry);
2019 exit3:
2020 unlock_rename(new_dir, old_dir);
2021 exit2:
2022 path_release(&newnd);
2023 exit1:
2024 path_release(&oldnd);
2025 exit:
2026 return error;
2029 int lento_rename(const char * oldname, const char * newname,
2030 struct lento_vfs_context *info)
2032 int error;
2033 char * from;
2034 char * to;
2036 from = getname(oldname);
2037 if(IS_ERR(from))
2038 return PTR_ERR(from);
2039 to = getname(newname);
2040 error = PTR_ERR(to);
2041 if (!IS_ERR(to)) {
2042 error = lento_do_rename(from,to, info);
2043 putname(to);
2045 putname(from);
2046 return error;
2049 struct dentry *presto_iopen(struct dentry *dentry,
2050 ino_t ino, unsigned int generation)
2052 struct presto_file_set *fset;
2053 char name[48];
2054 int error;
2056 ENTRY;
2057 /* see if we already have the dentry we want */
2058 if (dentry->d_inode && dentry->d_inode->i_ino == ino &&
2059 dentry->d_inode->i_generation == generation) {
2060 EXIT;
2061 return dentry;
2064 /* Make sure we have a cache beneath us. We should always find at
2065 * least one dentry inside the cache (if it exists), otherwise not
2066 * even the cache root exists, or we passed in a bad name.
2068 fset = presto_fset(dentry);
2069 error = -EINVAL;
2070 if (!fset) {
2071 CERROR("No fileset for %*s!\n",
2072 dentry->d_name.len, dentry->d_name.name);
2073 EXIT;
2074 dput(dentry);
2075 return ERR_PTR(error);
2077 dput(dentry);
2079 sprintf(name, "%s%#lx%c%#x",
2080 PRESTO_ILOOKUP_MAGIC, ino, PRESTO_ILOOKUP_SEP, generation);
2081 CDEBUG(D_PIOCTL, "opening %ld by number (as %s)\n", ino, name);
2082 return lookup_one_len(name, fset->fset_dentry, strlen(name));
2085 static struct file *presto_filp_dopen(struct dentry *dentry, int flags)
2087 struct file *f;
2088 struct inode *inode;
2089 int flag, error;
2091 ENTRY;
2092 error = -ENFILE;
2093 f = get_empty_filp();
2094 if (!f) {
2095 CDEBUG(D_PIOCTL, "error getting file pointer\n");
2096 EXIT;
2097 goto out;
2099 f->f_flags = flag = flags;
2100 f->f_mode = (flag+1) & O_ACCMODE;
2101 inode = dentry->d_inode;
2102 if (f->f_mode & FMODE_WRITE) {
2103 error = get_write_access(inode);
2104 if (error) {
2105 CDEBUG(D_PIOCTL, "error getting write access\n");
2106 EXIT; goto cleanup_file;
2110 f->f_dentry = dentry;
2111 f->f_pos = 0;
2112 //f->f_reada = 0;
2113 f->f_op = NULL;
2114 if (inode->i_op)
2115 /* XXX should we set to presto ops, or leave at cache ops? */
2116 f->f_op = inode->i_fop;
2117 if (f->f_op && f->f_op->open) {
2118 error = f->f_op->open(inode, f);
2119 if (error) {
2120 CDEBUG(D_PIOCTL, "error calling cache 'open'\n");
2121 EXIT;
2122 goto cleanup_all;
2125 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
2127 return f;
2129 cleanup_all:
2130 if (f->f_mode & FMODE_WRITE)
2131 put_write_access(inode);
2132 cleanup_file:
2133 put_filp(f);
2134 out:
2135 return ERR_PTR(error);
2139 /* Open an inode by number. We pass in the cache root name (or a subdirectory
2140 * from the cache that is guaranteed to exist) to be able to access the cache.
2142 int lento_iopen(const char *name, ino_t ino, unsigned int generation,
2143 int flags)
2145 char * tmp;
2146 struct dentry *dentry;
2147 struct nameidata nd;
2148 int fd;
2149 int error;
2151 ENTRY;
2152 CDEBUG(D_PIOCTL,
2153 "open %s:inode %#lx (%ld), generation %x (%d), flags %d \n",
2154 name, ino, ino, generation, generation, flags);
2155 /* We don't allow creation of files by number only, as it would
2156 * lead to a dangling files not in any directory. We could also
2157 * just turn off the flag and ignore it.
2159 if (flags & O_CREAT) {
2160 CERROR("%s: create file by inode number (%ld) not allowed\n",
2161 __FUNCTION__, ino);
2162 EXIT;
2163 return -EACCES;
2166 tmp = getname(name);
2167 if (IS_ERR(tmp)) {
2168 EXIT;
2169 return PTR_ERR(tmp);
2172 lock_kernel();
2173 again: /* look the named file or a parent directory so we can get the cache */
2174 error = presto_walk(tmp, &nd);
2175 if ( error && error != -ENOENT ) {
2176 EXIT;
2177 unlock_kernel();
2178 return error;
2180 if (error == -ENOENT)
2181 dentry = NULL;
2182 else
2183 dentry = nd.dentry;
2185 /* we didn't find the named file, so see if a parent exists */
2186 if (!dentry) {
2187 char *slash;
2189 slash = strrchr(tmp, '/');
2190 if (slash && slash != tmp) {
2191 *slash = '\0';
2192 path_release(&nd);
2193 goto again;
2195 /* we should never get here... */
2196 CDEBUG(D_PIOCTL, "no more path components to try!\n");
2197 fd = -ENOENT;
2198 goto exit;
2200 CDEBUG(D_PIOCTL, "returned dentry %p\n", dentry);
2202 dentry = presto_iopen(dentry, ino, generation);
2203 fd = PTR_ERR(dentry);
2204 if (IS_ERR(dentry)) {
2205 EXIT;
2206 goto exit;
2209 /* XXX start of code that might be replaced by something like:
2210 * if (flags & (O_WRONLY | O_RDWR)) {
2211 * error = get_write_access(dentry->d_inode);
2212 * if (error) {
2213 * EXIT;
2214 * goto cleanup_dput;
2217 * fd = open_dentry(dentry, flags);
2219 * including the presto_filp_dopen() function (check dget counts!)
2221 fd = get_unused_fd();
2222 if (fd < 0) {
2223 EXIT;
2224 goto cleanup_dput;
2228 int error;
2229 struct file * f = presto_filp_dopen(dentry, flags);
2230 error = PTR_ERR(f);
2231 if (IS_ERR(f)) {
2232 put_unused_fd(fd);
2233 fd = error;
2234 EXIT;
2235 goto cleanup_dput;
2237 fd_install(fd, f);
2239 /* end of code that might be replaced by open_dentry */
2241 EXIT;
2242 exit:
2243 unlock_kernel();
2244 path_release(&nd);
2245 putname(tmp);
2246 return fd;
2248 cleanup_dput:
2249 putname(&nd);
2250 goto exit;
2253 #ifdef CONFIG_FS_EXT_ATTR
2255 #if 0 /* was a broken check for Posix ACLs */
2256 /* Posix ACL code changes i_mode without using a notify_change (or
2257 * a mark_inode_dirty!). We need to duplicate this at the reintegrator
2258 * which is done by this function. This function also takes care of
2259 * resetting the cached posix acls in this inode. If we don't reset these
2260 * VFS continues using the old acl information, which by now may be out of
2261 * date.
2263 int presto_setmode(struct presto_file_set *fset, struct dentry *dentry,
2264 mode_t mode)
2266 struct inode *inode = dentry->d_inode;
2268 ENTRY;
2269 /* The extended attributes for this inode were modified.
2270 * At this point we can not be sure if any of the ACL
2271 * information for this inode was updated. So we will
2272 * force VFS to reread the acls. Note that we do this
2273 * only when called from the SETEXTATTR ioctl, which is why we
2274 * do this while setting the mode of the file. Also note
2275 * that mark_inode_dirty is not be needed for i_*acl only
2276 * to force i_mode info to disk, and should be removed once
2277 * we use notify_change to update the mode.
2278 * XXX: is mode setting really needed? Just setting acl's should
2279 * be enough! VFS should change the i_mode as needed? SHP
2281 if (inode->i_acl &&
2282 inode->i_acl != POSIX_ACL_NOT_CACHED)
2283 posix_acl_release(inode->i_acl);
2284 if (inode->i_default_acl &&
2285 inode->i_default_acl != POSIX_ACL_NOT_CACHED)
2286 posix_acl_release(inode->i_default_acl);
2287 inode->i_acl = POSIX_ACL_NOT_CACHED;
2288 inode->i_default_acl = POSIX_ACL_NOT_CACHED;
2289 inode->i_mode = mode;
2290 /* inode should already be dirty...but just in case */
2291 mark_inode_dirty(inode);
2292 return 0;
2294 #if 0
2295 /* XXX: The following code is the preferred way to set mode,
2296 * however, I need to carefully go through possible recursion
2297 * paths back into presto. See comments in presto_do_setattr.
2300 int error=0;
2301 struct super_operations *sops;
2302 struct iattr iattr;
2304 iattr.ia_mode = mode;
2305 iattr.ia_valid = ATTR_MODE|ATTR_FORCE;
2307 error = -EPERM;
2308 sops = filter_c2csops(fset->fset_cache->cache_filter);
2309 if (!sops &&
2310 !sops->notify_change) {
2311 EXIT;
2312 return error;
2315 error = sops->notify_change(dentry, &iattr);
2317 EXIT;
2318 return error;
2320 #endif
2322 #endif
2324 /* setextattr Interface to cache filesystem */
2325 int presto_do_set_ext_attr(struct presto_file_set *fset,
2326 struct dentry *dentry,
2327 const char *name, void *buffer,
2328 size_t buffer_len, int flags, mode_t *mode,
2329 struct lento_vfs_context *info)
2331 struct rec_info rec;
2332 struct inode *inode = dentry->d_inode;
2333 struct inode_operations *iops;
2334 int error;
2335 struct presto_version ver;
2336 void *handle;
2337 char temp[PRESTO_EXT_ATTR_NAME_MAX+1];
2339 ENTRY;
2340 error = -EROFS;
2341 if (IS_RDONLY(inode)) {
2342 EXIT;
2343 return -EROFS;
2346 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
2347 EXIT;
2348 return -EPERM;
2351 presto_getversion(&ver, inode);
2352 error = -EPERM;
2353 /* We need to invoke different filters based on whether
2354 * this dentry is a regular file, directory or symlink.
2356 switch (inode->i_mode & S_IFMT) {
2357 case S_IFLNK: /* symlink */
2358 iops = filter_c2csiops(fset->fset_cache->cache_filter);
2359 break;
2360 case S_IFDIR: /* directory */
2361 iops = filter_c2cdiops(fset->fset_cache->cache_filter);
2362 break;
2363 case S_IFREG:
2364 default: /* everything else including regular files */
2365 iops = filter_c2cfiops(fset->fset_cache->cache_filter);
2368 if (!iops && !iops->set_ext_attr) {
2369 EXIT;
2370 return error;
2373 error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH);
2374 if (error) {
2375 EXIT;
2376 return error;
2380 handle = presto_trans_start(fset,dentry->d_inode,KML_OPCODE_SETEXTATTR);
2381 if ( IS_ERR(handle) ) {
2382 CERROR("presto_do_set_ext_attr: no space for transaction\n");
2383 presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
2384 return -ENOSPC;
2387 /* We first "truncate" name to the maximum allowable in presto */
2388 /* This simulates the strncpy_from_use code in fs/ext_attr.c */
2389 strncpy(temp,name,sizeof(temp));
2391 /* Pass down to cache*/
2392 error = iops->set_ext_attr(inode,temp,buffer,buffer_len,flags);
2393 if (error) {
2394 EXIT;
2395 goto exit;
2398 #if 0 /* was a broken check for Posix ACLs */
2399 /* Reset mode if specified*/
2400 /* XXX: when we do native acl support, move this code out! */
2401 if (mode != NULL) {
2402 error = presto_setmode(fset, dentry, *mode);
2403 if (error) {
2404 EXIT;
2405 goto exit;
2408 #endif
2410 /* Reset ctime. Only inode change time (ctime) is affected */
2411 error = presto_settime(fset, NULL, NULL, dentry, info, ATTR_CTIME);
2412 if (error) {
2413 EXIT;
2414 goto exit;
2417 if (flags & EXT_ATTR_FLAG_USER) {
2418 CERROR(" USER flag passed to presto_do_set_ext_attr!\n");
2419 BUG();
2422 /* We are here, so set_ext_attr succeeded. We no longer need to keep
2423 * track of EXT_ATTR_FLAG_{EXISTS,CREATE}, instead, we will force
2424 * the attribute value during log replay. -SHP
2426 flags &= ~(EXT_ATTR_FLAG_EXISTS | EXT_ATTR_FLAG_CREATE);
2428 presto_debug_fail_blkdev(fset, KML_OPCODE_SETEXTATTR | 0x10);
2429 if ( presto_do_kml(info, dentry) )
2430 error = presto_journal_set_ext_attr
2431 (&rec, fset, dentry, &ver, name, buffer,
2432 buffer_len, flags);
2434 presto_debug_fail_blkdev(fset, KML_OPCODE_SETEXTATTR | 0x20);
2435 if ( presto_do_rcvd(info, dentry) )
2436 error = presto_write_last_rcvd(&rec, fset, info);
2438 presto_debug_fail_blkdev(fset, KML_OPCODE_SETEXTATTR | 0x30);
2439 EXIT;
2440 exit:
2441 presto_release_space(fset->fset_cache, PRESTO_REQHIGH);
2442 presto_trans_commit(fset, handle);
2444 return error;
2446 #endif