1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or https://opensource.org/licenses/CDDL-1.0. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (C) 2011 Lawrence Livermore National Security, LLC. 23 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). 24 * LLNL-CODE-403049. 25 * Rewritten for Linux by: 26 * Rohan Puri <rohan.puri15@gmail.com> 27 * Brian Behlendorf <behlendorf1@llnl.gov> 28 */ 29 30 #include <sys/zfs_znode.h> 31 #include <sys/zfs_vfsops.h> 32 #include <sys/zfs_vnops.h> 33 #include <sys/zfs_ctldir.h> 34 #include <sys/zpl.h> 35 #include <sys/dmu.h> 36 #include <sys/dsl_dataset.h> 37 #include <sys/zap.h> 38 39 /* 40 * Common open routine. Disallow any write access. 41 */ 42 static int 43 zpl_common_open(struct inode *ip, struct file *filp) 44 { 45 if (filp->f_mode & FMODE_WRITE) 46 return (-EACCES); 47 48 return (generic_file_open(ip, filp)); 49 } 50 51 /* 52 * Get root directory contents. 53 */ 54 static int 55 zpl_root_iterate(struct file *filp, zpl_dir_context_t *ctx) 56 { 57 zfsvfs_t *zfsvfs = ITOZSB(file_inode(filp)); 58 int error = 0; 59 60 if ((error = zpl_enter(zfsvfs, FTAG)) != 0) 61 return (error); 62 63 if (!zpl_dir_emit_dots(filp, ctx)) 64 goto out; 65 66 if (ctx->pos == 2) { 67 if (!zpl_dir_emit(ctx, ZFS_SNAPDIR_NAME, 68 strlen(ZFS_SNAPDIR_NAME), ZFSCTL_INO_SNAPDIR, DT_DIR)) 69 goto out; 70 71 ctx->pos++; 72 } 73 74 if (ctx->pos == 3) { 75 if (!zpl_dir_emit(ctx, ZFS_SHAREDIR_NAME, 76 strlen(ZFS_SHAREDIR_NAME), ZFSCTL_INO_SHARES, DT_DIR)) 77 goto out; 78 79 ctx->pos++; 80 } 81 out: 82 zpl_exit(zfsvfs, FTAG); 83 84 return (error); 85 } 86 87 #if !defined(HAVE_VFS_ITERATE) && !defined(HAVE_VFS_ITERATE_SHARED) 88 static int 89 zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir) 90 { 91 zpl_dir_context_t ctx = 92 ZPL_DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos); 93 int error; 94 95 error = zpl_root_iterate(filp, &ctx); 96 filp->f_pos = ctx.pos; 97 98 return (error); 99 } 100 #endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */ 101 102 /* 103 * Get root directory attributes. 104 */ 105 static int 106 #ifdef HAVE_IDMAP_IOPS_GETATTR 107 zpl_root_getattr_impl(struct mnt_idmap *user_ns, 108 const struct path *path, struct kstat *stat, u32 request_mask, 109 unsigned int query_flags) 110 #elif defined(HAVE_USERNS_IOPS_GETATTR) 111 zpl_root_getattr_impl(struct user_namespace *user_ns, 112 const struct path *path, struct kstat *stat, u32 request_mask, 113 unsigned int query_flags) 114 #else 115 zpl_root_getattr_impl(const struct path *path, struct kstat *stat, 116 u32 request_mask, unsigned int query_flags) 117 #endif 118 { 119 (void) request_mask, (void) query_flags; 120 struct inode *ip = path->dentry->d_inode; 121 122 #if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR)) 123 #ifdef HAVE_GENERIC_FILLATTR_USERNS 124 generic_fillattr(user_ns, ip, stat); 125 #elif defined(HAVE_GENERIC_FILLATTR_IDMAP) 126 generic_fillattr(user_ns, ip, stat); 127 #else 128 (void) user_ns; 129 #endif 130 #else 131 generic_fillattr(ip, stat); 132 #endif 133 stat->atime = current_time(ip); 134 135 return (0); 136 } 137 ZPL_GETATTR_WRAPPER(zpl_root_getattr); 138 139 static struct dentry * 140 zpl_root_lookup(struct inode *dip, struct dentry *dentry, unsigned int flags) 141 { 142 cred_t *cr = CRED(); 143 struct inode *ip; 144 int error; 145 146 crhold(cr); 147 error = -zfsctl_root_lookup(dip, dname(dentry), &ip, 0, cr, NULL, NULL); 148 ASSERT3S(error, <=, 0); 149 crfree(cr); 150 151 if (error) { 152 if (error == -ENOENT) 153 return (d_splice_alias(NULL, dentry)); 154 else 155 return (ERR_PTR(error)); 156 } 157 158 return (d_splice_alias(ip, dentry)); 159 } 160 161 /* 162 * The '.zfs' control directory file and inode operations. 163 */ 164 const struct file_operations zpl_fops_root = { 165 .open = zpl_common_open, 166 .llseek = generic_file_llseek, 167 .read = generic_read_dir, 168 #ifdef HAVE_VFS_ITERATE_SHARED 169 .iterate_shared = zpl_root_iterate, 170 #elif defined(HAVE_VFS_ITERATE) 171 .iterate = zpl_root_iterate, 172 #else 173 .readdir = zpl_root_readdir, 174 #endif 175 }; 176 177 const struct inode_operations zpl_ops_root = { 178 .lookup = zpl_root_lookup, 179 .getattr = zpl_root_getattr, 180 }; 181 182 static struct vfsmount * 183 zpl_snapdir_automount(struct path *path) 184 { 185 int error; 186 187 error = -zfsctl_snapshot_mount(path, 0); 188 if (error) 189 return (ERR_PTR(error)); 190 191 /* 192 * Rather than returning the new vfsmount for the snapshot we must 193 * return NULL to indicate a mount collision. This is done because 194 * the user space mount calls do_add_mount() which adds the vfsmount 195 * to the name space. If we returned the new mount here it would be 196 * added again to the vfsmount list resulting in list corruption. 197 */ 198 return (NULL); 199 } 200 201 /* 202 * Negative dentries must always be revalidated so newly created snapshots 203 * can be detected and automounted. Normal dentries should be kept because 204 * as of the 3.18 kernel revaliding the mountpoint dentry will result in 205 * the snapshot being immediately unmounted. 206 */ 207 static int 208 #ifdef HAVE_D_REVALIDATE_NAMEIDATA 209 zpl_snapdir_revalidate(struct dentry *dentry, struct nameidata *i) 210 #else 211 zpl_snapdir_revalidate(struct dentry *dentry, unsigned int flags) 212 #endif 213 { 214 return (!!dentry->d_inode); 215 } 216 217 static dentry_operations_t zpl_dops_snapdirs = { 218 /* 219 * Auto mounting of snapshots is only supported for 2.6.37 and 220 * newer kernels. Prior to this kernel the ops->follow_link() 221 * callback was used as a hack to trigger the mount. The 222 * resulting vfsmount was then explicitly grafted in to the 223 * name space. While it might be possible to add compatibility 224 * code to accomplish this it would require considerable care. 225 */ 226 .d_automount = zpl_snapdir_automount, 227 .d_revalidate = zpl_snapdir_revalidate, 228 }; 229 230 static struct dentry * 231 zpl_snapdir_lookup(struct inode *dip, struct dentry *dentry, 232 unsigned int flags) 233 { 234 fstrans_cookie_t cookie; 235 cred_t *cr = CRED(); 236 struct inode *ip = NULL; 237 int error; 238 239 crhold(cr); 240 cookie = spl_fstrans_mark(); 241 error = -zfsctl_snapdir_lookup(dip, dname(dentry), &ip, 242 0, cr, NULL, NULL); 243 ASSERT3S(error, <=, 0); 244 spl_fstrans_unmark(cookie); 245 crfree(cr); 246 247 if (error && error != -ENOENT) 248 return (ERR_PTR(error)); 249 250 ASSERT(error == 0 || ip == NULL); 251 d_clear_d_op(dentry); 252 d_set_d_op(dentry, &zpl_dops_snapdirs); 253 dentry->d_flags |= DCACHE_NEED_AUTOMOUNT; 254 255 return (d_splice_alias(ip, dentry)); 256 } 257 258 static int 259 zpl_snapdir_iterate(struct file *filp, zpl_dir_context_t *ctx) 260 { 261 zfsvfs_t *zfsvfs = ITOZSB(file_inode(filp)); 262 fstrans_cookie_t cookie; 263 char snapname[MAXNAMELEN]; 264 boolean_t case_conflict; 265 uint64_t id, pos; 266 int error = 0; 267 268 if ((error = zpl_enter(zfsvfs, FTAG)) != 0) 269 return (error); 270 cookie = spl_fstrans_mark(); 271 272 if (!zpl_dir_emit_dots(filp, ctx)) 273 goto out; 274 275 /* Start the position at 0 if it already emitted . and .. */ 276 pos = (ctx->pos == 2 ? 0 : ctx->pos); 277 while (error == 0) { 278 dsl_pool_config_enter(dmu_objset_pool(zfsvfs->z_os), FTAG); 279 error = -dmu_snapshot_list_next(zfsvfs->z_os, MAXNAMELEN, 280 snapname, &id, &pos, &case_conflict); 281 dsl_pool_config_exit(dmu_objset_pool(zfsvfs->z_os), FTAG); 282 if (error) 283 goto out; 284 285 if (!zpl_dir_emit(ctx, snapname, strlen(snapname), 286 ZFSCTL_INO_SHARES - id, DT_DIR)) 287 goto out; 288 289 ctx->pos = pos; 290 } 291 out: 292 spl_fstrans_unmark(cookie); 293 zpl_exit(zfsvfs, FTAG); 294 295 if (error == -ENOENT) 296 return (0); 297 298 return (error); 299 } 300 301 #if !defined(HAVE_VFS_ITERATE) && !defined(HAVE_VFS_ITERATE_SHARED) 302 static int 303 zpl_snapdir_readdir(struct file *filp, void *dirent, filldir_t filldir) 304 { 305 zpl_dir_context_t ctx = 306 ZPL_DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos); 307 int error; 308 309 error = zpl_snapdir_iterate(filp, &ctx); 310 filp->f_pos = ctx.pos; 311 312 return (error); 313 } 314 #endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */ 315 316 static int 317 #ifdef HAVE_IOPS_RENAME_USERNS 318 zpl_snapdir_rename2(struct user_namespace *user_ns, struct inode *sdip, 319 struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry, 320 unsigned int flags) 321 #elif defined(HAVE_IOPS_RENAME_IDMAP) 322 zpl_snapdir_rename2(struct mnt_idmap *user_ns, struct inode *sdip, 323 struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry, 324 unsigned int flags) 325 #else 326 zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry, 327 struct inode *tdip, struct dentry *tdentry, unsigned int flags) 328 #endif 329 { 330 cred_t *cr = CRED(); 331 int error; 332 333 /* We probably don't want to support renameat2(2) in ctldir */ 334 if (flags) 335 return (-EINVAL); 336 337 crhold(cr); 338 error = -zfsctl_snapdir_rename(sdip, dname(sdentry), 339 tdip, dname(tdentry), cr, 0); 340 ASSERT3S(error, <=, 0); 341 crfree(cr); 342 343 return (error); 344 } 345 346 #if (!defined(HAVE_RENAME_WANTS_FLAGS) && \ 347 !defined(HAVE_IOPS_RENAME_USERNS) && \ 348 !defined(HAVE_IOPS_RENAME_IDMAP)) 349 static int 350 zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry, 351 struct inode *tdip, struct dentry *tdentry) 352 { 353 return (zpl_snapdir_rename2(sdip, sdentry, tdip, tdentry, 0)); 354 } 355 #endif 356 357 static int 358 zpl_snapdir_rmdir(struct inode *dip, struct dentry *dentry) 359 { 360 cred_t *cr = CRED(); 361 int error; 362 363 crhold(cr); 364 error = -zfsctl_snapdir_remove(dip, dname(dentry), cr, 0); 365 ASSERT3S(error, <=, 0); 366 crfree(cr); 367 368 return (error); 369 } 370 371 static int 372 #ifdef HAVE_IOPS_MKDIR_USERNS 373 zpl_snapdir_mkdir(struct user_namespace *user_ns, struct inode *dip, 374 struct dentry *dentry, umode_t mode) 375 #elif defined(HAVE_IOPS_MKDIR_IDMAP) 376 zpl_snapdir_mkdir(struct mnt_idmap *user_ns, struct inode *dip, 377 struct dentry *dentry, umode_t mode) 378 #else 379 zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) 380 #endif 381 { 382 cred_t *cr = CRED(); 383 vattr_t *vap; 384 struct inode *ip; 385 int error; 386 387 crhold(cr); 388 vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); 389 #if (defined(HAVE_IOPS_MKDIR_USERNS) || defined(HAVE_IOPS_MKDIR_IDMAP)) 390 zpl_vap_init(vap, dip, mode | S_IFDIR, cr, user_ns); 391 #else 392 zpl_vap_init(vap, dip, mode | S_IFDIR, cr, zfs_init_idmap); 393 #endif 394 395 error = -zfsctl_snapdir_mkdir(dip, dname(dentry), vap, &ip, cr, 0); 396 if (error == 0) { 397 d_clear_d_op(dentry); 398 d_set_d_op(dentry, &zpl_dops_snapdirs); 399 d_instantiate(dentry, ip); 400 } 401 402 kmem_free(vap, sizeof (vattr_t)); 403 ASSERT3S(error, <=, 0); 404 crfree(cr); 405 406 return (error); 407 } 408 409 /* 410 * Get snapshot directory attributes. 411 */ 412 static int 413 #ifdef HAVE_IDMAP_IOPS_GETATTR 414 zpl_snapdir_getattr_impl(struct mnt_idmap *user_ns, 415 const struct path *path, struct kstat *stat, u32 request_mask, 416 unsigned int query_flags) 417 #elif defined(HAVE_USERNS_IOPS_GETATTR) 418 zpl_snapdir_getattr_impl(struct user_namespace *user_ns, 419 const struct path *path, struct kstat *stat, u32 request_mask, 420 unsigned int query_flags) 421 #else 422 zpl_snapdir_getattr_impl(const struct path *path, struct kstat *stat, 423 u32 request_mask, unsigned int query_flags) 424 #endif 425 { 426 (void) request_mask, (void) query_flags; 427 struct inode *ip = path->dentry->d_inode; 428 zfsvfs_t *zfsvfs = ITOZSB(ip); 429 int error; 430 431 if ((error = zpl_enter(zfsvfs, FTAG)) != 0) 432 return (error); 433 #if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR)) 434 #ifdef HAVE_GENERIC_FILLATTR_USERNS 435 generic_fillattr(user_ns, ip, stat); 436 #elif defined(HAVE_GENERIC_FILLATTR_IDMAP) 437 generic_fillattr(user_ns, ip, stat); 438 #else 439 (void) user_ns; 440 #endif 441 #else 442 generic_fillattr(ip, stat); 443 #endif 444 445 stat->nlink = stat->size = 2; 446 447 dsl_dataset_t *ds = dmu_objset_ds(zfsvfs->z_os); 448 if (dsl_dataset_phys(ds)->ds_snapnames_zapobj != 0) { 449 uint64_t snap_count; 450 int err = zap_count( 451 dmu_objset_pool(ds->ds_objset)->dp_meta_objset, 452 dsl_dataset_phys(ds)->ds_snapnames_zapobj, &snap_count); 453 if (err != 0) { 454 zpl_exit(zfsvfs, FTAG); 455 return (-err); 456 } 457 stat->nlink += snap_count; 458 } 459 460 stat->ctime = stat->mtime = dmu_objset_snap_cmtime(zfsvfs->z_os); 461 stat->atime = current_time(ip); 462 zpl_exit(zfsvfs, FTAG); 463 464 return (0); 465 } 466 ZPL_GETATTR_WRAPPER(zpl_snapdir_getattr); 467 468 /* 469 * The '.zfs/snapshot' directory file operations. These mainly control 470 * generating the list of available snapshots when doing an 'ls' in the 471 * directory. See zpl_snapdir_readdir(). 472 */ 473 const struct file_operations zpl_fops_snapdir = { 474 .open = zpl_common_open, 475 .llseek = generic_file_llseek, 476 .read = generic_read_dir, 477 #ifdef HAVE_VFS_ITERATE_SHARED 478 .iterate_shared = zpl_snapdir_iterate, 479 #elif defined(HAVE_VFS_ITERATE) 480 .iterate = zpl_snapdir_iterate, 481 #else 482 .readdir = zpl_snapdir_readdir, 483 #endif 484 485 }; 486 487 /* 488 * The '.zfs/snapshot' directory inode operations. These mainly control 489 * creating an inode for a snapshot directory and initializing the needed 490 * infrastructure to automount the snapshot. See zpl_snapdir_lookup(). 491 */ 492 const struct inode_operations zpl_ops_snapdir = { 493 .lookup = zpl_snapdir_lookup, 494 .getattr = zpl_snapdir_getattr, 495 #if (defined(HAVE_RENAME_WANTS_FLAGS) || \ 496 defined(HAVE_IOPS_RENAME_USERNS) || \ 497 defined(HAVE_IOPS_RENAME_IDMAP)) 498 .rename = zpl_snapdir_rename2, 499 #else 500 .rename = zpl_snapdir_rename, 501 #endif 502 .rmdir = zpl_snapdir_rmdir, 503 .mkdir = zpl_snapdir_mkdir, 504 }; 505 506 static struct dentry * 507 zpl_shares_lookup(struct inode *dip, struct dentry *dentry, 508 unsigned int flags) 509 { 510 fstrans_cookie_t cookie; 511 cred_t *cr = CRED(); 512 struct inode *ip = NULL; 513 int error; 514 515 crhold(cr); 516 cookie = spl_fstrans_mark(); 517 error = -zfsctl_shares_lookup(dip, dname(dentry), &ip, 518 0, cr, NULL, NULL); 519 ASSERT3S(error, <=, 0); 520 spl_fstrans_unmark(cookie); 521 crfree(cr); 522 523 if (error) { 524 if (error == -ENOENT) 525 return (d_splice_alias(NULL, dentry)); 526 else 527 return (ERR_PTR(error)); 528 } 529 530 return (d_splice_alias(ip, dentry)); 531 } 532 533 static int 534 zpl_shares_iterate(struct file *filp, zpl_dir_context_t *ctx) 535 { 536 fstrans_cookie_t cookie; 537 cred_t *cr = CRED(); 538 zfsvfs_t *zfsvfs = ITOZSB(file_inode(filp)); 539 znode_t *dzp; 540 int error = 0; 541 542 if ((error = zpl_enter(zfsvfs, FTAG)) != 0) 543 return (error); 544 cookie = spl_fstrans_mark(); 545 546 if (zfsvfs->z_shares_dir == 0) { 547 zpl_dir_emit_dots(filp, ctx); 548 goto out; 549 } 550 551 error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp); 552 if (error) 553 goto out; 554 555 crhold(cr); 556 error = -zfs_readdir(ZTOI(dzp), ctx, cr); 557 crfree(cr); 558 559 iput(ZTOI(dzp)); 560 out: 561 spl_fstrans_unmark(cookie); 562 zpl_exit(zfsvfs, FTAG); 563 ASSERT3S(error, <=, 0); 564 565 return (error); 566 } 567 568 #if !defined(HAVE_VFS_ITERATE) && !defined(HAVE_VFS_ITERATE_SHARED) 569 static int 570 zpl_shares_readdir(struct file *filp, void *dirent, filldir_t filldir) 571 { 572 zpl_dir_context_t ctx = 573 ZPL_DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos); 574 int error; 575 576 error = zpl_shares_iterate(filp, &ctx); 577 filp->f_pos = ctx.pos; 578 579 return (error); 580 } 581 #endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */ 582 583 static int 584 #ifdef HAVE_USERNS_IOPS_GETATTR 585 zpl_shares_getattr_impl(struct user_namespace *user_ns, 586 const struct path *path, struct kstat *stat, u32 request_mask, 587 unsigned int query_flags) 588 #elif defined(HAVE_IDMAP_IOPS_GETATTR) 589 zpl_shares_getattr_impl(struct mnt_idmap *user_ns, 590 const struct path *path, struct kstat *stat, u32 request_mask, 591 unsigned int query_flags) 592 #else 593 zpl_shares_getattr_impl(const struct path *path, struct kstat *stat, 594 u32 request_mask, unsigned int query_flags) 595 #endif 596 { 597 (void) request_mask, (void) query_flags; 598 struct inode *ip = path->dentry->d_inode; 599 zfsvfs_t *zfsvfs = ITOZSB(ip); 600 znode_t *dzp; 601 int error; 602 603 if ((error = zpl_enter(zfsvfs, FTAG)) != 0) 604 return (error); 605 606 if (zfsvfs->z_shares_dir == 0) { 607 #if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR)) 608 #ifdef HAVE_GENERIC_FILLATTR_USERNS 609 generic_fillattr(user_ns, path->dentry->d_inode, stat); 610 #elif defined(HAVE_GENERIC_FILLATTR_IDMAP) 611 generic_fillattr(user_ns, path->dentry->d_inode, stat); 612 #else 613 (void) user_ns; 614 #endif 615 #else 616 generic_fillattr(path->dentry->d_inode, stat); 617 #endif 618 stat->nlink = stat->size = 2; 619 stat->atime = current_time(ip); 620 zpl_exit(zfsvfs, FTAG); 621 return (0); 622 } 623 624 error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp); 625 if (error == 0) { 626 #if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR)) 627 error = -zfs_getattr_fast(user_ns, ZTOI(dzp), stat); 628 #else 629 error = -zfs_getattr_fast(kcred->user_ns, ZTOI(dzp), stat); 630 #endif 631 iput(ZTOI(dzp)); 632 } 633 634 zpl_exit(zfsvfs, FTAG); 635 ASSERT3S(error, <=, 0); 636 637 return (error); 638 } 639 ZPL_GETATTR_WRAPPER(zpl_shares_getattr); 640 641 /* 642 * The '.zfs/shares' directory file operations. 643 */ 644 const struct file_operations zpl_fops_shares = { 645 .open = zpl_common_open, 646 .llseek = generic_file_llseek, 647 .read = generic_read_dir, 648 #ifdef HAVE_VFS_ITERATE_SHARED 649 .iterate_shared = zpl_shares_iterate, 650 #elif defined(HAVE_VFS_ITERATE) 651 .iterate = zpl_shares_iterate, 652 #else 653 .readdir = zpl_shares_readdir, 654 #endif 655 656 }; 657 658 /* 659 * The '.zfs/shares' directory inode operations. 660 */ 661 const struct inode_operations zpl_ops_shares = { 662 .lookup = zpl_shares_lookup, 663 .getattr = zpl_shares_getattr, 664 }; 665