/* try to make de an entry in dir_inodde linked to source_de */ 
static int coda_link(struct dentry *source_de, struct inode *dir_inode, 
	  struct dentry *de)
{
	struct inode *inode = source_de->d_inode;
        const char * name = de->d_name.name;
	int len = de->d_name.len;
	int error;

	coda_vfs_stat.link++;

	if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
		return -EPERM;

	CDEBUG(D_INODE, "old: fid: %s\n", coda_i2s(inode));
	CDEBUG(D_INODE, "directory: %s\n", coda_i2s(dir_inode));

	error = venus_link(dir_inode->i_sb, coda_i2f(inode),
			   coda_i2f(dir_inode), (const char *)name, len);

	if (error) { 
		d_drop(de);
		goto out;
	}

	coda_dir_changed(dir_inode, 0);
	atomic_inc(&inode->i_count);
	d_instantiate(de, inode);
	inode->i_nlink++;
        
out:
	CDEBUG(D_INODE, "link result %d\n",error);
	return(error);
}
Exemple #2
0
/* access routines: lookup, readlink, permission */
static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd)
{
	struct super_block *sb = dir->i_sb;
	const char *name = entry->d_name.name;
	size_t length = entry->d_name.len;
	struct inode *inode;
	int type = 0;

	if (length > CODA_MAXNAMLEN) {
		printk(KERN_ERR "name too long: lookup, %s (%*s)\n",
		       coda_i2s(dir), (int)length, name);
		return ERR_PTR(-ENAMETOOLONG);
	}

	/* control object, create inode on the fly */
	if (coda_isroot(dir) && coda_iscontrol(name, length)) {
		inode = coda_cnode_makectl(sb);
		type = CODA_NOCACHE;
	} else {
		struct CodaFid fid = { { 0, } };
		int error = venus_lookup(sb, coda_i2f(dir), name, length,
				     &type, &fid);
		inode = !error ? coda_cnode_make(&fid, sb) : ERR_PTR(error);
	}

	if (!IS_ERR(inode) && (type & CODA_NOCACHE))
		coda_flag_inode(inode, C_VATTR | C_PURGE);

	if (inode == ERR_PTR(-ENOENT))
		inode = NULL;

	return d_splice_alias(inode, entry);
}
int coda_permission(struct inode *inode, int mask)
{
        int error;
 
	coda_vfs_stat.permission++;

        if ( mask == 0 )
                return 0;

	if ( coda_access_cache ) {
		coda_permission_stat.count++;

		if ( coda_cache_check(inode, mask) ) {
			coda_permission_stat.hit_count++;
			return 0; 
		}
	}

        CDEBUG(D_INODE, "mask is %o\n", mask);
        error = venus_access(inode->i_sb, coda_i2f(inode), mask);
    
        CDEBUG(D_INODE, "fid: %s, ino: %ld (mask: %o) error: %d\n", 
	       coda_i2s(inode), inode->i_ino, mask, error);

	if (!error)
		coda_cache_enter(inode, mask);

        return error; 
}
Exemple #4
0
/* access routines: lookup, readlink, permission */
static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd)
{
	struct inode *res_inode = NULL;
	struct CodaFid resfid = { { 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);
	}

	lock_kernel();
        /* control object, create inode on the fly */
        if (coda_isroot(dir) && coda_iscontrol(name, length)) {
	        error = coda_cnode_makectl(&res_inode, dir->i_sb);
		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);
			dropme = 1;
		}

	    	error = coda_cnode_make(&res_inode, &resfid, dir->i_sb);
		if (error) {
			unlock_kernel();
			return ERR_PTR(error);
		}
	} else if (error != -ENOENT) {
		unlock_kernel();
		return ERR_PTR(error);
	}

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);
	}
	unlock_kernel();
        return NULL;
}
Exemple #5
0
/* access routines: lookup, readlink, permission */
static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd)
{
	struct inode *inode = NULL;
	struct CodaFid resfid = { { 0, } };
	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(KERN_ERR "name too long: lookup, %s (%*s)\n",
		       coda_i2s(dir), (int)length, name);
		return ERR_PTR(-ENAMETOOLONG);
	}

	/* control object, create inode on the fly */
	if (coda_isroot(dir) && coda_iscontrol(name, length)) {
		error = coda_cnode_makectl(&inode, dir->i_sb);
		type = CODA_NOCACHE;
		goto exit;
	}

	lock_kernel();

	error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length,
			     &type, &resfid);
	if (!error)
		error = coda_cnode_make(&inode, &resfid, dir->i_sb);

	unlock_kernel();

	if (error && error != -ENOENT)
		return ERR_PTR(error);

exit:
	entry->d_op = &coda_dentry_operations;

	if (inode && (type & CODA_NOCACHE))
		coda_flag_inode(inode, C_VATTR | C_PURGE);

	return d_splice_alias(inode, entry);
}
static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
{
	struct inode *inode;
	struct coda_vattr attrs;
	const char *name = de->d_name.name;
	int len = de->d_name.len;
	int error;
	struct ViceFid newfid;

	coda_vfs_stat.mkdir++;

	if (coda_isroot(dir) && coda_iscontrol(name, len))
		return -EPERM;

	CDEBUG(D_INODE, "mkdir %s (len %d) in %s, mode %o.\n", 
	       name, len, coda_i2s(dir), mode);

	attrs.va_mode = mode;
	error = venus_mkdir(dir->i_sb, coda_i2f(dir), 
			       name, len, &newfid, &attrs);
        
        if ( error ) {
	        CDEBUG(D_INODE, "mkdir error: %s result %d\n", 
		       coda_f2s(&newfid), error); 
		d_drop(de);
                return error;
        }
         
	CDEBUG(D_INODE, "mkdir: new dir has fid %s.\n", 
	       coda_f2s(&newfid)); 

	inode = coda_iget(dir->i_sb, &newfid, &attrs);
	if ( IS_ERR(inode) ) {
		d_drop(de);
		return PTR_ERR(inode);
	}
	
	/* invalidate the directory cnode's attributes */
	coda_dir_changed(dir, 1);
	d_instantiate(de, inode);
        return 0;
}
/* destruction routines: unlink, rmdir */
int coda_unlink(struct inode *dir, struct dentry *de)
{
        int error;
	const char *name = de->d_name.name;
	int len = de->d_name.len;

	coda_vfs_stat.unlink++;

        CDEBUG(D_INODE, " %s in %s, dirino %ld\n", name , 
	       coda_i2s(dir), dir->i_ino);

        error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
        if ( error ) {
                CDEBUG(D_INODE, "upc returned error %d\n", error);
                return error;
        }

	coda_dir_changed(dir, 0);
	de->d_inode->i_nlink--;

        return 0;
}
/* 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;
}