Пример #1
0
ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf,
			 size_t count, loff_t *ppos)
{
	ssize_t err;

	LKTRTrace("%.*s, cnt %zu, pos %lld\n",
		  AuDLNPair(file->f_dentry), count, *ppos);

	lockdep_off();
	err = vfs_write(file, ubuf, count, ppos);
	lockdep_on();
	if (err >= 0)
		au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
	/*ignore*/
	return err;
}
Пример #2
0
long do_vfsub_splice_to(struct file *in, loff_t *ppos,
			struct pipe_inode_info *pipe, size_t len,
			unsigned int flags)
{
	long err;

	LKTRTrace("%.*s, pos %lld, len %zu, 0x%x\n",
		  AuDLNPair(in->f_dentry), *ppos, len, flags);

	lockdep_off();
	err = vfs_splice_to(in, ppos, pipe, len, flags);
	lockdep_on();
	if (err >= 0)
		au_update_fuse_h_inode(in->f_vfsmnt, in->f_dentry); /*ignore*/
	return err;
}
Пример #3
0
int do_vfsub_unlink(struct inode *dir, struct dentry *dentry)
{
	int err;

	LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
	IMustLock(dir);

	/* vfs_unlink() locks inode */
	lockdep_off();
	err = vfs_unlink(dir, dentry);
	lockdep_on();
	/* dir inode is locked */
	if (!err)
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
	return err;
}
Пример #4
0
struct file *vfsub_filp_open(const char *path, int oflags, int mode)
{
	struct file *file;

	lockdep_off();
	file = filp_open(path,
			 oflags /* | __FMODE_NONOTIFY */,
			 mode);
	lockdep_on();
	if (IS_ERR(file))
		goto out;
	vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/

out:
	return file;
}
Пример #5
0
int vfsub_fsync(struct file *file, struct path *path, int datasync)
{
	int err;

	/* file can be NULL */
	lockdep_off();
	err = vfs_fsync(file, datasync);
	lockdep_on();
	if (!err) {
		if (!path) {
			AuDebugOn(!file);
			path = &file->f_path;
		}
		vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
	}
	return err;
}
Пример #6
0
static void call_notify_change(void *args)
{
	struct notify_change_args *a = args;
	struct inode *h_inode;

	h_inode = a->path->dentry->d_inode;
	IMustLock(h_inode);

	*a->errp = -EPERM;
	if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
		lockdep_off();
		*a->errp = notify_change(a->path->dentry, a->ia);
		lockdep_on();
		if (!*a->errp)
			vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
	}
	AuTraceErr(*a->errp);
}
Пример #7
0
int vfsub_flush(struct file *file, fl_owner_t id)
{
	int err;

	err = 0;
	if (file->f_op && file->f_op->flush) {
		if (!au_test_nfs(file->f_dentry->d_sb))
			err = file->f_op->flush(file, id);
		else {
			lockdep_off();
			err = file->f_op->flush(file, id);
			lockdep_on();
		}
		if (!err)
			vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
		/*ignore*/
	}
	return err;
}
Пример #8
0
int vfsub_rmdir(struct inode *dir, struct path *path)
{
	int err;
	struct dentry *d;

	IMustLock(dir);

	d = path->dentry;
	path->dentry = d->d_parent;
	err = security_path_rmdir(path, d);
	path->dentry = d;
	if (unlikely(err))
		goto out;

	lockdep_off();
	err = vfs_rmdir(dir, path->dentry);
	lockdep_on();
	if (!err) {
		struct path tmp = {
			.dentry	= path->dentry->d_parent,
			.mnt	= path->mnt
		};

		vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
	}

out:
	return err;
}

/* ---------------------------------------------------------------------- */

ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
		     loff_t *ppos)
{
	ssize_t err;

	err = vfs_read(file, ubuf, count, ppos);
	if (err >= 0)
		vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
	return err;
}
Пример #9
0
ssize_t do_vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
			loff_t *ppos)
{
	ssize_t err;

	LKTRTrace("%.*s, cnt %zu, pos %lld\n",
		  AuDLNPair(file->f_dentry), count, *ppos);

	if (0 /*!au_test_nfs(file->f_vfsmnt->mnt_sb)*/)
		err = vfs_read(file, ubuf, count, ppos);
	else {
		lockdep_off();
		err = vfs_read(file, ubuf, count, ppos);
		lockdep_on();
	}
	if (err >= 0)
		au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
	/*ignore*/
	return err;
}
Пример #10
0
int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path,
	       struct inode **delegated_inode)
{
	int err;
	struct dentry *d;

	IMustLock(dir);

	err = au_test_nlink(d_inode(src_dentry));
	if (unlikely(err))
		return err;

	/* we don't call may_linkat() */
	d = path->dentry;
	path->dentry = d->d_parent;
	err = security_path_link(src_dentry, path, d);
	path->dentry = d;
	if (unlikely(err))
		goto out;

	lockdep_off();
	err = vfs_link(src_dentry, dir, path->dentry, delegated_inode);
	lockdep_on();
	if (!err) {
		struct path tmp = *path;
		int did;

		/* fuse has different memory inode for the same inumber */
		vfsub_update_h_iattr(&tmp, &did);
		if (did) {
			tmp.dentry = path->dentry->d_parent;
			vfsub_update_h_iattr(&tmp, /*did*/NULL);
			tmp.dentry = src_dentry;
			vfsub_update_h_iattr(&tmp, /*did*/NULL);
		}
		/*ignore*/
	}

out:
	return err;
}
Пример #11
0
/**
 * ubi_io_write_vid_hdr - write a volume identifier header.
 * @ubi: UBI device description object
 * @pnum: the physical eraseblock number to write to
 * @vid_hdr: the volume identifier header to write
 *
 * This function writes the volume identifier header described by @vid_hdr to
 * physical eraseblock @pnum. This function automatically fills the
 * @vid_hdr->magic and the @vid_hdr->version fields, as well as calculates
 * header CRC checksum and stores it at vid_hdr->hdr_crc.
 *
 * This function returns zero in case of success and a negative error code in
 * case of failure. If %-EIO is returned, the physical eraseblock probably went
 * bad.
 */
int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
			 struct ubi_vid_hdr *vid_hdr)
{
	int err;
	uint32_t crc;
	void *p;

	dbg_io("write VID header to PEB %d", pnum);
	ubi_assert(pnum >= 0 &&  pnum < ubi->peb_count);

	err = self_check_peb_ec_hdr(ubi, pnum);
	if (err)
		return err;

	vid_hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
	vid_hdr->version = UBI_VERSION;
	crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC);
	vid_hdr->hdr_crc = cpu_to_be32(crc);

	err = self_check_vid_hdr(ubi, pnum, vid_hdr);
	if (err)
		return err;

#ifdef CONFIG_BLB
	{
	extern int blb_record_page1(struct ubi_device *ubi, int pnum,
			 struct ubi_vid_hdr *vid_hdr, int);
		int vol_id =  be32_to_cpu(vid_hdr->vol_id);
		if(vol_id < UBI_INTERNAL_VOL_START) {
			lockdep_off();
			blb_record_page1(ubi, pnum, vid_hdr, 0);
			lockdep_on();
		}
	}
#endif
	p = (char *)vid_hdr - ubi->vid_hdr_shift;
	err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset,
			   ubi->vid_hdr_alsize);
	return err;
}
Пример #12
0
/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
		struct file *h_file)
{
	int err;
	struct inode *h_inode;

	h_inode = h_path->dentry->d_inode;
	if (!h_file) {
		err = mnt_want_write(h_path->mnt);
		if (err)
			goto out;
		err = inode_permission(h_inode, MAY_WRITE);
		if (err)
			goto out_mnt;
		err = get_write_access(h_inode);
		if (err)
			goto out_mnt;
		err = break_lease(h_inode, O_WRONLY);
		if (err)
			goto out_inode;
	}

	err = locks_verify_truncate(h_inode, h_file, length);
	if (!err)
		err = security_path_truncate(h_path);
	if (!err) {
		lockdep_off();
		err = do_truncate(h_path->dentry, length, attr, h_file);
		lockdep_on();
	}

out_inode:
	if (!h_file)
		put_write_access(h_inode);
out_mnt:
	if (!h_file)
		mnt_drop_write(h_path->mnt);
out:
	return err;
}
Пример #13
0
int vfsub_sio_rmdir(struct inode *dir, struct path *path)
{
	int err, do_sio, wkq_err;

	do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
	if (!do_sio) {
		lockdep_off();
		err = vfsub_rmdir(dir, path);
		lockdep_on();
	} else {
		struct au_vfsub_rmdir_args args = {
			.errp	= &err,
			.dir	= dir,
			.path	= path
		};
		wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
		if (unlikely(wkq_err))
			err = wkq_err;
	}

	return err;
}
Пример #14
0
static ssize_t do_xino_fwrite(writef_t func, struct file *file, void *buf,
			      size_t size, loff_t *pos)
{
	ssize_t err;
	mm_segment_t oldfs;

	lockdep_off();
	oldfs = get_fs();
	set_fs(KERNEL_DS);
	do {
		err = func(file, (const char __user*)buf, size, pos);
	} while (err == -EAGAIN || err == -EINTR);
	set_fs(oldfs);
	lockdep_on();

#if 0
	if (err > 0)
		fsnotify_modify(file->f_dentry);
#endif

	TraceErr(err);
	return err;
}
Пример #15
0
int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
		    struct inode *dir, struct dentry *dentry)
{
	int err;

	LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
		  src_dir->i_ino, AuDLNPair(src_dentry),
		  dir->i_ino, AuDLNPair(dentry));
	IMustLock(dir);
	IMustLock(src_dir);
	AuDebugOn(src_dir != dir && !vfsub_is_rename_mutex_locked(dir->i_sb));

	lockdep_off();
	err = vfs_rename(src_dir, src_dentry, dir, dentry);
	lockdep_on();
	if (!err) {
		/* dir inode is locked */
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
		au_update_fuse_h_inode(NULL, src_dentry->d_parent); /*ignore*/
		au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/
	}
	return err;
}
Пример #16
0
int do_vfsub_link(struct dentry *src_dentry, struct inode *dir,
		  struct dentry *dentry)
{
	int err;

	LKTRTrace("%.*s, i%lu, %.*s\n",
		  AuDLNPair(src_dentry), dir->i_ino, AuDLNPair(dentry));
	IMustLock(dir);

	lockdep_off();
	err = vfs_link(src_dentry, dir, dentry);
	lockdep_on();
	if (!err) {
		LKTRTrace("src_i %p, dst_i %p\n",
			  src_dentry->d_inode, dentry->d_inode);
		/* fuse has different memory inode for the same inumber */
		au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/
		/* dir inode is locked */
		au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
		au_update_fuse_h_inode(NULL, dentry); /*ignore*/
	}
	return err;
}
Пример #17
0
static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *buf,
			      size_t size, loff_t *pos)
{
	ssize_t err;
	mm_segment_t oldfs;

	oldfs = get_fs();
	set_fs(KERNEL_DS);
	lockdep_off();
	do {
		/* todo: signal_pending? */
		err = func(file, (const char __user *)buf, size, pos);
	} while (err == -EAGAIN || err == -EINTR);
	lockdep_on();
	set_fs(oldfs);

#if 0 /* reserved for future use */
	if (err > 0)
		fsnotify_modify(file->f_dentry);
#endif

	return err;
}
Пример #18
0
/*
 * free a single branch
 */
static void au_br_do_free(struct au_branch *br)
{
	int i;
	struct au_wbr *wbr;
	struct au_dykey **key;

	au_hnotify_fin_br(br);

	if (br->br_xino.xi_file)
		fput(br->br_xino.xi_file);
	mutex_destroy(&br->br_xino.xi_nondir_mtx);

	AuDebugOn(atomic_read(&br->br_count));

	wbr = br->br_wbr;
	if (wbr) {
		for (i = 0; i < AuBrWh_Last; i++)
			dput(wbr->wbr_wh[i]);
		AuDebugOn(atomic_read(&wbr->wbr_wh_running));
		AuRwDestroy(&wbr->wbr_wh_rwsem);
	}

	key = br->br_dykey;
	for (i = 0; i < AuBrDynOp; i++, key++)
		if (*key)
			au_dy_put(*key);
		else
			break;

	/* recursive lock, s_umount of branch's */
	lockdep_off();
	mntput(br->br_mnt);
	lockdep_on();
	kfree(wbr);
	kfree(br);
}
Пример #19
0
static void call_notify_change(void *args)
{
	struct notify_change_args *a = args;
	struct inode *h_inode;

	LKTRTrace("%.*s, ia_valid 0x%x\n",
		  AuDLNPair(a->h_dentry), a->ia->ia_valid);
	h_inode = a->h_dentry->d_inode;
	IMustLock(h_inode);

	*a->errp = -EPERM;
	if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
		vfsub_ignore(a->vargs);
		lockdep_off();
		*a->errp = notify_change(a->h_dentry, a->ia);
		lockdep_on();
		if (!*a->errp)
			au_update_fuse_h_inode(NULL, a->h_dentry); /*ignore*/
		else
			vfsub_unignore(a->vargs);
		au_dbg_hin_list(a->vargs);
	}
	AuTraceErr(*a->errp);
}
Пример #20
0
RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock)
{
    PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
    RT_ASSERT_PREEMPT_CPUID_VAR();
    AssertMsg(pThis && pThis->u32Magic == RTSPINLOCK_MAGIC,
              ("pThis=%p u32Magic=%08x\n", pThis, pThis ? (int)pThis->u32Magic : 0));

#ifdef CONFIG_PROVE_LOCKING
    lockdep_off();
#endif
    if (pThis->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE)
    {
        unsigned long fIntSaved;
        spin_lock_irqsave(&pThis->Spinlock, fIntSaved);
        pThis->fIntSaved = fIntSaved;
    }
    else
        spin_lock(&pThis->Spinlock);
#ifdef CONFIG_PROVE_LOCKING
    lockdep_on();
#endif

    RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED(pThis);
}
Пример #21
0
int ib_umem_odp_get(struct ib_ucontext *context, struct ib_umem *umem)
{
	int ret_val;
	struct pid *our_pid;
	struct mm_struct *mm = get_task_mm(current);
	BUG_ON(!mm);

	/* Prevent creating ODP MRs in child processes */
	rcu_read_lock();
	our_pid = get_task_pid(current->group_leader, PIDTYPE_PID);
	rcu_read_unlock();
	put_pid(our_pid);
	if (context->tgid != our_pid) {
		ret_val = -EINVAL;
		goto out_mm;
	}

	umem->hugetlb = 0;
	umem->odp_data = kzalloc(sizeof(*umem->odp_data), GFP_KERNEL);
	if (!umem->odp_data) {
		ret_val = -ENOMEM;
		goto out_mm;
	}
	umem->odp_data->umem = umem;

	mutex_init(&umem->odp_data->umem_mutex);

	init_completion(&umem->odp_data->notifier_completion);

	umem->odp_data->page_list = vzalloc(ib_umem_num_pages(umem) *
					    sizeof(*umem->odp_data->page_list));
	if (!umem->odp_data->page_list) {
		ret_val = -ENOMEM;
		goto out_odp_data;
	}

	umem->odp_data->dma_list = vzalloc(ib_umem_num_pages(umem) *
					  sizeof(*umem->odp_data->dma_list));
	if (!umem->odp_data->dma_list) {
		ret_val = -ENOMEM;
		goto out_page_list;
	}

	/*
	 * When using MMU notifiers, we will get a
	 * notification before the "current" task (and MM) is
	 * destroyed. We use the umem_mutex lock to synchronize.
	 */
	down_write(&context->umem_mutex);
	context->odp_mrs_count++;
	if (likely(ib_umem_start(umem) != ib_umem_end(umem)))
		rbt_ib_umem_insert(&umem->odp_data->interval_tree,
				   &context->umem_tree);
	downgrade_write(&context->umem_mutex);

	if (context->odp_mrs_count == 1) {
		/*
		 * Note that at this point, no MMU notifier is running
		 * for this context!
		 */
		INIT_HLIST_NODE(&context->mn.hlist);
		context->mn.ops = &ib_umem_notifiers;
		/*
		 * Lock-dep detects a false positive for mmap_sem vs.
		 * umem_mutex, due to not grasping downgrade_write correctly.
		 */
		lockdep_off();
		ret_val = mmu_notifier_register(&context->mn, mm);
		lockdep_on();
		if (ret_val) {
			pr_err("Failed to register mmu_notifier %d\n", ret_val);
			ret_val = -EBUSY;
			goto out_mutex;
		}
	}

	up_read(&context->umem_mutex);

	/*
	 * Note that doing an mmput can cause a notifier for the relevant mm.
	 * If the notifier is called while we hold the umem_mutex, this will
	 * cause a deadlock. Therefore, we release the reference only after we
	 * released the mutex.
	 */
	mmput(mm);
	return 0;

out_mutex:
	up_read(&context->umem_mutex);
	vfree(umem->odp_data->dma_list);
out_page_list:
	vfree(umem->odp_data->page_list);
out_odp_data:
	kfree(umem->odp_data);
out_mm:
	mmput(mm);
	return ret_val;
}
Пример #22
0
static int unionfs_link(struct dentry *old_dentry, struct inode *dir,
			struct dentry *new_dentry)
{
	int err = 0;
	struct dentry *lower_old_dentry = NULL;
	struct dentry *lower_new_dentry = NULL;
	struct dentry *lower_dir_dentry = NULL;
	struct dentry *old_parent, *new_parent;
	char *name = NULL;
	bool valid;

	unionfs_read_lock(old_dentry->d_sb, UNIONFS_SMUTEX_CHILD);
	old_parent = dget_parent(old_dentry);
	new_parent = dget_parent(new_dentry);
	unionfs_double_lock_parents(old_parent, new_parent);
	unionfs_double_lock_dentry(old_dentry, new_dentry);

	valid = __unionfs_d_revalidate(old_dentry, old_parent, false, 0);
	if (unlikely(!valid)) {
		err = -ESTALE;
		goto out;
	}
	if (new_dentry->d_inode) {
		valid = __unionfs_d_revalidate(new_dentry, new_parent, false, 0);
		if (unlikely(!valid)) {
			err = -ESTALE;
			goto out;
		}
	}

	lower_new_dentry = unionfs_lower_dentry(new_dentry);

	/* check for a whiteout in new dentry branch, and delete it */
	err = check_unlink_whiteout(new_dentry, lower_new_dentry,
				    dbstart(new_dentry));
	if (err > 0) {	       /* whiteout found and removed successfully */
		lower_dir_dentry = dget_parent(lower_new_dentry);
		fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
		dput(lower_dir_dentry);
		set_nlink(dir, unionfs_get_nlinks(dir));
		err = 0;
	}
	if (err)
		goto out;

	/* check if parent hierachy is needed, then link in same branch */
	if (dbstart(old_dentry) != dbstart(new_dentry)) {
		lower_new_dentry = create_parents(dir, new_dentry,
						  new_dentry->d_name.name,
						  dbstart(old_dentry));
		err = PTR_ERR(lower_new_dentry);
		if (IS_COPYUP_ERR(err))
			goto docopyup;
		if (!lower_new_dentry || IS_ERR(lower_new_dentry))
			goto out;
	}
	lower_new_dentry = unionfs_lower_dentry(new_dentry);
	lower_old_dentry = unionfs_lower_dentry(old_dentry);

	BUG_ON(dbstart(old_dentry) != dbstart(new_dentry));
	lower_dir_dentry = lock_parent(lower_new_dentry);
	err = is_robranch(old_dentry);
	if (!err) {
		/* see Documentation/filesystems/unionfs/issues.txt */
		lockdep_off();
		err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
			       lower_new_dentry);
		lockdep_on();
	}
	unlock_dir(lower_dir_dentry);

docopyup:
	if (IS_COPYUP_ERR(err)) {
		int old_bstart = dbstart(old_dentry);
		int bindex;

		for (bindex = old_bstart - 1; bindex >= 0; bindex--) {
			err = copyup_dentry(old_parent->d_inode,
					    old_dentry, old_bstart,
					    bindex, old_dentry->d_name.name,
					    old_dentry->d_name.len, NULL,
					    i_size_read(old_dentry->d_inode));
			if (err)
				continue;
			lower_new_dentry =
				create_parents(dir, new_dentry,
					       new_dentry->d_name.name,
					       bindex);
			lower_old_dentry = unionfs_lower_dentry(old_dentry);
			lower_dir_dentry = lock_parent(lower_new_dentry);
			/* see Documentation/filesystems/unionfs/issues.txt */
			lockdep_off();
			/* do vfs_link */
			err = vfs_link(lower_old_dentry,
				       lower_dir_dentry->d_inode,
				       lower_new_dentry);
			lockdep_on();
			unlock_dir(lower_dir_dentry);
			goto check_link;
		}
		goto out;
	}

check_link:
	if (err || !lower_new_dentry->d_inode)
		goto out;

	/* Its a hard link, so use the same inode */
	new_dentry->d_inode = igrab(old_dentry->d_inode);
	d_add(new_dentry, new_dentry->d_inode);
	unionfs_copy_attr_all(dir, lower_new_dentry->d_parent->d_inode);
	fsstack_copy_inode_size(dir, lower_new_dentry->d_parent->d_inode);

	/* propagate number of hard-links */
	set_nlink(old_dentry->d_inode,
		  unionfs_get_nlinks(old_dentry->d_inode));
	/* new dentry's ctime may have changed due to hard-link counts */
	unionfs_copy_attr_times(new_dentry->d_inode);

out:
	if (!new_dentry->d_inode)
		d_drop(new_dentry);

	kfree(name);
	if (!err)
		unionfs_postcopyup_setmnt(new_dentry);

	unionfs_check_inode(dir);
	unionfs_check_dentry(new_dentry);
	unionfs_check_dentry(old_dentry);

	unionfs_double_unlock_dentry(old_dentry, new_dentry);
	unionfs_double_unlock_parents(old_parent, new_parent);
	dput(new_parent);
	dput(old_parent);
	unionfs_read_unlock(old_dentry->d_sb);

	return err;
}
Пример #23
0
wake_reason_t spm_go_to_dpidle(u32 spm_flags, u32 spm_data)
{
    struct wake_status wakesta;
    unsigned long flags;
    struct mtk_irq_mask mask;
    wake_reason_t wr = WR_NONE;
    struct pcm_desc *pcmdesc = __spm_dpidle.pcmdesc;
    struct pwr_ctrl *pwrctrl = __spm_dpidle.pwrctrl;

#if SPM_AEE_RR_REC
    aee_rr_rec_deepidle_val(1<<SPM_DEEPIDLE_ENTER);
#endif 

    set_pwrctrl_pcm_flags(pwrctrl, spm_flags);
    
    //pwrctrl->timer_val = 1 * 32768;

    spm_dpidle_before_wfi();

    lockdep_off();
    spin_lock_irqsave(&__spm_lock, flags);    
    mt_irq_mask_all(&mask);
    mt_irq_unmask_for_sleep(SPM_IRQ0_ID);
    mt_cirq_clone_gic();
    mt_cirq_enable();

#if SPM_AEE_RR_REC
    aee_rr_rec_deepidle_val(aee_rr_curr_deepidle_val()|(1<<SPM_DEEPIDLE_ENTER_UART_SLEEP));
#endif     

    if (request_uart_to_sleep()) {
        wr = WR_UART_BUSY;
        goto RESTORE_IRQ;
    }

    __spm_reset_and_init_pcm(pcmdesc);

    __spm_kick_im_to_fetch(pcmdesc);
	
    __spm_init_pcm_register();

    __spm_init_event_vector(pcmdesc);

    __spm_set_power_control(pwrctrl);

    __spm_set_wakeup_event(pwrctrl);

    spm_dpidle_pre_process();

    __spm_kick_pcm_to_run(pwrctrl);

#if SPM_AEE_RR_REC
    aee_rr_rec_deepidle_val(aee_rr_curr_deepidle_val()|(1<<SPM_DEEPIDLE_ENTER_WFI));
#endif

#ifdef SPM_DEEPIDLE_PROFILE_TIME
    gpt_get_cnt(SPM_PROFILE_APXGPT,&dpidle_profile[1]);
#endif   
    spm_trigger_wfi_for_dpidle(pwrctrl);
#ifdef SPM_DEEPIDLE_PROFILE_TIME
    gpt_get_cnt(SPM_PROFILE_APXGPT,&dpidle_profile[2]);
#endif

#if SPM_AEE_RR_REC
    aee_rr_rec_deepidle_val(aee_rr_curr_deepidle_val()|(1<<SPM_DEEPIDLE_LEAVE_WFI));
#endif 

    spm_dpidle_post_process();

    __spm_get_wakeup_status(&wakesta);

    __spm_clean_after_wakeup();

#if SPM_AEE_RR_REC
    aee_rr_rec_deepidle_val(aee_rr_curr_deepidle_val()|(1<<SPM_DEEPIDLE_ENTER_UART_AWAKE));
#endif

    request_uart_to_wakeup();

    wr = __spm_output_wake_reason(&wakesta, pcmdesc, false);

RESTORE_IRQ:
    mt_cirq_flush();
    mt_cirq_disable();
    mt_irq_mask_restore(&mask);  
    spin_unlock_irqrestore(&__spm_lock, flags);
    lockdep_on();
    spm_dpidle_after_wfi();

#if SPM_AEE_RR_REC
    aee_rr_rec_deepidle_val(0);
#endif 
    return wr;
}
Пример #24
0
asmlinkage int vprintk(const char *fmt, va_list args)
{
	unsigned long flags;
	int printed_len;
	char *p;
	static char printk_buf[1024];
	static int log_level_unknown = 1;

	boot_delay_msec();

	preempt_disable();
	if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id())
		/* If a crash is occurring during printk() on this CPU,
		 * make sure we can't deadlock */
		zap_locks();

	/* This stops the holder of console_sem just where we want him */
	raw_local_irq_save(flags);
	lockdep_off();
	spin_lock(&logbuf_lock);
	printk_cpu = smp_processor_id();

	/* Emit the output into the temporary buffer */
	printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);

	/*
	 * Copy the output into log_buf.  If the caller didn't provide
	 * appropriate log level tags, we insert them here
	 */
	for (p = printk_buf; *p; p++) {
		if (log_level_unknown) {
                        /* log_level_unknown signals the start of a new line */
			if (printk_time) {
				int loglev_char;
				char tbuf[50], *tp;
				unsigned tlen;
				unsigned long long t;
				unsigned long nanosec_rem;

				/*
				 * force the log level token to be
				 * before the time output.
				 */
				if (p[0] == '<' && p[1] >='0' &&
				   p[1] <= '7' && p[2] == '>') {
					loglev_char = p[1];
					p += 3;
					printed_len -= 3;
				} else {
					loglev_char = default_message_loglevel
						+ '0';
				}
				t = printk_clock();
				nanosec_rem = do_div(t, 1000000000);
				tlen = sprintf(tbuf,
						"<%c>[%5lu.%06lu] ",
						loglev_char,
						(unsigned long)t,
						nanosec_rem/1000);

				for (tp = tbuf; tp < tbuf + tlen; tp++)
					emit_log_char(*tp);
				printed_len += tlen;
			} else {
				if (p[0] != '<' || p[1] < '0' ||
				   p[1] > '7' || p[2] != '>') {
					emit_log_char('<');
					emit_log_char(default_message_loglevel
						+ '0');
					emit_log_char('>');
					printed_len += 3;
				}
			}
			log_level_unknown = 0;
			if (!*p)
				break;
		}
		emit_log_char(*p);
		if (*p == '\n')
			log_level_unknown = 1;
	}

	if (!down_trylock(&console_sem)) {
		/*
		 * We own the drivers.  We can drop the spinlock and
		 * let release_console_sem() print the text, maybe ...
		 */
		console_locked = 1;
		printk_cpu = UINT_MAX;
		spin_unlock(&logbuf_lock);

		/*
		 * Console drivers may assume that per-cpu resources have
		 * been allocated. So unless they're explicitly marked as
		 * being able to cope (CON_ANYTIME) don't call them until
		 * this CPU is officially up.
		 */
		if (cpu_online(smp_processor_id()) || have_callable_console()) {
			console_may_schedule = 0;
			release_console_sem();
		} else {
			/* Release by hand to avoid flushing the buffer. */
			console_locked = 0;
			up(&console_sem);
		}
		lockdep_on();
		raw_local_irq_restore(flags);
	} else {
		/*
		 * Someone else owns the drivers.  We drop the spinlock, which
		 * allows the semaphore holder to proceed and to call the
		 * console drivers with the output which we just produced.
		 */
		printk_cpu = UINT_MAX;
		spin_unlock(&logbuf_lock);
		lockdep_on();
		raw_local_irq_restore(flags);
	}

	preempt_enable();
	return printed_len;
}
Пример #25
0
void au_fi_mmap_unlock(struct file *file)
{
	lockdep_off();
	mutex_unlock(&au_fi(file)->fi_mmap);
	lockdep_on();
}
Пример #26
0
int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
		 struct inode *dir, struct path *path)
{
	int err;
	struct path tmp = {
		.mnt	= path->mnt
	};
	struct dentry *d;

	IMustLock(dir);
	IMustLock(src_dir);

	d = path->dentry;
	path->dentry = d->d_parent;
	tmp.dentry = src_dentry->d_parent;
	err = security_path_rename(&tmp, src_dentry, path, d);
	path->dentry = d;
	if (unlikely(err))
		goto out;

	lockdep_off();
	err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
	lockdep_on();
	if (!err) {
		int did;

		tmp.dentry = d->d_parent;
		vfsub_update_h_iattr(&tmp, &did);
		if (did) {
			tmp.dentry = src_dentry;
			vfsub_update_h_iattr(&tmp, /*did*/NULL);
			tmp.dentry = src_dentry->d_parent;
			vfsub_update_h_iattr(&tmp, /*did*/NULL);
		}
		/*ignore*/
	}

out:
	return err;
}

int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
{
	int err;
	struct dentry *d;

	IMustLock(dir);

	d = path->dentry;
	path->dentry = d->d_parent;
	err = security_path_mkdir(path, d, mode);
	path->dentry = d;
	if (unlikely(err))
		goto out;

	err = vfs_mkdir(dir, path->dentry, mode);
	if (!err) {
		struct path tmp = *path;
		int did;

		vfsub_update_h_iattr(&tmp, &did);
		if (did) {
			tmp.dentry = path->dentry->d_parent;
			vfsub_update_h_iattr(&tmp, /*did*/NULL);
		}
		/*ignore*/
	}

out:
	return err;
}
Пример #27
0
struct dentry *vfsub_lookup_hash(struct nameidata *nd)
{
	struct path path = {
		.mnt = nd->path.mnt
	};

	IMustLock(nd->path.dentry->d_inode);

	path.dentry = lookup_hash(nd);
	if (IS_ERR(path.dentry))
		goto out;
	if (path.dentry->d_inode)
		vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/

out:
	AuTraceErrPtr(path.dentry);
	return path.dentry;
}

/*
 * this is "VFS:__lookup_one_len()" which was removed and merged into
 * VFS:lookup_one_len() by the commit.
 *	6a96ba5 2011-03-14 kill __lookup_one_len()
 * this function should always be equivalent to the corresponding part in
 * VFS:lookup_one_len().
 */
int vfsub_name_hash(const char *name, struct qstr *this, int len)
{
	unsigned int c;

	this->name = name;
	this->len = len;
	this->hash = full_name_hash(name, len);
	if (!len)
		return -EACCES;

	while (len--) {
		c = *(const unsigned char *)name++;
		if (c == '/' || c == '\0')
			return -EACCES;
	}
	return 0;
}

/* ---------------------------------------------------------------------- */

struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
				 struct dentry *d2, struct au_hinode *hdir2)
{
	struct dentry *d;

	lockdep_off();
	d = lock_rename(d1, d2);
	lockdep_on();
	au_hn_suspend(hdir1);
	if (hdir1 != hdir2)
		au_hn_suspend(hdir2);

	return d;
}

void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
			 struct dentry *d2, struct au_hinode *hdir2)
{
	au_hn_resume(hdir1);
	if (hdir1 != hdir2)
		au_hn_resume(hdir2);
	lockdep_off();
	unlock_rename(d1, d2);
	lockdep_on();
}
Пример #28
0
asmlinkage int vprintk(const char *fmt, va_list args)
{
	static int log_level_unknown = 1;
	static char printk_buf[1024];

	unsigned long flags;
	int printed_len = 0;
	int this_cpu;
	char *p;

	boot_delay_msec();

	preempt_disable();
	/* This stops the holder of console_sem just where we want him */
	/* 20100623,HSL@RK,audio broken,but system crash if comment */
	raw_local_irq_save(flags);
	this_cpu = smp_processor_id();

	/*
	 * Ouch, printk recursed into itself!
	 */
	if (unlikely(printk_cpu == this_cpu)) {
		/*
		 * If a crash is occurring during printk() on this CPU,
		 * then try to get the crash message out but make sure
		 * we can't deadlock. Otherwise just return to avoid the
		 * recursion and return - but flag the recursion so that
		 * it can be printed at the next appropriate moment:
		 */
		if (!oops_in_progress) {
			printk_recursion_bug = 1;
			// call printk when at printk.
		                goto out_restore_irqs;
		}
		zap_locks();
	}

	lockdep_off();
	spin_lock(&logbuf_lock);
	printk_cpu = this_cpu;

	if (printk_recursion_bug) {
		printk_recursion_bug = 0;
		strcpy(printk_buf, printk_recursion_bug_msg);
		printed_len = sizeof(printk_recursion_bug_msg);
	}
	/* Emit the output into the temporary buffer */
	printed_len += vscnprintf(printk_buf + printed_len,
				  sizeof(printk_buf) - printed_len, fmt, args);
//#ifdef CONFIG_DEBUG_LL
//	printascii(printk_buf);
//#endif

	/*
	 * Copy the output into log_buf.  If the caller didn't provide
	 * appropriate log level tags, we insert them here
	 */
	for (p = printk_buf; *p; p++) {
		if (log_level_unknown) {
                        /* log_level_unknown signals the start of a new line */
			if (printk_time) {
				int loglev_char;
				char tbuf[50], *tp;
				unsigned tlen;
				unsigned long long t;
				unsigned long nanosec_rem;

				/*
				 * force the log level token to be
				 * before the time output.
				 */
				if (p[0] == '<' && p[1] >='0' &&
				   p[1] <= '7' && p[2] == '>') {
					loglev_char = p[1];
					p += 3;
					printed_len -= 3;
				} else {
					loglev_char = default_message_loglevel
						+ '0';
				}
				#if 0
				t = cpu_clock(printk_cpu);
				nanosec_rem = do_div(t, 1000000000);
				tlen = sprintf(tbuf,
						"<%c>[%5lu.%06lu] ",
						loglev_char,
						(unsigned long)t,
						nanosec_rem/1000);
				#else
				nanosec_rem = nanosec_rem;
				t =t;
				tlen = sprintf(tbuf,
				"[%lu] ",
				printk_clock());
				#endif
				for (tp = tbuf; tp < tbuf + tlen; tp++)
					emit_log_char(*tp);
				printed_len += tlen;
			} else {
				if (p[0] != '<' || p[1] < '0' ||
				   p[1] > '7' || p[2] != '>') {
					emit_log_char('<');
					emit_log_char(default_message_loglevel
						+ '0');
					emit_log_char('>');
					printed_len += 3;
				}
			}
			log_level_unknown = 0;
			if (!*p)
				break;
		}
		emit_log_char(*p);
		if (*p == '\n')
			log_level_unknown = 1;
	}

	/*
	 * Try to acquire and then immediately release the
	 * console semaphore. The release will do all the
	 * actual magic (print out buffers, wake up klogd,
	 * etc). 
	 *
	 * The acquire_console_semaphore_for_printk() function
	 * will release 'logbuf_lock' regardless of whether it
	 * actually gets the semaphore or not.
	 */
	if (acquire_console_semaphore_for_printk(this_cpu))
		release_console_sem();

	lockdep_on();
out_restore_irqs:
	raw_local_irq_restore(flags);

	preempt_enable();
	return printed_len;
}
Пример #29
0
asmlinkage int vprintk(const char *fmt, va_list args)
{
	int printed_len = 0;
	int current_log_level = default_message_loglevel;
	unsigned long flags;
	int this_cpu;
	char *p;

	boot_delay_msec();

	preempt_disable();
	/* This stops the holder of console_sem just where we want him */
	raw_local_irq_save(flags);
	this_cpu = smp_processor_id();

	/*
	 * Ouch, printk recursed into itself!
	 */
	if (unlikely(printk_cpu == this_cpu)) {
		/*
		 * If a crash is occurring during printk() on this CPU,
		 * then try to get the crash message out but make sure
		 * we can't deadlock. Otherwise just return to avoid the
		 * recursion and return - but flag the recursion so that
		 * it can be printed at the next appropriate moment:
		 */
		if (!oops_in_progress) {
			recursion_bug = 1;
			goto out_restore_irqs;
		}
		zap_locks();
	}

	lockdep_off();
	spin_lock(&logbuf_lock);
	printk_cpu = this_cpu;

	if (recursion_bug) {
		recursion_bug = 0;
		strcpy(printk_buf, recursion_bug_msg);
		printed_len = strlen(recursion_bug_msg);
	}
	/* Emit the output into the temporary buffer */
	printed_len += vscnprintf(printk_buf + printed_len,
				  sizeof(printk_buf) - printed_len, fmt, args);


#ifdef	CONFIG_DEBUG_LL
	printascii(printk_buf);
#endif

	/*
	 * Copy the output into log_buf.  If the caller didn't provide
	 * appropriate log level tags, we insert them here
	 */
	for (p = printk_buf; *p; p++) {
		if (new_text_line) {
			/* If a token, set current_log_level and skip over */
			if (p[0] == '<' && p[1] >= '0' && p[1] <= '7' &&
			    p[2] == '>') {
				current_log_level = p[1] - '0';
				p += 3;
				printed_len -= 3;
			}

			/* Always output the token */
			emit_log_char('<');
			emit_log_char(current_log_level + '0');
			emit_log_char('>');
			printed_len += 3;
			new_text_line = 0;

			if (printk_time) {
				/* Follow the token with the time */
				char tbuf[50], *tp;
				unsigned tlen;
				unsigned long long t;
				unsigned long nanosec_rem;

				t = cpu_clock(printk_cpu);
				nanosec_rem = do_div(t, 1000000000);
				tlen = sprintf(tbuf, "[%5lu.%06lu] ",
						(unsigned long) t,
						nanosec_rem / 1000);

				for (tp = tbuf; tp < tbuf + tlen; tp++)
					emit_log_char(*tp);
				printed_len += tlen;
			}

			if (!*p)
				break;
		}

		emit_log_char(*p);
		if (*p == '\n')
			new_text_line = 1;
	}

	/*
	 * Try to acquire and then immediately release the
	 * console semaphore. The release will do all the
	 * actual magic (print out buffers, wake up klogd,
	 * etc). 
	 *
	 * The acquire_console_semaphore_for_printk() function
	 * will release 'logbuf_lock' regardless of whether it
	 * actually gets the semaphore or not.
	 */
	if (acquire_console_semaphore_for_printk(this_cpu))
		release_console_sem();

	lockdep_on();
out_restore_irqs:
	raw_local_irq_restore(flags);

	preempt_enable();
	return printed_len;
}
Пример #30
0
static int __copyup_reg_data(struct dentry *dentry,
			     struct dentry *new_lower_dentry, int new_bindex,
			     struct dentry *old_lower_dentry, int old_bindex,
			     struct file **copyup_file, loff_t len)
{
	struct super_block *sb = dentry->d_sb;
	struct file *input_file;
	struct file *output_file;
	struct vfsmount *output_mnt;
	mm_segment_t old_fs;
	char *buf = NULL;
	ssize_t read_bytes, write_bytes;
	loff_t size;
	int err = 0;

	/* open old file */
	unionfs_mntget(dentry, old_bindex);
	branchget(sb, old_bindex);
	/* dentry_open calls dput and mntput if it returns an error */
	input_file = dentry_open(old_lower_dentry,
				 unionfs_lower_mnt_idx(dentry, old_bindex),
				 O_RDONLY | O_LARGEFILE);
	if (IS_ERR(input_file)) {
		dput(old_lower_dentry);
		err = PTR_ERR(input_file);
		goto out;
	}
	if (unlikely(!input_file->f_op || !input_file->f_op->read)) {
		err = -EINVAL;
		goto out_close_in;
	}

	/* open new file */
	dget(new_lower_dentry);
	output_mnt = unionfs_mntget(sb->s_root, new_bindex);
	branchget(sb, new_bindex);
	output_file = dentry_open(new_lower_dentry, output_mnt,
				  O_RDWR | O_LARGEFILE);
	if (IS_ERR(output_file)) {
		err = PTR_ERR(output_file);
		goto out_close_in2;
	}
	if (unlikely(!output_file->f_op || !output_file->f_op->write)) {
		err = -EINVAL;
		goto out_close_out;
	}

	/* allocating a buffer */
	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (unlikely(!buf)) {
		err = -ENOMEM;
		goto out_close_out;
	}

	input_file->f_pos = 0;
	output_file->f_pos = 0;

	old_fs = get_fs();
	set_fs(KERNEL_DS);

	size = len;
	err = 0;
	do {
		if (len >= PAGE_SIZE)
			size = PAGE_SIZE;
		else if ((len < PAGE_SIZE) && (len > 0))
			size = len;

		len -= PAGE_SIZE;

		read_bytes =
			input_file->f_op->read(input_file,
					       (char __user *)buf, size,
					       &input_file->f_pos);
		if (read_bytes <= 0) {
			err = read_bytes;
			break;
		}

		/* see Documentation/filesystems/unionfs/issues.txt */
		lockdep_off();
		write_bytes =
			output_file->f_op->write(output_file,
						 (char __user *)buf,
						 read_bytes,
						 &output_file->f_pos);
		lockdep_on();
		if ((write_bytes < 0) || (write_bytes < read_bytes)) {
			err = write_bytes;
			break;
		}
	} while ((read_bytes > 0) && (len > 0));

	set_fs(old_fs);

	kfree(buf);

	if (!err)
		err = output_file->f_op->fsync(output_file,
					       new_lower_dentry, 0);

	if (err)
		goto out_close_out;

	if (copyup_file) {
		*copyup_file = output_file;
		goto out_close_in;
	}

out_close_out:
	fput(output_file);

out_close_in2:
	branchput(sb, new_bindex);

out_close_in:
	fput(input_file);

out:
	branchput(sb, old_bindex);

	return err;
}