aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Brandenburg <martin@omnibond.com>2016-03-17 15:15:16 -0400
committerMike Marshall <hubcap@omnibond.com>2016-03-23 17:36:15 -0400
commit5859d77e56e470ba16960befcd948c97a6f62102 (patch)
treeba4c3743738156281a9f43268c787b86e01b2a80
parent8f24928d195fc32a6ba53c2329c5bbcaa59119bc (diff)
orangefs: use new getattr for revalidate and remove old getattr
Signed-off-by: Martin Brandenburg <martin@omnibond.com> Signed-off-by: Mike Marshall <hubcap@omnibond.com>
-rw-r--r--fs/orangefs/dcache.c3
-rw-r--r--fs/orangefs/orangefs-kernel.h4
-rw-r--r--fs/orangefs/orangefs-utils.c367
3 files changed, 49 insertions, 325 deletions
diff --git a/fs/orangefs/dcache.c b/fs/orangefs/dcache.c
index cc5487a1d040..5dfc4f3cfe68 100644
--- a/fs/orangefs/dcache.c
+++ b/fs/orangefs/dcache.c
@@ -117,8 +117,7 @@ static int orangefs_d_revalidate(struct dentry *dentry, unsigned int flags)
117 117
118 /* Now we must perform a getattr to validate the inode contents. */ 118 /* Now we must perform a getattr to validate the inode contents. */
119 119
120 ret = orangefs_inode_old_getattr(dentry->d_inode, 120 ret = orangefs_inode_check_changed(dentry->d_inode);
121 ORANGEFS_ATTR_SYS_TYPE|ORANGEFS_ATTR_SYS_LNK_TARGET, 1);
122 if (ret < 0) { 121 if (ret < 0) {
123 gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n", 122 gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n",
124 __FILE__, __func__, __LINE__); 123 __FILE__, __func__, __LINE__);
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index 276685cdf38d..5e85b199dee2 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -544,10 +544,10 @@ int orangefs_inode_setxattr(struct inode *inode,
544 size_t size, 544 size_t size,
545 int flags); 545 int flags);
546 546
547int orangefs_inode_old_getattr(struct inode *inode, __u32 mask, int check);
548
549int orangefs_inode_getattr(struct inode *inode, int new, int size); 547int orangefs_inode_getattr(struct inode *inode, int new, int size);
550 548
549int orangefs_inode_check_changed(struct inode *inode);
550
551int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr); 551int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr);
552 552
553void orangefs_make_bad_inode(struct inode *inode); 553void orangefs_make_bad_inode(struct inode *inode);
diff --git a/fs/orangefs/orangefs-utils.c b/fs/orangefs/orangefs-utils.c
index 59c51e2c5a71..6643a6a87fa1 100644
--- a/fs/orangefs/orangefs-utils.c
+++ b/fs/orangefs/orangefs-utils.c
@@ -129,141 +129,6 @@ static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs)
129 return perm_mode; 129 return perm_mode;
130} 130}
131 131
132/* NOTE: symname is ignored unless the inode is a sym link */
133static int copy_attributes_to_inode(struct inode *inode,
134 struct ORANGEFS_sys_attr_s *attrs,
135 char *symname)
136{
137 int ret = -1;
138 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
139 loff_t inode_size = 0;
140 loff_t rounded_up_size = 0;
141
142
143 /*
144 * arbitrarily set the inode block size; FIXME: we need to
145 * resolve the difference between the reported inode blocksize
146 * and the PAGE_CACHE_SIZE, since our block count will always
147 * be wrong.
148 *
149 * For now, we're setting the block count to be the proper
150 * number assuming the block size is 512 bytes, and the size is
151 * rounded up to the nearest 4K. This is apparently required
152 * to get proper size reports from the 'du' shell utility.
153 *
154 * changing the inode->i_blkbits to something other than
155 * PAGE_CACHE_SHIFT breaks mmap/execution as we depend on that.
156 */
157 gossip_debug(GOSSIP_UTILS_DEBUG,
158 "attrs->mask = %x (objtype = %s)\n",
159 attrs->mask,
160 attrs->objtype == ORANGEFS_TYPE_METAFILE ? "file" :
161 attrs->objtype == ORANGEFS_TYPE_DIRECTORY ? "directory" :
162 attrs->objtype == ORANGEFS_TYPE_SYMLINK ? "symlink" :
163 "invalid/unknown");
164
165 switch (attrs->objtype) {
166 case ORANGEFS_TYPE_METAFILE:
167 inode->i_flags = orangefs_inode_flags(attrs);
168 if (attrs->mask & ORANGEFS_ATTR_SYS_SIZE) {
169 inode_size = (loff_t) attrs->size;
170 rounded_up_size =
171 (inode_size + (4096 - (inode_size % 4096)));
172
173 spin_lock(&inode->i_lock);
174 inode->i_bytes = inode_size;
175 inode->i_blocks =
176 (unsigned long)(rounded_up_size / 512);
177 spin_unlock(&inode->i_lock);
178
179 /*
180 * NOTE: make sure all the places we're called
181 * from have the inode->i_sem lock. We're fine
182 * in 99% of the cases since we're mostly
183 * called from a lookup.
184 */
185 inode->i_size = inode_size;
186 }
187 break;
188 case ORANGEFS_TYPE_SYMLINK:
189 if (symname != NULL) {
190 inode->i_size = (loff_t) strlen(symname);
191 break;
192 }
193 /*FALLTHRU*/
194 default:
195 inode->i_size = PAGE_CACHE_SIZE;
196
197 spin_lock(&inode->i_lock);
198 inode_set_bytes(inode, inode->i_size);
199 spin_unlock(&inode->i_lock);
200 break;
201 }
202
203 inode->i_uid = make_kuid(&init_user_ns, attrs->owner);
204 inode->i_gid = make_kgid(&init_user_ns, attrs->group);
205 inode->i_atime.tv_sec = (time64_t) attrs->atime;
206 inode->i_mtime.tv_sec = (time64_t) attrs->mtime;
207 inode->i_ctime.tv_sec = (time64_t) attrs->ctime;
208 inode->i_atime.tv_nsec = 0;
209 inode->i_mtime.tv_nsec = 0;
210 inode->i_ctime.tv_nsec = 0;
211
212 inode->i_mode = orangefs_inode_perms(attrs);
213
214 if (is_root_handle(inode)) {
215 /* special case: mark the root inode as sticky */
216 inode->i_mode |= S_ISVTX;
217 gossip_debug(GOSSIP_UTILS_DEBUG,
218 "Marking inode %pU as sticky\n",
219 get_khandle_from_ino(inode));
220 }
221
222 switch (attrs->objtype) {
223 case ORANGEFS_TYPE_METAFILE:
224 inode->i_mode |= S_IFREG;
225 ret = 0;
226 break;
227 case ORANGEFS_TYPE_DIRECTORY:
228 inode->i_mode |= S_IFDIR;
229 /* NOTE: we have no good way to keep nlink consistent
230 * for directories across clients; keep constant at 1.
231 * Why 1? If we go with 2, then find(1) gets confused
232 * and won't work properly withouth the -noleaf option
233 */
234 set_nlink(inode, 1);
235 ret = 0;
236 break;
237 case ORANGEFS_TYPE_SYMLINK:
238 inode->i_mode |= S_IFLNK;
239
240 /* copy link target to inode private data */
241 if (orangefs_inode && symname) {
242 strncpy(orangefs_inode->link_target,
243 symname,
244 ORANGEFS_NAME_MAX);
245 gossip_debug(GOSSIP_UTILS_DEBUG,
246 "Copied attr link target %s\n",
247 orangefs_inode->link_target);
248 }
249 gossip_debug(GOSSIP_UTILS_DEBUG,
250 "symlink mode %o\n",
251 inode->i_mode);
252 ret = 0;
253 break;
254 default:
255 gossip_err("orangefs: copy_attributes_to_inode: got invalid attribute type %x\n",
256 attrs->objtype);
257 }
258
259 gossip_debug(GOSSIP_UTILS_DEBUG,
260 "orangefs: copy_attributes_to_inode: setting i_mode to %o, i_size to %lu\n",
261 inode->i_mode,
262 (unsigned long)i_size_read(inode));
263
264 return ret;
265}
266
267/* 132/*
268 * NOTE: in kernel land, we never use the sys_attr->link_target for 133 * NOTE: in kernel land, we never use the sys_attr->link_target for
269 * anything, so don't bother copying it into the sys_attr object here. 134 * anything, so don't bother copying it into the sys_attr object here.
@@ -351,192 +216,6 @@ static inline int copy_attributes_from_inode(struct inode *inode,
351 return 0; 216 return 0;
352} 217}
353 218
354static int compare_attributes_to_inode(struct inode *inode,
355 struct ORANGEFS_sys_attr_s *attrs,
356 char *symname,
357 int mask)
358{
359 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
360 loff_t inode_size, rounded_up_size;
361
362 /* Much of what happens below relies on the type being around. */
363 if (!(mask & ORANGEFS_ATTR_SYS_TYPE))
364 return 0;
365
366 if (attrs->objtype == ORANGEFS_TYPE_METAFILE &&
367 inode->i_flags != orangefs_inode_flags(attrs))
368 return 0;
369
370 /* Compare file size. */
371
372 switch (attrs->objtype) {
373 case ORANGEFS_TYPE_METAFILE:
374 if (mask & ORANGEFS_ATTR_SYS_SIZE) {
375 inode_size = attrs->size;
376 rounded_up_size = inode_size +
377 (4096 - (inode_size % 4096));
378 if (inode->i_bytes != inode_size ||
379 inode->i_blocks != rounded_up_size/512)
380 return 0;
381 }
382 break;
383 case ORANGEFS_TYPE_SYMLINK:
384 if (mask & ORANGEFS_ATTR_SYS_SIZE)
385 if (symname && strlen(symname) != inode->i_size)
386 return 0;
387 break;
388 default:
389 if (inode->i_size != PAGE_CACHE_SIZE &&
390 inode_get_bytes(inode) != PAGE_CACHE_SIZE)
391 return 0;
392 }
393
394 /* Compare general attributes. */
395
396 if (mask & ORANGEFS_ATTR_SYS_UID &&
397 !uid_eq(inode->i_uid, make_kuid(&init_user_ns, attrs->owner)))
398 return 0;
399 if (mask & ORANGEFS_ATTR_SYS_GID &&
400 !gid_eq(inode->i_gid, make_kgid(&init_user_ns, attrs->group)))
401 return 0;
402 if (mask & ORANGEFS_ATTR_SYS_ATIME &&
403 inode->i_atime.tv_sec != attrs->atime)
404 return 0;
405 if (mask & ORANGEFS_ATTR_SYS_MTIME &&
406 inode->i_atime.tv_sec != attrs->mtime)
407 return 0;
408 if (mask & ORANGEFS_ATTR_SYS_CTIME &&
409 inode->i_atime.tv_sec != attrs->ctime)
410 return 0;
411 if (inode->i_atime.tv_nsec != 0 ||
412 inode->i_mtime.tv_nsec != 0 ||
413 inode->i_ctime.tv_nsec != 0)
414 return 0;
415
416 if (mask & ORANGEFS_ATTR_SYS_PERM &&
417 (inode->i_mode & ~(S_ISVTX|S_IFREG|S_IFDIR|S_IFLNK)) !=
418 orangefs_inode_perms(attrs))
419 return 0;
420
421 if (is_root_handle(inode))
422 if (!(inode->i_mode & S_ISVTX))
423 return 0;
424
425 /* Compare file type. */
426
427 switch (attrs->objtype) {
428 case ORANGEFS_TYPE_METAFILE:
429 if (!S_ISREG(inode->i_mode))
430 return 0;
431 break;
432 case ORANGEFS_TYPE_DIRECTORY:
433 if (!S_ISDIR(inode->i_mode))
434 return 0;
435 if (inode->i_nlink != 1)
436 return 0;
437 break;
438 case ORANGEFS_TYPE_SYMLINK:
439 if (!S_ISLNK(inode->i_mode))
440 return 0;
441 if (orangefs_inode && symname &&
442 mask & ORANGEFS_ATTR_SYS_LNK_TARGET)
443 if (strcmp(orangefs_inode->link_target, symname))
444 return 0;
445 break;
446 default:
447 gossip_err("orangefs: compare_attributes_to_inode: got invalid attribute type %x\n",
448 attrs->objtype);
449
450 }
451
452 return 1;
453}
454
455/*
456 * Issues a orangefs getattr request and fills in the appropriate inode
457 * attributes if successful. When check is 0, returns 0 on success and -errno
458 * otherwise. When check is 1, returns 1 on success where the inode is valid
459 * and 0 on success where the inode is stale and -errno otherwise.
460 */
461int orangefs_inode_old_getattr(struct inode *inode, __u32 getattr_mask,
462 int check)
463{
464 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
465 struct orangefs_kernel_op_s *new_op;
466 int ret = -EINVAL;
467
468 gossip_debug(GOSSIP_UTILS_DEBUG,
469 "%s: called on inode %pU\n",
470 __func__,
471 get_khandle_from_ino(inode));
472
473 new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
474 if (!new_op)
475 return -ENOMEM;
476 new_op->upcall.req.getattr.refn = orangefs_inode->refn;
477 new_op->upcall.req.getattr.mask = getattr_mask;
478
479 ret = service_operation(new_op, __func__,
480 get_interruptible_flag(inode));
481 if (ret != 0)
482 goto out;
483
484 if (check) {
485 ret = compare_attributes_to_inode(inode,
486 &new_op->downcall.resp.getattr.attributes,
487 new_op->downcall.resp.getattr.link_target,
488 getattr_mask);
489
490 if (new_op->downcall.resp.getattr.attributes.objtype ==
491 ORANGEFS_TYPE_METAFILE) {
492 if (orangefs_inode->blksize !=
493 new_op->downcall.resp.getattr.attributes.blksize)
494 ret = 0;
495 } else {
496 if (orangefs_inode->blksize != 1 << inode->i_blkbits)
497 ret = 0;
498 }
499 } else {
500 if (copy_attributes_to_inode(inode,
501 &new_op->downcall.resp.getattr.attributes,
502 new_op->downcall.resp.getattr.link_target)) {
503 gossip_err("%s: failed to copy attributes\n", __func__);
504 ret = -ENOENT;
505 goto out;
506 }
507
508 /*
509 * Store blksize in orangefs specific part of inode structure;
510 * we are only going to use this to report to stat to make sure
511 * it doesn't perturb any inode related code paths.
512 */
513 if (new_op->downcall.resp.getattr.attributes.objtype ==
514 ORANGEFS_TYPE_METAFILE) {
515 orangefs_inode->blksize = new_op->downcall.resp.
516 getattr.attributes.blksize;
517 } else {
518 /*
519 * mimic behavior of generic_fillattr() for other file
520 * types.
521 */
522 orangefs_inode->blksize = (1 << inode->i_blkbits);
523
524 }
525 }
526
527out:
528 gossip_debug(GOSSIP_UTILS_DEBUG,
529 "Getattr on handle %pU, "
530 "fsid %d\n (inode ct = %d) returned %d\n",
531 &orangefs_inode->refn.khandle,
532 orangefs_inode->refn.fs_id,
533 (int)atomic_read(&inode->i_count),
534 ret);
535
536 op_release(new_op);
537 return ret;
538}
539
540static int orangefs_inode_type(enum orangefs_ds_type objtype) 219static int orangefs_inode_type(enum orangefs_ds_type objtype)
541{ 220{
542 if (objtype == ORANGEFS_TYPE_METAFILE) 221 if (objtype == ORANGEFS_TYPE_METAFILE)
@@ -655,6 +334,52 @@ out:
655 return ret; 334 return ret;
656} 335}
657 336
337int orangefs_inode_check_changed(struct inode *inode)
338{
339 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
340 struct orangefs_kernel_op_s *new_op;
341 int ret;
342
343 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
344 get_khandle_from_ino(inode));
345
346 new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
347 if (!new_op)
348 return -ENOMEM;
349 new_op->upcall.req.getattr.refn = orangefs_inode->refn;
350 new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE |
351 ORANGEFS_ATTR_SYS_LNK_TARGET;
352
353 ret = service_operation(new_op, __func__,
354 get_interruptible_flag(inode));
355 if (ret != 0)
356 goto out;
357
358 ret = orangefs_inode_type(new_op->
359 downcall.resp.getattr.attributes.objtype);
360 /*
361 * If the inode type or symlink target have changed then this
362 * inode is stale.
363 */
364 if (ret == -1 || !(inode->i_mode & ret)) {
365 orangefs_make_bad_inode(inode);
366 ret = 1;
367 goto out;
368 }
369 if (ret == S_IFLNK && strncmp(orangefs_inode->link_target,
370 new_op->downcall.resp.getattr.link_target,
371 ORANGEFS_NAME_MAX)) {
372 orangefs_make_bad_inode(inode);
373 ret = 1;
374 goto out;
375 }
376
377 ret = 0;
378out:
379 op_release(new_op);
380 return ret;
381}
382
658/* 383/*
659 * issues a orangefs setattr request to make sure the new attribute values 384 * issues a orangefs setattr request to make sure the new attribute values
660 * take effect if successful. returns 0 on success; -errno otherwise 385 * take effect if successful. returns 0 on success; -errno otherwise