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