📄 presto.c
字号:
/* * intermezzo.c * * This file implements basic routines supporting the semantics * * Author: Peter J. Braam <braam@cs.cmu.edu> * Copyright (C) 1998 Stelias Computing Inc * Copyright (C) 1999 Red Hat Inc. * */#include <linux/types.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/stat.h>#include <linux/errno.h>#include <linux/vmalloc.h>#include <linux/slab.h>#include <linux/locks.h>#include <asm/segment.h>#include <asm/uaccess.h>#include <linux/string.h>#include <linux/smp_lock.h>#include <linux/intermezzo_fs.h>#include <linux/intermezzo_upcall.h>#include <linux/intermezzo_psdev.h>#include <linux/intermezzo_kml.h>extern int presto_init_last_rcvd_file(struct presto_file_set *);extern int presto_init_lml_file(struct presto_file_set *);extern int presto_init_kml_file(struct presto_file_set *);int presto_walk(const char *name, struct nameidata *nd){ int err; /* we do not follow symlinks to support symlink operations correctly. The vfs should always hand us resolved dentries so we should not be required to use LOOKUP_FOLLOW. At the reintegrating end, lento again should be working with the resolved pathname and not the symlink. SHP XXX: This code implies that direct symlinks do not work. SHP */ unsigned int flags = LOOKUP_POSITIVE; ENTRY; err = 0; if (path_init(name, flags, nd)) err = path_walk(name, nd); return err;}static inline int presto_dentry_is_fsetroot(struct dentry *dentry){ return ((long) dentry->d_fsdata) & PRESTO_FSETROOT;}static inline struct presto_file_set *presto_dentry2fset(struct dentry *dentry){ return (struct presto_file_set *) (((long) dentry->d_fsdata) - PRESTO_FSETROOT);}/* find the presto minor device for this inode */int presto_i2m(struct inode *inode){ struct presto_cache *cache; ENTRY; cache = presto_get_cache(inode); CDEBUG(D_PSDEV, "\n"); if ( !cache ) { printk("PRESTO: BAD: cannot find cache for dev %d, ino %ld\n", inode->i_dev, inode->i_ino); EXIT; return -1; } EXIT; return cache->cache_psdev->uc_minor;}inline int presto_f2m(struct presto_file_set *fset){ return fset->fset_cache->cache_psdev->uc_minor;}inline int presto_c2m(struct presto_cache *cache){ return cache->cache_psdev->uc_minor;}int presto_has_all_data(struct inode *inode){ ENTRY; if ( (inode->i_size >> inode->i_sb->s_blocksize_bits) > inode->i_blocks) { EXIT; return 0; } EXIT; return 1;}/* find the fileset dentry for this dentry */struct presto_file_set *presto_fset(struct dentry *de){ struct dentry *fsde; ENTRY; fsde = de; for ( ; ; ) { if ( presto_dentry_is_fsetroot(fsde) ) { EXIT; return presto_dentry2fset(fsde); } /* are we at the cache "/" ?? */ if ( fsde->d_parent == fsde ) { if ( !de->d_inode ) { printk("Warning %*s has no fileset inode.\n", de->d_name.len, de->d_name.name); } /* better to return a BAD thing */ EXIT; return NULL; } fsde = fsde->d_parent; } /* not reached */ EXIT; return NULL;}/* XXX check this out */struct presto_file_set *presto_path2fileset(const char *name){ struct nameidata nd; struct presto_file_set *fileset; int error; ENTRY; error = presto_walk(name, &nd); if (!error) { #if 0 error = do_revalidate(nd.dentry);#endif if (!error) fileset = presto_fset(nd.dentry); path_release(&nd); EXIT; } else fileset = ERR_PTR(error); EXIT; return fileset;}/* check a flag on this dentry or fset root. Semantics: - most flags: test if it is set - PRESTO_ATTR, PRESTO_DATA return 1 if PRESTO_FSETINSYNC is set*/int presto_chk(struct dentry *dentry, int flag){ int minor; struct presto_file_set *fset = presto_fset(dentry); ENTRY; minor = presto_i2m(dentry->d_inode); if ( upc_comms[minor].uc_no_filter ) { EXIT; return ~0; } /* if the fileset is in sync DATA and ATTR are OK */ if ( fset && (flag == PRESTO_ATTR || flag == PRESTO_DATA) && (fset->fset_flags & FSET_INSYNC) ) { CDEBUG(D_INODE, "fset in sync (ino %ld)!\n", fset->fset_mtpt->d_inode->i_ino); EXIT; return 1; } /* if it is a fsetroot, it's stored in the fset_flags */ if ( fset && presto_dentry_is_fsetroot(dentry) ) { EXIT; return fset->fset_data & flag; } EXIT; return ((int)(long)dentry->d_fsdata & flag);}/* set a bit in the dentry flags */void presto_set(struct dentry *dentry, int flag){ if ( dentry->d_inode ) { CDEBUG(D_INODE, "SET ino %ld, flag %x\n", dentry->d_inode->i_ino, flag); } if ( presto_dentry_is_fsetroot(dentry)) { struct presto_file_set *fset = presto_dentry2fset(dentry); if (fset) { fset->fset_data |= flag; CDEBUG(D_INODE, "Setting fset->fset_data: now %x\n", fset->fset_data); } } else { CDEBUG(D_INODE, "Setting dentry->d_fsdata\n"); ((int)(long)dentry->d_fsdata) |= flag; }}/* given a path: complete the closes on the fset */int lento_complete_closes(char *path){ struct nameidata nd; struct dentry *dentry; int error; struct presto_file_set *fset; ENTRY; error = presto_walk(path, &nd); if (error) { EXIT; return error; } dentry = nd.dentry; error = -ENXIO; if ( !presto_ispresto(dentry->d_inode) ) { EXIT; goto out_complete; } fset = presto_fset(dentry); error = -EINVAL; if ( !fset ) { printk("No fileset!\n"); EXIT; goto out_complete; } /* transactions and locking are internal to this function */ error = presto_complete_lml(fset); EXIT; out_complete: path_release(&nd); return error;} /* set the fset recno and offset to a given value */ int lento_reset_fset(char *path, __u64 offset, __u32 recno){ struct nameidata nd; struct dentry *dentry; int error; struct presto_file_set *fset; ENTRY; error = presto_walk(path, &nd); if (error) return error; dentry = nd.dentry; error = -ENXIO; if ( !presto_ispresto(dentry->d_inode) ) { EXIT; goto out_complete; } fset = presto_fset(dentry); error = -EINVAL; if ( !fset ) { printk("No fileset!\n"); EXIT; goto out_complete; } write_lock(&fset->fset_kml.fd_lock); fset->fset_kml.fd_recno = recno; fset->fset_kml.fd_offset = offset; read_lock(&fset->fset_kml.fd_lock); EXIT; out_complete: path_release(&nd); return error;} /* given a path, write an LML record for it - thus must have root's group array settings, since lento is doing this */ int lento_write_lml(char *path, __u64 remote_ino, __u32 remote_generation, __u32 remote_version, struct presto_version *remote_file_version){ struct nameidata nd; struct rec_info rec; struct dentry *dentry; struct file file; int error; struct presto_file_set *fset; ENTRY; error = presto_walk(path, &nd); if (error) { EXIT; return error; } dentry = nd.dentry; file.f_dentry = dentry; file.private_data = NULL; error = -ENXIO; if ( !presto_ispresto(dentry->d_inode) ) { EXIT; goto out_lml; } fset = presto_fset(dentry); error = -EINVAL; if ( !fset ) { printk("No fileset!\n"); EXIT; goto out_lml; } /* setting offset to -1 appends */ rec.offset = -1; /* this only requires a transaction below which is automatic */ error = presto_write_lml_close(&rec, fset, &file, remote_ino, remote_generation, remote_version, remote_file_version); EXIT; out_lml: path_release(&nd); return error;} /* given a path: write a close record and cancel an LML record, finally call truncate LML. Lento is doing this so it goes in with uid/gid's root. */ int lento_cancel_lml(char *path, __u64 lml_offset, __u64 remote_ino, __u32 remote_generation, __u32 remote_version, struct lento_vfs_context *info){ struct nameidata nd; struct rec_info rec; struct dentry *dentry; int error; struct presto_file_set *fset; void *handle; struct presto_version new_ver; ENTRY; error = presto_walk(path, &nd); if (error) { EXIT; return error; } dentry = nd.dentry; error = -ENXIO; if ( !presto_ispresto(dentry->d_inode) ) { EXIT; goto out_cancel_lml;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -