]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/gnu/fs/reiserfs/reiserfs_vnops.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / gnu / fs / reiserfs / reiserfs_vnops.c
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
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
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
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
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
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
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
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
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 }