int coda_open(struct inode *coda_inode, struct file *coda_file)
{
	struct file *host_file = NULL;
	int error;
	unsigned short flags = coda_file->f_flags & (~O_EXCL);
	unsigned short coda_flags = coda_flags_to_cflags(flags);
	struct coda_file_info *cfi;

	cfi = kmalloc(sizeof(struct coda_file_info), GFP_KERNEL);
	if (!cfi)
		return -ENOMEM;

	error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
			   &host_file);
	if (!host_file)
		error = -EIO;

	if (error) {
		kfree(cfi);
		return error;
	}

	host_file->f_flags |= coda_file->f_flags & (O_APPEND | O_SYNC);

	cfi->cfi_magic = CODA_MAGIC;
	cfi->cfi_mapcount = 0;
	cfi->cfi_container = host_file;

	BUG_ON(coda_file->private_data != NULL);
	coda_file->private_data = cfi;
	return 0;
}
int coda_open(struct inode *coda_inode, struct file *coda_file)
{
	struct file *host_file = NULL;
	int error;
	unsigned short flags = coda_file->f_flags & (~O_EXCL);
	unsigned short coda_flags = coda_flags_to_cflags(flags);
	struct coda_file_info *cfi;
	struct inode *host_inode;

	coda_vfs_stat.open++;

	cfi = kmalloc(sizeof(struct coda_file_info), GFP_KERNEL);
	if (!cfi) {
		unlock_kernel();
		return -ENOMEM;
	}

	lock_kernel();

	error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
			   &host_file); 
	if (error || !host_file) {
		kfree(cfi);
		unlock_kernel();
		return error;
	}

	host_file->f_flags |= coda_file->f_flags & (O_APPEND | O_SYNC);

	cfi->cfi_magic = CODA_MAGIC;
	cfi->cfi_mapcount = 0;
	cfi->cfi_container = host_file;
	coda_load_creds(&cfi->cfi_cred);

	host_inode = host_file->f_dentry->d_inode;
	if (coda_inode->i_mapping == &coda_inode->i_data)
		coda_inode->i_mapping = host_inode->i_mapping;

	else if (coda_inode->i_mapping != host_inode->i_mapping) {
		/* This is not a good thing, it doesn't happen with 'venus'
		 * Coda's own userspace daemon, but others might not provide
		 * the same guarantees. Still looking for the real fix. */
		printk("coda_open: changed mapping\n");
		coda_inode->i_mapping = host_inode->i_mapping;
	}

	if (coda_file->private_data != NULL) BUG();
	coda_file->private_data = cfi;

	unlock_kernel();
	return 0;
}
Example #3
0
File: file.c Project: nhanh0/hah
int coda_open(struct inode *i, struct file *f)
{
	struct file *fh = NULL;
	int error = 0;
	unsigned short flags = f->f_flags & (~O_EXCL);
	unsigned short coda_flags = coda_flags_to_cflags(flags);
	struct coda_cred *cred;
	struct coda_inode_info *cii;

	lock_kernel();
	coda_vfs_stat.open++;

	CDEBUG(D_SPECIAL, "OPEN inode number: %ld, count %d, flags %o.\n", 
	       f->f_dentry->d_inode->i_ino, atomic_read(&f->f_dentry->d_count), flags);

	error = venus_open(i->i_sb, coda_i2f(i), coda_flags, &fh); 
	if (error || !fh) {
	        CDEBUG(D_FILE, "coda_open: venus_open result %d\n", error);
		unlock_kernel();
		return error;
	}

	/* coda_upcall returns filehandle of container file object */
	cii = ITOC(i);
	if (cii->c_container)
		fput(cii->c_container);

	cii->c_contcount++;
	cii->c_container = fh;
	i->i_mapping = &cii->c_container->f_dentry->d_inode->i_data;

	cred = kmalloc(sizeof(struct coda_cred), GFP_KERNEL);

	/* If the allocation failed, we'll just muddle on. This actually works
	 * fine for normal cases. (i.e. when open credentials are the same as
	 * close credentials) */
	if (cred) {
		coda_load_creds(cred);
		f->private_data = cred;
	}

	CDEBUG(D_FILE, "result %d, coda i->i_count is %d, cii->contcount is %d for ino %ld\n", 
	       error, atomic_read(&i->i_count), cii->c_contcount, i->i_ino);
	CDEBUG(D_FILE, "cache ino: %ld, count %d, ops %p\n", 
	       fh->f_dentry->d_inode->i_ino,
	       atomic_read(&fh->f_dentry->d_inode->i_count),
               fh->f_dentry->d_inode->i_op);
	unlock_kernel();
	return 0;
}
Example #4
0
/*
 * coda_open calls Venus which returns an open file descriptor the cache file
 * holding the data.  We get the vnode while we are still in the context of
 * the venus process in coda_psdev.c.  This vnode is then passed back to the
 * caller and opened.
 */
int
coda_open(struct vop_open_args *ap)
{

	/*
	 * FreeBSD can pass the O_EXCL flag in mode, even though the check
	 * has already happened.  Venus defensively assumes that if open is
	 * passed the EXCL, it must be a bug.  We strip the flag here.
	 */
	/* true args */
	struct vnode **vpp = &(ap->a_vp);
	struct cnode *cp = VTOC(*vpp);
	int flag = ap->a_mode & (~O_EXCL);
	struct ucred *cred = ap->a_cred;
	struct thread *td = ap->a_td;
	/* locals */
	int error;
	struct vnode *vp;

	MARK_ENTRY(CODA_OPEN_STATS);

	/*
	 * Check for open of control file.
	 */
	if (IS_CTL_VP(*vpp)) {
		/* XXX */
		/* if (WRITEABLE(flag)) */
		if (flag & (FWRITE | O_TRUNC | O_CREAT | O_EXCL)) {
			MARK_INT_FAIL(CODA_OPEN_STATS);
			return (EACCES);
		}
		MARK_INT_SAT(CODA_OPEN_STATS);
		return (0);
	}
	error = venus_open(vtomi((*vpp)), &cp->c_fid, flag, cred,
	    td->td_proc, &vp);
	if (error)
		return (error);
	CODADEBUG(CODA_OPEN, myprintf(("open: vp %p result %d\n", vp,
	    error)););