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
12static vop_access_t	reiserfs_access;
13static vop_bmap_t	reiserfs_bmap;
14static vop_getattr_t	reiserfs_getattr;
15static vop_open_t	reiserfs_open;
16static vop_pathconf_t	reiserfs_pathconf;
17static vop_readlink_t	reiserfs_readlink;
18static vop_strategy_t	reiserfs_strategy;
19static vop_vptofh_t	reiserfs_vptofh;
20
21/* Global vfs data structures for ReiserFS */
22struct 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
41struct 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
54static int
55reiserfs_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
94static int
95reiserfs_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 */
123static int
124reiserfs_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
151static int
152reiserfs_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 */
165static int
166reiserfs_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. */
176static int
177reiserfs_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. */
306static int
307reiserfs_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 */
365static int
366reiserfs_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