diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_iops.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 121 |
1 files changed, 81 insertions, 40 deletions
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 9b8ee3470ecc..4bd3d03b23ed 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -54,11 +54,46 @@ | |||
54 | #include <linux/capability.h> | 54 | #include <linux/capability.h> |
55 | #include <linux/xattr.h> | 55 | #include <linux/xattr.h> |
56 | #include <linux/namei.h> | 56 | #include <linux/namei.h> |
57 | #include <linux/security.h> | ||
57 | 58 | ||
58 | #define IS_NOATIME(inode) ((inode->i_sb->s_flags & MS_NOATIME) || \ | 59 | #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 | (S_ISDIR(inode->i_mode) && inode->i_sb->s_flags & MS_NODIRATIME)) |
60 | 61 | ||
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 | } | ||
95 | |||
96 | /* | ||
62 | * Change the requested timestamp in the given inode. | 97 | * Change the requested timestamp in the given inode. |
63 | * We don't lock across timestamp updates, and we don't log them but | 98 | * 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. | 99 | * we do record the fact that there is dirty information in core. |
@@ -77,23 +112,6 @@ xfs_ichgtime( | |||
77 | struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip)); | 112 | struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip)); |
78 | timespec_t tv; | 113 | timespec_t tv; |
79 | 114 | ||
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); | 115 | nanotime(&tv); |
98 | if (flags & XFS_ICHGTIME_MOD) { | 116 | if (flags & XFS_ICHGTIME_MOD) { |
99 | inode->i_mtime = tv; | 117 | inode->i_mtime = tv; |
@@ -130,8 +148,6 @@ xfs_ichgtime( | |||
130 | * Variant on the above which avoids querying the system clock | 148 | * Variant on the above which avoids querying the system clock |
131 | * in situations where we know the Linux inode timestamps have | 149 | * in situations where we know the Linux inode timestamps have |
132 | * just been updated (and so we can update our inode cheaply). | 150 | * 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 | */ | 151 | */ |
136 | void | 152 | void |
137 | xfs_ichgtime_fast( | 153 | xfs_ichgtime_fast( |
@@ -142,20 +158,16 @@ xfs_ichgtime_fast( | |||
142 | timespec_t *tvp; | 158 | timespec_t *tvp; |
143 | 159 | ||
144 | /* | 160 | /* |
145 | * We're not supposed to change timestamps in readonly-mounted | 161 | * Atime updates for read() & friends are handled lazily now, and |
146 | * filesystems. Throw it away if anyone asks us. | 162 | * explicit updates must go through xfs_ichgtime() |
147 | */ | 163 | */ |
148 | if (unlikely(IS_RDONLY(inode))) | 164 | ASSERT((flags & XFS_ICHGTIME_ACC) == 0); |
149 | return; | ||
150 | 165 | ||
151 | /* | 166 | /* |
152 | * Don't update access timestamps on reads if mounted "noatime". | 167 | * We're not supposed to change timestamps in readonly-mounted |
153 | * Throw it away if anyone asks us. | 168 | * filesystems. Throw it away if anyone asks us. |
154 | */ | 169 | */ |
155 | if (unlikely( | 170 | if (unlikely(IS_RDONLY(inode))) |
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; | 171 | return; |
160 | 172 | ||
161 | if (flags & XFS_ICHGTIME_MOD) { | 173 | if (flags & XFS_ICHGTIME_MOD) { |
@@ -163,11 +175,6 @@ xfs_ichgtime_fast( | |||
163 | 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; |
164 | 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; |
165 | } | 177 | } |
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) { | 178 | if (flags & XFS_ICHGTIME_CHG) { |
172 | tvp = &inode->i_ctime; | 179 | tvp = &inode->i_ctime; |
173 | 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; |
@@ -214,6 +221,39 @@ validate_fields( | |||
214 | } | 221 | } |
215 | 222 | ||
216 | /* | 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 | /* | ||
217 | * Determine whether a process has a valid fs_struct (kernel daemons | 257 | * Determine whether a process has a valid fs_struct (kernel daemons |
218 | * like knfsd don't have an fs_struct). | 258 | * like knfsd don't have an fs_struct). |
219 | * | 259 | * |
@@ -278,6 +318,9 @@ linvfs_mknod( | |||
278 | break; | 318 | break; |
279 | } | 319 | } |
280 | 320 | ||
321 | if (!error) | ||
322 | error = linvfs_init_security(vp, dir); | ||
323 | |||
281 | if (default_acl) { | 324 | if (default_acl) { |
282 | if (!error) { | 325 | if (!error) { |
283 | error = _ACL_INHERIT(vp, &va, default_acl); | 326 | error = _ACL_INHERIT(vp, &va, default_acl); |
@@ -294,8 +337,6 @@ linvfs_mknod( | |||
294 | teardown.d_inode = ip = LINVFS_GET_IP(vp); | 337 | teardown.d_inode = ip = LINVFS_GET_IP(vp); |
295 | teardown.d_name = dentry->d_name; | 338 | teardown.d_name = dentry->d_name; |
296 | 339 | ||
297 | vn_mark_bad(vp); | ||
298 | |||
299 | if (S_ISDIR(mode)) | 340 | if (S_ISDIR(mode)) |
300 | VOP_RMDIR(dvp, &teardown, NULL, err2); | 341 | VOP_RMDIR(dvp, &teardown, NULL, err2); |
301 | else | 342 | else |
@@ -506,7 +547,7 @@ linvfs_follow_link( | |||
506 | ASSERT(dentry); | 547 | ASSERT(dentry); |
507 | ASSERT(nd); | 548 | ASSERT(nd); |
508 | 549 | ||
509 | link = (char *)kmalloc(MAXNAMELEN+1, GFP_KERNEL); | 550 | link = (char *)kmalloc(MAXPATHLEN+1, GFP_KERNEL); |
510 | if (!link) { | 551 | if (!link) { |
511 | nd_set_link(nd, ERR_PTR(-ENOMEM)); | 552 | nd_set_link(nd, ERR_PTR(-ENOMEM)); |
512 | return NULL; | 553 | return NULL; |
@@ -522,12 +563,12 @@ linvfs_follow_link( | |||
522 | vp = LINVFS_GET_VP(dentry->d_inode); | 563 | vp = LINVFS_GET_VP(dentry->d_inode); |
523 | 564 | ||
524 | iov.iov_base = link; | 565 | iov.iov_base = link; |
525 | iov.iov_len = MAXNAMELEN; | 566 | iov.iov_len = MAXPATHLEN; |
526 | 567 | ||
527 | uio->uio_iov = &iov; | 568 | uio->uio_iov = &iov; |
528 | uio->uio_offset = 0; | 569 | uio->uio_offset = 0; |
529 | uio->uio_segflg = UIO_SYSSPACE; | 570 | uio->uio_segflg = UIO_SYSSPACE; |
530 | uio->uio_resid = MAXNAMELEN; | 571 | uio->uio_resid = MAXPATHLEN; |
531 | uio->uio_iovcnt = 1; | 572 | uio->uio_iovcnt = 1; |
532 | 573 | ||
533 | VOP_READLINK(vp, uio, 0, NULL, error); | 574 | VOP_READLINK(vp, uio, 0, NULL, error); |
@@ -535,7 +576,7 @@ linvfs_follow_link( | |||
535 | kfree(link); | 576 | kfree(link); |
536 | link = ERR_PTR(-error); | 577 | link = ERR_PTR(-error); |
537 | } else { | 578 | } else { |
538 | link[MAXNAMELEN - uio->uio_resid] = '\0'; | 579 | link[MAXPATHLEN - uio->uio_resid] = '\0'; |
539 | } | 580 | } |
540 | kfree(uio); | 581 | kfree(uio); |
541 | 582 | ||