diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_iops.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 127 |
1 files changed, 86 insertions, 41 deletions
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 14215a7db59f..4bd3d03b23ed 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -51,8 +51,47 @@ | |||
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 | #define IS_NOATIME(inode) ((inode->i_sb->s_flags & MS_NOATIME) || \ | ||
60 | (S_ISDIR(inode->i_mode) && inode->i_sb->s_flags & MS_NODIRATIME)) | ||
61 | |||
62 | /* | ||
63 | * Get a XFS inode from a given vnode. | ||
64 | */ | ||
65 | xfs_inode_t * | ||
66 | xfs_vtoi( | ||
67 | struct vnode *vp) | ||
68 | { | ||
69 | bhv_desc_t *bdp; | ||
70 | |||
71 | bdp = bhv_lookup_range(VN_BHV_HEAD(vp), | ||
72 | VNODE_POSITION_XFS, VNODE_POSITION_XFS); | ||
73 | if (unlikely(bdp == NULL)) | ||
74 | return NULL; | ||
75 | return XFS_BHVTOI(bdp); | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * Bring the atime in the XFS inode uptodate. | ||
80 | * Used before logging the inode to disk or when the Linux inode goes away. | ||
81 | */ | ||
82 | void | ||
83 | xfs_synchronize_atime( | ||
84 | xfs_inode_t *ip) | ||
85 | { | ||
86 | vnode_t *vp; | ||
87 | |||
88 | vp = XFS_ITOV_NULL(ip); | ||
89 | if (vp) { | ||
90 | struct inode *inode = &vp->v_inode; | ||
91 | ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; | ||
92 | ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec; | ||
93 | } | ||
94 | } | ||
56 | 95 | ||
57 | /* | 96 | /* |
58 | * Change the requested timestamp in the given inode. | 97 | * Change the requested timestamp in the given inode. |
@@ -73,23 +112,6 @@ xfs_ichgtime( | |||
73 | struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip)); | 112 | struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip)); |
74 | timespec_t tv; | 113 | timespec_t tv; |
75 | 114 | ||
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); | 115 | nanotime(&tv); |
94 | if (flags & XFS_ICHGTIME_MOD) { | 116 | if (flags & XFS_ICHGTIME_MOD) { |
95 | inode->i_mtime = tv; | 117 | inode->i_mtime = tv; |
@@ -126,8 +148,6 @@ xfs_ichgtime( | |||
126 | * Variant on the above which avoids querying the system clock | 148 | * Variant on the above which avoids querying the system clock |
127 | * in situations where we know the Linux inode timestamps have | 149 | * in situations where we know the Linux inode timestamps have |
128 | * just been updated (and so we can update our inode cheaply). | 150 | * 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 | */ | 151 | */ |
132 | void | 152 | void |
133 | xfs_ichgtime_fast( | 153 | xfs_ichgtime_fast( |
@@ -138,20 +158,16 @@ xfs_ichgtime_fast( | |||
138 | timespec_t *tvp; | 158 | timespec_t *tvp; |
139 | 159 | ||
140 | /* | 160 | /* |
141 | * We're not supposed to change timestamps in readonly-mounted | 161 | * Atime updates for read() & friends are handled lazily now, and |
142 | * filesystems. Throw it away if anyone asks us. | 162 | * explicit updates must go through xfs_ichgtime() |
143 | */ | 163 | */ |
144 | if (unlikely(IS_RDONLY(inode))) | 164 | ASSERT((flags & XFS_ICHGTIME_ACC) == 0); |
145 | return; | ||
146 | 165 | ||
147 | /* | 166 | /* |
148 | * Don't update access timestamps on reads if mounted "noatime". | 167 | * We're not supposed to change timestamps in readonly-mounted |
149 | * Throw it away if anyone asks us. | 168 | * filesystems. Throw it away if anyone asks us. |
150 | */ | 169 | */ |
151 | if (unlikely( | 170 | 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; | 171 | return; |
156 | 172 | ||
157 | if (flags & XFS_ICHGTIME_MOD) { | 173 | if (flags & XFS_ICHGTIME_MOD) { |
@@ -159,11 +175,6 @@ xfs_ichgtime_fast( | |||
159 | ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec; | 175 | 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; | 176 | ip->i_d.di_mtime.t_nsec = (__int32_t)tvp->tv_nsec; |
161 | } | 177 | } |
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) { | 178 | if (flags & XFS_ICHGTIME_CHG) { |
168 | tvp = &inode->i_ctime; | 179 | tvp = &inode->i_ctime; |
169 | ip->i_d.di_ctime.t_sec = (__int32_t)tvp->tv_sec; | 180 | ip->i_d.di_ctime.t_sec = (__int32_t)tvp->tv_sec; |
@@ -203,13 +214,46 @@ validate_fields( | |||
203 | ip->i_nlink = va.va_nlink; | 214 | ip->i_nlink = va.va_nlink; |
204 | ip->i_blocks = va.va_nblocks; | 215 | ip->i_blocks = va.va_nblocks; |
205 | 216 | ||
206 | /* we're under i_sem so i_size can't change under us */ | 217 | /* we're under i_mutex so i_size can't change under us */ |
207 | if (i_size_read(ip) != va.va_size) | 218 | if (i_size_read(ip) != va.va_size) |
208 | i_size_write(ip, va.va_size); | 219 | i_size_write(ip, va.va_size); |
209 | } | 220 | } |
210 | } | 221 | } |
211 | 222 | ||
212 | /* | 223 | /* |
224 | * Hook in SELinux. This is not quite correct yet, what we really need | ||
225 | * here (as we do for default ACLs) is a mechanism by which creation of | ||
226 | * these attrs can be journalled at inode creation time (along with the | ||
227 | * inode, of course, such that log replay can't cause these to be lost). | ||
228 | */ | ||
229 | STATIC int | ||
230 | linvfs_init_security( | ||
231 | struct vnode *vp, | ||
232 | struct inode *dir) | ||
233 | { | ||
234 | struct inode *ip = LINVFS_GET_IP(vp); | ||
235 | size_t length; | ||
236 | void *value; | ||
237 | char *name; | ||
238 | int error; | ||
239 | |||
240 | error = security_inode_init_security(ip, dir, &name, &value, &length); | ||
241 | if (error) { | ||
242 | if (error == -EOPNOTSUPP) | ||
243 | return 0; | ||
244 | return -error; | ||
245 | } | ||
246 | |||
247 | VOP_ATTR_SET(vp, name, value, length, ATTR_SECURE, NULL, error); | ||
248 | if (!error) | ||
249 | VMODIFY(vp); | ||
250 | |||
251 | kfree(name); | ||
252 | kfree(value); | ||
253 | return error; | ||
254 | } | ||
255 | |||
256 | /* | ||
213 | * Determine whether a process has a valid fs_struct (kernel daemons | 257 | * Determine whether a process has a valid fs_struct (kernel daemons |
214 | * like knfsd don't have an fs_struct). | 258 | * like knfsd don't have an fs_struct). |
215 | * | 259 | * |
@@ -274,6 +318,9 @@ linvfs_mknod( | |||
274 | break; | 318 | break; |
275 | } | 319 | } |
276 | 320 | ||
321 | if (!error) | ||
322 | error = linvfs_init_security(vp, dir); | ||
323 | |||
277 | if (default_acl) { | 324 | if (default_acl) { |
278 | if (!error) { | 325 | if (!error) { |
279 | error = _ACL_INHERIT(vp, &va, default_acl); | 326 | error = _ACL_INHERIT(vp, &va, default_acl); |
@@ -290,8 +337,6 @@ linvfs_mknod( | |||
290 | teardown.d_inode = ip = LINVFS_GET_IP(vp); | 337 | teardown.d_inode = ip = LINVFS_GET_IP(vp); |
291 | teardown.d_name = dentry->d_name; | 338 | teardown.d_name = dentry->d_name; |
292 | 339 | ||
293 | vn_mark_bad(vp); | ||
294 | |||
295 | if (S_ISDIR(mode)) | 340 | if (S_ISDIR(mode)) |
296 | VOP_RMDIR(dvp, &teardown, NULL, err2); | 341 | VOP_RMDIR(dvp, &teardown, NULL, err2); |
297 | else | 342 | else |
@@ -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 | ||