📄 presto.c
字号:
} fset = presto_fset(dentry); error=-EINVAL; if (fset==NULL) { printk("No fileset!\n"); EXIT; goto out_cancel_lml; } /* this only requires a transaction below which is automatic */ handle = presto_trans_start(fset, dentry->d_inode, PRESTO_OP_RELEASE); if ( !handle ) { error = -ENOMEM; EXIT; goto out_cancel_lml; } if (info->flags & LENTO_FL_CANCEL_LML) { error = presto_clear_lml_close(fset, lml_offset); if ( error ) { presto_trans_commit(fset, handle); EXIT; goto out_cancel_lml; } } if (info->flags & LENTO_FL_WRITE_KML) { struct file file; file.private_data = NULL; file.f_dentry = dentry; presto_getversion(&new_ver, dentry->d_inode); error = presto_journal_close(&rec, fset, &file, dentry, &new_ver); if ( error ) { EXIT; presto_trans_commit(fset, handle); goto out_cancel_lml; } } if (info->flags & LENTO_FL_WRITE_EXPECT) { error = presto_write_last_rcvd(&rec, fset, info); if ( error ) { EXIT; presto_trans_commit(fset, handle); goto out_cancel_lml; } } presto_trans_commit(fset, handle); if (info->flags & LENTO_FL_CANCEL_LML) { presto_truncate_lml(fset); } out_cancel_lml: EXIT; path_release(&nd); return error;} /* given a path, operate on the flags in its dentry. Used by downcalls */int presto_mark_dentry(const char *name, int and_flag, int or_flag, int *res){ struct nameidata nd; struct dentry *dentry; int error; CDEBUG(D_INODE, "name: %s, and flag %x, or flag %x\n", name, and_flag, or_flag); error = presto_walk(name, &nd); if (error) return error; dentry = nd.dentry; CDEBUG(D_INODE, "dentry at %p, d_fsdata %p\n", dentry, dentry->d_fsdata); error = -ENXIO; if ( !presto_ispresto(dentry->d_inode) ) goto out; error = 0; if ( presto_dentry_is_fsetroot(dentry) ) { struct presto_file_set *fset = presto_dentry2fset(dentry); CDEBUG(D_INODE, "Setting fset fset_data: fset %p\n", fset); if ( fset ) { fset->fset_data &= and_flag; fset->fset_data |= or_flag; if (res) { *res = fset->fset_data; } } CDEBUG(D_INODE, "fset %p, flags %x data %x\n", fset, fset->fset_flags, fset->fset_data); } else { ((int)(long)dentry->d_fsdata) &= and_flag; ((int)(long)dentry->d_fsdata) |= or_flag; if (res) *res = (int)(long)dentry->d_fsdata; } /* indicate if we were the only users while changing the flag */ if ( atomic_read(&dentry->d_count) > 1 ) error = -EBUSY;out: path_release(&nd); return error;}/* given a path, operate on the flags in its cache. Used by mark_ioctl */int presto_mark_cache(const char *name, int and_flag, int or_flag, int *res){ struct nameidata nd; struct dentry *dentry; struct presto_cache *cache; int error; CDEBUG(D_INODE, "presto_mark_cache :: name: %s, and flag %x, or flag %x\n", name, and_flag, or_flag); error = presto_walk(name, &nd); if (error) return error; dentry = nd.dentry; error = -ENXIO; if ( !presto_ispresto(dentry->d_inode) ) goto out; error = -EBADF; cache = presto_get_cache(dentry->d_inode); if ( !cache ) { printk("PRESTO: BAD: cannot find cache in presto_mark_cache\n"); make_bad_inode(dentry->d_inode); goto out; } error = 0; ((int)cache->cache_flags) &= and_flag; ((int)cache->cache_flags) |= or_flag; if (res) { *res = (int)cache->cache_flags; }out: path_release(&nd); return error;}int presto_mark_fset_dentry(struct dentry *dentry, int and_flag, int or_flag, int * res){ int error; struct presto_file_set *fset; error = -ENXIO; if ( !presto_ispresto(dentry->d_inode) ) return error; error = -EBADF; fset = presto_fset(dentry); if ( !fset ) { printk("PRESTO: BAD: cannot find cache in presto_mark_cache\n"); make_bad_inode(dentry->d_inode); return error; } error = 0; ((int)fset->fset_flags) &= and_flag; ((int)fset->fset_flags) |= or_flag; if (res) { *res = (int)fset->fset_flags; } return error;}/* given a path, operate on the flags in its cache. Used by mark_ioctl */inline int presto_mark_fset(const char *name, int and_flag, int or_flag, int * res){ struct nameidata nd; struct dentry *dentry; int error; ENTRY; error = presto_walk(name, &nd); if (error) return error; dentry = nd.dentry; error = presto_mark_fset_dentry(dentry, and_flag, or_flag, res); path_release(&nd); return error;}/* talk to Lento about the permit */static int presto_permit_upcall(struct dentry *dentry){ int rc; char *path, *buffer; int pathlen; int minor; int fsetnamelen; struct presto_file_set *fset = NULL; if ( (minor = presto_i2m(dentry->d_inode)) < 0) return -EINVAL; fset = presto_fset(dentry); if (!fset) { EXIT; return -ENOTCONN; } if ( !presto_lento_up(minor) ) { if ( fset->fset_flags & FSET_STEAL_PERMIT ) { return 0; } else { return -ENOTCONN; } } PRESTO_ALLOC(buffer, char *, PAGE_SIZE); if ( !buffer ) { printk("PRESTO: out of memory!\n"); return -ENOMEM; } path = presto_path(dentry, fset->fset_mtpt, buffer, PAGE_SIZE); pathlen = MYPATHLEN(buffer, path); fsetnamelen = strlen(fset->fset_name); rc = lento_permit(minor, pathlen, fsetnamelen, path, fset->fset_name); PRESTO_FREE(buffer, PAGE_SIZE); return rc;}/* get a write permit for the fileset of this inode * - if this returns a negative value there was an error * - if 0 is returned the permit was already in the kernel -- or -- * Lento gave us the permit without reintegration * - lento returns the number of records it reintegrated */int presto_get_permit(struct inode * inode){ struct dentry *de; struct presto_file_set *fset; int minor = presto_i2m(inode); int rc; ENTRY; if (minor < 0) { EXIT; return -1; } if ( ISLENTO(minor) ) { EXIT; return -EINVAL; } if (list_empty(&inode->i_dentry)) { printk("No alias for inode %d\n", (int) inode->i_ino); EXIT; return -EINVAL; } de = list_entry(inode->i_dentry.next, struct dentry, d_alias); fset = presto_fset(de); if ( !fset ) { printk("Presto: no fileset in presto_get_permit!\n"); EXIT; return -EINVAL; } if (fset->fset_flags & FSET_HASPERMIT) { lock_kernel(); fset->fset_permit_count++; CDEBUG(D_INODE, "permit count now %d, inode %lx\n", fset->fset_permit_count, inode->i_ino); unlock_kernel(); EXIT; return 0; } else { /* Allow reintegration to proceed without locks -SHP */ rc = presto_permit_upcall(fset->fset_mtpt); lock_kernel(); if ( !rc ) { presto_mark_fset_dentry (fset->fset_mtpt, ~0, FSET_HASPERMIT, NULL); fset->fset_permit_count++; } CDEBUG(D_INODE, "permit count now %d, ino %lx (likely 1), rc %d\n", fset->fset_permit_count, inode->i_ino, rc); unlock_kernel(); EXIT; return rc; }}int presto_put_permit(struct inode * inode){ struct dentry *de; struct presto_file_set *fset; int minor = presto_i2m(inode); ENTRY; if (minor < 0) { EXIT; return -1; } if ( ISLENTO(minor) ) { EXIT; return -1; } if (list_empty(&inode->i_dentry)) { printk("No alias for inode %d\n", (int) inode->i_ino); EXIT; return -1; } de = list_entry(inode->i_dentry.next, struct dentry, d_alias); fset = presto_fset(de); if ( !fset ) { printk("Presto: no fileset in presto_get_permit!\n"); EXIT; return -1; } lock_kernel(); if (fset->fset_flags & FSET_HASPERMIT) { if (fset->fset_permit_count > 0) fset->fset_permit_count--; else printk("Put permit while permit count is 0, inode %lx!\n", inode->i_ino); } else { fset->fset_permit_count=0; printk("Put permit while no permit, inode %lx, flags %x!\n", inode->i_ino, fset->fset_flags); } CDEBUG(D_INODE, "permit count now %d, inode %lx\n", fset->fset_permit_count, inode->i_ino); if (fset->fset_flags & FSET_PERMIT_WAITING && fset->fset_permit_count == 0) { CDEBUG(D_INODE, "permit count now 0, ino %lx, notify Lento\n", inode->i_ino); presto_mark_fset_dentry(fset->fset_mtpt, ~FSET_PERMIT_WAITING, 0, NULL); presto_mark_fset_dentry(fset->fset_mtpt, ~FSET_HASPERMIT, 0, NULL); lento_release_permit(fset->fset_cache->cache_psdev->uc_minor, fset->fset_permit_cookie); fset->fset_permit_cookie = 0; } unlock_kernel(); EXIT; return 0;}void presto_getversion(struct presto_version * presto_version, struct inode * inode){ presto_version->pv_mtime = cpu_to_le64((__u64)inode->i_mtime); presto_version->pv_ctime = cpu_to_le64((__u64)inode->i_ctime); presto_version->pv_size = cpu_to_le64((__u64)inode->i_size);}/* * note: this routine "pins" a dentry for a fileset root */int presto_set_fsetroot(char *path, char *fsetname, unsigned int fsetid, unsigned int flags){ struct presto_file_set *fset; struct presto_file_set *fset2; struct dentry *dentry; struct presto_cache *cache; int error;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -