linux-afs-translator-xen-20060731
[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 RCSID
18     ("$Header$");
19
20 #include <linux/module.h> /* early to avoid printf->printk mapping */
21 #include "afs/sysincludes.h"
22 #include "afsincludes.h"
23 #include "afs/afs_stats.h"
24 #if defined(AFS_LINUX24_ENV)
25 #include "h/smp_lock.h"
26 #endif
27 #if defined(AFS_LINUX26_ENV)
28 #include "h/namei.h"
29 #include "h/kthread.h"
30 #endif
31
32 int afs_osicred_initialized = 0;
33 struct AFS_UCRED afs_osi_cred;
34
35 void
36 afs_osi_SetTime(osi_timeval_t * tvp)
37 {
38 #if defined(AFS_LINUX24_ENV)
39
40 #if defined(AFS_LINUX26_ENV)
41     struct timespec tv;
42     tv.tv_sec = tvp->tv_sec;
43     tv.tv_nsec = tvp->tv_usec * NSEC_PER_USEC;
44 #else
45     struct timeval tv;
46     tv.tv_sec = tvp->tv_sec;
47     tv.tv_usec = tvp->tv_usec;
48 #endif
49
50     AFS_STATCNT(osi_SetTime);
51
52     do_settimeofday(&tv);
53 #else
54     extern int (*sys_settimeofdayp) (struct timeval * tv,
55                                      struct timezone * tz);
56
57     KERNEL_SPACE_DECL;
58
59     AFS_STATCNT(osi_SetTime);
60
61     TO_USER_SPACE();
62     if (sys_settimeofdayp)
63         (void)(*sys_settimeofdayp) (tvp, NULL);
64     TO_KERNEL_SPACE();
65 #endif
66 }
67
68 struct task_struct *rxk_ListenerTask;
69
70 void
71 osi_linux_mask(void)
72 {
73     SIG_LOCK(current);
74     sigfillset(&current->blocked);
75     RECALC_SIGPENDING(current);
76     SIG_UNLOCK(current);
77 }
78
79 void
80 osi_linux_rxkreg(void)
81 {
82     rxk_ListenerTask = current;
83 }
84
85
86 #if defined(AFS_LINUX24_ENV)
87 /* LOOKUP_POSITIVE is becoming the default */
88 #ifndef LOOKUP_POSITIVE
89 #define LOOKUP_POSITIVE 0
90 #endif
91 /* Lookup name and return vnode for same. */
92 int
93 osi_lookupname_internal(char *aname, int followlink, struct vfsmount **mnt,
94                         struct dentry **dpp)
95 {
96     int code;
97     struct nameidata nd;
98     int flags = LOOKUP_POSITIVE;
99     code = ENOENT;
100
101     if (followlink)
102        flags |= LOOKUP_FOLLOW;
103 #if defined(AFS_LINUX26_ENV)
104     code = path_lookup(aname, flags, &nd);
105 #else
106     if (path_init(aname, flags, &nd))
107         code = path_walk(aname, &nd);
108 #endif
109
110     if (!code) {
111         *dpp = dget(nd.dentry);
112         if (mnt)
113            *mnt = mntget(nd.mnt);
114         path_release(&nd);
115     }
116     return code;
117 }
118 int
119 osi_lookupname(char *aname, uio_seg_t seg, int followlink, 
120                         struct dentry **dpp)
121 {
122     int code;
123     char *tname;
124     code = ENOENT;
125     if (seg == AFS_UIOUSER) {
126         tname = getname(aname);
127         if (IS_ERR(tname)) 
128             return PTR_ERR(tname);
129     } else {
130         tname = aname;
131     }
132     code = osi_lookupname_internal(tname, followlink, NULL, dpp);   
133     if (seg == AFS_UIOUSER) {
134         putname(tname);
135     }
136     return code;
137 }
138 #else
139 int
140 osi_lookupname(char *aname, uio_seg_t seg, int followlink, struct dentry **dpp)
141 {
142     struct dentry *dp = NULL;
143     int code;
144
145     code = ENOENT;
146     if (seg == AFS_UIOUSER) {
147         dp = followlink ? namei(aname) : lnamei(aname);
148     } else {
149         dp = lookup_dentry(aname, NULL, followlink ? 1 : 0);
150     }
151
152     if (dp && !IS_ERR(dp)) {
153         if (dp->d_inode) {
154             *dpp = dp;
155             code = 0;
156         } else
157             dput(dp);
158     }
159
160     return code;
161 }
162 #endif
163
164
165 #ifdef AFS_LINUX26_ENV
166 /* This is right even for Linux 2.4, but on that version d_path is inline
167  * and implemented in terms of __d_path, which is not exported.
168  */
169 int osi_abspath(char *aname, char *buf, int buflen,
170                 int followlink, char **pathp)
171 {
172     struct dentry *dp = NULL;
173     struct vfsmnt *mnt = NULL;
174     char *tname, *path;
175     int code;
176
177     code = ENOENT;
178     tname = getname(aname);
179     if (IS_ERR(tname)) 
180         return -PTR_ERR(tname);
181     code = osi_lookupname_internal(tname, followlink, &mnt, &dp);   
182     if (!code) {
183         path = d_path(dp, mnt, buf, buflen);
184
185         if (IS_ERR(path)) {
186             code = -PTR_ERR(path);
187         } else {
188             *pathp = path;
189         }
190
191         dput(dp);
192         mntput(mnt);
193     }
194
195     putname(tname);
196     return code;
197 }
198
199
200 /* This could use some work, and support on more platforms. */
201 int afs_thread_wrapper(void *rock)
202 {
203     void (*proc)(void) = rock;
204     __module_get(THIS_MODULE);
205     AFS_GLOCK();
206     (*proc)();
207     AFS_GUNLOCK();
208     module_put(THIS_MODULE);
209     return 0;
210 }
211
212 void afs_start_thread(void (*proc)(void), char *name)
213 {
214     kthread_run(afs_thread_wrapper, proc, "%s", name);
215 }
216 #endif