freebsd-20040310
[openafs.git] / src / afs / FBSD / osi_vfsops.c
1 #include <afsconfig.h>
2 #include <afs/param.h>
3
4 RCSID
5     ("$Header$");
6
7 #include <afs/sysincludes.h>    /* Standard vendor system headers */
8 #include <afsincludes.h>        /* Afs-based standard headers */
9 #include <afs/afs_stats.h>      /* statistics */
10 #include <sys/malloc.h>
11 #include <sys/namei.h>
12 #include <sys/conf.h>
13 #include <sys/syscall.h>
14
15 struct vcache *afs_globalVp = 0;
16 struct mount *afs_globalVFS = 0;
17 int afs_pbuf_freecnt = -1;
18
19 #ifdef AFS_FBSD50_ENV
20 #define THREAD_OR_PROC struct thread *p
21 #else
22 #define THREAD_OR_PROC struct proc *p
23 #endif
24
25 int
26 afs_start(struct mount *mp, int flags, THREAD_OR_PROC)
27 {
28     afs_pbuf_freecnt = nswbuf / 2 + 1;
29     return (0);                 /* nothing to do. ? */
30 }
31
32 int
33 afs_mount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp,
34         THREAD_OR_PROC)
35 {
36     /* ndp contains the mounted-from device.  Just ignore it.
37      * we also don't care about our proc struct. */
38     size_t size;
39
40     if (mp->mnt_flag & MNT_UPDATE)
41         return EINVAL;
42
43     AFS_GLOCK();
44     AFS_STATCNT(afs_mount);
45
46     if (afs_globalVFS) {        /* Don't allow remounts. */
47         AFS_GUNLOCK();
48         return (EBUSY);
49     }
50
51     afs_globalVFS = mp;
52     mp->vfs_bsize = 8192;
53     vfs_getnewfsid(mp);
54     mp->mnt_stat.f_iosize = 8192;
55
56     (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
57     memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
58     memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
59     strcpy(mp->mnt_stat.f_mntfromname, "AFS");
60     /* null terminated string "AFS" will fit, just leave it be. */
61     strcpy(mp->mnt_stat.f_fstypename, "afs");
62     AFS_GUNLOCK();
63     (void)afs_statfs(mp, &mp->mnt_stat, p);
64     return 0;
65 }
66
67 int
68 afs_unmount(struct mount *mp, int flags, THREAD_OR_PROC)
69 {
70
71     /*
72      * Release any remaining vnodes on this mount point.
73      * The `1' means that we hold one extra reference on
74      * the root vnode (this is just a guess right now).
75      * This has to be done outside the global lock.
76      */
77     vflush(mp, 1, (flags & MNT_FORCE) ? FORCECLOSE : 0);
78     AFS_GLOCK();
79     AFS_STATCNT(afs_unmount);
80     afs_globalVFS = 0;
81     afs_shutdown();
82     AFS_GUNLOCK();
83
84     return 0;
85 }
86
87 int
88 afs_root(struct mount *mp, struct vnode **vpp)
89 {
90     int error;
91     struct vrequest treq;
92     register struct vcache *tvp = 0;
93 #ifdef AFS_FBSD50_ENV
94     struct thread *td = curthread;
95     struct ucred *cr = td->td_ucred;
96 #else
97     struct proc *p = curproc;
98     struct ucred *cr = p->p_cred->pc_ucred;
99 #endif
100
101     AFS_GLOCK();
102     AFS_STATCNT(afs_root);
103     crhold(cr);
104     if (afs_globalVp && (afs_globalVp->states & CStatd)) {
105         tvp = afs_globalVp;
106         error = 0;
107     } else {
108 tryagain:
109         if (afs_globalVp) {
110             afs_PutVCache(afs_globalVp);
111             /* vrele() needed here or not? */
112             afs_globalVp = NULL;
113         }
114
115         if (!(error = afs_InitReq(&treq, cr)) && !(error = afs_CheckInit())) {
116             tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
117             /* we really want this to stay around */
118             if (tvp)
119                 afs_globalVp = tvp;
120             else
121                 error = ENOENT;
122         }
123     }
124     if (tvp) {
125         struct vnode *vp = AFSTOV(tvp);
126
127 #ifdef AFS_FBSD50_ENV
128         ASSERT_VI_UNLOCKED(vp, "afs_root");
129 #endif
130         AFS_GUNLOCK();
131         /*
132          * I'm uncomfortable about this.  Shouldn't this happen at a
133          * higher level, and shouldn't we busy the top-level directory
134          * to prevent recycling?
135          */
136 #ifdef AFS_FBSD50_ENV
137         error = vget(vp, LK_EXCLUSIVE | LK_RETRY, td);
138         vp->v_vflag |= VV_ROOT;
139 #else
140         error = vget(vp, LK_EXCLUSIVE | LK_RETRY, p);
141         vp->v_flag |= VROOT;
142 #endif
143         AFS_GLOCK();
144         if (error != 0)
145                 goto tryagain;
146
147         afs_globalVFS = mp;
148         *vpp = vp;
149     }
150
151     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *vpp,
152                ICL_TYPE_INT32, error);
153     AFS_GUNLOCK();
154     crfree(cr);
155     return error;
156 }
157
158 int
159 afs_statfs(struct mount *mp, struct statfs *abp, THREAD_OR_PROC)
160 {
161     AFS_GLOCK();
162     AFS_STATCNT(afs_statfs);
163
164     abp->f_bsize = mp->vfs_bsize;
165     abp->f_iosize = mp->vfs_bsize;
166
167     /* Fake a high number below to satisfy programs that use the statfs call
168      * to make sure that there's enough space in the device partition before
169      * storing something there.
170      */
171     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
172         abp->f_ffree = 2000000;
173
174     abp->f_fsid.val[0] = mp->mnt_stat.f_fsid.val[0];
175     abp->f_fsid.val[1] = mp->mnt_stat.f_fsid.val[1];
176     if (abp != &mp->mnt_stat) {
177         abp->f_type = mp->mnt_vfc->vfc_typenum;
178         memcpy((caddr_t) & abp->f_mntonname[0],
179                (caddr_t) mp->mnt_stat.f_mntonname, MNAMELEN);
180         memcpy((caddr_t) & abp->f_mntfromname[0],
181                (caddr_t) mp->mnt_stat.f_mntfromname, MNAMELEN);
182     }
183
184     AFS_GUNLOCK();
185     return 0;
186 }
187
188 int
189 afs_sync(struct mount *mp, int waitfor, struct ucred *cred, THREAD_OR_PROC)
190 {
191     return 0;
192 }
193
194 int
195 afs_init(struct vfsconf *vfc)
196 {
197     return 0;
198 }
199
200 struct vfsops afs_vfsops = {
201     afs_mount,
202     afs_start,
203     afs_unmount,
204     afs_root,
205     vfs_stdquotactl,
206     afs_statfs,
207     afs_sync,
208     vfs_stdvget,
209     vfs_stdfhtovp,
210     vfs_stdcheckexp,
211     vfs_stdvptofh,
212     afs_init,
213     vfs_stduninit,
214     vfs_stdextattrctl,
215 #ifdef AFS_FBSD50_ENV
216     NULL,
217 #endif
218 };