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