xref: /NextBSD/sys/gnu/fs/reiserfs/reiserfs_vnops.c (revision eb1a5f8de9f7ea602c373a710f531abbf81141c4)
1 /*-
2  * Copyright 2000 Hans Reiser
3  * See README for licensing and copyright details
4  *
5  * Ported to FreeBSD by Jean-Sébastien Pédron <jspedron@club-internet.fr>
6  *
7  * $FreeBSD$
8  */
9 
10 #include <gnu/fs/reiserfs/reiserfs_fs.h>
11 
12 static vop_access_t	reiserfs_access;
13 static vop_bmap_t	reiserfs_bmap;
14 static vop_getattr_t	reiserfs_getattr;
15 static vop_open_t	reiserfs_open;
16 static vop_pathconf_t	reiserfs_pathconf;
17 static vop_readlink_t	reiserfs_readlink;
18 static vop_strategy_t	reiserfs_strategy;
19 static vop_vptofh_t	reiserfs_vptofh;
20 
21 /* Global vfs data structures for ReiserFS */
22 struct vop_vector reiserfs_vnodeops = {
23 	.vop_default      = &default_vnodeops,
24 
25 	.vop_access       = reiserfs_access,
26 	.vop_bmap         = reiserfs_bmap,
27 	.vop_cachedlookup = reiserfs_lookup,
28 	.vop_getattr      = reiserfs_getattr,
29 	.vop_inactive     = reiserfs_inactive,
30 	.vop_lookup       = vfs_cache_lookup,
31 	.vop_open         = reiserfs_open,
32 	.vop_reclaim      = reiserfs_reclaim,
33 	.vop_read         = reiserfs_read,
34 	.vop_readdir      = reiserfs_readdir,
35 	.vop_readlink     = reiserfs_readlink,
36 	.vop_pathconf     = reiserfs_pathconf,
37 	.vop_strategy     = reiserfs_strategy,
38 	.vop_vptofh       = reiserfs_vptofh,
39 };
40 
41 struct vop_vector reiserfs_specops = {
42 	.vop_default  = &default_vnodeops,
43 
44 	.vop_access   = reiserfs_access,
45 	.vop_getattr  = reiserfs_getattr,
46 	.vop_inactive = reiserfs_inactive,
47 	.vop_reclaim  = reiserfs_reclaim,
48 };
49 
50 /* -------------------------------------------------------------------
51  * vnode operations
52  * -------------------------------------------------------------------*/
53 
54 static int
reiserfs_access(struct vop_access_args * ap)55 reiserfs_access(struct vop_access_args *ap)
56 {
57 	int error;
58 	struct vnode *vp = ap->a_vp;
59 	struct reiserfs_node *ip = VTOI(vp);
60 	accmode_t accmode = ap->a_accmode;
61 
62 	/*
63 	 * Disallow write attempts on read-only file systems; unless the file
64 	 * is a socket, fifo, or a block or character device resident on the
65 	 * file system.
66 	 */
67 	if (accmode & VWRITE) {
68 		switch (vp->v_type) {
69 		case VDIR:
70 		case VLNK:
71 		case VREG:
72 			if (vp->v_mount->mnt_flag & MNT_RDONLY) {
73 				reiserfs_log(LOG_DEBUG,
74 				    "no write access (read-only fs)\n");
75 				return (EROFS);
76 			}
77 			break;
78 		default:
79 			break;
80 		}
81 	}
82 
83 	/* If immutable bit set, nobody gets to write it. */
84 	if ((accmode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT))) {
85 		reiserfs_log(LOG_DEBUG, "no write access (immutable)\n");
86 		return (EPERM);
87 	}
88 
89 	error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
90 	    ap->a_accmode, ap->a_cred, NULL);
91 	return (error);
92 }
93 
94 static int
reiserfs_getattr(struct vop_getattr_args * ap)95 reiserfs_getattr(struct vop_getattr_args *ap)
96 {
97 	struct vnode *vp         = ap->a_vp;
98 	struct vattr *vap        = ap->a_vap;
99 	struct reiserfs_node *ip = VTOI(vp);
100 
101 	vap->va_fsid      = dev2udev(ip->i_dev);
102 	vap->va_fileid    = ip->i_number;
103 	vap->va_mode      = ip->i_mode & ~S_IFMT;
104 	vap->va_nlink     = ip->i_nlink;
105 	vap->va_uid       = ip->i_uid;
106 	vap->va_gid       = ip->i_gid;
107 	//XXX vap->va_rdev      = ip->i_rdev;
108 	vap->va_size      = ip->i_size;
109 	vap->va_atime     = ip->i_atime;
110 	vap->va_mtime     = ip->i_mtime;
111 	vap->va_ctime     = ip->i_ctime;
112 	vap->va_flags     = ip->i_flags;
113 	vap->va_gen       = ip->i_generation;
114 	vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
115 	vap->va_bytes     = dbtob((u_quad_t)ip->i_blocks);
116 	vap->va_type      = vp->v_type;
117 	//XXX vap->va_filerev   = ip->i_modrev;
118 
119 	return (0);
120 }
121 
122 /* Return POSIX pathconf information applicable to ReiserFS filesystems */
123 static int
reiserfs_pathconf(struct vop_pathconf_args * ap)124 reiserfs_pathconf(struct vop_pathconf_args *ap)
125 {
126 	switch (ap->a_name) {
127 	case _PC_LINK_MAX:
128 		*ap->a_retval = REISERFS_LINK_MAX;
129 		return (0);
130 	case _PC_NAME_MAX:
131 		*ap->a_retval =
132 		    REISERFS_MAX_NAME(VTOI(ap->a_vp)->i_reiserfs->s_blocksize);
133 		return (0);
134 	case _PC_PATH_MAX:
135 		*ap->a_retval = PATH_MAX;
136 		return (0);
137 	case _PC_PIPE_BUF:
138 		*ap->a_retval = PIPE_BUF;
139 		return (0);
140 	case _PC_CHOWN_RESTRICTED:
141 		*ap->a_retval = 1;
142 		return (0);
143 	case _PC_NO_TRUNC:
144 		*ap->a_retval = 1;
145 		return (0);
146 	default:
147 		return (EINVAL);
148 	}
149 }
150 
151 static int
reiserfs_open(struct vop_open_args * ap)152 reiserfs_open(struct vop_open_args *ap)
153 {
154 	/* Files marked append-only must be opened for appending. */
155 	if ((VTOI(ap->a_vp)->i_flags & APPEND) &&
156 	    (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
157 		return (EPERM);
158 
159 	vnode_create_vobject(ap->a_vp, VTOI(ap->a_vp)->i_size, ap->a_td);
160 
161 	return (0);
162 }
163 
164 /* Return target name of a symbolic link */
165 static int
reiserfs_readlink(struct vop_readlink_args * ap)166 reiserfs_readlink(struct vop_readlink_args *ap)
167 {
168 	struct vnode *vp = ap->a_vp;
169 
170 	reiserfs_log(LOG_DEBUG, "redirect to VOP_READ()\n");
171 	return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
172 }
173 
174 /* Bmap converts the logical block number of a file to its physical
175  * block number on the disk. */
176 static int
reiserfs_bmap(ap)177 reiserfs_bmap(ap)
178 	struct vop_bmap_args /* {
179 				struct vnode *a_vp;
180 				daddr_t a_bn;
181 				struct bufobj **a_bop;
182 				daddr_t *a_bnp;
183 				int *a_runp;
184 				int *a_runb;
185 				} */ *ap;
186 {
187 	daddr_t blkno;
188 	struct buf *bp;
189 	struct cpu_key key;
190 	struct item_head *ih;
191 
192 	struct vnode *vp = ap->a_vp;
193 	struct reiserfs_node *ip = VTOI(vp);
194 	struct reiserfs_sb_info *sbi = ip->i_reiserfs;
195 	INITIALIZE_PATH(path);
196 
197 	/* Prepare the key to look for the 'block'-th block of file
198 	 * (XXX we suppose that statfs.f_iosize == sbi->s_blocksize) */
199 	make_cpu_key(&key, ip, (off_t)ap->a_bn * sbi->s_blocksize + 1,
200 	    TYPE_ANY, 3);
201 
202 	/* Search item */
203 	if (search_for_position_by_key(sbi, &key, &path) != POSITION_FOUND) {
204 		reiserfs_log(LOG_DEBUG, "position not found\n");
205 		pathrelse(&path);
206 		return (ENOENT);
207 	}
208 
209 	bp = get_last_bp(&path);
210 	ih = get_ih(&path);
211 
212 	if (is_indirect_le_ih(ih)) {
213 		/* Indirect item can be read by the underlying layer, instead of
214 		 * VOP_STRATEGY. */
215 		int i;
216 		uint32_t *ind_item = (uint32_t *)B_I_PITEM(bp, ih);
217 		reiserfs_log(LOG_DEBUG, "found an INDIRECT item\n");
218 		blkno = get_block_num(ind_item, path.pos_in_item);
219 
220 		/* Read-ahead */
221 		if (ap->a_runb) {
222 			uint32_t count = 0;
223 			for (i = path.pos_in_item - 1; i >= 0; --i) {
224 				if ((blkno - get_block_num(ind_item, i)) !=
225 				    count + 1)
226 					break;
227 				++count;
228 			}
229 
230 			/*
231 			 * This count isn't expressed in DEV_BSIZE base but
232 			 * in fs' own block base
233 			 * (see sys/vm/vnode_pager.c:vnode_pager_addr())
234 			 */
235 			*ap->a_runb = count;
236 			reiserfs_log(LOG_DEBUG,
237 			    " read-ahead: %d blocks before\n", *ap->a_runb);
238 		}
239 		if (ap->a_runp) {
240 			uint32_t count = 0;
241 			/*
242 			 * ih is an uint32_t array, that's why we use
243 			 * its length (in bytes) divided by 4 to know
244 			 * the number of items
245 			 */
246 			for (i = path.pos_in_item + 1;
247 			    i < ih_item_len(ih) / 4; ++i) {
248 				if ((get_block_num(ind_item, i) - blkno) !=
249 				    count + 1)
250 					break;
251 				++count;
252 			}
253 
254 			/*
255 			 * This count isn't expressed in DEV_BSIZE base but
256 			 * in fs' own block base
257 			 * (see sys/vm/vnode_pager.c:vnode_pager_addr()) */
258 			*ap->a_runp = count;
259 			reiserfs_log(LOG_DEBUG,
260 			    " read-ahead: %d blocks after\n", *ap->a_runp);
261 		}
262 
263 		/* Indirect items can be read using the device VOP_STRATEGY */
264 		if (ap->a_bop)
265 			*ap->a_bop = &VTOI(ap->a_vp)->i_devvp->v_bufobj;
266 
267 		/* Convert the block number into DEV_BSIZE base */
268 		blkno *= btodb(sbi->s_blocksize);
269 	} else {
270 		/*
271 		 * Direct item are not DEV_BSIZE aligned, VOP_STRATEGY will
272 		 * have to handle this case specifically
273 		 */
274 		reiserfs_log(LOG_DEBUG, "found a DIRECT item\n");
275 		blkno = ap->a_bn;
276 
277 		if (ap->a_runp)
278 			*ap->a_runp = 0;
279 		if (ap->a_runb)
280 			*ap->a_runb = 0;
281 
282 		/* Direct item must be read by reiserfs_strategy */
283 		if (ap->a_bop)
284 			*ap->a_bop = &vp->v_bufobj;
285 	}
286 
287 	if (ap->a_bnp)
288 		*ap->a_bnp = blkno;
289 
290 	pathrelse(&path);
291 
292 	if (ap->a_bnp) {
293 		reiserfs_log(LOG_DEBUG, "logical block: %ju (%ju),"
294 		    " physical block: %ju (%ju)\n",
295 		    (intmax_t)ap->a_bn,
296 		    (intmax_t)(ap->a_bn / btodb(sbi->s_blocksize)),
297 		    (intmax_t)*ap->a_bnp,
298 		    (intmax_t)(*ap->a_bnp / btodb(sbi->s_blocksize)));
299 	}
300 
301 	return (0);
302 }
303 
304 /* Does simply the same as reiserfs_read. It's called when reiserfs_bmap find
305  * an direct item. */
306 static int
reiserfs_strategy(struct vop_strategy_args * ap)307 reiserfs_strategy(struct vop_strategy_args /* {
308 					      struct vnode *a_vp;
309 					      struct buf *a_bp;
310 					      } */ *ap)
311 {
312 	int error;
313 	struct uio auio;
314 	struct iovec aiov;
315 	struct reiserfs_node *ip;
316 	struct buf *bp = ap->a_bp;
317 	struct vnode *vp = ap->a_vp;
318 
319 	reiserfs_log(LOG_DEBUG, "logical block: %ju,"
320 	    " physical block: %ju\n", (intmax_t)bp->b_lblkno,
321 	    (intmax_t)bp->b_blkno);
322 
323 	ip = VTOI(vp);
324 
325 	if (bp->b_iocmd == BIO_READ) {
326 		/* Prepare the uio structure */
327 		reiserfs_log(LOG_DEBUG, "prepare uio structure\n");
328 		aiov.iov_base = bp->b_data;
329 		aiov.iov_len  = MIN(bp->b_bcount, ip->i_size);
330 		reiserfs_log(LOG_DEBUG, "  vector length: %ju\n",
331 		    (intmax_t)aiov.iov_len);
332 
333 		auio.uio_iov    = &aiov;
334 		auio.uio_iovcnt = 1;
335 		auio.uio_offset = 0;
336 		auio.uio_rw     = UIO_READ;
337 		auio.uio_segflg = UIO_SYSSPACE;
338 		auio.uio_td     = curthread;
339 		auio.uio_resid  = bp->b_bcount;
340 		reiserfs_log(LOG_DEBUG, "  buffer length: %u\n",
341 		    auio.uio_resid);
342 
343 		reiserfs_log(LOG_DEBUG, "reading block #%ju\n",
344 		    (intmax_t)bp->b_blkno);
345 		error = reiserfs_get_block(ip, bp->b_blkno, 0, &auio);
346 	} else {
347 		/* No write support yet */
348 		error = (EOPNOTSUPP);
349 		bp->b_error    = error;
350 		bp->b_ioflags |= BIO_ERROR;
351 	}
352 
353 	if (error) {
354 		bp->b_ioflags |= BIO_ERROR;
355 		bp->b_error = error;
356 	}
357 
358 	bufdone(bp);
359 	return (0);
360 }
361 
362 /*
363  * Vnode pointer to File handle
364  */
365 static int
reiserfs_vptofh(struct vop_vptofh_args * ap)366 reiserfs_vptofh(struct vop_vptofh_args /* {
367 					  struct vnode *a_vp;
368 					  struct fid *a_fhp;
369 					  } */ *ap)
370 {
371 	struct rfid *rfhp;
372 	struct reiserfs_node *ip;
373 
374 	ip = VTOI(ap->a_vp);
375 	reiserfs_log(LOG_DEBUG,
376 	    "fill *fhp with inode (dirid=%d, objectid=%d)\n",
377 	    ip->i_ino, ip->i_number);
378 
379 	rfhp = (struct rfid *)ap->a_fhp;
380 	rfhp->rfid_len      = sizeof(struct rfid);
381 	rfhp->rfid_dirid    = ip->i_ino;
382 	rfhp->rfid_objectid = ip->i_number;
383 	rfhp->rfid_gen      = ip->i_generation;
384 
385 	reiserfs_log(LOG_DEBUG, "return it\n");
386 	return (0);
387 }
388