aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_iops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_iops.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c137
1 files changed, 91 insertions, 46 deletions
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 14215a7db59f..76c6df34d0db 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -51,8 +51,44 @@
51#include "xfs_buf_item.h" 51#include "xfs_buf_item.h"
52#include "xfs_utils.h" 52#include "xfs_utils.h"
53 53
54#include <linux/capability.h>
54#include <linux/xattr.h> 55#include <linux/xattr.h>
55#include <linux/namei.h> 56#include <linux/namei.h>
57#include <linux/security.h>
58
59/*
60 * Get a XFS inode from a given vnode.
61 */
62xfs_inode_t *
63xfs_vtoi(
64 struct vnode *vp)
65{
66 bhv_desc_t *bdp;
67
68 bdp = bhv_lookup_range(VN_BHV_HEAD(vp),
69 VNODE_POSITION_XFS, VNODE_POSITION_XFS);
70 if (unlikely(bdp == NULL))
71 return NULL;
72 return XFS_BHVTOI(bdp);
73}
74
75/*
76 * Bring the atime in the XFS inode uptodate.
77 * Used before logging the inode to disk or when the Linux inode goes away.
78 */
79void
80xfs_synchronize_atime(
81 xfs_inode_t *ip)
82{
83 vnode_t *vp;
84
85 vp = XFS_ITOV_NULL(ip);
86 if (vp) {
87 struct inode *inode = &vp->v_inode;
88 ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
89 ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
90 }
91}
56 92
57/* 93/*
58 * Change the requested timestamp in the given inode. 94 * Change the requested timestamp in the given inode.
@@ -73,23 +109,6 @@ xfs_ichgtime(
73 struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip)); 109 struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip));
74 timespec_t tv; 110 timespec_t tv;
75 111
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); 112 nanotime(&tv);
94 if (flags & XFS_ICHGTIME_MOD) { 113 if (flags & XFS_ICHGTIME_MOD) {
95 inode->i_mtime = tv; 114 inode->i_mtime = tv;
@@ -126,8 +145,6 @@ xfs_ichgtime(
126 * Variant on the above which avoids querying the system clock 145 * Variant on the above which avoids querying the system clock
127 * in situations where we know the Linux inode timestamps have 146 * in situations where we know the Linux inode timestamps have
128 * just been updated (and so we can update our inode cheaply). 147 * 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 */ 148 */
132void 149void
133xfs_ichgtime_fast( 150xfs_ichgtime_fast(
@@ -138,20 +155,16 @@ xfs_ichgtime_fast(
138 timespec_t *tvp; 155 timespec_t *tvp;
139 156
140 /* 157 /*
141 * We're not supposed to change timestamps in readonly-mounted 158 * Atime updates for read() & friends are handled lazily now, and
142 * filesystems. Throw it away if anyone asks us. 159 * explicit updates must go through xfs_ichgtime()
143 */ 160 */
144 if (unlikely(IS_RDONLY(inode))) 161 ASSERT((flags & XFS_ICHGTIME_ACC) == 0);
145 return;
146 162
147 /* 163 /*
148 * Don't update access timestamps on reads if mounted "noatime". 164 * We're not supposed to change timestamps in readonly-mounted
149 * Throw it away if anyone asks us. 165 * filesystems. Throw it away if anyone asks us.
150 */ 166 */
151 if (unlikely( 167 if (unlikely(IS_RDONLY(inode)))
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; 168 return;
156 169
157 if (flags & XFS_ICHGTIME_MOD) { 170 if (flags & XFS_ICHGTIME_MOD) {
@@ -159,11 +172,6 @@ xfs_ichgtime_fast(
159 ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec; 172 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; 173 ip->i_d.di_mtime.t_nsec = (__int32_t)tvp->tv_nsec;
161 } 174 }
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) { 175 if (flags & XFS_ICHGTIME_CHG) {
168 tvp = &inode->i_ctime; 176 tvp = &inode->i_ctime;
169 ip->i_d.di_ctime.t_sec = (__int32_t)tvp->tv_sec; 177 ip->i_d.di_ctime.t_sec = (__int32_t)tvp->tv_sec;
@@ -203,13 +211,46 @@ validate_fields(
203 ip->i_nlink = va.va_nlink; 211 ip->i_nlink = va.va_nlink;
204 ip->i_blocks = va.va_nblocks; 212 ip->i_blocks = va.va_nblocks;
205 213
206 /* we're under i_sem so i_size can't change under us */ 214 /* we're under i_mutex so i_size can't change under us */
207 if (i_size_read(ip) != va.va_size) 215 if (i_size_read(ip) != va.va_size)
208 i_size_write(ip, va.va_size); 216 i_size_write(ip, va.va_size);
209 } 217 }
210} 218}
211 219
212/* 220/*
221 * Hook in SELinux. This is not quite correct yet, what we really need
222 * here (as we do for default ACLs) is a mechanism by which creation of
223 * these attrs can be journalled at inode creation time (along with the
224 * inode, of course, such that log replay can't cause these to be lost).
225 */
226STATIC int
227linvfs_init_security(
228 struct vnode *vp,
229 struct inode *dir)
230{
231 struct inode *ip = LINVFS_GET_IP(vp);
232 size_t length;
233 void *value;
234 char *name;
235 int error;
236
237 error = security_inode_init_security(ip, dir, &name, &value, &length);
238 if (error) {
239 if (error == -EOPNOTSUPP)
240 return 0;
241 return -error;
242 }
243
244 VOP_ATTR_SET(vp, name, value, length, ATTR_SECURE, NULL, error);
245 if (!error)
246 VMODIFY(vp);
247
248 kfree(name);
249 kfree(value);
250 return error;
251}
252
253/*
213 * Determine whether a process has a valid fs_struct (kernel daemons 254 * Determine whether a process has a valid fs_struct (kernel daemons
214 * like knfsd don't have an fs_struct). 255 * like knfsd don't have an fs_struct).
215 * 256 *
@@ -274,6 +315,9 @@ linvfs_mknod(
274 break; 315 break;
275 } 316 }
276 317
318 if (!error)
319 error = linvfs_init_security(vp, dir);
320
277 if (default_acl) { 321 if (default_acl) {
278 if (!error) { 322 if (!error) {
279 error = _ACL_INHERIT(vp, &va, default_acl); 323 error = _ACL_INHERIT(vp, &va, default_acl);
@@ -290,8 +334,6 @@ linvfs_mknod(
290 teardown.d_inode = ip = LINVFS_GET_IP(vp); 334 teardown.d_inode = ip = LINVFS_GET_IP(vp);
291 teardown.d_name = dentry->d_name; 335 teardown.d_name = dentry->d_name;
292 336
293 vn_mark_bad(vp);
294
295 if (S_ISDIR(mode)) 337 if (S_ISDIR(mode))
296 VOP_RMDIR(dvp, &teardown, NULL, err2); 338 VOP_RMDIR(dvp, &teardown, NULL, err2);
297 else 339 else
@@ -429,11 +471,14 @@ linvfs_symlink(
429 471
430 error = 0; 472 error = 0;
431 VOP_SYMLINK(dvp, dentry, &va, (char *)symname, &cvp, NULL, error); 473 VOP_SYMLINK(dvp, dentry, &va, (char *)symname, &cvp, NULL, error);
432 if (!error && cvp) { 474 if (likely(!error && cvp)) {
433 ip = LINVFS_GET_IP(cvp); 475 error = linvfs_init_security(cvp, dir);
434 d_instantiate(dentry, ip); 476 if (likely(!error)) {
435 validate_fields(dir); 477 ip = LINVFS_GET_IP(cvp);
436 validate_fields(ip); /* size needs update */ 478 d_instantiate(dentry, ip);
479 validate_fields(dir);
480 validate_fields(ip);
481 }
437 } 482 }
438 return -error; 483 return -error;
439} 484}
@@ -502,7 +547,7 @@ linvfs_follow_link(
502 ASSERT(dentry); 547 ASSERT(dentry);
503 ASSERT(nd); 548 ASSERT(nd);
504 549
505 link = (char *)kmalloc(MAXNAMELEN+1, GFP_KERNEL); 550 link = (char *)kmalloc(MAXPATHLEN+1, GFP_KERNEL);
506 if (!link) { 551 if (!link) {
507 nd_set_link(nd, ERR_PTR(-ENOMEM)); 552 nd_set_link(nd, ERR_PTR(-ENOMEM));
508 return NULL; 553 return NULL;
@@ -518,12 +563,12 @@ linvfs_follow_link(
518 vp = LINVFS_GET_VP(dentry->d_inode); 563 vp = LINVFS_GET_VP(dentry->d_inode);
519 564
520 iov.iov_base = link; 565 iov.iov_base = link;
521 iov.iov_len = MAXNAMELEN; 566 iov.iov_len = MAXPATHLEN;
522 567
523 uio->uio_iov = &iov; 568 uio->uio_iov = &iov;
524 uio->uio_offset = 0; 569 uio->uio_offset = 0;
525 uio->uio_segflg = UIO_SYSSPACE; 570 uio->uio_segflg = UIO_SYSSPACE;
526 uio->uio_resid = MAXNAMELEN; 571 uio->uio_resid = MAXPATHLEN;
527 uio->uio_iovcnt = 1; 572 uio->uio_iovcnt = 1;
528 573
529 VOP_READLINK(vp, uio, 0, NULL, error); 574 VOP_READLINK(vp, uio, 0, NULL, error);
@@ -531,7 +576,7 @@ linvfs_follow_link(
531 kfree(link); 576 kfree(link);
532 link = ERR_PTR(-error); 577 link = ERR_PTR(-error);
533 } else { 578 } else {
534 link[MAXNAMELEN - uio->uio_resid] = '\0'; 579 link[MAXPATHLEN - uio->uio_resid] = '\0';
535 } 580 }
536 kfree(uio); 581 kfree(uio);
537 582