static int coda_fill_super(struct super_block *sb, void *data, int silent) { struct inode *root = NULL; struct venus_comm *vc; struct CodaFid fid; int error; int idx; idx = get_device_index((struct coda_mount_data *) data); /* Ignore errors in data, for backward compatibility */ if(idx == -1) idx = 0; printk(KERN_INFO "coda_read_super: device index: %i\n", idx); vc = &coda_comms[idx]; mutex_lock(&vc->vc_mutex); if (!vc->vc_inuse) { printk("coda_read_super: No pseudo device\n"); error = -EINVAL; goto unlock_out; } if (vc->vc_sb) { printk("coda_read_super: Device already mounted\n"); error = -EBUSY; goto unlock_out; } error = bdi_setup_and_register(&vc->bdi, "coda", BDI_CAP_MAP_COPY); if (error) goto unlock_out; vc->vc_sb = sb; mutex_unlock(&vc->vc_mutex); sb->s_fs_info = vc; sb->s_flags |= MS_NOATIME; sb->s_blocksize = 4096; /* XXXXX what do we put here?? */ sb->s_blocksize_bits = 12; sb->s_magic = CODA_SUPER_MAGIC; sb->s_op = &coda_super_operations; sb->s_d_op = &coda_dentry_operations; sb->s_bdi = &vc->bdi; /* get root fid from Venus: this needs the root inode */ error = venus_rootfid(sb, &fid); if ( error ) { printk("coda_read_super: coda_get_rootfid failed with %d\n", error); goto error; } printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid)); /* make root inode */ root = coda_cnode_make(&fid, sb); if (IS_ERR(root)) { error = PTR_ERR(root); printk("Failure of coda_cnode_make for root: error %d\n", error); goto error; } printk("coda_read_super: rootinode is %ld dev %s\n", root->i_ino, root->i_sb->s_id); sb->s_root = d_make_root(root); if (!sb->s_root) { error = -EINVAL; goto error; } return 0; error: mutex_lock(&vc->vc_mutex); bdi_destroy(&vc->bdi); vc->vc_sb = NULL; sb->s_fs_info = NULL; unlock_out: mutex_unlock(&vc->vc_mutex); return error; }
/* access routines: lookup, readlink, permission */ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry) { struct inode *res_inode = NULL; struct ViceFid resfid = {0,0,0}; int dropme = 0; /* to indicate entry should not be cached */ int type = 0; int error = 0; const char *name = entry->d_name.name; size_t length = entry->d_name.len; if ( length > CODA_MAXNAMLEN ) { printk("name too long: lookup, %s (%*s)\n", coda_i2s(dir), (int)length, name); return ERR_PTR(-ENAMETOOLONG); } CDEBUG(D_INODE, "name %s, len %ld in ino %ld, fid %s\n", name, (long)length, dir->i_ino, coda_i2s(dir)); /* control object, create inode on the fly */ if (coda_isroot(dir) && coda_iscontrol(name, length)) { error = coda_cnode_makectl(&res_inode, dir->i_sb); CDEBUG(D_SPECIAL, "Lookup on CTL object; dir ino %ld, count %d\n", dir->i_ino, atomic_read(&dir->i_count)); dropme = 1; goto exit; } error = venus_lookup(dir->i_sb, coda_i2f(dir), (const char *)name, length, &type, &resfid); res_inode = NULL; if (!error) { if (type & CODA_NOCACHE) { type &= (~CODA_NOCACHE); CDEBUG(D_INODE, "dropme set for %s\n", coda_f2s(&resfid)); dropme = 1; } error = coda_cnode_make(&res_inode, &resfid, dir->i_sb); if (error) return ERR_PTR(error); } else if (error != -ENOENT) { CDEBUG(D_INODE, "error for %s(%*s)%d\n", coda_i2s(dir), (int)length, name, error); return ERR_PTR(error); } CDEBUG(D_INODE, "lookup: %s is (%s), type %d result %d, dropme %d\n", name, coda_f2s(&resfid), type, error, dropme); exit: entry->d_time = 0; entry->d_op = &coda_dentry_operations; d_add(entry, res_inode); if ( dropme ) { d_drop(entry); coda_flag_inode(res_inode, C_VATTR); } return NULL; }