diff options
| -rw-r--r-- | arch/ia64/kernel/perfmon.c | 199 | 
1 files changed, 87 insertions, 112 deletions
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 7fbb51e10bbe..c1ad27de2dd2 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c  | |||
| @@ -867,7 +867,7 @@ pfm_rvfree(void *mem, unsigned long size) | |||
| 867 | } | 867 | } | 
| 868 | 868 | ||
| 869 | static pfm_context_t * | 869 | static pfm_context_t * | 
| 870 | pfm_context_alloc(void) | 870 | pfm_context_alloc(int ctx_flags) | 
| 871 | { | 871 | { | 
| 872 | pfm_context_t *ctx; | 872 | pfm_context_t *ctx; | 
| 873 | 873 | ||
| @@ -878,6 +878,46 @@ pfm_context_alloc(void) | |||
| 878 | ctx = kzalloc(sizeof(pfm_context_t), GFP_KERNEL); | 878 | ctx = kzalloc(sizeof(pfm_context_t), GFP_KERNEL); | 
| 879 | if (ctx) { | 879 | if (ctx) { | 
| 880 | DPRINT(("alloc ctx @%p\n", ctx)); | 880 | DPRINT(("alloc ctx @%p\n", ctx)); | 
| 881 | |||
| 882 | /* | ||
| 883 | * init context protection lock | ||
| 884 | */ | ||
| 885 | spin_lock_init(&ctx->ctx_lock); | ||
| 886 | |||
| 887 | /* | ||
| 888 | * context is unloaded | ||
| 889 | */ | ||
| 890 | ctx->ctx_state = PFM_CTX_UNLOADED; | ||
| 891 | |||
| 892 | /* | ||
| 893 | * initialization of context's flags | ||
| 894 | */ | ||
| 895 | ctx->ctx_fl_block = (ctx_flags & PFM_FL_NOTIFY_BLOCK) ? 1 : 0; | ||
| 896 | ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0; | ||
| 897 | ctx->ctx_fl_no_msg = (ctx_flags & PFM_FL_OVFL_NO_MSG) ? 1: 0; | ||
| 898 | /* | ||
| 899 | * will move to set properties | ||
| 900 | * ctx->ctx_fl_excl_idle = (ctx_flags & PFM_FL_EXCL_IDLE) ? 1: 0; | ||
| 901 | */ | ||
| 902 | |||
| 903 | /* | ||
| 904 | * init restart semaphore to locked | ||
| 905 | */ | ||
| 906 | init_completion(&ctx->ctx_restart_done); | ||
| 907 | |||
| 908 | /* | ||
| 909 | * activation is used in SMP only | ||
| 910 | */ | ||
| 911 | ctx->ctx_last_activation = PFM_INVALID_ACTIVATION; | ||
| 912 | SET_LAST_CPU(ctx, -1); | ||
| 913 | |||
| 914 | /* | ||
| 915 | * initialize notification message queue | ||
| 916 | */ | ||
| 917 | ctx->ctx_msgq_head = ctx->ctx_msgq_tail = 0; | ||
| 918 | init_waitqueue_head(&ctx->ctx_msgq_wait); | ||
| 919 | init_waitqueue_head(&ctx->ctx_zombieq); | ||
| 920 | |||
| 881 | } | 921 | } | 
| 882 | return ctx; | 922 | return ctx; | 
| 883 | } | 923 | } | 
| @@ -2165,28 +2205,21 @@ static struct dentry_operations pfmfs_dentry_operations = { | |||
| 2165 | }; | 2205 | }; | 
| 2166 | 2206 | ||
| 2167 | 2207 | ||
| 2168 | static int | 2208 | static struct file * | 
| 2169 | pfm_alloc_fd(struct file **cfile) | 2209 | pfm_alloc_file(pfm_context_t *ctx) | 
| 2170 | { | 2210 | { | 
| 2171 | int fd, ret = 0; | 2211 | struct file *file; | 
| 2172 | struct file *file = NULL; | 2212 | struct inode *inode; | 
| 2173 | struct inode * inode; | 2213 | struct dentry *dentry; | 
| 2174 | char name[32]; | 2214 | char name[32]; | 
| 2175 | struct qstr this; | 2215 | struct qstr this; | 
| 2176 | 2216 | ||
| 2177 | fd = get_unused_fd(); | ||
| 2178 | if (fd < 0) return -ENFILE; | ||
| 2179 | |||
| 2180 | ret = -ENFILE; | ||
| 2181 | |||
| 2182 | file = get_empty_filp(); | ||
| 2183 | if (!file) goto out; | ||
| 2184 | |||
| 2185 | /* | 2217 | /* | 
| 2186 | * allocate a new inode | 2218 | * allocate a new inode | 
| 2187 | */ | 2219 | */ | 
| 2188 | inode = new_inode(pfmfs_mnt->mnt_sb); | 2220 | inode = new_inode(pfmfs_mnt->mnt_sb); | 
| 2189 | if (!inode) goto out; | 2221 | if (!inode) | 
| 2222 | return ERR_PTR(-ENOMEM); | ||
| 2190 | 2223 | ||
| 2191 | DPRINT(("new inode ino=%ld @%p\n", inode->i_ino, inode)); | 2224 | DPRINT(("new inode ino=%ld @%p\n", inode->i_ino, inode)); | 
| 2192 | 2225 | ||
| @@ -2199,59 +2232,28 @@ pfm_alloc_fd(struct file **cfile) | |||
| 2199 | this.len = strlen(name); | 2232 | this.len = strlen(name); | 
| 2200 | this.hash = inode->i_ino; | 2233 | this.hash = inode->i_ino; | 
| 2201 | 2234 | ||
| 2202 | ret = -ENOMEM; | ||
| 2203 | |||
| 2204 | /* | 2235 | /* | 
| 2205 | * allocate a new dcache entry | 2236 | * allocate a new dcache entry | 
| 2206 | */ | 2237 | */ | 
| 2207 | file->f_path.dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this); | 2238 | dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this); | 
| 2208 | if (!file->f_path.dentry) goto out; | 2239 | if (!dentry) { | 
| 2240 | iput(inode); | ||
| 2241 | return ERR_PTR(-ENOMEM); | ||
| 2242 | } | ||
| 2209 | 2243 | ||
| 2210 | file->f_path.dentry->d_op = &pfmfs_dentry_operations; | 2244 | dentry->d_op = &pfmfs_dentry_operations; | 
| 2245 | d_add(dentry, inode); | ||
| 2211 | 2246 | ||
| 2212 | d_add(file->f_path.dentry, inode); | 2247 | file = alloc_file(pfmfs_mnt, dentry, FMODE_READ, &pfm_file_ops); | 
| 2213 | file->f_path.mnt = mntget(pfmfs_mnt); | 2248 | if (!file) { | 
| 2214 | file->f_mapping = inode->i_mapping; | 2249 | dput(dentry); | 
| 2250 | return ERR_PTR(-ENFILE); | ||
| 2251 | } | ||
| 2215 | 2252 | ||
| 2216 | file->f_op = &pfm_file_ops; | ||
| 2217 | file->f_mode = FMODE_READ; | ||
| 2218 | file->f_flags = O_RDONLY; | 2253 | file->f_flags = O_RDONLY; | 
| 2219 | file->f_pos = 0; | 2254 | file->private_data = ctx; | 
| 2220 | |||
| 2221 | /* | ||
| 2222 | * may have to delay until context is attached? | ||
| 2223 | */ | ||
| 2224 | fd_install(fd, file); | ||
| 2225 | |||
| 2226 | /* | ||
| 2227 | * the file structure we will use | ||
| 2228 | */ | ||
| 2229 | *cfile = file; | ||
| 2230 | |||
| 2231 | return fd; | ||
| 2232 | out: | ||
| 2233 | if (file) put_filp(file); | ||
| 2234 | put_unused_fd(fd); | ||
| 2235 | return ret; | ||
| 2236 | } | ||
| 2237 | |||
| 2238 | static void | ||
| 2239 | pfm_free_fd(int fd, struct file *file) | ||
| 2240 | { | ||
| 2241 | struct files_struct *files = current->files; | ||
| 2242 | struct fdtable *fdt; | ||
| 2243 | 2255 | ||
| 2244 | /* | 2256 | return file; | 
| 2245 | * there ie no fd_uninstall(), so we do it here | ||
| 2246 | */ | ||
| 2247 | spin_lock(&files->file_lock); | ||
| 2248 | fdt = files_fdtable(files); | ||
| 2249 | rcu_assign_pointer(fdt->fd[fd], NULL); | ||
| 2250 | spin_unlock(&files->file_lock); | ||
| 2251 | |||
| 2252 | if (file) | ||
| 2253 | put_filp(file); | ||
| 2254 | put_unused_fd(fd); | ||
| 2255 | } | 2257 | } | 
| 2256 | 2258 | ||
| 2257 | static int | 2259 | static int | 
| @@ -2475,6 +2477,7 @@ pfm_setup_buffer_fmt(struct task_struct *task, struct file *filp, pfm_context_t | |||
| 2475 | 2477 | ||
| 2476 | /* link buffer format and context */ | 2478 | /* link buffer format and context */ | 
| 2477 | ctx->ctx_buf_fmt = fmt; | 2479 | ctx->ctx_buf_fmt = fmt; | 
| 2480 | ctx->ctx_fl_is_sampling = 1; /* assume record() is defined */ | ||
| 2478 | 2481 | ||
| 2479 | /* | 2482 | /* | 
| 2480 | * check if buffer format wants to use perfmon buffer allocation/mapping service | 2483 | * check if buffer format wants to use perfmon buffer allocation/mapping service | 
| @@ -2669,78 +2672,45 @@ pfm_context_create(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg | |||
| 2669 | { | 2672 | { | 
| 2670 | pfarg_context_t *req = (pfarg_context_t *)arg; | 2673 | pfarg_context_t *req = (pfarg_context_t *)arg; | 
| 2671 | struct file *filp; | 2674 | struct file *filp; | 
| 2675 | struct path path; | ||
| 2672 | int ctx_flags; | 2676 | int ctx_flags; | 
| 2677 | int fd; | ||
| 2673 | int ret; | 2678 | int ret; | 
| 2674 | 2679 | ||
| 2675 | /* let's check the arguments first */ | 2680 | /* let's check the arguments first */ | 
| 2676 | ret = pfarg_is_sane(current, req); | 2681 | ret = pfarg_is_sane(current, req); | 
| 2677 | if (ret < 0) return ret; | 2682 | if (ret < 0) | 
| 2683 | return ret; | ||
| 2678 | 2684 | ||
| 2679 | ctx_flags = req->ctx_flags; | 2685 | ctx_flags = req->ctx_flags; | 
| 2680 | 2686 | ||
| 2681 | ret = -ENOMEM; | 2687 | ret = -ENOMEM; | 
| 2682 | 2688 | ||
| 2683 | ctx = pfm_context_alloc(); | 2689 | fd = get_unused_fd(); | 
| 2684 | if (!ctx) goto error; | 2690 | if (fd < 0) | 
| 2691 | return fd; | ||
| 2685 | 2692 | ||
| 2686 | ret = pfm_alloc_fd(&filp); | 2693 | ctx = pfm_context_alloc(ctx_flags); | 
| 2687 | if (ret < 0) goto error_file; | 2694 | if (!ctx) | 
| 2695 | goto error; | ||
| 2688 | 2696 | ||
| 2689 | req->ctx_fd = ctx->ctx_fd = ret; | 2697 | filp = pfm_alloc_file(ctx); | 
| 2698 | if (IS_ERR(filp)) { | ||
| 2699 | ret = PTR_ERR(filp); | ||
| 2700 | goto error_file; | ||
| 2701 | } | ||
| 2690 | 2702 | ||
| 2691 | /* | 2703 | req->ctx_fd = ctx->ctx_fd = fd; | 
| 2692 | * attach context to file | ||
| 2693 | */ | ||
| 2694 | filp->private_data = ctx; | ||
| 2695 | 2704 | ||
| 2696 | /* | 2705 | /* | 
| 2697 | * does the user want to sample? | 2706 | * does the user want to sample? | 
| 2698 | */ | 2707 | */ | 
| 2699 | if (pfm_uuid_cmp(req->ctx_smpl_buf_id, pfm_null_uuid)) { | 2708 | if (pfm_uuid_cmp(req->ctx_smpl_buf_id, pfm_null_uuid)) { | 
| 2700 | ret = pfm_setup_buffer_fmt(current, filp, ctx, ctx_flags, 0, req); | 2709 | ret = pfm_setup_buffer_fmt(current, filp, ctx, ctx_flags, 0, req); | 
| 2701 | if (ret) goto buffer_error; | 2710 | if (ret) | 
| 2711 | goto buffer_error; | ||
| 2702 | } | 2712 | } | 
| 2703 | 2713 | ||
| 2704 | /* | ||
| 2705 | * init context protection lock | ||
| 2706 | */ | ||
| 2707 | spin_lock_init(&ctx->ctx_lock); | ||
| 2708 | |||
| 2709 | /* | ||
| 2710 | * context is unloaded | ||
| 2711 | */ | ||
| 2712 | ctx->ctx_state = PFM_CTX_UNLOADED; | ||
| 2713 | |||
| 2714 | /* | ||
| 2715 | * initialization of context's flags | ||
| 2716 | */ | ||
| 2717 | ctx->ctx_fl_block = (ctx_flags & PFM_FL_NOTIFY_BLOCK) ? 1 : 0; | ||
| 2718 | ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0; | ||
| 2719 | ctx->ctx_fl_is_sampling = ctx->ctx_buf_fmt ? 1 : 0; /* assume record() is defined */ | ||
| 2720 | ctx->ctx_fl_no_msg = (ctx_flags & PFM_FL_OVFL_NO_MSG) ? 1: 0; | ||
| 2721 | /* | ||
| 2722 | * will move to set properties | ||
| 2723 | * ctx->ctx_fl_excl_idle = (ctx_flags & PFM_FL_EXCL_IDLE) ? 1: 0; | ||
| 2724 | */ | ||
| 2725 | |||
| 2726 | /* | ||
| 2727 | * init restart semaphore to locked | ||
| 2728 | */ | ||
| 2729 | init_completion(&ctx->ctx_restart_done); | ||
| 2730 | |||
| 2731 | /* | ||
| 2732 | * activation is used in SMP only | ||
| 2733 | */ | ||
| 2734 | ctx->ctx_last_activation = PFM_INVALID_ACTIVATION; | ||
| 2735 | SET_LAST_CPU(ctx, -1); | ||
| 2736 | |||
| 2737 | /* | ||
| 2738 | * initialize notification message queue | ||
| 2739 | */ | ||
| 2740 | ctx->ctx_msgq_head = ctx->ctx_msgq_tail = 0; | ||
| 2741 | init_waitqueue_head(&ctx->ctx_msgq_wait); | ||
| 2742 | init_waitqueue_head(&ctx->ctx_zombieq); | ||
| 2743 | |||
| 2744 | DPRINT(("ctx=%p flags=0x%x system=%d notify_block=%d excl_idle=%d no_msg=%d ctx_fd=%d \n", | 2714 | DPRINT(("ctx=%p flags=0x%x system=%d notify_block=%d excl_idle=%d no_msg=%d ctx_fd=%d \n", | 
| 2745 | ctx, | 2715 | ctx, | 
| 2746 | ctx_flags, | 2716 | ctx_flags, | 
| @@ -2755,10 +2725,14 @@ pfm_context_create(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg | |||
| 2755 | */ | 2725 | */ | 
| 2756 | pfm_reset_pmu_state(ctx); | 2726 | pfm_reset_pmu_state(ctx); | 
| 2757 | 2727 | ||
| 2728 | fd_install(fd, filp); | ||
| 2729 | |||
| 2758 | return 0; | 2730 | return 0; | 
| 2759 | 2731 | ||
| 2760 | buffer_error: | 2732 | buffer_error: | 
| 2761 | pfm_free_fd(ctx->ctx_fd, filp); | 2733 | path = filp->f_path; | 
| 2734 | put_filp(filp); | ||
| 2735 | path_put(&path); | ||
| 2762 | 2736 | ||
| 2763 | if (ctx->ctx_buf_fmt) { | 2737 | if (ctx->ctx_buf_fmt) { | 
| 2764 | pfm_buf_fmt_exit(ctx->ctx_buf_fmt, current, NULL, regs); | 2738 | pfm_buf_fmt_exit(ctx->ctx_buf_fmt, current, NULL, regs); | 
| @@ -2767,6 +2741,7 @@ error_file: | |||
| 2767 | pfm_context_free(ctx); | 2741 | pfm_context_free(ctx); | 
| 2768 | 2742 | ||
| 2769 | error: | 2743 | error: | 
| 2744 | put_unused_fd(fd); | ||
| 2770 | return ret; | 2745 | return ret; | 
| 2771 | } | 2746 | } | 
| 2772 | 2747 | ||
