📄 vfs.c
字号:
presto_release_space(fset->fset_cache, PRESTO_REQLOW); presto_trans_commit(fset, handle); return error;}int lento_unlink(const char *pathname, struct lento_vfs_context *info){ int error = 0; char * name; struct dentry *dentry; struct nameidata nd; struct presto_file_set *fset; ENTRY; name = getname(pathname); if(IS_ERR(name)) return PTR_ERR(name); if (path_init(name, LOOKUP_PARENT, &nd)) error = path_walk(name, &nd); if (error) goto exit; error = -EISDIR; if (nd.last_type != LAST_NORM) goto exit1; down(&nd.dentry->d_inode->i_sem); dentry = lookup_hash(&nd.last, nd.dentry); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { fset = presto_fset(dentry); error = -EINVAL; if ( !fset ) { printk("No fileset!\n"); EXIT; goto exit2; } /* Why not before? Because we want correct error value */ if (nd.last.name[nd.last.len]) goto slashes; error = presto_do_unlink(fset, nd.dentry, dentry, info); exit2: EXIT; dput(dentry); } up(&nd.dentry->d_inode->i_sem);exit1: path_release(&nd);exit: putname(name); return error;slashes: error = !dentry->d_inode ? -ENOENT : S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR; goto exit2;}int presto_do_symlink(struct presto_file_set *fset, struct dentry *dir, struct dentry *dentry, const char *oldname, struct lento_vfs_context *info){ struct rec_info rec; int error; struct presto_version tgt_dir_ver, new_link_ver; struct inode_operations *iops; void *handle; ENTRY; down(&dir->d_inode->i_zombie); /* record + max path len + space to free */ error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH + 4096); if (error) { EXIT; up(&dir->d_inode->i_zombie); return error; } error = may_create(dir->d_inode, dentry); if (error) { EXIT; goto exit_lock; } error = -EPERM; iops = filter_c2cdiops(fset->fset_cache->cache_filter); if (!iops->symlink) { EXIT; goto exit_lock; } presto_getversion(&tgt_dir_ver, dir->d_inode); handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_SYMLINK); if ( IS_ERR(handle) ) { presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096); printk("ERROR: presto_do_symlink: no space for transaction. Tell Peter.\n"); EXIT; return -ENOSPC; } DQUOT_INIT(dir->d_inode); lock_kernel(); error = iops->symlink(dir->d_inode, dentry, oldname); if (error) { EXIT; goto exit; } if (dentry->d_inode && dentry->d_inode->i_gid != presto_excluded_gid) { struct presto_cache *cache = fset->fset_cache; /* was this already done? */ if ( !filter_c2csiops(cache->cache_filter) ) filter_setup_symlink_ops(cache->cache_filter, dentry->d_inode, &presto_sym_iops, NULL); /* make the new inode ours */ dentry->d_inode->i_op = filter_c2usiops(cache->cache_filter); filter_setup_dentry_ops(cache->cache_filter, dentry->d_op, &presto_dentry_ops); dentry->d_op = filter_c2udops(cache->cache_filter); /* XXX ? Cache state ? if Lento creates a symlink */ if ( ISLENTO(presto_c2m(cache)) ) { presto_set(dentry, PRESTO_ATTR); } else { presto_set(dentry, PRESTO_ATTR | PRESTO_DATA); } } error = presto_settime(fset, dir, info, ATTR_CTIME | ATTR_MTIME); if (error) { EXIT; goto exit; } error = presto_settime(fset, dentry, info, ATTR_CTIME | ATTR_MTIME); if (error) { EXIT; goto exit; } presto_debug_fail_blkdev(fset, PRESTO_OP_SYMLINK | 0x10); presto_getversion(&new_link_ver, dentry->d_inode); if ( presto_do_kml(info, dentry->d_inode) ) error = presto_journal_symlink(&rec, fset, dentry, oldname, &tgt_dir_ver, &new_link_ver); presto_debug_fail_blkdev(fset, PRESTO_OP_SYMLINK | 0x20); if ( presto_do_expect(info, dentry->d_inode) ) error = presto_write_last_rcvd(&rec, fset, info); presto_debug_fail_blkdev(fset, PRESTO_OP_SYMLINK | 0x30); EXIT;exit: unlock_kernel(); presto_trans_commit(fset, handle); exit_lock: presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096); up(&dir->d_inode->i_zombie); return error;}int lento_symlink(const char *oldname, const char *newname, struct lento_vfs_context *info){ int error; char *from; char *to; struct dentry *dentry; struct presto_file_set *fset; struct nameidata nd; ENTRY; lock_kernel(); from = getname(oldname); error = PTR_ERR(from); if (IS_ERR(from)) { EXIT; goto exit; } to = getname(newname); error = PTR_ERR(to); if (IS_ERR(to)) { EXIT; goto exit_from; } if (path_init(to, LOOKUP_PARENT, &nd)) error = path_walk(to, &nd); if (error) { EXIT; goto exit_to; } dentry = lookup_create(&nd, 0); error = PTR_ERR(dentry); if (IS_ERR(dentry)) { path_release(&nd); EXIT; goto exit_to; } fset = presto_fset(dentry); error = -EINVAL; if ( !fset ) { printk("No fileset!\n"); path_release(&nd); EXIT; goto exit_lock; } error = presto_do_symlink(fset, nd.dentry, dentry, oldname, info); path_release(&nd); EXIT; exit_lock: up(&nd.dentry->d_inode->i_sem); dput(dentry); exit_to: putname(to); exit_from: putname(from); exit: unlock_kernel(); return error;}int presto_do_mkdir(struct presto_file_set *fset, struct dentry *dir, struct dentry *dentry, int mode, struct lento_vfs_context *info){ struct rec_info rec; int error; struct presto_version tgt_dir_ver, new_dir_ver; void *handle; ENTRY; down(&dir->d_inode->i_zombie); /* one journal record + directory block + room for removals*/ error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH + 4096); if (error) { EXIT; up(&dir->d_inode->i_zombie); return error; } error = may_create(dir->d_inode, dentry); if (error) { EXIT; goto exit_lock; } error = -EPERM; if (!filter_c2cdiops(fset->fset_cache->cache_filter)->mkdir) { EXIT; goto exit_lock; } error = -ENOSPC; presto_getversion(&tgt_dir_ver, dir->d_inode); handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_MKDIR); if ( IS_ERR(handle) ) { presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096); printk("presto_do_mkdir: no space for transaction\n"); goto exit_lock; } DQUOT_INIT(dir->d_inode); mode &= (S_IRWXUGO|S_ISVTX); lock_kernel(); error = filter_c2cdiops(fset->fset_cache->cache_filter)->mkdir(dir->d_inode, dentry, mode); if (error) { EXIT; goto exit; } if ( dentry->d_inode && !error && dentry->d_inode->i_gid != presto_excluded_gid) { struct presto_cache *cache = fset->fset_cache; /* make it ours */ dentry->d_inode->i_op = filter_c2udiops(cache->cache_filter); filter_setup_dentry_ops(cache->cache_filter, dentry->d_op, &presto_dentry_ops); dentry->d_op = filter_c2udops(cache->cache_filter); /* if Lento does this, we won't have data */ if ( ISLENTO(presto_c2m(cache)) ) { presto_set(dentry, PRESTO_ATTR); } else { presto_set(dentry, PRESTO_ATTR | PRESTO_DATA); } } error = presto_settime(fset, dir, info, ATTR_CTIME | ATTR_MTIME); if (error) { EXIT; goto exit; } error = presto_settime(fset, dentry, info, ATTR_CTIME | ATTR_MTIME); if (error) { EXIT; goto exit; } presto_debug_fail_blkdev(fset, PRESTO_OP_MKDIR | 0x10); presto_getversion(&new_dir_ver, dentry->d_inode); if ( presto_do_kml(info, dentry->d_inode) ) error = presto_journal_mkdir(&rec, fset, dentry, &tgt_dir_ver, &new_dir_ver, dentry->d_inode->i_mode); presto_debug_fail_blkdev(fset, PRESTO_OP_MKDIR | 0x20); if ( presto_do_expect(info, dentry->d_inode) ) error = presto_write_last_rcvd(&rec, fset, info); presto_debug_fail_blkdev(fset, PRESTO_OP_MKDIR | 0x30); EXIT;exit: unlock_kernel(); presto_trans_commit(fset, handle); exit_lock: presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096); up(&dir->d_inode->i_zombie); return error;}/* * Look out: this function may change a normal dentry * into a directory dentry (different size).. */int lento_mkdir(const char *name, int mode, struct lento_vfs_context *info){ int error; char *pathname; struct dentry *dentry; struct presto_file_set *fset; struct nameidata nd; ENTRY; CDEBUG(D_PIOCTL, "name: %s, mode %o, offset %d, recno %d, flags %x\n", name, mode, info->slot_offset, info->recno, info->flags); pathname = getname(name); error = PTR_ERR(pathname); if (IS_ERR(pathname)) { EXIT; return error; } if (path_init(pathname, LOOKUP_PARENT, &nd)) error = path_walk(pathname, &nd); if (error) goto out_name; dentry = lookup_create(&nd, 1); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { fset = presto_fset(dentry); error = -EINVAL; if ( !fset ) { printk("No fileset!\n"); EXIT; goto out_dput; } error = presto_do_mkdir(fset, nd.dentry, dentry, mode & S_IALLUGO, info);out_dput: dput(dentry); } up(&nd.dentry->d_inode->i_sem); path_release(&nd);out_name: EXIT; putname(pathname); CDEBUG(D_PIOCTL, "error: %d\n", error); return error;}static void d_unhash(struct dentry *dentry){ dget(dentry); switch (atomic_read(&dentry->d_count)) { default: shrink_dcache_parent(dentry); if (atomic_read(&dentry->d_count) != 2) break; case 2: d_drop(dentry); }}int presto_do_rmdir(struct presto_file_set *fset, struct dentry *dir, struct dentry *dentry, struct lento_vfs_context *info){ struct rec_info rec; int error; struct presto_version tgt_dir_ver, old_dir_ver; struct inode_operations *iops; void *handle; int do_kml, do_expect; int size; ENTRY; error = may_delete(dir->d_inode, dentry, 1); if (error) return error; error = -EPERM; iops = filter_c2cdiops(fset->fset_cache->cache_filter); if (!iops->rmdir) { EXIT; return error; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -