afs: Drop GLOCK for various Rx calls
[openafs.git] / src / afs / LINUX / osi_misc.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Linux support routines.
12  *
13  */
14 #include <afsconfig.h>
15 #include "afs/param.h"
16
17
18 #include <linux/module.h> /* early to avoid printf->printk mapping */
19 #include <linux/dcache.h>
20 #include <linux/namei.h>
21 #include <linux/kthread.h>
22 #include "afs/sysincludes.h"
23 #include "afsincludes.h"
24 #include "afs/afs_stats.h"
25
26 #include "osi_compat.h"
27
28 int afs_osicred_initialized = 0;
29 afs_ucred_t afs_osi_cred;
30
31 void
32 osi_linux_mask(void)
33 {
34     SIG_LOCK(current);
35     sigfillset(&current->blocked);
36     RECALC_SIGPENDING(current);
37     SIG_UNLOCK(current);
38 }
39
40 void
41 osi_linux_unmaskrxk(void)
42 {
43     extern struct task_struct *rxk_ListenerTask;
44     /* Note this unblocks signals on the rxk_Listener
45      * thread from a thread that is stopping rxk */
46     SIG_LOCK(rxk_ListenerTask);
47     sigdelset(&rxk_ListenerTask->blocked, SIGKILL);
48     SIG_UNLOCK(rxk_ListenerTask);
49 }
50
51 /* LOOKUP_POSITIVE is becoming the default */
52 #ifndef LOOKUP_POSITIVE
53 #define LOOKUP_POSITIVE 0
54 #endif
55 /* Lookup name and return vnode for same. */
56 int
57 osi_lookupname_internal(char *aname, int followlink, struct vfsmount **mnt,
58                         struct dentry **dpp)
59 {
60     int code;
61 #if defined(HAVE_LINUX_PATH_LOOKUP)
62     struct nameidata path_data;
63 #else
64     afs_linux_path_t path_data;
65 #endif
66     int flags = LOOKUP_POSITIVE;
67
68     if (followlink)
69        flags |= LOOKUP_FOLLOW;
70     code = afs_kern_path(aname, flags, &path_data);
71
72     if (!code)
73         afs_get_dentry_ref(&path_data, mnt, dpp);
74
75     return code;
76 }
77
78 static char *
79 afs_getname(char *aname)
80 {
81     int len;
82     char *name = kmem_cache_alloc(names_cachep, GFP_KERNEL);
83
84     if (!name)
85         return ERR_PTR(-ENOMEM);
86
87     len = strncpy_from_user(name, aname, PATH_MAX);
88     if (len < 0)
89         goto error;
90     if (len >= PATH_MAX) {
91         len = -ENAMETOOLONG;
92         goto error;
93     }
94     return name;
95
96 error:
97     kmem_cache_free(names_cachep, name);
98     return ERR_PTR(len);
99 }
100
101 static void
102 afs_putname(char *name)
103 {
104     kmem_cache_free(names_cachep, name);
105 }
106
107 int
108 osi_lookupname(char *aname, uio_seg_t seg, int followlink,
109                struct dentry **dpp)
110 {
111     int code;
112     char *name;
113
114     if (seg == AFS_UIOUSER) {
115         name = afs_getname(aname);
116         if (IS_ERR(name))
117             return -PTR_ERR(name);
118     } else {
119         name = aname;
120     }
121     code = osi_lookupname_internal(name, followlink, NULL, dpp);
122     if (seg == AFS_UIOUSER) {
123         afs_putname(name);
124     }
125     return code;
126 }
127
128 int osi_abspath(char *aname, char *buf, int buflen,
129                 int followlink, char **pathp)
130 {
131     struct dentry *dp = NULL;
132     struct vfsmount *mnt = NULL;
133     char *name, *path;
134     int code;
135
136     name = afs_getname(aname);
137     if (IS_ERR(name))
138         return -PTR_ERR(name);
139     code = osi_lookupname_internal(name, followlink, &mnt, &dp);
140     if (!code) {
141         path = afs_d_path(dp, mnt, buf, buflen);
142         if (IS_ERR(path)) {
143             code = -PTR_ERR(path);
144         } else {
145             *pathp = path;
146         }
147
148         dput(dp);
149         mntput(mnt);
150     }
151
152     afs_putname(name);
153     return code;
154 }
155
156
157 /* This could use some work, and support on more platforms. */
158 static int
159 afs_thread_wrapper(void *rock)
160 {
161     void (*proc)(void) = rock;
162     __module_get(THIS_MODULE);
163     (*proc)();
164     module_put(THIS_MODULE);
165     return 0;
166 }
167
168 static int
169 afs_thread_wrapper_glock(void *rock)
170 {
171     void (*proc)(void) = rock;
172     __module_get(THIS_MODULE);
173     AFS_GLOCK();
174     (*proc)();
175     AFS_GUNLOCK();
176     module_put(THIS_MODULE);
177     return 0;
178 }
179
180 void
181 afs_start_thread(void (*proc)(void), char *name, int needs_glock)
182 {
183     if (needs_glock) {
184         kthread_run(afs_thread_wrapper_glock, proc, "%s", name);
185     } else {
186         kthread_run(afs_thread_wrapper, proc, "%s", name);
187     }
188 }