Пример #1
0
void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, 
		      struct CodaFid *newfid)
{
	struct coda_inode_info *cii;
	unsigned long hash = coda_f2i(newfid);
	
	cii = ITOC(inode);

	BUG_ON(!coda_fideq(&cii->c_fid, oldfid));

	/* replace fid and rehash inode */
	/* XXX we probably need to hold some lock here! */
	remove_inode_hash(inode);
	cii->c_fid = *newfid;
	inode->i_ino = hash;
	__insert_inode_hash(inode, hash);
}
Пример #2
0
void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid, 
		      struct ViceFid *newfid)
{
	struct coda_inode_info *cii;
	
	cii = ITOC(inode);

	if (!coda_fideq(&cii->c_fid, oldfid))
		BUG();

	/* replace fid and rehash inode */
	/* XXX we probably need to hold some lock here! */
	remove_inode_hash(inode);
	cii->c_fid = *newfid;
	inode->i_ino = coda_f2i(newfid);
	insert_inode_hash(inode);
}
Пример #3
0
int coda_release(struct inode *coda_inode, struct file *coda_file)
{
	unsigned short flags = (coda_file->f_flags) & (~O_EXCL);
	unsigned short coda_flags = coda_flags_to_cflags(flags);
	struct coda_file_info *cfi;
	struct coda_inode_info *cii;
	struct inode *host_inode;
	int err = 0;

	lock_kernel();
	coda_vfs_stat.release++;
 
	if (!use_coda_close) {
		err = venus_release(coda_inode->i_sb, coda_i2f(coda_inode),
				    coda_flags);
		if (err == -EOPNOTSUPP) {
			use_coda_close = 1;
			err = 0;
		}
	}

	cfi = CODA_FTOC(coda_file);
	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);

	if (use_coda_close)
		err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
				  coda_flags, coda_file->f_uid);

	host_inode = cfi->cfi_container->f_dentry->d_inode;
	cii = ITOC(coda_inode);

	/* did we mmap this file? */
	if (coda_inode->i_mapping == &host_inode->i_data) {
		cii->c_mapcount -= cfi->cfi_mapcount;
		if (!cii->c_mapcount)
			coda_inode->i_mapping = &coda_inode->i_data;
	}

	fput(cfi->cfi_container);
	kfree(coda_file->private_data);
	coda_file->private_data = NULL;

	unlock_kernel();
	return err;
}
Пример #4
0
/* all filling in of inodes postponed until lookup */
static void coda_read_inode(struct inode *inode)
{
	struct coda_sb_info *sbi = coda_sbp(inode->i_sb);
	struct coda_inode_info *cii;
	ENTRY;

        if (!sbi) BUG();

	cii = ITOC(inode);
        if (cii->c_magic == CODA_CNODE_MAGIC) {
            printk("coda_read_inode: initialized inode");
            return;
        }

	memset(cii, 0, sizeof(struct coda_inode_info));
	list_add(&cii->c_cilist, &sbi->sbi_cihead);
        cii->c_magic = CODA_CNODE_MAGIC;
}
Пример #5
0
/*
 * This is called when we want to check if the inode has
 * changed on the server.  Coda makes this easy since the
 * cache manager Venus issues a downcall to the kernel when this 
 * happens 
 */
int coda_revalidate_inode(struct dentry *dentry)
{
	struct coda_vattr attr;
	int error;
	int old_mode;
	ino_t old_ino;
	struct inode *inode = dentry->d_inode;
	struct coda_inode_info *cii = ITOC(inode);

	if (!cii->c_flags)
		return 0;

	if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
		error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
		if (error)
			return -EIO;

		/* this inode may be lost if:
		   - it's ino changed 
		   - type changes must be permitted for repair and
		   missing mount points.
		*/
		old_mode = inode->i_mode;
		old_ino = inode->i_ino;
		coda_vattr_to_iattr(inode, &attr);

		if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {
			printk("Coda: inode %ld, fid %s changed type!\n",
			       inode->i_ino, coda_f2s(&(cii->c_fid)));
		}

		/* the following can happen when a local fid is replaced 
		   with a global one, here we lose and declare the inode bad */
		if (inode->i_ino != old_ino)
			return -EIO;
		
		coda_flag_inode_children(inode, C_FLUSH);

		spin_lock(&cii->c_lock);
		cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
		spin_unlock(&cii->c_lock);
	}
	return 0;
}
Пример #6
0
static int coda_pioctl(struct inode * inode, struct file * filp, 
                       unsigned int cmd, unsigned long user_data)
{
	struct nameidata nd;
        int error;
	struct PioctlData data;
        struct inode *target_inode = NULL;
        struct coda_inode_info *cnp;

        /* get the Pioctl data arguments from user space */
        if (copy_from_user(&data, (void __user *)user_data, sizeof(data))) {
	    return -EINVAL;
	}
       
        /* 
         * Look up the pathname. Note that the pathname is in 
         * user memory, and namei takes care of this
         */
        if ( data.follow ) {
                error = user_path_walk(data.path, &nd);
	} else {
	        error = user_path_walk_link(data.path, &nd);
	}
		
	if ( error ) {
		return error;
        } else {
	        target_inode = nd.dentry->d_inode;
	}
	
	/* return if it is not a Coda inode */
	if ( target_inode->i_sb != inode->i_sb ) {
		path_release(&nd);
	        return  -EINVAL;
	}

	/* now proceed to make the upcall */
        cnp = ITOC(target_inode);

	error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data);

	path_release(&nd);
        return error;
}
Пример #7
0
Файл: file.c Проект: nhanh0/hah
int coda_release(struct inode *i, struct file *f)
{
	unsigned short flags = (f->f_flags) & (~O_EXCL);
	unsigned short cflags = coda_flags_to_cflags(flags);
	struct coda_inode_info *cii;
	struct file *cfile;
	int err = 0;

	lock_kernel();
	coda_vfs_stat.release++;
 
	if (!use_coda_close) {
		err = venus_release(i->i_sb, coda_i2f(i), cflags);
		if (err == -EOPNOTSUPP) {
			use_coda_close = 1;
			err = 0;
		}
	}

	if (use_coda_close)
		err = venus_close(i->i_sb, coda_i2f(i), cflags,
                                  (struct coda_cred *)f->private_data);

	cii = ITOC(i);
	cfile = cii->c_container;
	if (!cfile) BUG();

	if (--cii->c_contcount) {
		unlock_kernel();
		return err;
	}

	i->i_mapping = &i->i_data;
	fput(cfile);
	cii->c_container = NULL;

	if (f->private_data) {
		kfree(f->private_data);
		f->private_data = NULL;
	}

	unlock_kernel();
	return err;
}
Пример #8
0
Файл: file.c Проект: nhanh0/hah
int coda_flush(struct file *file)
{
	unsigned short flags = (file->f_flags) & (~O_EXCL);
	unsigned short cflags;
	struct coda_inode_info *cii;
	struct file *cfile;
	struct inode *cinode, *inode;
	int err = 0, fcnt;

	coda_vfs_stat.flush++;

	/* No need to make an upcall when we have not made any modifications
	 * to the file */
	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
		return 0;

	if (use_coda_close)
		return 0;

	fcnt = file_count(file);
	if (fcnt > 1) return 0;

	cflags = coda_flags_to_cflags(flags);

	inode = file->f_dentry->d_inode;
	cii = ITOC(inode);
	cfile = cii->c_container;
	if (!cfile) BUG();

	cinode = cfile->f_dentry->d_inode;

	CDEBUG(D_FILE, "FLUSH coda (file %p ct %d)\n", file, fcnt);

	err = venus_store(inode->i_sb, coda_i2f(inode), cflags,
                          (struct coda_cred *)file->private_data);
	if (err == -EOPNOTSUPP) {
		use_coda_close = 1;
		err = 0;
	}

	CDEBUG(D_FILE, "coda_flush: result: %d\n", err);
	return err;
}
Пример #9
0
Файл: inode.c Проект: nhanh0/hah
static void coda_clear_inode(struct inode *inode)
{
	struct coda_inode_info *cii = ITOC(inode);

        CDEBUG(D_SUPER, " inode->ino: %ld, count: %d\n", 
	       inode->i_ino, atomic_read(&inode->i_count));        
	CDEBUG(D_DOWNCALL, "clearing inode: %ld, %x\n", inode->i_ino, cii->c_flags);

	if (cii->c_container) BUG();
	
        list_del_init(&cii->c_cilist);
	inode->i_mapping = &inode->i_data;
	coda_cache_clear_inode(inode);

#if 0
	cii_free(inode->u.generic_ip);
	inode->u.generic_ip = NULL;
#endif
}
static long coda_pioctl(struct file *filp, unsigned int cmd,
			unsigned long user_data)
{
	struct path path;
	int error;
	struct PioctlData data;
	struct inode *inode = filp->f_dentry->d_inode;
	struct inode *target_inode = NULL;
	struct coda_inode_info *cnp;

	/* get the Pioctl data arguments from user space */
	if (copy_from_user(&data, (void __user *)user_data, sizeof(data)))
		return -EINVAL;

	/*
	 * Look up the pathname. Note that the pathname is in
	 * user memory, and namei takes care of this
	 */
	if (data.follow)
		error = user_path(data.path, &path);
	else
		error = user_lpath(data.path, &path);

	if (error)
		return error;

	target_inode = path.dentry->d_inode;

	/* return if it is not a Coda inode */
	if (target_inode->i_sb != inode->i_sb) {
		error = -EINVAL;
		goto out;
	}

	/* now proceed to make the upcall */
	cnp = ITOC(target_inode);

	error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data);
out:
	path_put(&path);
	return error;
}
Пример #11
0
static ssize_t
coda_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
	struct inode *inode = file->f_dentry->d_inode;
	struct coda_inode_info *cii = ITOC(inode);
	struct file *cfile;
	ssize_t ret;

	cfile = cii->c_container;
	if (!cfile) BUG();

	if (!cfile->f_op || !cfile->f_op->read)
		return -EINVAL;

	down(&inode->i_sem);
	ret = cfile->f_op->read(cfile, buf, count, ppos);
	UPDATE_ATIME(inode);
	up(&inode->i_sem);

	return ret;
}
/* called when a cache lookup succeeds */
static int coda_dentry_revalidate(struct dentry *de, int flags)
{
	struct inode *inode = de->d_inode;
	struct coda_inode_info *cii;

	if (!inode)
		return 1;
	lock_kernel();
	if (coda_isroot(inode))
		goto out;
	if (is_bad_inode(inode))
		goto bad;

	cii = ITOC(de->d_inode);
	if (!(cii->c_flags & (C_PURGE | C_FLUSH)))
		goto out;

	shrink_dcache_parent(de);

	/* propagate for a flush */
	if (cii->c_flags & C_FLUSH) 
		coda_flag_inode_children(inode, C_FLUSH);

	if (atomic_read(&de->d_count) > 1) {
		/* pretend it's valid, but don't change the flags */
		CDEBUG(D_DOWNCALL, "BOOM for: ino %ld, %s\n",
		       de->d_inode->i_ino, coda_f2s(&cii->c_fid));
		goto out;
	}

	/* clear the flags. */
	cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);

bad:
	unlock_kernel();
	return 0;
out:
	unlock_kernel();
	return 1;
}
Пример #13
0
static ssize_t coda_file_write(struct file *coda_file, const char *buff, 
			    size_t count, loff_t *ppos)
{
        struct coda_inode_info *cnp;
	struct inode *coda_inode = coda_file->f_dentry->d_inode;
        struct inode *cont_inode = NULL;
        struct file  cont_file;
	struct dentry cont_dentry;
        int result = 0;

        ENTRY;
	coda_vfs_stat.file_write++;

        cnp = ITOC(coda_inode);

        cont_inode = cnp->c_ovp;
        if ( cont_inode == NULL ) {
                printk("coda_file_write: cached inode is 0!\n");
                return -1; 
        }

        coda_prepare_openfile(coda_inode, coda_file, cont_inode, 
			      &cont_file, &cont_dentry);

        if (!cont_file.f_op || !cont_file.f_op->write) {
                printk("coda_file_write: container file has no file ops.\n");
                return -1;
        }

	down(&cont_inode->i_sem);
        result = cont_file.f_op->write(&cont_file , buff, count, 
				       &(cont_file.f_pos));
	up(&cont_inode->i_sem);
        coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
	
	if (result)
		cnp->c_flags |= C_VATTR;

        return result;
}
Пример #14
0
static int
coda_file_mmap(struct file *file, struct vm_area_struct *vma)
{
	struct inode *inode = file->f_dentry->d_inode;
	struct coda_inode_info *cii = ITOC(inode);
	struct file *cfile;
	int ret;

	cfile = cii->c_container;

	if (!cfile) BUG();

	if (!cfile->f_op || !cfile->f_op->mmap)
		return -ENODEV;

	down(&inode->i_sem);
	ret = cfile->f_op->mmap(cfile, vma);
	UPDATE_ATIME(inode);
	up(&inode->i_sem);

	return ret;
}
Пример #15
0
int coda_fsync(struct file *coda_file, struct dentry *coda_dentry)
{
        struct coda_inode_info *cnp;
	struct inode *coda_inode = coda_dentry->d_inode;
        struct inode *cont_inode = NULL;
        struct file  cont_file;
	struct dentry cont_dentry;
        int result = 0;
        ENTRY;
	coda_vfs_stat.fsync++;

	if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) ||
	      S_ISLNK(coda_inode->i_mode)))
		return -EINVAL;

        cnp = ITOC(coda_inode);

        cont_inode = cnp->c_ovp;
        if ( cont_inode == NULL ) {
                printk("coda_file_write: cached inode is 0!\n");
                return -1; 
        }

        coda_prepare_openfile(coda_inode, coda_file, cont_inode, 
			      &cont_file, &cont_dentry);

	down(&cont_inode->i_sem);

        result = file_fsync(&cont_file ,&cont_dentry);
	if ( result == 0 ) {
		result = venus_fsync(coda_inode->i_sb, &(cnp->c_fid));
	}

	up(&cont_inode->i_sem);

        coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
        return result;
}
Пример #16
0
static ssize_t coda_file_read(struct file *coda_file, char *buff, 
			   size_t count, loff_t *ppos)
{
        struct coda_inode_info *cnp;
	struct inode *coda_inode = coda_file->f_dentry->d_inode;
        struct inode *cont_inode = NULL;
        struct file  cont_file;
	struct dentry cont_dentry;
        int result = 0;

	ENTRY;
	coda_vfs_stat.file_read++;

        cnp = ITOC(coda_inode);
	
        cont_inode = cnp->c_ovp;
        if ( cont_inode == NULL ) {
                printk("coda_file_read: cached inode is 0!\n");
                return -1;
        }

        coda_prepare_openfile(coda_inode, coda_file, cont_inode, 
			      &cont_file, &cont_dentry);

        if (!cont_file.f_op || ! cont_file.f_op->read) { 
                printk( "container file has no read in file operations.\n");
                return -1;
        }

        result = cont_file.f_op->read(&cont_file , buff, count, 
				      &(cont_file.f_pos));

        CDEBUG(D_FILE, "ops at %p result %d, count %ld, position: %d\n", 
	       cont_file.f_op, result, (long)count, (int)cont_file.f_pos);

        coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
        return result;
}
Пример #17
0
static int
coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
{
	struct coda_file_info *cfi;
	struct coda_inode_info *cii;
	struct file *host_file;
	struct inode *coda_inode, *host_inode;

	cfi = CODA_FTOC(coda_file);
	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
	host_file = cfi->cfi_container;

	if (!host_file->f_op || !host_file->f_op->mmap)
		return -ENODEV;

	coda_inode = coda_file->f_path.dentry->d_inode;
	host_inode = host_file->f_path.dentry->d_inode;

	cii = ITOC(coda_inode);
	spin_lock(&cii->c_lock);
	coda_file->f_mapping = host_file->f_mapping;
	if (coda_inode->i_mapping == &coda_inode->i_data)
		coda_inode->i_mapping = host_inode->i_mapping;

	/* only allow additional mmaps as long as userspace isn't changing
	 * the container file on us! */
	else if (coda_inode->i_mapping != host_inode->i_mapping) {
		spin_unlock(&cii->c_lock);
		return -EBUSY;
	}

	/* keep track of how often the coda_inode/host_file has been mmapped */
	cii->c_mapcount++;
	cfi->cfi_mapcount++;
	spin_unlock(&cii->c_lock);

	return host_file->f_op->mmap(host_file, vma);
}
Пример #18
0
/* called when a cache lookup succeeds */
static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
{
	struct inode *inode;
	struct coda_inode_info *cii;

	if (nd->flags & LOOKUP_RCU)
		return -ECHILD;

	inode = de->d_inode;
	if (!inode || coda_isroot(inode))
		goto out;
	if (is_bad_inode(inode))
		goto bad;

	cii = ITOC(de->d_inode);
	if (!(cii->c_flags & (C_PURGE | C_FLUSH)))
		goto out;

	shrink_dcache_parent(de);

	/* propagate for a flush */
	if (cii->c_flags & C_FLUSH) 
		coda_flag_inode_children(inode, C_FLUSH);

	if (de->d_count > 1)
		/* pretend it's valid, but don't change the flags */
		goto out;

	/* clear the flags. */
	spin_lock(&cii->c_lock);
	cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
	spin_unlock(&cii->c_lock);
bad:
	return 0;
out:
	return 1;
}
Пример #19
0
/* called when a cache lookup succeeds */
static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
{
	struct inode *inode = de->d_inode;
	struct coda_inode_info *cii;

	if (!inode)
		return 1;
	lock_kernel();
	if (coda_isroot(inode))
		goto out;
	if (is_bad_inode(inode))
		goto bad;

	cii = ITOC(de->d_inode);
	if (!(cii->c_flags & (C_PURGE | C_FLUSH)))
		goto out;

	shrink_dcache_parent(de);

	/* propagate for a flush */
	if (cii->c_flags & C_FLUSH) 
		coda_flag_inode_children(inode, C_FLUSH);

	if (atomic_read(&de->d_count) > 1)
		/* pretend it's valid, but don't change the flags */
		goto out;

	/* clear the flags. */
	cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);

bad:
	unlock_kernel();
	return 0;
out:
	unlock_kernel();
	return 1;
}
Пример #20
0
int coda_revalidate_inode(struct dentry *dentry)
{
	struct coda_vattr attr;
	int error;
	int old_mode;
	ino_t old_ino;
	struct inode *inode = dentry->d_inode;
	struct coda_inode_info *cii = ITOC(inode);

	if (!cii->c_flags)
		return 0;

	if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
		error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
		if (error)
			return -EIO;

		old_mode = inode->i_mode;
		old_ino = inode->i_ino;
		coda_vattr_to_iattr(inode, &attr);

		if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {
			printk("Coda: inode %ld, fid %s changed type!\n",
			       inode->i_ino, coda_f2s(&(cii->c_fid)));
		}

		if (inode->i_ino != old_ino)
			return -EIO;
		
		coda_flag_inode_children(inode, C_FLUSH);

		spin_lock(&cii->c_lock);
		cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
		spin_unlock(&cii->c_lock);
	}
	return 0;
}
Пример #21
0
int coda_release(struct inode *coda_inode, struct file *coda_file)
{
    unsigned short flags = (coda_file->f_flags) & (~O_EXCL);
    unsigned short coda_flags = coda_flags_to_cflags(flags);
    struct coda_file_info *cfi;
    struct coda_inode_info *cii;
    struct inode *host_inode;
    int err = 0;

    lock_kernel();

    cfi = CODA_FTOC(coda_file);
    BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);

    err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
                      coda_flags, coda_file->f_cred->fsuid);

    host_inode = cfi->cfi_container->f_path.dentry->d_inode;
    cii = ITOC(coda_inode);

    /* did we mmap this file? */
    if (coda_inode->i_mapping == &host_inode->i_data) {
        cii->c_mapcount -= cfi->cfi_mapcount;
        if (!cii->c_mapcount)
            coda_inode->i_mapping = &coda_inode->i_data;
    }

    fput(cfi->cfi_container);
    kfree(coda_file->private_data);
    coda_file->private_data = NULL;

    unlock_kernel();

    /* VFS fput ignores the return value from file_operations->release, so
     * there is no use returning an error here */
    return 0;
}
Пример #22
0
struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
			 struct coda_vattr * attr)
{
	struct inode *inode;
	struct coda_inode_info *cii;
	unsigned long hash = coda_f2i(fid);

	inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid);

	if (!inode)
		return ERR_PTR(-ENOMEM);

	if (inode->i_state & I_NEW) {
		cii = ITOC(inode);
		/* we still need to set i_ino for things like stat(2) */
		inode->i_ino = hash;
		cii->c_mapcount = 0;
		unlock_new_inode(inode);
	}

	/* always replace the attributes, type might have changed */
	coda_fill_inode(inode, attr);
	return inode;
}
Пример #23
0
/* convert a fid to an inode. */
struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) 
{
	ino_t nr;
	struct inode *inode;
	struct coda_inode_info *cii;

	if ( !sb ) {
		printk("coda_fid_to_inode: no sb!\n");
		return NULL;
	}

	CDEBUG(D_INODE, "%s\n", coda_f2s(fid));

	nr = coda_f2i(fid);
	inode = iget4(sb, nr, coda_inocmp, fid);
	if ( !inode ) {
		printk("coda_fid_to_inode: null from iget, sb %p, nr %ld.\n",
		       sb, (long)nr);
		return NULL;
	}

	cii = ITOC(inode);

	/* The inode could already be purged due to memory pressure */
	if (coda_isnullfid(&cii->c_fid)) {
		inode->i_nlink = 0;
		iput(inode);
		return NULL;
	}

	/* we shouldn't see inode collisions anymore */
	if ( !coda_fideq(fid, &cii->c_fid) ) BUG();

        CDEBUG(D_INODE, "found %ld\n", inode->i_ino);
        return inode;
}
Пример #24
0
static int coda_symlink_filler(struct file *file, struct page *page)
{
	struct inode *inode = page->mapping->host;
	int error;
	struct coda_inode_info *cii;
	unsigned int len = PAGE_SIZE;
	char *p = kmap(page);

	cii = ITOC(inode);

	error = venus_readlink(inode->i_sb, &cii->c_fid, p, &len);
	if (error)
		goto fail;
	SetPageUptodate(page);
	kunmap(page);
	unlock_page(page);
	return 0;

fail:
	SetPageError(page);
	kunmap(page);
	unlock_page(page);
	return error;
}
Пример #25
0
static int coda_test_inode(struct inode *inode, void *data)
{
	struct CodaFid *fid = (struct CodaFid *)data;
	struct coda_inode_info *cii = ITOC(inode);
	return coda_fideq(&cii->c_fid, fid);
}
Пример #26
0
static int coda_set_inode(struct inode *inode, void *data)
{
	struct CodaFid *fid = (struct CodaFid *)data;
	ITOC(inode)->c_fid = *fid;
	return 0;
}
Пример #27
0
static int coda_test_inode(struct inode *inode, void *data)
{
	struct CodaFid *fid = (struct CodaFid *)data;
	return coda_fideq(&(ITOC(inode)->c_fid), fid);
}
Пример #28
0
static void coda_i_callback(struct rcu_head *head)
{
	struct inode *inode = container_of(head, struct inode, i_rcu);
	kmem_cache_free(coda_inode_cachep, ITOC(inode));
}
Пример #29
0
/* support routines */
static int coda_venus_readdir(struct file *coda_file, struct dir_context *ctx)
{
    struct coda_file_info *cfi;
    struct coda_inode_info *cii;
    struct file *host_file;
    struct venus_dirent *vdir;
    unsigned long vdir_size = offsetof(struct venus_dirent, d_name);
    unsigned int type;
    struct qstr name;
    ino_t ino;
    int ret;

    cfi = CODA_FTOC(coda_file);
    BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
    host_file = cfi->cfi_container;

    cii = ITOC(file_inode(coda_file));

    vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);
    if (!vdir) return -ENOMEM;

    if (!dir_emit_dots(coda_file, ctx))
        goto out;

    while (1) {
        /* read entries from the directory file */
        ret = kernel_read(host_file, ctx->pos - 2, (char *)vdir,
                          sizeof(*vdir));
        if (ret < 0) {
            pr_err("%s: read dir %s failed %d\n",
                   __func__, coda_f2s(&cii->c_fid), ret);
            break;
        }
        if (ret == 0) break; /* end of directory file reached */

        /* catch truncated reads */
        if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {
            pr_err("%s: short read on %s\n",
                   __func__, coda_f2s(&cii->c_fid));
            ret = -EBADF;
            break;
        }
        /* validate whether the directory file actually makes sense */
        if (vdir->d_reclen < vdir_size + vdir->d_namlen) {
            pr_err("%s: invalid dir %s\n",
                   __func__, coda_f2s(&cii->c_fid));
            ret = -EBADF;
            break;
        }

        name.len = vdir->d_namlen;
        name.name = vdir->d_name;

        /* Make sure we skip '.' and '..', we already got those */
        if (name.name[0] == '.' && (name.len == 1 ||
                                    (name.name[1] == '.' && name.len == 2)))
            vdir->d_fileno = name.len = 0;

        /* skip null entries */
        if (vdir->d_fileno && name.len) {
            ino = vdir->d_fileno;
            type = CDT2DT(vdir->d_type);
            if (!dir_emit(ctx, name.name, name.len, ino, type))
                break;
        }
        /* we'll always have progress because d_reclen is unsigned and
         * we've already established it is non-zero. */
        ctx->pos += vdir->d_reclen;
    }
out:
    kfree(vdir);
    return 0;
}
Пример #30
0
/* support routines */
static int coda_venus_readdir(struct file *coda_file, void *buf,
			      filldir_t filldir)
{
	int result = 0; /* # of entries returned */
	struct coda_file_info *cfi;
	struct coda_inode_info *cii;
	struct file *host_file;
	struct dentry *de;
	struct venus_dirent *vdir;
	unsigned long vdir_size =
	    (unsigned long)(&((struct venus_dirent *)0)->d_name);
	unsigned int type;
	struct qstr name;
	ino_t ino;
	int ret;

	cfi = CODA_FTOC(coda_file);
	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
	host_file = cfi->cfi_container;

	de = coda_file->f_path.dentry;
	cii = ITOC(de->d_inode);

	vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);
	if (!vdir) return -ENOMEM;

	if (coda_file->f_pos == 0) {
		ret = filldir(buf, ".", 1, 0, de->d_inode->i_ino, DT_DIR);
		if (ret < 0)
			goto out;
		result++;
		coda_file->f_pos++;
	}
	if (coda_file->f_pos == 1) {
		ret = filldir(buf, "..", 2, 1, de->d_parent->d_inode->i_ino, DT_DIR);
		if (ret < 0)
			goto out;
		result++;
		coda_file->f_pos++;
	}
	while (1) {
		/* read entries from the directory file */
		ret = kernel_read(host_file, coda_file->f_pos - 2, (char *)vdir,
				  sizeof(*vdir));
		if (ret < 0) {
			printk(KERN_ERR "coda readdir: read dir %s failed %d\n",
			       coda_f2s(&cii->c_fid), ret);
			break;
		}
		if (ret == 0) break; /* end of directory file reached */

		/* catch truncated reads */
		if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {
			printk(KERN_ERR "coda readdir: short read on %s\n",
			       coda_f2s(&cii->c_fid));
			ret = -EBADF;
			break;
		}
		/* validate whether the directory file actually makes sense */
		if (vdir->d_reclen < vdir_size + vdir->d_namlen) {
			printk(KERN_ERR "coda readdir: invalid dir %s\n",
			       coda_f2s(&cii->c_fid));
			ret = -EBADF;
			break;
		}

		name.len = vdir->d_namlen;
		name.name = vdir->d_name;

		/* Make sure we skip '.' and '..', we already got those */
		if (name.name[0] == '.' && (name.len == 1 ||
		    (vdir->d_name[1] == '.' && name.len == 2)))
			vdir->d_fileno = name.len = 0;

		/* skip null entries */
		if (vdir->d_fileno && name.len) {
			/* try to look up this entry in the dcache, that way
			 * userspace doesn't have to worry about breaking
			 * getcwd by having mismatched inode numbers for
			 * internal volume mountpoints. */
			ino = find_inode_number(de, &name);
			if (!ino) ino = vdir->d_fileno;

			type = CDT2DT(vdir->d_type);
			ret = filldir(buf, name.name, name.len,
				      coda_file->f_pos, ino, type);
			/* failure means no space for filling in this round */
			if (ret < 0) break;
			result++;
		}
		/* we'll always have progress because d_reclen is unsigned and
		 * we've already established it is non-zero. */
		coda_file->f_pos += vdir->d_reclen;
	}
out:
	kfree(vdir);
	return result ? result : ret;
}