| .. | .. |
|---|
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
|---|
| 2 | 2 | /* |
|---|
| 3 | 3 | * (C) 2001 Clemson University and The University of Chicago |
|---|
| 4 | + * Copyright 2018 Omnibond Systems, L.L.C. |
|---|
| 4 | 5 | * |
|---|
| 5 | 6 | * See COPYING in top-level directory. |
|---|
| 6 | 7 | */ |
|---|
| .. | .. |
|---|
| 135 | 136 | * NOTE: in kernel land, we never use the sys_attr->link_target for |
|---|
| 136 | 137 | * anything, so don't bother copying it into the sys_attr object here. |
|---|
| 137 | 138 | */ |
|---|
| 138 | | -static inline int copy_attributes_from_inode(struct inode *inode, |
|---|
| 139 | | - struct ORANGEFS_sys_attr_s *attrs, |
|---|
| 140 | | - struct iattr *iattr) |
|---|
| 139 | +static inline void copy_attributes_from_inode(struct inode *inode, |
|---|
| 140 | + struct ORANGEFS_sys_attr_s *attrs) |
|---|
| 141 | 141 | { |
|---|
| 142 | | - umode_t tmp_mode; |
|---|
| 143 | | - |
|---|
| 144 | | - if (!iattr || !inode || !attrs) { |
|---|
| 145 | | - gossip_err("NULL iattr (%p), inode (%p), attrs (%p) " |
|---|
| 146 | | - "in copy_attributes_from_inode!\n", |
|---|
| 147 | | - iattr, |
|---|
| 148 | | - inode, |
|---|
| 149 | | - attrs); |
|---|
| 150 | | - return -EINVAL; |
|---|
| 151 | | - } |
|---|
| 152 | | - /* |
|---|
| 153 | | - * We need to be careful to only copy the attributes out of the |
|---|
| 154 | | - * iattr object that we know are valid. |
|---|
| 155 | | - */ |
|---|
| 142 | + struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); |
|---|
| 156 | 143 | attrs->mask = 0; |
|---|
| 157 | | - if (iattr->ia_valid & ATTR_UID) { |
|---|
| 158 | | - attrs->owner = from_kuid(&init_user_ns, iattr->ia_uid); |
|---|
| 144 | + if (orangefs_inode->attr_valid & ATTR_UID) { |
|---|
| 145 | + attrs->owner = from_kuid(&init_user_ns, inode->i_uid); |
|---|
| 159 | 146 | attrs->mask |= ORANGEFS_ATTR_SYS_UID; |
|---|
| 160 | 147 | gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner); |
|---|
| 161 | 148 | } |
|---|
| 162 | | - if (iattr->ia_valid & ATTR_GID) { |
|---|
| 163 | | - attrs->group = from_kgid(&init_user_ns, iattr->ia_gid); |
|---|
| 149 | + if (orangefs_inode->attr_valid & ATTR_GID) { |
|---|
| 150 | + attrs->group = from_kgid(&init_user_ns, inode->i_gid); |
|---|
| 164 | 151 | attrs->mask |= ORANGEFS_ATTR_SYS_GID; |
|---|
| 165 | 152 | gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group); |
|---|
| 166 | 153 | } |
|---|
| 167 | 154 | |
|---|
| 168 | | - if (iattr->ia_valid & ATTR_ATIME) { |
|---|
| 155 | + if (orangefs_inode->attr_valid & ATTR_ATIME) { |
|---|
| 169 | 156 | attrs->mask |= ORANGEFS_ATTR_SYS_ATIME; |
|---|
| 170 | | - if (iattr->ia_valid & ATTR_ATIME_SET) { |
|---|
| 171 | | - attrs->atime = (time64_t)iattr->ia_atime.tv_sec; |
|---|
| 157 | + if (orangefs_inode->attr_valid & ATTR_ATIME_SET) { |
|---|
| 158 | + attrs->atime = (time64_t)inode->i_atime.tv_sec; |
|---|
| 172 | 159 | attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET; |
|---|
| 173 | 160 | } |
|---|
| 174 | 161 | } |
|---|
| 175 | | - if (iattr->ia_valid & ATTR_MTIME) { |
|---|
| 162 | + if (orangefs_inode->attr_valid & ATTR_MTIME) { |
|---|
| 176 | 163 | attrs->mask |= ORANGEFS_ATTR_SYS_MTIME; |
|---|
| 177 | | - if (iattr->ia_valid & ATTR_MTIME_SET) { |
|---|
| 178 | | - attrs->mtime = (time64_t)iattr->ia_mtime.tv_sec; |
|---|
| 164 | + if (orangefs_inode->attr_valid & ATTR_MTIME_SET) { |
|---|
| 165 | + attrs->mtime = (time64_t)inode->i_mtime.tv_sec; |
|---|
| 179 | 166 | attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET; |
|---|
| 180 | 167 | } |
|---|
| 181 | 168 | } |
|---|
| 182 | | - if (iattr->ia_valid & ATTR_CTIME) |
|---|
| 169 | + if (orangefs_inode->attr_valid & ATTR_CTIME) |
|---|
| 183 | 170 | attrs->mask |= ORANGEFS_ATTR_SYS_CTIME; |
|---|
| 184 | 171 | |
|---|
| 185 | 172 | /* |
|---|
| .. | .. |
|---|
| 188 | 175 | * worry about ATTR_SIZE |
|---|
| 189 | 176 | */ |
|---|
| 190 | 177 | |
|---|
| 191 | | - if (iattr->ia_valid & ATTR_MODE) { |
|---|
| 192 | | - tmp_mode = iattr->ia_mode; |
|---|
| 193 | | - if (tmp_mode & (S_ISVTX)) { |
|---|
| 194 | | - if (is_root_handle(inode)) { |
|---|
| 195 | | - /* |
|---|
| 196 | | - * allow sticky bit to be set on root (since |
|---|
| 197 | | - * it shows up that way by default anyhow), |
|---|
| 198 | | - * but don't show it to the server |
|---|
| 199 | | - */ |
|---|
| 200 | | - tmp_mode -= S_ISVTX; |
|---|
| 201 | | - } else { |
|---|
| 202 | | - gossip_debug(GOSSIP_UTILS_DEBUG, |
|---|
| 203 | | - "%s: setting sticky bit not supported.\n", |
|---|
| 204 | | - __func__); |
|---|
| 205 | | - return -EINVAL; |
|---|
| 206 | | - } |
|---|
| 207 | | - } |
|---|
| 208 | | - |
|---|
| 209 | | - if (tmp_mode & (S_ISUID)) { |
|---|
| 210 | | - gossip_debug(GOSSIP_UTILS_DEBUG, |
|---|
| 211 | | - "%s: setting setuid bit not supported.\n", |
|---|
| 212 | | - __func__); |
|---|
| 213 | | - return -EINVAL; |
|---|
| 214 | | - } |
|---|
| 215 | | - |
|---|
| 216 | | - attrs->perms = ORANGEFS_util_translate_mode(tmp_mode); |
|---|
| 178 | + if (orangefs_inode->attr_valid & ATTR_MODE) { |
|---|
| 179 | + attrs->perms = ORANGEFS_util_translate_mode(inode->i_mode); |
|---|
| 217 | 180 | attrs->mask |= ORANGEFS_ATTR_SYS_PERM; |
|---|
| 218 | 181 | } |
|---|
| 219 | | - |
|---|
| 220 | | - return 0; |
|---|
| 221 | 182 | } |
|---|
| 222 | 183 | |
|---|
| 223 | 184 | static int orangefs_inode_type(enum orangefs_ds_type objtype) |
|---|
| .. | .. |
|---|
| 272 | 233 | return 0; |
|---|
| 273 | 234 | } |
|---|
| 274 | 235 | |
|---|
| 275 | | -int orangefs_inode_getattr(struct inode *inode, int new, int bypass, |
|---|
| 276 | | - u32 request_mask) |
|---|
| 236 | +int orangefs_inode_getattr(struct inode *inode, int flags) |
|---|
| 277 | 237 | { |
|---|
| 278 | 238 | struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); |
|---|
| 279 | 239 | struct orangefs_kernel_op_s *new_op; |
|---|
| 280 | 240 | loff_t inode_size; |
|---|
| 281 | 241 | int ret, type; |
|---|
| 282 | 242 | |
|---|
| 283 | | - gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__, |
|---|
| 284 | | - get_khandle_from_ino(inode)); |
|---|
| 243 | + gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU flags %d\n", |
|---|
| 244 | + __func__, get_khandle_from_ino(inode), flags); |
|---|
| 285 | 245 | |
|---|
| 286 | | - if (!new && !bypass) { |
|---|
| 287 | | - /* |
|---|
| 288 | | - * Must have all the attributes in the mask and be within cache |
|---|
| 289 | | - * time. |
|---|
| 290 | | - */ |
|---|
| 291 | | - if ((request_mask & orangefs_inode->getattr_mask) == |
|---|
| 292 | | - request_mask && |
|---|
| 293 | | - time_before(jiffies, orangefs_inode->getattr_time)) |
|---|
| 294 | | - return 0; |
|---|
| 246 | +again: |
|---|
| 247 | + spin_lock(&inode->i_lock); |
|---|
| 248 | + /* Must have all the attributes in the mask and be within cache time. */ |
|---|
| 249 | + if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) || |
|---|
| 250 | + orangefs_inode->attr_valid || inode->i_state & I_DIRTY_PAGES) { |
|---|
| 251 | + if (orangefs_inode->attr_valid) { |
|---|
| 252 | + spin_unlock(&inode->i_lock); |
|---|
| 253 | + write_inode_now(inode, 1); |
|---|
| 254 | + goto again; |
|---|
| 255 | + } |
|---|
| 256 | + spin_unlock(&inode->i_lock); |
|---|
| 257 | + return 0; |
|---|
| 295 | 258 | } |
|---|
| 259 | + spin_unlock(&inode->i_lock); |
|---|
| 296 | 260 | |
|---|
| 297 | 261 | new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR); |
|---|
| 298 | 262 | if (!new_op) |
|---|
| .. | .. |
|---|
| 302 | 266 | * Size is the hardest attribute to get. The incremental cost of any |
|---|
| 303 | 267 | * other attribute is essentially zero. |
|---|
| 304 | 268 | */ |
|---|
| 305 | | - if (request_mask & STATX_SIZE || new) |
|---|
| 269 | + if (flags) |
|---|
| 306 | 270 | new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT; |
|---|
| 307 | 271 | else |
|---|
| 308 | 272 | new_op->upcall.req.getattr.mask = |
|---|
| .. | .. |
|---|
| 313 | 277 | if (ret != 0) |
|---|
| 314 | 278 | goto out; |
|---|
| 315 | 279 | |
|---|
| 316 | | - if (!new) { |
|---|
| 280 | +again2: |
|---|
| 281 | + spin_lock(&inode->i_lock); |
|---|
| 282 | + /* Must have all the attributes in the mask and be within cache time. */ |
|---|
| 283 | + if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) || |
|---|
| 284 | + orangefs_inode->attr_valid || inode->i_state & I_DIRTY_PAGES) { |
|---|
| 285 | + if (orangefs_inode->attr_valid) { |
|---|
| 286 | + spin_unlock(&inode->i_lock); |
|---|
| 287 | + write_inode_now(inode, 1); |
|---|
| 288 | + goto again2; |
|---|
| 289 | + } |
|---|
| 290 | + if (inode->i_state & I_DIRTY_PAGES) { |
|---|
| 291 | + ret = 0; |
|---|
| 292 | + goto out_unlock; |
|---|
| 293 | + } |
|---|
| 294 | + gossip_debug(GOSSIP_UTILS_DEBUG, "%s: in cache or dirty\n", |
|---|
| 295 | + __func__); |
|---|
| 296 | + ret = 0; |
|---|
| 297 | + goto out_unlock; |
|---|
| 298 | + } |
|---|
| 299 | + |
|---|
| 300 | + if (!(flags & ORANGEFS_GETATTR_NEW)) { |
|---|
| 317 | 301 | ret = orangefs_inode_is_stale(inode, |
|---|
| 318 | 302 | &new_op->downcall.resp.getattr.attributes, |
|---|
| 319 | 303 | new_op->downcall.resp.getattr.link_target); |
|---|
| 320 | 304 | if (ret) { |
|---|
| 321 | 305 | ret = -ESTALE; |
|---|
| 322 | | - goto out; |
|---|
| 306 | + goto out_unlock; |
|---|
| 323 | 307 | } |
|---|
| 324 | 308 | } |
|---|
| 325 | 309 | |
|---|
| .. | .. |
|---|
| 329 | 313 | case S_IFREG: |
|---|
| 330 | 314 | inode->i_flags = orangefs_inode_flags(&new_op-> |
|---|
| 331 | 315 | downcall.resp.getattr.attributes); |
|---|
| 332 | | - if (request_mask & STATX_SIZE || new) { |
|---|
| 316 | + if (flags) { |
|---|
| 333 | 317 | inode_size = (loff_t)new_op-> |
|---|
| 334 | 318 | downcall.resp.getattr.attributes.size; |
|---|
| 335 | 319 | inode->i_size = inode_size; |
|---|
| 336 | 320 | inode->i_blkbits = ffs(new_op->downcall.resp.getattr. |
|---|
| 337 | 321 | attributes.blksize); |
|---|
| 338 | | - spin_lock(&inode->i_lock); |
|---|
| 339 | 322 | inode->i_bytes = inode_size; |
|---|
| 340 | 323 | inode->i_blocks = |
|---|
| 341 | 324 | (inode_size + 512 - inode_size % 512)/512; |
|---|
| 342 | | - spin_unlock(&inode->i_lock); |
|---|
| 343 | 325 | } |
|---|
| 344 | 326 | break; |
|---|
| 345 | 327 | case S_IFDIR: |
|---|
| 346 | | - if (request_mask & STATX_SIZE || new) { |
|---|
| 328 | + if (flags) { |
|---|
| 347 | 329 | inode->i_size = PAGE_SIZE; |
|---|
| 348 | | - spin_lock(&inode->i_lock); |
|---|
| 349 | 330 | inode_set_bytes(inode, inode->i_size); |
|---|
| 350 | | - spin_unlock(&inode->i_lock); |
|---|
| 351 | 331 | } |
|---|
| 352 | 332 | set_nlink(inode, 1); |
|---|
| 353 | 333 | break; |
|---|
| 354 | 334 | case S_IFLNK: |
|---|
| 355 | | - if (new) { |
|---|
| 335 | + if (flags & ORANGEFS_GETATTR_NEW) { |
|---|
| 356 | 336 | inode->i_size = (loff_t)strlen(new_op-> |
|---|
| 357 | 337 | downcall.resp.getattr.link_target); |
|---|
| 358 | 338 | ret = strscpy(orangefs_inode->link_target, |
|---|
| .. | .. |
|---|
| 360 | 340 | ORANGEFS_NAME_MAX); |
|---|
| 361 | 341 | if (ret == -E2BIG) { |
|---|
| 362 | 342 | ret = -EIO; |
|---|
| 363 | | - goto out; |
|---|
| 343 | + goto out_unlock; |
|---|
| 364 | 344 | } |
|---|
| 365 | 345 | inode->i_link = orangefs_inode->link_target; |
|---|
| 366 | 346 | } |
|---|
| .. | .. |
|---|
| 370 | 350 | /* XXX: ESTALE? This is what is done if it is not new. */ |
|---|
| 371 | 351 | orangefs_make_bad_inode(inode); |
|---|
| 372 | 352 | ret = -ESTALE; |
|---|
| 373 | | - goto out; |
|---|
| 353 | + goto out_unlock; |
|---|
| 374 | 354 | } |
|---|
| 375 | 355 | |
|---|
| 376 | 356 | inode->i_uid = make_kuid(&init_user_ns, new_op-> |
|---|
| .. | .. |
|---|
| 393 | 373 | |
|---|
| 394 | 374 | orangefs_inode->getattr_time = jiffies + |
|---|
| 395 | 375 | orangefs_getattr_timeout_msecs*HZ/1000; |
|---|
| 396 | | - if (request_mask & STATX_SIZE || new) |
|---|
| 397 | | - orangefs_inode->getattr_mask = STATX_BASIC_STATS; |
|---|
| 398 | | - else |
|---|
| 399 | | - orangefs_inode->getattr_mask = STATX_BASIC_STATS & ~STATX_SIZE; |
|---|
| 400 | 376 | ret = 0; |
|---|
| 377 | +out_unlock: |
|---|
| 378 | + spin_unlock(&inode->i_lock); |
|---|
| 401 | 379 | out: |
|---|
| 402 | 380 | op_release(new_op); |
|---|
| 403 | 381 | return ret; |
|---|
| .. | .. |
|---|
| 436 | 414 | * issues a orangefs setattr request to make sure the new attribute values |
|---|
| 437 | 415 | * take effect if successful. returns 0 on success; -errno otherwise |
|---|
| 438 | 416 | */ |
|---|
| 439 | | -int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr) |
|---|
| 417 | +int orangefs_inode_setattr(struct inode *inode) |
|---|
| 440 | 418 | { |
|---|
| 441 | 419 | struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); |
|---|
| 442 | 420 | struct orangefs_kernel_op_s *new_op; |
|---|
| .. | .. |
|---|
| 446 | 424 | if (!new_op) |
|---|
| 447 | 425 | return -ENOMEM; |
|---|
| 448 | 426 | |
|---|
| 427 | + spin_lock(&inode->i_lock); |
|---|
| 428 | + new_op->upcall.uid = from_kuid(&init_user_ns, orangefs_inode->attr_uid); |
|---|
| 429 | + new_op->upcall.gid = from_kgid(&init_user_ns, orangefs_inode->attr_gid); |
|---|
| 449 | 430 | new_op->upcall.req.setattr.refn = orangefs_inode->refn; |
|---|
| 450 | | - ret = copy_attributes_from_inode(inode, |
|---|
| 451 | | - &new_op->upcall.req.setattr.attributes, |
|---|
| 452 | | - iattr); |
|---|
| 453 | | - if (ret >= 0) { |
|---|
| 454 | | - ret = service_operation(new_op, __func__, |
|---|
| 455 | | - get_interruptible_flag(inode)); |
|---|
| 456 | | - |
|---|
| 457 | | - gossip_debug(GOSSIP_UTILS_DEBUG, |
|---|
| 458 | | - "orangefs_inode_setattr: returning %d\n", |
|---|
| 459 | | - ret); |
|---|
| 431 | + copy_attributes_from_inode(inode, |
|---|
| 432 | + &new_op->upcall.req.setattr.attributes); |
|---|
| 433 | + orangefs_inode->attr_valid = 0; |
|---|
| 434 | + if (!new_op->upcall.req.setattr.attributes.mask) { |
|---|
| 435 | + spin_unlock(&inode->i_lock); |
|---|
| 436 | + op_release(new_op); |
|---|
| 437 | + return 0; |
|---|
| 460 | 438 | } |
|---|
| 439 | + spin_unlock(&inode->i_lock); |
|---|
| 440 | + |
|---|
| 441 | + ret = service_operation(new_op, __func__, |
|---|
| 442 | + get_interruptible_flag(inode) | ORANGEFS_OP_WRITEBACK); |
|---|
| 443 | + gossip_debug(GOSSIP_UTILS_DEBUG, |
|---|
| 444 | + "orangefs_inode_setattr: returning %d\n", ret); |
|---|
| 445 | + if (ret) |
|---|
| 446 | + orangefs_make_bad_inode(inode); |
|---|
| 461 | 447 | |
|---|
| 462 | 448 | op_release(new_op); |
|---|
| 463 | 449 | |
|---|
| 464 | 450 | if (ret == 0) |
|---|
| 465 | 451 | orangefs_inode->getattr_time = jiffies - 1; |
|---|
| 466 | | - |
|---|
| 467 | 452 | return ret; |
|---|
| 468 | 453 | } |
|---|
| 469 | 454 | |
|---|