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