]> err.no Git - linux-2.6/blob - fs/xfs/linux-2.6/xfs_iops.c
[XFS] fix, speedup and simplify atime handling let the VFS handle atime
[linux-2.6] / fs / xfs / linux-2.6 / xfs_iops.c
1 /*
2  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include "xfs.h"
19 #include "xfs_fs.h"
20 #include "xfs_bit.h"
21 #include "xfs_log.h"
22 #include "xfs_inum.h"
23 #include "xfs_trans.h"
24 #include "xfs_sb.h"
25 #include "xfs_ag.h"
26 #include "xfs_dir.h"
27 #include "xfs_dir2.h"
28 #include "xfs_alloc.h"
29 #include "xfs_dmapi.h"
30 #include "xfs_quota.h"
31 #include "xfs_mount.h"
32 #include "xfs_bmap_btree.h"
33 #include "xfs_alloc_btree.h"
34 #include "xfs_ialloc_btree.h"
35 #include "xfs_dir_sf.h"
36 #include "xfs_dir2_sf.h"
37 #include "xfs_attr_sf.h"
38 #include "xfs_dinode.h"
39 #include "xfs_inode.h"
40 #include "xfs_bmap.h"
41 #include "xfs_btree.h"
42 #include "xfs_ialloc.h"
43 #include "xfs_rtalloc.h"
44 #include "xfs_error.h"
45 #include "xfs_itable.h"
46 #include "xfs_rw.h"
47 #include "xfs_acl.h"
48 #include "xfs_cap.h"
49 #include "xfs_mac.h"
50 #include "xfs_attr.h"
51 #include "xfs_buf_item.h"
52 #include "xfs_utils.h"
53
54 #include <linux/xattr.h>
55 #include <linux/namei.h>
56
57 #define IS_NOATIME(inode) ((inode->i_sb->s_flags & MS_NOATIME) ||       \
58         (S_ISDIR(inode->i_mode) && inode->i_sb->s_flags & MS_NODIRATIME))
59
60 /*
61  * Bring the atime in the XFS inode uptodate.
62  * Used before logging the inode to disk or when the Linux inode goes away.
63  */
64 void
65 xfs_synchronize_atime(
66         xfs_inode_t     *ip)
67 {
68         vnode_t         *vp;
69
70         vp = XFS_ITOV_NULL(ip);
71         if (vp) {
72                 struct inode *inode = &vp->v_inode;
73                 ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
74                 ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
75         }
76 }
77
78 /*
79  * Change the requested timestamp in the given inode.
80  * We don't lock across timestamp updates, and we don't log them but
81  * we do record the fact that there is dirty information in core.
82  *
83  * NOTE -- callers MUST combine XFS_ICHGTIME_MOD or XFS_ICHGTIME_CHG
84  *              with XFS_ICHGTIME_ACC to be sure that access time
85  *              update will take.  Calling first with XFS_ICHGTIME_ACC
86  *              and then XFS_ICHGTIME_MOD may fail to modify the access
87  *              timestamp if the filesystem is mounted noacctm.
88  */
89 void
90 xfs_ichgtime(
91         xfs_inode_t     *ip,
92         int             flags)
93 {
94         struct inode    *inode = LINVFS_GET_IP(XFS_ITOV(ip));
95         timespec_t      tv;
96
97         nanotime(&tv);
98         if (flags & XFS_ICHGTIME_MOD) {
99                 inode->i_mtime = tv;
100                 ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec;
101                 ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec;
102         }
103         if (flags & XFS_ICHGTIME_ACC) {
104                 inode->i_atime = tv;
105                 ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec;
106                 ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec;
107         }
108         if (flags & XFS_ICHGTIME_CHG) {
109                 inode->i_ctime = tv;
110                 ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec;
111                 ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec;
112         }
113
114         /*
115          * We update the i_update_core field _after_ changing
116          * the timestamps in order to coordinate properly with
117          * xfs_iflush() so that we don't lose timestamp updates.
118          * This keeps us from having to hold the inode lock
119          * while doing this.  We use the SYNCHRONIZE macro to
120          * ensure that the compiler does not reorder the update
121          * of i_update_core above the timestamp updates above.
122          */
123         SYNCHRONIZE();
124         ip->i_update_core = 1;
125         if (!(inode->i_state & I_LOCK))
126                 mark_inode_dirty_sync(inode);
127 }
128
129 /*
130  * Variant on the above which avoids querying the system clock
131  * in situations where we know the Linux inode timestamps have
132  * just been updated (and so we can update our inode cheaply).
133  */
134 void
135 xfs_ichgtime_fast(
136         xfs_inode_t     *ip,
137         struct inode    *inode,
138         int             flags)
139 {
140         timespec_t      *tvp;
141
142         /*
143          * Atime updates for read() & friends are handled lazily now, and
144          * explicit updates must go through xfs_ichgtime()
145          */
146         ASSERT((flags & XFS_ICHGTIME_ACC) == 0);
147
148         /*
149          * We're not supposed to change timestamps in readonly-mounted
150          * filesystems.  Throw it away if anyone asks us.
151          */
152         if (unlikely(IS_RDONLY(inode)))
153                 return;
154
155         if (flags & XFS_ICHGTIME_MOD) {
156                 tvp = &inode->i_mtime;
157                 ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec;
158                 ip->i_d.di_mtime.t_nsec = (__int32_t)tvp->tv_nsec;
159         }
160         if (flags & XFS_ICHGTIME_CHG) {
161                 tvp = &inode->i_ctime;
162                 ip->i_d.di_ctime.t_sec = (__int32_t)tvp->tv_sec;
163                 ip->i_d.di_ctime.t_nsec = (__int32_t)tvp->tv_nsec;
164         }
165
166         /*
167          * We update the i_update_core field _after_ changing
168          * the timestamps in order to coordinate properly with
169          * xfs_iflush() so that we don't lose timestamp updates.
170          * This keeps us from having to hold the inode lock
171          * while doing this.  We use the SYNCHRONIZE macro to
172          * ensure that the compiler does not reorder the update
173          * of i_update_core above the timestamp updates above.
174          */
175         SYNCHRONIZE();
176         ip->i_update_core = 1;
177         if (!(inode->i_state & I_LOCK))
178                 mark_inode_dirty_sync(inode);
179 }
180
181
182 /*
183  * Pull the link count and size up from the xfs inode to the linux inode
184  */
185 STATIC void
186 validate_fields(
187         struct inode    *ip)
188 {
189         vnode_t         *vp = LINVFS_GET_VP(ip);
190         vattr_t         va;
191         int             error;
192
193         va.va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS;
194         VOP_GETATTR(vp, &va, ATTR_LAZY, NULL, error);
195         if (likely(!error)) {
196                 ip->i_nlink = va.va_nlink;
197                 ip->i_blocks = va.va_nblocks;
198
199                 /* we're under i_mutex so i_size can't change under us */
200                 if (i_size_read(ip) != va.va_size)
201                         i_size_write(ip, va.va_size);
202         }
203 }
204
205 /*
206  * Determine whether a process has a valid fs_struct (kernel daemons
207  * like knfsd don't have an fs_struct).
208  *
209  * XXX(hch):  nfsd is broken, better fix it instead.
210  */
211 STATIC inline int
212 has_fs_struct(struct task_struct *task)
213 {
214         return (task->fs != init_task.fs);
215 }
216
217 STATIC int
218 linvfs_mknod(
219         struct inode    *dir,
220         struct dentry   *dentry,
221         int             mode,
222         dev_t           rdev)
223 {
224         struct inode    *ip;
225         vattr_t         va;
226         vnode_t         *vp = NULL, *dvp = LINVFS_GET_VP(dir);
227         xfs_acl_t       *default_acl = NULL;
228         attrexists_t    test_default_acl = _ACL_DEFAULT_EXISTS;
229         int             error;
230
231         /*
232          * Irix uses Missed'em'V split, but doesn't want to see
233          * the upper 5 bits of (14bit) major.
234          */
235         if (!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff)
236                 return -EINVAL;
237
238         if (test_default_acl && test_default_acl(dvp)) {
239                 if (!_ACL_ALLOC(default_acl))
240                         return -ENOMEM;
241                 if (!_ACL_GET_DEFAULT(dvp, default_acl)) {
242                         _ACL_FREE(default_acl);
243                         default_acl = NULL;
244                 }
245         }
246
247         if (IS_POSIXACL(dir) && !default_acl && has_fs_struct(current))
248                 mode &= ~current->fs->umask;
249
250         memset(&va, 0, sizeof(va));
251         va.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
252         va.va_mode = mode;
253
254         switch (mode & S_IFMT) {
255         case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
256                 va.va_rdev = sysv_encode_dev(rdev);
257                 va.va_mask |= XFS_AT_RDEV;
258                 /*FALLTHROUGH*/
259         case S_IFREG:
260                 VOP_CREATE(dvp, dentry, &va, &vp, NULL, error);
261                 break;
262         case S_IFDIR:
263                 VOP_MKDIR(dvp, dentry, &va, &vp, NULL, error);
264                 break;
265         default:
266                 error = EINVAL;
267                 break;
268         }
269
270         if (default_acl) {
271                 if (!error) {
272                         error = _ACL_INHERIT(vp, &va, default_acl);
273                         if (!error) {
274                                 VMODIFY(vp);
275                         } else {
276                                 struct dentry   teardown = {};
277                                 int             err2;
278
279                                 /* Oh, the horror.
280                                  * If we can't add the ACL we must back out.
281                                  * ENOSPC can hit here, among other things.
282                                  */
283                                 teardown.d_inode = ip = LINVFS_GET_IP(vp);
284                                 teardown.d_name = dentry->d_name;
285
286                                 vn_mark_bad(vp);
287                                 
288                                 if (S_ISDIR(mode))
289                                         VOP_RMDIR(dvp, &teardown, NULL, err2);
290                                 else
291                                         VOP_REMOVE(dvp, &teardown, NULL, err2);
292                                 VN_RELE(vp);
293                         }
294                 }
295                 _ACL_FREE(default_acl);
296         }
297
298         if (!error) {
299                 ASSERT(vp);
300                 ip = LINVFS_GET_IP(vp);
301
302                 if (S_ISCHR(mode) || S_ISBLK(mode))
303                         ip->i_rdev = rdev;
304                 else if (S_ISDIR(mode))
305                         validate_fields(ip);
306                 d_instantiate(dentry, ip);
307                 validate_fields(dir);
308         }
309         return -error;
310 }
311
312 STATIC int
313 linvfs_create(
314         struct inode    *dir,
315         struct dentry   *dentry,
316         int             mode,
317         struct nameidata *nd)
318 {
319         return linvfs_mknod(dir, dentry, mode, 0);
320 }
321
322 STATIC int
323 linvfs_mkdir(
324         struct inode    *dir,
325         struct dentry   *dentry,
326         int             mode)
327 {
328         return linvfs_mknod(dir, dentry, mode|S_IFDIR, 0);
329 }
330
331 STATIC struct dentry *
332 linvfs_lookup(
333         struct inode    *dir,
334         struct dentry   *dentry,
335         struct nameidata *nd)
336 {
337         struct vnode    *vp = LINVFS_GET_VP(dir), *cvp;
338         int             error;
339
340         if (dentry->d_name.len >= MAXNAMELEN)
341                 return ERR_PTR(-ENAMETOOLONG);
342
343         VOP_LOOKUP(vp, dentry, &cvp, 0, NULL, NULL, error);
344         if (error) {
345                 if (unlikely(error != ENOENT))
346                         return ERR_PTR(-error);
347                 d_add(dentry, NULL);
348                 return NULL;
349         }
350
351         return d_splice_alias(LINVFS_GET_IP(cvp), dentry);
352 }
353
354 STATIC int
355 linvfs_link(
356         struct dentry   *old_dentry,
357         struct inode    *dir,
358         struct dentry   *dentry)
359 {
360         struct inode    *ip;    /* inode of guy being linked to */
361         vnode_t         *tdvp;  /* target directory for new name/link */
362         vnode_t         *vp;    /* vp of name being linked */
363         int             error;
364
365         ip = old_dentry->d_inode;       /* inode being linked to */
366         if (S_ISDIR(ip->i_mode))
367                 return -EPERM;
368
369         tdvp = LINVFS_GET_VP(dir);
370         vp = LINVFS_GET_VP(ip);
371
372         VOP_LINK(tdvp, vp, dentry, NULL, error);
373         if (!error) {
374                 VMODIFY(tdvp);
375                 VN_HOLD(vp);
376                 validate_fields(ip);
377                 d_instantiate(dentry, ip);
378         }
379         return -error;
380 }
381
382 STATIC int
383 linvfs_unlink(
384         struct inode    *dir,
385         struct dentry   *dentry)
386 {
387         struct inode    *inode;
388         vnode_t         *dvp;   /* directory containing name to remove */
389         int             error;
390
391         inode = dentry->d_inode;
392         dvp = LINVFS_GET_VP(dir);
393
394         VOP_REMOVE(dvp, dentry, NULL, error);
395         if (!error) {
396                 validate_fields(dir);   /* For size only */
397                 validate_fields(inode);
398         }
399
400         return -error;
401 }
402
403 STATIC int
404 linvfs_symlink(
405         struct inode    *dir,
406         struct dentry   *dentry,
407         const char      *symname)
408 {
409         struct inode    *ip;
410         vattr_t         va;
411         vnode_t         *dvp;   /* directory containing name of symlink */
412         vnode_t         *cvp;   /* used to lookup symlink to put in dentry */
413         int             error;
414
415         dvp = LINVFS_GET_VP(dir);
416         cvp = NULL;
417
418         memset(&va, 0, sizeof(va));
419         va.va_mode = S_IFLNK |
420                 (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO);
421         va.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
422
423         error = 0;
424         VOP_SYMLINK(dvp, dentry, &va, (char *)symname, &cvp, NULL, error);
425         if (!error && cvp) {
426                 ip = LINVFS_GET_IP(cvp);
427                 d_instantiate(dentry, ip);
428                 validate_fields(dir);
429                 validate_fields(ip); /* size needs update */
430         }
431         return -error;
432 }
433
434 STATIC int
435 linvfs_rmdir(
436         struct inode    *dir,
437         struct dentry   *dentry)
438 {
439         struct inode    *inode = dentry->d_inode;
440         vnode_t         *dvp = LINVFS_GET_VP(dir);
441         int             error;
442
443         VOP_RMDIR(dvp, dentry, NULL, error);
444         if (!error) {
445                 validate_fields(inode);
446                 validate_fields(dir);
447         }
448         return -error;
449 }
450
451 STATIC int
452 linvfs_rename(
453         struct inode    *odir,
454         struct dentry   *odentry,
455         struct inode    *ndir,
456         struct dentry   *ndentry)
457 {
458         struct inode    *new_inode = ndentry->d_inode;
459         vnode_t         *fvp;   /* from directory */
460         vnode_t         *tvp;   /* target directory */
461         int             error;
462
463         fvp = LINVFS_GET_VP(odir);
464         tvp = LINVFS_GET_VP(ndir);
465
466         VOP_RENAME(fvp, odentry, tvp, ndentry, NULL, error);
467         if (error)
468                 return -error;
469
470         if (new_inode)
471                 validate_fields(new_inode);
472
473         validate_fields(odir);
474         if (ndir != odir)
475                 validate_fields(ndir);
476         return 0;
477 }
478
479 /*
480  * careful here - this function can get called recursively, so
481  * we need to be very careful about how much stack we use.
482  * uio is kmalloced for this reason...
483  */
484 STATIC void *
485 linvfs_follow_link(
486         struct dentry           *dentry,
487         struct nameidata        *nd)
488 {
489         vnode_t                 *vp;
490         uio_t                   *uio;
491         iovec_t                 iov;
492         int                     error;
493         char                    *link;
494
495         ASSERT(dentry);
496         ASSERT(nd);
497
498         link = (char *)kmalloc(MAXNAMELEN+1, GFP_KERNEL);
499         if (!link) {
500                 nd_set_link(nd, ERR_PTR(-ENOMEM));
501                 return NULL;
502         }
503
504         uio = (uio_t *)kmalloc(sizeof(uio_t), GFP_KERNEL);
505         if (!uio) {
506                 kfree(link);
507                 nd_set_link(nd, ERR_PTR(-ENOMEM));
508                 return NULL;
509         }
510
511         vp = LINVFS_GET_VP(dentry->d_inode);
512
513         iov.iov_base = link;
514         iov.iov_len = MAXNAMELEN;
515
516         uio->uio_iov = &iov;
517         uio->uio_offset = 0;
518         uio->uio_segflg = UIO_SYSSPACE;
519         uio->uio_resid = MAXNAMELEN;
520         uio->uio_iovcnt = 1;
521
522         VOP_READLINK(vp, uio, 0, NULL, error);
523         if (error) {
524                 kfree(link);
525                 link = ERR_PTR(-error);
526         } else {
527                 link[MAXNAMELEN - uio->uio_resid] = '\0';
528         }
529         kfree(uio);
530
531         nd_set_link(nd, link);
532         return NULL;
533 }
534
535 STATIC void
536 linvfs_put_link(
537         struct dentry   *dentry,
538         struct nameidata *nd,
539         void            *p)
540 {
541         char            *s = nd_get_link(nd);
542
543         if (!IS_ERR(s))
544                 kfree(s);
545 }
546
547 #ifdef CONFIG_XFS_POSIX_ACL
548 STATIC int
549 linvfs_permission(
550         struct inode    *inode,
551         int             mode,
552         struct nameidata *nd)
553 {
554         vnode_t         *vp = LINVFS_GET_VP(inode);
555         int             error;
556
557         mode <<= 6;             /* convert from linux to vnode access bits */
558         VOP_ACCESS(vp, mode, NULL, error);
559         return -error;
560 }
561 #else
562 #define linvfs_permission NULL
563 #endif
564
565 STATIC int
566 linvfs_getattr(
567         struct vfsmount *mnt,
568         struct dentry   *dentry,
569         struct kstat    *stat)
570 {
571         struct inode    *inode = dentry->d_inode;
572         vnode_t         *vp = LINVFS_GET_VP(inode);
573         int             error = 0;
574
575         if (unlikely(vp->v_flag & VMODIFIED))
576                 error = vn_revalidate(vp);
577         if (!error)
578                 generic_fillattr(inode, stat);
579         return 0;
580 }
581
582 STATIC int
583 linvfs_setattr(
584         struct dentry   *dentry,
585         struct iattr    *attr)
586 {
587         struct inode    *inode = dentry->d_inode;
588         unsigned int    ia_valid = attr->ia_valid;
589         vnode_t         *vp = LINVFS_GET_VP(inode);
590         vattr_t         vattr;
591         int             flags = 0;
592         int             error;
593
594         memset(&vattr, 0, sizeof(vattr_t));
595         if (ia_valid & ATTR_UID) {
596                 vattr.va_mask |= XFS_AT_UID;
597                 vattr.va_uid = attr->ia_uid;
598         }
599         if (ia_valid & ATTR_GID) {
600                 vattr.va_mask |= XFS_AT_GID;
601                 vattr.va_gid = attr->ia_gid;
602         }
603         if (ia_valid & ATTR_SIZE) {
604                 vattr.va_mask |= XFS_AT_SIZE;
605                 vattr.va_size = attr->ia_size;
606         }
607         if (ia_valid & ATTR_ATIME) {
608                 vattr.va_mask |= XFS_AT_ATIME;
609                 vattr.va_atime = attr->ia_atime;
610         }
611         if (ia_valid & ATTR_MTIME) {
612                 vattr.va_mask |= XFS_AT_MTIME;
613                 vattr.va_mtime = attr->ia_mtime;
614         }
615         if (ia_valid & ATTR_CTIME) {
616                 vattr.va_mask |= XFS_AT_CTIME;
617                 vattr.va_ctime = attr->ia_ctime;
618         }
619         if (ia_valid & ATTR_MODE) {
620                 vattr.va_mask |= XFS_AT_MODE;
621                 vattr.va_mode = attr->ia_mode;
622                 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
623                         inode->i_mode &= ~S_ISGID;
624         }
625
626         if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET))
627                 flags |= ATTR_UTIME;
628 #ifdef ATTR_NO_BLOCK
629         if ((ia_valid & ATTR_NO_BLOCK))
630                 flags |= ATTR_NONBLOCK;
631 #endif
632
633         VOP_SETATTR(vp, &vattr, flags, NULL, error);
634         if (error)
635                 return -error;
636         vn_revalidate(vp);
637         return error;
638 }
639
640 STATIC void
641 linvfs_truncate(
642         struct inode    *inode)
643 {
644         block_truncate_page(inode->i_mapping, inode->i_size, linvfs_get_block);
645 }
646
647 STATIC int
648 linvfs_setxattr(
649         struct dentry   *dentry,
650         const char      *name,
651         const void      *data,
652         size_t          size,
653         int             flags)
654 {
655         vnode_t         *vp = LINVFS_GET_VP(dentry->d_inode);
656         char            *attr = (char *)name;
657         attrnames_t     *namesp;
658         int             xflags = 0;
659         int             error;
660
661         namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
662         if (!namesp)
663                 return -EOPNOTSUPP;
664         attr += namesp->attr_namelen;
665         error = namesp->attr_capable(vp, NULL);
666         if (error)
667                 return error;
668
669         /* Convert Linux syscall to XFS internal ATTR flags */
670         if (flags & XATTR_CREATE)
671                 xflags |= ATTR_CREATE;
672         if (flags & XATTR_REPLACE)
673                 xflags |= ATTR_REPLACE;
674         xflags |= namesp->attr_flag;
675         return namesp->attr_set(vp, attr, (void *)data, size, xflags);
676 }
677
678 STATIC ssize_t
679 linvfs_getxattr(
680         struct dentry   *dentry,
681         const char      *name,
682         void            *data,
683         size_t          size)
684 {
685         vnode_t         *vp = LINVFS_GET_VP(dentry->d_inode);
686         char            *attr = (char *)name;
687         attrnames_t     *namesp;
688         int             xflags = 0;
689         ssize_t         error;
690
691         namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
692         if (!namesp)
693                 return -EOPNOTSUPP;
694         attr += namesp->attr_namelen;
695         error = namesp->attr_capable(vp, NULL);
696         if (error)
697                 return error;
698
699         /* Convert Linux syscall to XFS internal ATTR flags */
700         if (!size) {
701                 xflags |= ATTR_KERNOVAL;
702                 data = NULL;
703         }
704         xflags |= namesp->attr_flag;
705         return namesp->attr_get(vp, attr, (void *)data, size, xflags);
706 }
707
708 STATIC ssize_t
709 linvfs_listxattr(
710         struct dentry           *dentry,
711         char                    *data,
712         size_t                  size)
713 {
714         vnode_t                 *vp = LINVFS_GET_VP(dentry->d_inode);
715         int                     error, xflags = ATTR_KERNAMELS;
716         ssize_t                 result;
717
718         if (!size)
719                 xflags |= ATTR_KERNOVAL;
720         xflags |= capable(CAP_SYS_ADMIN) ? ATTR_KERNFULLS : ATTR_KERNORMALS;
721
722         error = attr_generic_list(vp, data, size, xflags, &result);
723         if (error < 0)
724                 return error;
725         return result;
726 }
727
728 STATIC int
729 linvfs_removexattr(
730         struct dentry   *dentry,
731         const char      *name)
732 {
733         vnode_t         *vp = LINVFS_GET_VP(dentry->d_inode);
734         char            *attr = (char *)name;
735         attrnames_t     *namesp;
736         int             xflags = 0;
737         int             error;
738
739         namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
740         if (!namesp)
741                 return -EOPNOTSUPP;
742         attr += namesp->attr_namelen;
743         error = namesp->attr_capable(vp, NULL);
744         if (error)
745                 return error;
746         xflags |= namesp->attr_flag;
747         return namesp->attr_remove(vp, attr, xflags);
748 }
749
750
751 struct inode_operations linvfs_file_inode_operations = {
752         .permission             = linvfs_permission,
753         .truncate               = linvfs_truncate,
754         .getattr                = linvfs_getattr,
755         .setattr                = linvfs_setattr,
756         .setxattr               = linvfs_setxattr,
757         .getxattr               = linvfs_getxattr,
758         .listxattr              = linvfs_listxattr,
759         .removexattr            = linvfs_removexattr,
760 };
761
762 struct inode_operations linvfs_dir_inode_operations = {
763         .create                 = linvfs_create,
764         .lookup                 = linvfs_lookup,
765         .link                   = linvfs_link,
766         .unlink                 = linvfs_unlink,
767         .symlink                = linvfs_symlink,
768         .mkdir                  = linvfs_mkdir,
769         .rmdir                  = linvfs_rmdir,
770         .mknod                  = linvfs_mknod,
771         .rename                 = linvfs_rename,
772         .permission             = linvfs_permission,
773         .getattr                = linvfs_getattr,
774         .setattr                = linvfs_setattr,
775         .setxattr               = linvfs_setxattr,
776         .getxattr               = linvfs_getxattr,
777         .listxattr              = linvfs_listxattr,
778         .removexattr            = linvfs_removexattr,
779 };
780
781 struct inode_operations linvfs_symlink_inode_operations = {
782         .readlink               = generic_readlink,
783         .follow_link            = linvfs_follow_link,
784         .put_link               = linvfs_put_link,
785         .permission             = linvfs_permission,
786         .getattr                = linvfs_getattr,
787         .setattr                = linvfs_setattr,
788         .setxattr               = linvfs_setxattr,
789         .getxattr               = linvfs_getxattr,
790         .listxattr              = linvfs_listxattr,
791         .removexattr            = linvfs_removexattr,
792 };