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.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
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]
22 * Copyright (c) 2011 Gunnar Beutner
23 * Copyright (c) 2012 Cyril Plisko. All rights reserved.
27 #include <sys/zfs_znode.h>
28 #include <sys/zfs_vnops.h>
29 #include <sys/zfs_ctldir.h>
34 #ifdef HAVE_ENCODE_FH_WITH_INODE
35 zpl_encode_fh(struct inode
*ip
, __u32
*fh
, int *max_len
, struct inode
*parent
)
38 zpl_encode_fh(struct dentry
*dentry
, __u32
*fh
, int *max_len
, int connectable
)
41 struct inode
*ip
= dentry
->d_inode
;
42 #endif /* HAVE_ENCODE_FH_WITH_INODE */
43 fstrans_cookie_t cookie
;
44 ushort_t empty_fid
= 0;
48 len_bytes
= *max_len
* sizeof (__u32
);
50 if (len_bytes
< offsetof(fid_t
, fid_data
)) {
51 fid
= (fid_t
*)&empty_fid
;
54 fid
->fid_len
= len_bytes
- offsetof(fid_t
, fid_data
);
57 cookie
= spl_fstrans_mark();
59 if (zfsctl_is_node(ip
))
60 rc
= zfsctl_fid(ip
, fid
);
62 rc
= zfs_fid(ip
, fid
);
64 spl_fstrans_unmark(cookie
);
65 len_bytes
= offsetof(fid_t
, fid_data
) + fid
->fid_len
;
66 *max_len
= roundup(len_bytes
, sizeof (__u32
)) / sizeof (__u32
);
68 return (rc
== 0 ? FILEID_INO32_GEN
: 255);
71 static struct dentry
*
72 zpl_fh_to_dentry(struct super_block
*sb
, struct fid
*fh
,
73 int fh_len
, int fh_type
)
75 fid_t
*fid
= (fid_t
*)fh
;
76 fstrans_cookie_t cookie
;
80 len_bytes
= fh_len
* sizeof (__u32
);
82 if (fh_type
!= FILEID_INO32_GEN
||
83 len_bytes
< offsetof(fid_t
, fid_data
) ||
84 len_bytes
< offsetof(fid_t
, fid_data
) + fid
->fid_len
)
85 return (ERR_PTR(-EINVAL
));
87 cookie
= spl_fstrans_mark();
88 rc
= zfs_vget(sb
, &ip
, fid
);
89 spl_fstrans_unmark(cookie
);
93 * If we see ENOENT it might mean that an NFSv4 * client
94 * is using a cached inode value in a file handle and
95 * that the sought after file has had its inode changed
96 * by a third party. So change the error to ESTALE
97 * which will trigger a full lookup by the client and
98 * will find the new filename/inode pair if it still
104 return (ERR_PTR(-rc
));
107 ASSERT((ip
!= NULL
) && !IS_ERR(ip
));
109 return (d_obtain_alias(ip
));
112 static struct dentry
*
113 zpl_get_parent(struct dentry
*child
)
116 fstrans_cookie_t cookie
;
121 cookie
= spl_fstrans_mark();
122 error
= -zfs_lookup(ITOZ(child
->d_inode
), "..", &zp
, 0, cr
, NULL
, NULL
);
123 spl_fstrans_unmark(cookie
);
125 ASSERT3S(error
, <=, 0);
128 return (ERR_PTR(error
));
130 return (d_obtain_alias(ZTOI(zp
)));
134 zpl_commit_metadata(struct inode
*inode
)
137 fstrans_cookie_t cookie
;
140 if (zfsctl_is_node(inode
))
144 cookie
= spl_fstrans_mark();
145 error
= -zfs_fsync(ITOZ(inode
), 0, cr
);
146 spl_fstrans_unmark(cookie
);
148 ASSERT3S(error
, <=, 0);
153 const struct export_operations zpl_export_operations
= {
154 .encode_fh
= zpl_encode_fh
,
155 .fh_to_dentry
= zpl_fh_to_dentry
,
156 .get_parent
= zpl_get_parent
,
157 .commit_metadata
= zpl_commit_metadata
,