Beispiel #1
0
/* capfs_release()
 *
 * Called when the last open file reference for a given file is
 * finished.  We use this as an opportunity to tell the daemon to close
 * the file when it wants to.
 */
int capfs_release(struct inode *inode, struct file *f)
{
	int error = 0;
	struct capfs_inode *pinode;
	/* update the statistics */
	if(capfs_collect_stats) capfs_vfs_stat.release++;   
	PENTRY;

	update_atime(inode);
	if (S_ISDIR(inode->i_mode))
	{
		return dcache_dir_close(inode, f);
	}

	pinode = CAPFS_I(inode);

	PDEBUG(D_FILE, "capfs_release called for %s (%ld) [atime: %lu] [mtime: %lu] [ctime: %lu]\n", 
			pinode->name, (unsigned long) pinode->handle, inode->i_atime.tv_sec,
			inode->i_mtime.tv_sec, inode->i_ctime.tv_sec);

	error = ll_capfs_hint(pinode, HINT_CLOSE, NULL);

	/* 
	 * remove all associated inode pages from the page cache
	 */
	truncate_inode_pages(f->f_dentry->d_inode->i_mapping, 0);
	
	PEXIT;
	return error;
}
Beispiel #2
0
static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
	unsigned long pos = filp->f_pos;
	struct inode *inode = filp->f_dentry->d_inode;
	struct super_block *sb = inode->i_sb;
	unsigned offset = pos & ~PAGE_CACHE_MASK;
	unsigned long n = pos >> PAGE_CACHE_SHIFT;
	unsigned long npages = dir_pages(inode);

	lock_kernel();

	pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1);
	if (pos >= inode->i_size)
		goto done;

	for ( ; n < npages; n++, offset = 0) {
		char *kaddr, *limit;
		struct sysv_dir_entry *de;
		struct page *page = dir_get_page(inode, n);

		if (IS_ERR(page))
			continue;
		kaddr = (char *)page_address(page);
		de = (struct sysv_dir_entry *)(kaddr+offset);
		limit = kaddr + PAGE_CACHE_SIZE - SYSV_DIRSIZE;
		for ( ;(char*)de <= limit; de++) {
			char *name = de->name;
			int over;

			if (!de->inode)
				continue;

			offset = (char *)de - kaddr;

			over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN),
					(n<<PAGE_CACHE_SHIFT) | offset,
					fs16_to_cpu(SYSV_SB(sb), de->inode),
					DT_UNKNOWN);
			if (over) {
				dir_put_page(page);
				goto done;
			}
		}
		dir_put_page(page);
	}

done:
	filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
	update_atime(inode);
	unlock_kernel();
	return 0;
}
Beispiel #3
0
/* Update usage from here to top of tree, so that scan of
   top-level directories will give a useful result */
static void autofs4_update_usage(struct dentry *dentry)
{
	struct dentry *top = dentry->d_sb->s_root;

	for(; dentry != top; dentry = dentry->d_parent) {
		struct autofs_info *ino = autofs4_dentry_ino(dentry);

		if (ino) {
			update_atime(dentry->d_inode);
			ino->last_used = jiffies;
		}
	}
}
Beispiel #4
0
extern int
vnode_shadow_iop_readlink(
    DENT_T *dentry,
    char * buf,
    int buflen
)
{
    DENT_T *real_dentry;
    INODE_T *real_inode;
    VNODE_T *cvp;
    int err = 0;

    real_dentry = REALDENTRY_LOCKED(dentry, &cvp);
    if (real_dentry == NULL)
        /* We lost a race with delete. */
        return -ENOENT;

    VNODE_DGET(real_dentry);
    if (real_dentry->d_inode == NULL) {
        /* We lost a race with delete. */
        err = -ENOENT;
        goto out;
    }
    real_inode = real_dentry->d_inode;
    if (real_inode->i_op && real_inode->i_op->readlink) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
        /* In the 2.6.16 kernel update_atime is replaced by touch_atime
         * which takes a pointer to the vfsmount structure as well.  We
         * don't have such a beast so we just punt since this will go
         * away when we get rid of the shadow filesystem.
         */
        update_atime(real_inode);
#endif
        /* Our caller has set the address space according to where the buffer is. */
        err = (*real_inode->i_op->readlink)(real_dentry, buf, buflen);
        dentry->d_inode->i_atime = real_inode->i_atime;
    } else {
        err = -EINVAL;
    }
  out:
    VNODE_DPUT(real_dentry);
    REALDENTRY_UNLOCK(dentry, cvp);
    return(err);
}
Beispiel #5
0
/* capfs_file_write(file, buf, count, ppos)
 *
 * Notes:
 * - generally the pointer to the position passed in is a pointer to
 * 	file->f_pos, so that doesn't need to be updated as well.
 */
static ssize_t capfs_file_write(struct file *file, const char *cbuf,
size_t count, loff_t *ppos)
{
	int error = 0, retsz = 0, kern_write = 0;
	struct inode *inode;
	capfs_off_t capfs_pos = *ppos;
	size_t xfersize;
	char *buf = (char *) cbuf;
	/* update the statistics */
	if(capfs_collect_stats) {
		capfs_vfs_stat.write++;
		capfs_rwop_stats(1,count);
	}
	if(get_fs().seg == get_ds().seg) {
		kern_write = 1;
	} 
	PENTRY;

	/* should we error check here? do we know for sure that the dentry is
	 * there?
	 */
	inode = file->f_dentry->d_inode;

	/* Added by Alan Rainey 9-10-2003 */
	if (strcmp(file->f_dentry->d_name.name, (char *)(strrchr(CAPFS_I(inode)->name, '/')+1)))
	{
		if ((error = capfs_inode_getattr(file->f_dentry)) < 0) {
			PEXIT;
			return error;
		}
	}

	PDEBUG(D_FILE, "capfs_file_write called for %s (%ld), offset %ld, size %ld\n",
			CAPFS_I(inode)->name, (unsigned long) CAPFS_I(inode)->handle,
			(long) capfs_pos, (long) count);


	if	(access_ok(VERIFY_READ, (char *)buf, count) == 0){
		PEXIT;
		return -EFAULT;
	}

	if (count == 0){
		PEXIT;
		return 0;
	}
	/* split our operation into blocks of capfs_maxsz or smaller */
	do {
		xfersize = (count < capfs_maxsz) ? count : capfs_maxsz;

		error = ll_capfs_file_write(CAPFS_I(inode), buf, xfersize, &capfs_pos, kern_write);
		if (error <= 0){
			int err = error;
			PEXIT;
			return err;
		}
		retsz += error;

		/* position is updated by ll_capfs_file_write() */
		count -= xfersize;
		buf += xfersize;
	} while (count > 0);

	*ppos = capfs_pos;
	if (capfs_pos > i_size_read(inode)) {
		i_size_write(inode, capfs_pos);
	}
	update_atime(inode);

	PEXIT;
	return retsz;
}