~ubuntu-branches/ubuntu/warty/openafs/warty

« back to all changes in this revision

Viewing changes to src/afs/SOLARIS/osi_inode.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman
  • Date: 2004-01-10 16:37:33 UTC
  • Revision ID: james.westby@ubuntu.com-20040110163733-jvr0n1uahshlb1uu
Tags: upstream-1.2.11
ImportĀ upstreamĀ versionĀ 1.2.11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 * SOLARIS inode operations
 
12
 *
 
13
 * Implements:
 
14
 *
 
15
 */
 
16
#include <afsconfig.h>
 
17
#include "../afs/param.h"
 
18
 
 
19
RCSID("$Header: /afs/sipb.mit.edu/project/openafs/debian/cvs/openafs/src/afs/SOLARIS/osi_inode.c,v 1.1.1.8 2002/05/10 23:44:12 hartmans Exp $");
 
20
 
 
21
#include "../afs/sysincludes.h" /* Standard vendor system headers */
 
22
#include "../afs/afsincludes.h" /* Afs-based standard headers */
 
23
#include "../afs/osi_inode.h"
 
24
#include "../afs/afs_stats.h" /* statistics stuff */
 
25
 
 
26
extern int (*ufs_iallocp)(), (*ufs_iupdatp)(), (*ufs_igetp)(),
 
27
           (*ufs_itimes_nolockp)();
 
28
 
 
29
#define AFS_ITIMES(ip) { \
 
30
        mutex_enter(&(ip)->i_tlock); \
 
31
        (*ufs_itimes_nolockp)(ip); \
 
32
        mutex_exit(&(ip)->i_tlock); \
 
33
}
 
34
 
 
35
#define AFS_ITIMES_NOLOCK(ip) \
 
36
        (*ufs_itimes_nolockp)(ip);
 
37
 
 
38
getinode(vfsp, dev, inode, ipp, credp,perror)
 
39
     struct vfs *vfsp;
 
40
     struct AFS_UCRED *credp;
 
41
     struct inode **ipp;
 
42
     dev_t dev;
 
43
     ino_t inode;
 
44
     int *perror;
 
45
{
 
46
    struct inode *ip;
 
47
    register afs_int32 code;
 
48
    struct vnode *vp;
 
49
    struct fs *fs;
 
50
    struct inode *pip;
 
51
    struct ufsvfs *ufsvfsp;
 
52
    
 
53
    AFS_STATCNT(getinode);
 
54
    
 
55
    *perror = 0;
 
56
    
 
57
    if (!vfsp 
 
58
#if !defined(AFS_SUN58_ENV)
 
59
        && !(vfsp = vfs_devsearch(dev))
 
60
#else
 
61
        && !(vfsp = vfs_dev2vfsp(dev))
 
62
#endif
 
63
        ) {
 
64
        return (ENODEV);
 
65
    }
 
66
    ufsvfsp = (struct ufsvfs *)vfsp->vfs_data;
 
67
 
 
68
#ifdef HAVE_VFS_DQRWLOCK
 
69
    rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
 
70
#endif
 
71
    code = (*ufs_igetp)(vfsp, inode, &ip, credp);
 
72
#ifdef HAVE_VFS_DQRWLOCK
 
73
    rw_exit(&ufsvfsp->vfs_dqrwlock);
 
74
#endif
 
75
 
 
76
    if (code) {
 
77
        *perror = BAD_IGET;
 
78
        return code;
 
79
    }
 
80
    *ipp = ip;
 
81
    return code;
 
82
}
 
83
 
 
84
/* get an existing inode.  Common code for iopen, iread/write, iinc/dec. */
 
85
igetinode(vfsp, dev, inode, ipp, credp,perror)
 
86
     struct AFS_UCRED *credp;
 
87
     struct inode **ipp;
 
88
     struct vfs *vfsp;
 
89
     dev_t dev;
 
90
     ino_t inode;
 
91
     int *perror;
 
92
{
 
93
    struct inode *pip, *ip;
 
94
    extern struct osi_dev cacheDev;
 
95
    register int code = 0;
 
96
    
 
97
    *perror = 0;
 
98
    
 
99
    AFS_STATCNT(igetinode);
 
100
    
 
101
    code = getinode(vfsp, dev, inode, &ip, credp,perror);
 
102
    if (code) 
 
103
        return code;
 
104
    
 
105
    rw_enter(&ip->i_contents, RW_READER);
 
106
    
 
107
    if (ip->i_mode == 0) {
 
108
        /* Not an allocated inode */
 
109
        rw_exit(&ip->i_contents);
 
110
        VN_RELE(ITOV(ip));
 
111
        return (ENOENT);
 
112
    }
 
113
    
 
114
    if (ip->i_nlink == 0 || (ip->i_mode&IFMT) != IFREG) {
 
115
        AFS_ITIMES(ip);
 
116
        rw_exit(&ip->i_contents);
 
117
        VN_RELE(ITOV(ip));
 
118
        return (ENOENT);
 
119
    }
 
120
    
 
121
    /* On VFS40 systems, iput does major synchronous write action, but only
 
122
       when the reference count on the vnode goes to 0.  Normally, Sun users
 
123
       don't notice this because the DNLC keep references for them, but we
 
124
       notice 'cause we don't.  So, we make a fake dnlc entry which gets
 
125
       cleaned up by iget when it needs the space. */
 
126
    if (dev != cacheDev.dev) {
 
127
        /* 
 
128
         * Don't call dnlc for the cm inodes since it's a big performance 
 
129
         * penalty there!
 
130
         */
 
131
        dnlc_enter(ITOV(ip), "a", ITOV(ip), (struct AFS_UCRED *) 0);
 
132
    }
 
133
    
 
134
    *ipp = ip;
 
135
    rw_exit(&ip->i_contents);
 
136
    return (code);
 
137
}
 
138
 
 
139
int CrSync = 1;
 
140
 
 
141
afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4, rvp, credp)
 
142
     rval_t *rvp;
 
143
     struct AFS_UCRED *credp;
 
144
     long near_inode, param1, param2, param3, param4;
 
145
     dev_t dev;
 
146
{
 
147
    int dummy, err=0;
 
148
    struct inode *ip, *newip;
 
149
    register int code;
 
150
    dev_t newdev;
 
151
    struct ufsvfs *ufsvfsp;
 
152
 
 
153
    AFS_STATCNT(afs_syscall_icreate);
 
154
    
 
155
    if (!afs_suser(credp))
 
156
        return (EPERM);
 
157
    
 
158
    /** Code to convert a 32 bit dev_t into a 64 bit dev_t
 
159
      * This conversion is needed only for the 64 bit OS.
 
160
      */
 
161
    
 
162
#ifdef AFS_SUN57_64BIT_ENV
 
163
    newdev = expldev( (dev32_t) dev);
 
164
#else
 
165
    newdev = dev;
 
166
#endif
 
167
 
 
168
    code = getinode(0, (dev_t)newdev, 2, &ip, credp,&dummy);
 
169
    if (code) {
 
170
        return (code);
 
171
    }
 
172
 
 
173
    ufsvfsp = ip->i_ufsvfs;
 
174
    rw_enter(&ip->i_rwlock, RW_WRITER);
 
175
#ifdef HAVE_VFS_DQRWLOCK
 
176
    rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
 
177
#endif
 
178
    rw_enter(&ip->i_contents, RW_WRITER);
 
179
    code = (*ufs_iallocp)(ip, near_inode, 0, &newip, credp);
 
180
    AFS_ITIMES_NOLOCK(ip);
 
181
    rw_exit(&ip->i_contents);
 
182
#ifdef HAVE_VFS_DQRWLOCK
 
183
    rw_exit(&ufsvfsp->vfs_dqrwlock);
 
184
#endif
 
185
    rw_exit(&ip->i_rwlock);
 
186
    VN_RELE(ITOV(ip));
 
187
 
 
188
    if (code) {
 
189
        return (code);
 
190
    }
 
191
    rw_enter(&newip->i_contents, RW_WRITER);
 
192
    newip->i_flag |= IACC|IUPD|ICHG;
 
193
 
 
194
#if     defined(AFS_SUN56_ENV)
 
195
    newip->i_vicemagic = VICEMAGIC;
 
196
#else
 
197
    newip->i_uid = 0;
 
198
    newip->i_gid = -2;
 
199
#endif
 
200
    newip->i_nlink = 1;
 
201
    newip->i_mode = IFREG;
 
202
    newip->i_vnode.v_type = VREG;
 
203
    
 
204
    newip->i_vicep1 = param1;
 
205
    if (param2 == 0x1fffffff/*INODESPECIAL*/)   {
 
206
        newip->i_vicep2 = ((0x1fffffff << 3) + (param4 & 0x3));
 
207
        newip->i_vicep3 = param3;
 
208
    } else {
 
209
        newip->i_vicep2 = (((param2 >> 16) & 0x1f) << 27) +
 
210
            (((param4 >> 16) & 0x1f) << 22) + 
 
211
                (param3 & 0x3fffff);        
 
212
        newip->i_vicep3 = ((param4 << 16) + (param2 & 0xffff));
 
213
    }
 
214
#ifdef AFS_SUN57_64BIT_ENV
 
215
    rvp->r_vals = newip->i_number;
 
216
#else
 
217
    rvp->r_val1 = newip->i_number;
 
218
#endif
 
219
    
 
220
    /* 
 
221
     * We're being conservative and sync to the disk
 
222
     */
 
223
    if (CrSync)
 
224
        (*ufs_iupdatp)(newip, 1);
 
225
    AFS_ITIMES_NOLOCK(newip);
 
226
    rw_exit(&newip->i_contents);
 
227
    VN_RELE(ITOV(newip));
 
228
    return (code);
 
229
}
 
230
 
 
231
afs_syscall_iopen(dev, inode, usrmod, rvp, credp)
 
232
     rval_t *rvp;
 
233
     struct AFS_UCRED *credp;
 
234
     int  inode, usrmod;
 
235
     dev_t dev;
 
236
{
 
237
    struct file *fp;
 
238
    struct inode *ip;
 
239
    struct vnode *vp = (struct vnode *)0;
 
240
    int dummy;
 
241
    int fd;
 
242
    register int code;
 
243
    dev_t newdev;
 
244
 
 
245
    AFS_STATCNT(afs_syscall_iopen);
 
246
 
 
247
    if (!afs_suser(credp))
 
248
        return (EPERM);
 
249
 
 
250
    /** Code to convert a 32 bit dev_t into a 64 bit dev_t
 
251
      * This conversion is needed only for the 64 bit OS.
 
252
      */
 
253
    
 
254
#ifdef AFS_SUN57_64BIT_ENV
 
255
    newdev = expldev( (dev32_t) dev);
 
256
#else
 
257
    newdev = dev;
 
258
#endif
 
259
 
 
260
    code = igetinode(0, (dev_t)newdev, (ino_t)inode, &ip, credp,&dummy);
 
261
    if (code) {
 
262
        return (code);
 
263
    }
 
264
    code = falloc((struct vnode *)NULL, FWRITE|FREAD, &fp, &fd);
 
265
    if (code) {
 
266
        rw_enter(&ip->i_contents, RW_READER);
 
267
        AFS_ITIMES(ip);
 
268
        rw_exit(&ip->i_contents);
 
269
        VN_RELE(ITOV(ip));
 
270
        return (code);
 
271
    }
 
272
    
 
273
    /* fp->f_count, f_audit_data are set by falloc */
 
274
    fp->f_vnode = ITOV(ip);
 
275
    
 
276
    fp->f_flag = (usrmod+1) & (FMASK);
 
277
    
 
278
    /* fp->f_count, f_msgcount are set by falloc */
 
279
    
 
280
    /* fp->f_offset zeroed by falloc */
 
281
    /* f_cred set by falloc */
 
282
    /*
 
283
     * falloc returns the fp write locked 
 
284
     */
 
285
    mutex_exit(&fp->f_tlock);
 
286
    /*
 
287
     * XXX We should set the fp to null since we don't need it in the icalls
 
288
     */
 
289
    setf(fd, fp);
 
290
#ifdef AFS_SUN57_64BIT_ENV
 
291
    rvp->r_val2 = fd;
 
292
#else
 
293
    rvp->r_val1 = fd;
 
294
#endif
 
295
 
 
296
    return code;
 
297
}
 
298
 
 
299
int IncSync = 1;
 
300
 
 
301
afs_syscall_iincdec(dev, inode, inode_p1, amount, rvp, credp)
 
302
     rval_t *rvp;
 
303
     struct AFS_UCRED *credp;
 
304
     int inode, inode_p1, amount;
 
305
     dev_t dev;
 
306
{
 
307
    int dummy;
 
308
    struct inode *ip;
 
309
    register afs_int32 code;
 
310
    dev_t newdev;
 
311
 
 
312
    if (!afs_suser(credp))
 
313
        return (EPERM);
 
314
 
 
315
        /** Code to convert a 32 bit dev_t into a 64 bit dev_t
 
316
      * This conversion is needed only for the 64 bit OS.
 
317
      */
 
318
    
 
319
#ifdef AFS_SUN57_64BIT_ENV
 
320
    newdev = expldev( (dev32_t) dev);
 
321
#else
 
322
    newdev = dev;
 
323
#endif
 
324
 
 
325
    code = igetinode(0, (dev_t)newdev, (ino_t)inode, &ip, credp,&dummy);
 
326
    if (code) {
 
327
        return (code);
 
328
    }
 
329
    if (!IS_VICEMAGIC(ip)) {
 
330
        code = EPERM;
 
331
        rw_enter(&ip->i_contents, RW_READER);
 
332
        AFS_ITIMES(ip);
 
333
        rw_exit(&ip->i_contents);
 
334
        VN_RELE(ITOV(ip));
 
335
    } else {
 
336
        rw_enter(&ip->i_contents, RW_WRITER);
 
337
        ip->i_nlink += amount;
 
338
        if (ip->i_nlink == 0) {
 
339
            /* remove the "a" name added by igetinode so that the space is reclaimed. */
 
340
            dnlc_remove(ITOV(ip), "a");
 
341
            CLEAR_VICEMAGIC(ip);
 
342
        }
 
343
        ip->i_flag |= ICHG;
 
344
        /* We may want to force the inode to the disk in case of crashes, other references, etc. */
 
345
        if (IncSync)
 
346
            (*ufs_iupdatp)(ip, 1);
 
347
        AFS_ITIMES_NOLOCK(ip);
 
348
        rw_exit(&ip->i_contents);
 
349
        VN_RELE(ITOV(ip));
 
350
    }
 
351
    return (code);
 
352
}
 
353