1 /* $NetBSD: dtfs_vfsops.c,v 1.23 2007/11/30 19:02:37 pooka Exp $ */
4 * Copyright (c) 2006 Antti Kantee. All Rights Reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/types.h>
29 #include <sys/resource.h>
43 rtstr(struct puffs_usermount
*pu
, const char *str
, enum vtype vt
)
45 struct puffs_node
*pn
= puffs_getroot(pu
);
46 struct vattr
*va
= &pn
->pn_va
;
47 struct dtfs_file
*df
= DTFS_PTOF(pn
);
50 if (sscanf(str
, "%*s %256s", ltarg
) != 1)
53 dtfs_baseattrs(va
, vt
, 2);
54 df
->df_linktarget
= estrdup(ltarg
);
57 va
->va_size
= strlen(df
->df_linktarget
);
59 puffs_setrootinfo(pu
, vt
, 0, 0);
65 rtdev(struct puffs_usermount
*pu
, const char *str
, enum vtype vt
)
67 struct puffs_node
*pn
= puffs_getroot(pu
);
68 struct vattr
*va
= &pn
->pn_va
;
71 if (sscanf(str
, "%*s %d %d", &major
, &minor
) != 2)
74 dtfs_baseattrs(va
, vt
, 2);
76 va
->va_rdev
= makedev(major
, minor
);
79 va
->va_mode
|= S_IFBLK
;
81 va
->va_mode
|= S_IFCHR
;
83 puffs_setrootinfo(pu
, vt
, 0, va
->va_rdev
);
89 rtnorm(struct puffs_usermount
*pu
, const char *str
, enum vtype vt
)
91 struct puffs_node
*pn
= puffs_getroot(pu
);
92 struct vattr
*va
= &pn
->pn_va
;
94 dtfs_baseattrs(va
, vt
, 2);
100 puffs_setrootinfo(pu
, vt
, 0, 0);
108 int (*pfunc
)(struct puffs_usermount
*, const char *, enum vtype
);
110 { "reg", VREG
, rtnorm
},
111 { "dir", VDIR
, rtnorm
},
112 { "blk", VBLK
, rtdev
},
113 { "chr", VCHR
, rtdev
},
114 { "lnk", VLNK
, rtstr
},
115 { "sock", VSOCK
, rtnorm
},
116 { "fifo", VFIFO
, rtnorm
}
118 #define NTYPES (sizeof(rtypes) / sizeof(rtypes[0]))
121 dtfs_domount(struct puffs_usermount
*pu
, const char *typestr
)
123 struct dtfs_mount
*dtm
;
124 struct dtfs_file
*dff
;
125 struct puffs_node
*pn
;
128 /* create mount-local thingie */
129 dtm
= puffs_getspecific(pu
);
130 dtm
->dtm_nextfileid
= 3;
133 LIST_INIT(&dtm
->dtm_pollent
);
136 * create root directory, do it "by hand" to avoid special-casing
140 dff
->df_dotdot
= NULL
;
141 pn
= puffs_pn_new(pu
, dff
);
143 errx(1, "puffs_newpnode");
144 puffs_setroot(pu
, pn
);
147 rtnorm(pu
, NULL
, VDIR
);
149 for (i
= 0; i
< NTYPES
; i
++) {
150 if (strncmp(rtypes
[i
].tstr
, typestr
,
151 strlen(rtypes
[i
].tstr
)) == 0) {
152 if (rtypes
[i
].pfunc(pu
, typestr
,
153 rtypes
[i
].vt
) != 0) {
154 fprintf(stderr
, "failed to parse "
155 "\"%s\"\n", typestr
);
162 fprintf(stderr
, "no maching type for %s\n", typestr
);
171 * statvfs() should fill in the following members of struct statvfs:
173 * unsigned long f_bsize; file system block size
174 * unsigned long f_frsize; fundamental file system block size
175 * unsigned long f_iosize; optimal file system block size
176 * fsblkcnt_t f_blocks; number of blocks in file system,
177 * (in units of f_frsize)
179 * fsblkcnt_t f_bfree; free blocks avail in file system
180 * fsblkcnt_t f_bavail; free blocks avail to non-root
181 * fsblkcnt_t f_bresvd; blocks reserved for root
183 * fsfilcnt_t f_files; total file nodes in file system
184 * fsfilcnt_t f_ffree; free file nodes in file system
185 * fsfilcnt_t f_favail; free file nodes avail to non-root
186 * fsfilcnt_t f_fresvd; file nodes reserved for root
189 * The rest are filled in by the kernel.
191 #define ROUND(a,b) (((a) + ((b)-1)) & ~((b)-1))
192 #define NFILES 1024*1024
194 dtfs_fs_statvfs(struct puffs_usermount
*pu
, struct statvfs
*sbp
)
197 struct dtfs_mount
*dtm
;
201 dtm
= puffs_getspecific(pu
);
202 pgsize
= getpagesize();
203 memset(sbp
, 0, sizeof(struct statvfs
));
206 * Use datasize rlimit as an _approximation_ for free size.
207 * This, of course, is not accurate due to overhead and not
208 * accounting for metadata.
210 if (getrlimit(RLIMIT_DATA
, &rlim
) == 0)
211 btot
= rlim
.rlim_cur
;
214 bfree
= btot
- dtm
->dtm_fsizes
;
216 sbp
->f_blocks
= ROUND(btot
, pgsize
) / pgsize
;
217 sbp
->f_files
= NFILES
;
219 sbp
->f_bsize
= sbp
->f_frsize
= sbp
->f_iosize
= pgsize
;
220 sbp
->f_bfree
= sbp
->f_bavail
= ROUND(bfree
, pgsize
) / pgsize
;
221 sbp
->f_ffree
= sbp
->f_favail
= NFILES
- dtm
->dtm_nfiles
;
223 sbp
->f_bresvd
= sbp
->f_fresvd
= 0;
230 addrcmp(struct puffs_usermount
*pu
, struct puffs_node
*pn
, void *arg
)
240 dtfs_fs_fhtonode(struct puffs_usermount
*pu
, void *fid
, size_t fidsize
,
241 struct puffs_newinfo
*pni
)
243 struct dtfs_fid
*dfid
;
244 struct puffs_node
*pn
;
246 assert(fidsize
== sizeof(struct dtfs_fid
));
249 pn
= puffs_pn_nodewalk(pu
, addrcmp
, dfid
->dfid_addr
);
253 if (pn
->pn_va
.va_fileid
!= dfid
->dfid_fileid
254 || pn
->pn_va
.va_gen
!= dfid
->dfid_gen
)
257 puffs_newinfo_setcookie(pni
, pn
);
258 puffs_newinfo_setvtype(pni
, pn
->pn_va
.va_type
);
259 puffs_newinfo_setsize(pni
, pn
->pn_va
.va_size
);
260 puffs_newinfo_setrdev(pni
, pn
->pn_va
.va_rdev
);
266 dtfs_fs_nodetofh(struct puffs_usermount
*pu
, void *cookie
,
267 void *fid
, size_t *fidsize
)
269 struct puffs_node
*pn
= cookie
;
270 struct dtfs_fid
*dfid
;
271 extern int dynamicfh
;
273 if (dynamicfh
== 0) {
274 assert(*fidsize
>= sizeof(struct dtfs_fid
));
276 if (*fidsize
< sizeof(struct dtfs_fid
)) {
277 *fidsize
= sizeof(struct dtfs_fid
);
280 *fidsize
= sizeof(struct dtfs_fid
);
285 dfid
->dfid_addr
= pn
;
286 dfid
->dfid_fileid
= pn
->pn_va
.va_fileid
;
287 dfid
->dfid_gen
= pn
->pn_va
.va_gen
;
293 dtfs_fs_unmount(struct puffs_usermount
*pu
, int flags
)