linux-nfstrans-updates-20080630
[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 void
69 osi_linux_mask(void)
70 {
71     SIG_LOCK(current);
72     sigfillset(&current->blocked);
73     RECALC_SIGPENDING(current);
74     SIG_UNLOCK(current);
75 }
76
77 #if defined(AFS_LINUX24_ENV)
78 /* LOOKUP_POSITIVE is becoming the default */
79 #ifndef LOOKUP_POSITIVE
80 #define LOOKUP_POSITIVE 0
81 #endif
82 /* Lookup name and return vnode for same. */
83 int
84 osi_lookupname_internal(char *aname, int followlink, struct vfsmount **mnt,
85                         struct dentry **dpp)
86 {
87     int code;
88     struct nameidata nd;
89     int flags = LOOKUP_POSITIVE;
90     code = ENOENT;
91
92     if (followlink)
93        flags |= LOOKUP_FOLLOW;
94 #if defined(AFS_LINUX26_ENV)
95     code = path_lookup(aname, flags, &nd);
96 #else
97     if (path_init(aname, flags, &nd))
98         code = path_walk(aname, &nd);
99 #endif
100
101     if (!code) {
102 #if defined(STRUCT_NAMEIDATA_HAS_PATH)
103         *dpp = dget(nd.path.dentry);
104         if (mnt)
105             *mnt = mntget(nd.path.mnt);
106         path_put(&nd.path);
107 #else
108         *dpp = dget(nd.dentry);
109         if (mnt)
110            *mnt = mntget(nd.mnt);
111         path_release(&nd);
112 #endif
113     }
114     return code;
115 }
116 int
117 osi_lookupname(char *aname, uio_seg_t seg, int followlink, 
118                         struct dentry **dpp)
119 {
120     int code;
121     char *tname;
122     code = ENOENT;
123     if (seg == AFS_UIOUSER) {
124         tname = getname(aname);
125         if (IS_ERR(tname)) 
126             return PTR_ERR(tname);
127     } else {
128         tname = aname;
129     }
130     code = osi_lookupname_internal(tname, followlink, NULL, dpp);   
131     if (seg == AFS_UIOUSER) {
132         putname(tname);
133     }
134     return code;
135 }
136 #else
137 int
138 osi_lookupname(char *aname, uio_seg_t seg, int followlink, struct dentry **dpp)
139 {
140     struct dentry *dp = NULL;
141     int code;
142
143     code = ENOENT;
144     if (seg == AFS_UIOUSER) {
145         dp = followlink ? namei(aname) : lnamei(aname);
146     } else {
147         dp = lookup_dentry(aname, NULL, followlink ? 1 : 0);
148     }
149
150     if (dp && !IS_ERR(dp)) {
151         if (dp->d_inode) {
152             *dpp = dp;
153             code = 0;
154         } else
155             dput(dp);
156     }
157
158     return code;
159 }
160 #endif
161
162
163 #ifdef AFS_LINUX26_ENV
164 /* This is right even for Linux 2.4, but on that version d_path is inline
165  * and implemented in terms of __d_path, which is not exported.
166  */
167 int osi_abspath(char *aname, char *buf, int buflen,
168                 int followlink, char **pathp)
169 {
170     struct dentry *dp = NULL;
171     struct vfsmount *mnt = NULL;
172     char *tname, *path;
173     int code;
174
175     code = ENOENT;
176     tname = getname(aname);
177     if (IS_ERR(tname)) 
178         return -PTR_ERR(tname);
179     code = osi_lookupname_internal(tname, followlink, &mnt, &dp);   
180     if (!code) {
181 #if defined(D_PATH_TAKES_STRUCT_PATH)
182         struct path p = { mnt, dp };
183         path = d_path(&p, buf, buflen);
184 #else
185         path = d_path(dp, mnt, buf, buflen);
186 #endif
187
188         if (IS_ERR(path)) {
189             code = -PTR_ERR(path);
190         } else {
191             *pathp = path;
192         }
193
194         dput(dp);
195         mntput(mnt);
196     }
197
198     putname(tname);
199     return code;
200 }
201
202
203 /* This could use some work, and support on more platforms. */
204 int afs_thread_wrapper(void *rock)
205 {
206     void (*proc)(void) = rock;
207     __module_get(THIS_MODULE);
208     AFS_GLOCK();
209     (*proc)();
210     AFS_GUNLOCK();
211     module_put(THIS_MODULE);
212     return 0;
213 }
214
215 void afs_start_thread(void (*proc)(void), char *name)
216 {
217     kthread_run(afs_thread_wrapper, proc, "%s", name);
218 }
219 #endif