1 /* $NetBSD: dtfs_vfsops.c,v 1.3 2012/11/04 23:37:02 christos 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>
44 rtstr(struct puffs_usermount
*pu
, const char *str
, enum vtype vt
)
46 struct puffs_node
*pn
= puffs_getroot(pu
);
47 struct vattr
*va
= &pn
->pn_va
;
48 struct dtfs_file
*df
= DTFS_PTOF(pn
);
51 if (sscanf(str
, "%*s %256s", ltarg
) != 1)
54 dtfs_baseattrs(va
, vt
, 2);
55 df
->df_linktarget
= estrdup(ltarg
);
58 va
->va_size
= strlen(df
->df_linktarget
);
60 puffs_setrootinfo(pu
, vt
, 0, 0);
66 rtdev(struct puffs_usermount
*pu
, const char *str
, enum vtype vt
)
68 struct puffs_node
*pn
= puffs_getroot(pu
);
69 struct vattr
*va
= &pn
->pn_va
;
72 if (sscanf(str
, "%*s %d %d", &major
, &minor
) != 2)
75 dtfs_baseattrs(va
, vt
, 2);
77 va
->va_rdev
= makedev(major
, minor
);
80 va
->va_mode
|= S_IFBLK
;
82 va
->va_mode
|= S_IFCHR
;
84 puffs_setrootinfo(pu
, vt
, 0, va
->va_rdev
);
90 rtnorm(struct puffs_usermount
*pu
, const char *str
, enum vtype vt
)
92 struct puffs_node
*pn
= puffs_getroot(pu
);
93 struct vattr
*va
= &pn
->pn_va
;
95 dtfs_baseattrs(va
, vt
, 2);
101 puffs_setrootinfo(pu
, vt
, 0, 0);
109 int (*pfunc
)(struct puffs_usermount
*, const char *, enum vtype
);
111 { "reg", VREG
, rtnorm
},
112 { "dir", VDIR
, rtnorm
},
113 { "blk", VBLK
, rtdev
},
114 { "chr", VCHR
, rtdev
},
115 { "lnk", VLNK
, rtstr
},
116 { "sock", VSOCK
, rtnorm
},
117 { "fifo", VFIFO
, rtnorm
}
119 #define NTYPES (sizeof(rtypes) / sizeof(rtypes[0]))
122 dtfs_domount(struct puffs_usermount
*pu
, const char *typestr
)
124 struct dtfs_mount
*dtm
;
125 struct dtfs_file
*dff
;
126 struct puffs_node
*pn
;
129 /* create mount-local thingie */
130 dtm
= puffs_getspecific(pu
);
131 dtm
->dtm_nextfileid
= 3;
134 LIST_INIT(&dtm
->dtm_pollent
);
137 * create root directory, do it "by hand" to avoid special-casing
141 dff
->df_dotdot
= NULL
;
142 pn
= puffs_pn_new(pu
, dff
);
144 errx(1, "puffs_newpnode");
145 puffs_setroot(pu
, pn
);
148 rtnorm(pu
, NULL
, VDIR
);
150 for (i
= 0; i
< NTYPES
; i
++) {
151 if (strncmp(rtypes
[i
].tstr
, typestr
,
152 strlen(rtypes
[i
].tstr
)) == 0) {
153 if (rtypes
[i
].pfunc(pu
, typestr
,
154 rtypes
[i
].vt
) != 0) {
155 fprintf(stderr
, "failed to parse "
156 "\"%s\"\n", typestr
);
163 fprintf(stderr
, "no maching type for %s\n", typestr
);
172 * statvfs() should fill in the following members of struct statvfs:
174 * unsigned long f_bsize; file system block size
175 * unsigned long f_frsize; fundamental file system block size
176 * unsigned long f_iosize; optimal file system block size
177 * fsblkcnt_t f_blocks; number of blocks in file system,
178 * (in units of f_frsize)
180 * fsblkcnt_t f_bfree; free blocks avail in file system
181 * fsblkcnt_t f_bavail; free blocks avail to non-root
182 * fsblkcnt_t f_bresvd; blocks reserved for root
184 * fsfilcnt_t f_files; total file nodes in file system
185 * fsfilcnt_t f_ffree; free file nodes in file system
186 * fsfilcnt_t f_favail; free file nodes avail to non-root
187 * fsfilcnt_t f_fresvd; file nodes reserved for root
190 * The rest are filled in by the kernel.
192 #define ROUND(a,b) (((a) + ((b)-1)) & ~((b)-1))
193 #define NFILES 1024*1024
195 dtfs_fs_statvfs(struct puffs_usermount
*pu
, struct statvfs
*sbp
)
198 struct dtfs_mount
*dtm
;
202 dtm
= puffs_getspecific(pu
);
203 pgsize
= getpagesize();
204 memset(sbp
, 0, sizeof(struct statvfs
));
207 * Use datasize rlimit as an _approximation_ for free size.
208 * This, of course, is not accurate due to overhead and not
209 * accounting for metadata.
211 if (getrlimit(RLIMIT_DATA
, &rlim
) == 0)
212 btot
= rlim
.rlim_cur
;
215 bfree
= btot
- dtm
->dtm_fsizes
;
217 sbp
->f_blocks
= ROUND(btot
, pgsize
) / pgsize
;
218 sbp
->f_files
= NFILES
;
220 sbp
->f_bsize
= sbp
->f_frsize
= sbp
->f_iosize
= pgsize
;
221 sbp
->f_bfree
= sbp
->f_bavail
= ROUND(bfree
, pgsize
) / pgsize
;
222 sbp
->f_ffree
= sbp
->f_favail
= NFILES
- dtm
->dtm_nfiles
;
224 sbp
->f_bresvd
= sbp
->f_fresvd
= 0;
231 addrcmp(struct puffs_usermount
*pu
, struct puffs_node
*pn
, void *arg
)
241 dtfs_fs_fhtonode(struct puffs_usermount
*pu
, void *fid
, size_t fidsize
,
242 struct puffs_newinfo
*pni
)
244 struct dtfs_fid
*dfid
;
245 struct puffs_node
*pn
;
247 assert(fidsize
== sizeof(struct dtfs_fid
));
250 pn
= puffs_pn_nodewalk(pu
, addrcmp
, dfid
->dfid_addr
);
254 if (pn
->pn_va
.va_fileid
!= dfid
->dfid_fileid
255 || pn
->pn_va
.va_gen
!= dfid
->dfid_gen
)
258 puffs_newinfo_setcookie(pni
, pn
);
259 puffs_newinfo_setvtype(pni
, pn
->pn_va
.va_type
);
260 puffs_newinfo_setsize(pni
, pn
->pn_va
.va_size
);
261 puffs_newinfo_setrdev(pni
, pn
->pn_va
.va_rdev
);
267 dtfs_fs_nodetofh(struct puffs_usermount
*pu
, void *cookie
,
268 void *fid
, size_t *fidsize
)
270 struct puffs_node
*pn
= cookie
;
271 struct dtfs_fid
*dfid
;
272 extern int dynamicfh
;
274 if (dynamicfh
== 0) {
275 assert(*fidsize
>= sizeof(struct dtfs_fid
));
277 if (*fidsize
< sizeof(struct dtfs_fid
)) {
278 *fidsize
= sizeof(struct dtfs_fid
);
281 *fidsize
= sizeof(struct dtfs_fid
);
286 dfid
->dfid_addr
= pn
;
287 dfid
->dfid_fileid
= pn
->pn_va
.va_fileid
;
288 dfid
->dfid_gen
= pn
->pn_va
.va_gen
;
294 dtfs_fs_unmount(struct puffs_usermount
*pu
, int flags
)