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