diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_iops.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 137 |
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 | */ | ||
62 | xfs_inode_t * | ||
63 | xfs_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 | */ | ||
79 | void | ||
80 | xfs_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 | */ |
132 | void | 149 | void |
133 | xfs_ichgtime_fast( | 150 | xfs_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 | */ | ||
226 | STATIC int | ||
227 | linvfs_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 | ||