/** * This should allocate memory for sf_inode_info, compute a unique inode * number, get an inode from vfs, initialize inode info, instantiate * dentry. * * @param parent inode entry of the directory * @param dentry directory cache entry * @param path path name * @param info file information * @param handle handle * @returns 0 on success, Linux error code otherwise */ static int sf_instantiate(struct inode *parent, struct dentry *dentry, SHFLSTRING *path, PSHFLFSOBJINFO info, SHFLHANDLE handle) { int err; ino_t ino; struct inode *inode; struct sf_inode_info *sf_new_i; struct sf_glob_info *sf_g = GET_GLOB_INFO(parent->i_sb); TRACE(); BUG_ON(!sf_g); sf_new_i = kmalloc(sizeof(*sf_new_i), GFP_KERNEL); if (!sf_new_i) { LogRelFunc(("could not allocate inode info.\n")); err = -ENOMEM; goto fail0; } ino = iunique(parent->i_sb, 1); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) inode = iget_locked(parent->i_sb, ino); #else inode = iget(parent->i_sb, ino); #endif if (!inode) { LogFunc(("iget failed\n")); err = -ENOMEM; goto fail1; } sf_init_inode(sf_g, inode, info); sf_new_i->path = path; SET_INODE_INFO(inode, sf_new_i); sf_new_i->force_restat = 1; sf_new_i->force_reread = 0; d_instantiate(dentry, inode); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) unlock_new_inode(inode); #endif /* Store this handle if we leave the handle open. */ sf_new_i->handle = handle; return 0; fail1: kfree(sf_new_i); fail0: return err; }
static int sf_remount_fs(struct super_block *sb, int *flags, char *data) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23) struct sf_glob_info *sf_g; struct vbsf_mount_info_new *info; struct sf_inode_info *sf_i; struct inode *iroot; SHFLFSOBJINFO fsinfo; int err; printk(KERN_DEBUG "ENTER: sf_remount_fs\n"); sf_g = GET_GLOB_INFO(sb); BUG_ON(!sf_g); BUG_ON(data[0] != 0); info = (struct vbsf_mount_info_new *)data; BUG_ON( info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0 || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1 || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2); sf_g->uid = info->uid; sf_g->gid = info->gid; sf_g->ttl = info->ttl; sf_g->dmode = info->dmode; sf_g->fmode = info->fmode; sf_g->dmask = info->dmask; sf_g->fmask = info->fmask; iroot = ilookup(sb, 0); if (!iroot) { printk(KERN_DEBUG "can't find root inode\n"); return -ENOSYS; } sf_i = GET_INODE_INFO(iroot); err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0); BUG_ON(err != 0); sf_init_inode(sf_g, iroot, &fsinfo); /*unlock_new_inode(iroot);*/ printk(KERN_DEBUG "LEAVE: sf_remount_fs\n"); return 0; #else return -ENOSYS; #endif }
static int sf_remount_fs(struct super_block *sb, int *flags, char *data) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23) struct sf_glob_info *sf_g; struct sf_inode_info *sf_i; struct inode *iroot; SHFLFSOBJINFO fsinfo; int err; sf_g = GET_GLOB_INFO(sb); BUG_ON(!sf_g); if (data && data[0] != 0) { struct vbsf_mount_info_new *info = (struct vbsf_mount_info_new *)data; if ( info->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0 && info->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1 && info->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2) { sf_g->uid = info->uid; sf_g->gid = info->gid; sf_g->ttl = info->ttl; sf_g->dmode = info->dmode; sf_g->fmode = info->fmode; sf_g->dmask = info->dmask; sf_g->fmask = info->fmask; } } iroot = ilookup(sb, 0); if (!iroot) return -ENOSYS; sf_i = GET_INODE_INFO(iroot); err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0); BUG_ON(err != 0); sf_init_inode(sf_g, iroot, &fsinfo); /*unlock_new_inode(iroot);*/ return 0; #else return -ENOSYS; #endif }
/* this is called directly as iop on 2.4, indirectly as dop [sf_dentry_revalidate] on 2.4/2.6, indirectly as iop through [sf_getattr] on 2.6. the job is to find out whether dentry/inode is still valid. the test is failed if [dentry] does not have an inode or [sf_stat] is unsuccessful, otherwise we return success and update inode attributes */ int sf_inode_revalidate(struct dentry *dentry) { int err; struct sf_glob_info *sf_g; struct sf_inode_info *sf_i; SHFLFSOBJINFO info; TRACE(); if (!dentry || !dentry->d_inode) { LogFunc(("no dentry(%p) or inode(%p)\n", dentry, dentry->d_inode)); return -EINVAL; } sf_g = GET_GLOB_INFO(dentry->d_inode->i_sb); sf_i = GET_INODE_INFO(dentry->d_inode); #if 0 printk("%s called by %p:%p\n", sf_i->path->String.utf8, __builtin_return_address (0), __builtin_return_address (1)); #endif BUG_ON(!sf_g); BUG_ON(!sf_i); if (!sf_i->force_restat) { if (jiffies - dentry->d_time < sf_g->ttl) return 0; } err = sf_stat(__func__, sf_g, sf_i->path, &info, 1); if (err) return err; dentry->d_time = jiffies; sf_init_inode(sf_g, dentry->d_inode, &info); return 0; }
/** * This is called (by sf_read_super_[24|26] when vfs mounts the fs and * wants to read super_block. * * calls [sf_glob_alloc] to map the folder and allocate global * information structure. * * initializes [sb], initializes root inode and dentry. * * should respect [flags] */ static int sf_read_super_aux(struct super_block *sb, void *data, int flags) { int err; struct dentry *droot; struct inode *iroot; struct sf_inode_info *sf_i; struct sf_glob_info *sf_g; SHFLFSOBJINFO fsinfo; struct vbsf_mount_info_new *info; TRACE(); if (!data) { LogFunc(("no mount info specified\n")); return -EINVAL; } info = data; if (flags & MS_REMOUNT) { LogFunc(("remounting is not supported\n")); return -ENOSYS; } err = sf_glob_alloc(info, &sf_g); if (err) goto fail0; sf_i = kmalloc(sizeof (*sf_i), GFP_KERNEL); if (!sf_i) { err = -ENOMEM; LogRelFunc(("could not allocate memory for root inode info\n")); goto fail1; } sf_i->handle = SHFL_HANDLE_NIL; sf_i->path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL); if (!sf_i->path) { err = -ENOMEM; LogRelFunc(("could not allocate memory for root inode path\n")); goto fail2; } sf_i->path->u16Length = 1; sf_i->path->u16Size = 2; sf_i->path->String.utf8[0] = '/'; sf_i->path->String.utf8[1] = 0; err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0); if (err) { LogFunc(("could not stat root of share\n")); goto fail3; } sb->s_magic = 0xface; sb->s_blocksize = 1024; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 3) /* Required for seek/sendfile. * * Must by less than or equal to INT64_MAX despite the fact that the * declaration of this variable is unsigned long long. See determination * of 'loff_t max' in fs/read_write.c / do_sendfile(). I don't know the * correct limit but MAX_LFS_FILESIZE (8TB-1 on 32-bit boxes) takes the * page cache into account and is the suggested limit. */ # if defined MAX_LFS_FILESIZE sb->s_maxbytes = MAX_LFS_FILESIZE; # else sb->s_maxbytes = 0x7fffffffffffffffULL; # endif #endif sb->s_op = &sf_super_ops; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) iroot = iget_locked(sb, 0); #else iroot = iget(sb, 0); #endif if (!iroot) { err = -ENOMEM; /* XXX */ LogFunc(("could not get root inode\n")); goto fail3; } if (sf_init_backing_dev(sf_g)) { err = -EINVAL; LogFunc(("could not init bdi\n")); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) unlock_new_inode(iroot); #endif goto fail4; } sf_init_inode(sf_g, iroot, &fsinfo); SET_INODE_INFO(iroot, sf_i); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) unlock_new_inode(iroot); #endif droot = d_alloc_root(iroot); if (!droot) { err = -ENOMEM; /* XXX */ LogFunc(("d_alloc_root failed\n")); goto fail5; } sb->s_root = droot; SET_GLOB_INFO(sb, sf_g); return 0; fail5: sf_done_backing_dev(sf_g); fail4: iput(iroot); fail3: kfree(sf_i->path); fail2: kfree(sf_i); fail1: sf_glob_free(sf_g); fail0: return err; }
/** * This is called when vfs failed to locate dentry in the cache. The * job of this function is to allocate inode and link it to dentry. * [dentry] contains the name to be looked in the [parent] directory. * Failure to locate the name is not a "hard" error, in this case NULL * inode is added to [dentry] and vfs should proceed trying to create * the entry via other means. NULL(or "positive" pointer) ought to be * returned in case of success and "negative" pointer on error */ static struct dentry *sf_lookup(struct inode *parent, struct dentry *dentry #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) , unsigned int flags #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) , struct nameidata *nd #endif ) { int err; struct sf_inode_info *sf_i, *sf_new_i; struct sf_glob_info *sf_g; SHFLSTRING *path; struct inode *inode; ino_t ino; SHFLFSOBJINFO fsinfo; TRACE(); sf_g = GET_GLOB_INFO(parent->i_sb); sf_i = GET_INODE_INFO(parent); BUG_ON(!sf_g); BUG_ON(!sf_i); err = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path); if (err) goto fail0; err = sf_stat(__func__, sf_g, path, &fsinfo, 1); if (err) { if (err == -ENOENT) { /* -ENOENT: add NULL inode to dentry so it later can be created via call to create/mkdir/open */ kfree(path); inode = NULL; } else goto fail1; } else { sf_new_i = kmalloc(sizeof(*sf_new_i), GFP_KERNEL); if (!sf_new_i) { LogRelFunc(("could not allocate memory for new inode info\n")); err = -ENOMEM; goto fail1; } sf_new_i->handle = SHFL_HANDLE_NIL; sf_new_i->force_reread = 0; ino = iunique(parent->i_sb, 1); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) inode = iget_locked(parent->i_sb, ino); #else inode = iget(parent->i_sb, ino); #endif if (!inode) { LogFunc(("iget failed\n")); err = -ENOMEM; /* XXX: ??? */ goto fail2; } SET_INODE_INFO(inode, sf_new_i); sf_init_inode(sf_g, inode, &fsinfo); sf_new_i->path = path; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) unlock_new_inode(inode); #endif } sf_i->force_restat = 0; dentry->d_time = jiffies; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) d_set_d_op(dentry, &sf_dentry_ops); #else dentry->d_op = &sf_dentry_ops; #endif d_add(dentry, inode); return NULL; fail2: kfree(sf_new_i); fail1: kfree(path); fail0: return ERR_PTR(err); }