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_vnops.h>
28 #include <sys/zfs_znode.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 fid_t
*fid
= (fid_t
*)fh
;
47 len_bytes
= *max_len
* sizeof (__u32
);
49 if (len_bytes
< offsetof(fid_t
, fid_data
))
52 fid
->fid_len
= len_bytes
- offsetof(fid_t
, fid_data
);
53 cookie
= spl_fstrans_mark();
55 if (zfsctl_is_node(ip
))
56 rc
= zfsctl_fid(ip
, fid
);
58 rc
= zfs_fid(ip
, fid
);
60 spl_fstrans_unmark(cookie
);
61 len_bytes
= offsetof(fid_t
, fid_data
) + fid
->fid_len
;
62 *max_len
= roundup(len_bytes
, sizeof (__u32
)) / sizeof (__u32
);
64 return (rc
== 0 ? FILEID_INO32_GEN
: 255);
67 static struct dentry
*
68 zpl_dentry_obtain_alias(struct inode
*ip
)
70 struct dentry
*result
;
72 #ifdef HAVE_D_OBTAIN_ALIAS
73 result
= d_obtain_alias(ip
);
75 result
= d_alloc_anon(ip
);
79 result
= ERR_PTR(-ENOMEM
);
81 #endif /* HAVE_D_OBTAIN_ALIAS */
86 static struct dentry
*
87 zpl_fh_to_dentry(struct super_block
*sb
, struct fid
*fh
,
88 int fh_len
, int fh_type
)
90 fid_t
*fid
= (fid_t
*)fh
;
91 fstrans_cookie_t cookie
;
95 len_bytes
= fh_len
* sizeof (__u32
);
97 if (fh_type
!= FILEID_INO32_GEN
||
98 len_bytes
< offsetof(fid_t
, fid_data
) ||
99 len_bytes
< offsetof(fid_t
, fid_data
) + fid
->fid_len
)
100 return (ERR_PTR(-EINVAL
));
102 cookie
= spl_fstrans_mark();
103 rc
= zfs_vget(sb
, &ip
, fid
);
104 spl_fstrans_unmark(cookie
);
108 * If we see ENOENT it might mean that an NFSv4 * client
109 * is using a cached inode value in a file handle and
110 * that the sought after file has had its inode changed
111 * by a third party. So change the error to ESTALE
112 * which will trigger a full lookup by the client and
113 * will find the new filename/inode pair if it still
119 return (ERR_PTR(-rc
));
122 ASSERT((ip
!= NULL
) && !IS_ERR(ip
));
124 return (zpl_dentry_obtain_alias(ip
));
127 static struct dentry
*
128 zpl_get_parent(struct dentry
*child
)
131 fstrans_cookie_t cookie
;
136 cookie
= spl_fstrans_mark();
137 error
= -zfs_lookup(child
->d_inode
, "..", &ip
, 0, cr
, NULL
, NULL
);
138 spl_fstrans_unmark(cookie
);
140 ASSERT3S(error
, <=, 0);
143 return (ERR_PTR(error
));
145 return (zpl_dentry_obtain_alias(ip
));
148 #ifdef HAVE_COMMIT_METADATA
150 zpl_commit_metadata(struct inode
*inode
)
153 fstrans_cookie_t cookie
;
156 if (zfsctl_is_node(inode
))
160 cookie
= spl_fstrans_mark();
161 error
= -zfs_fsync(inode
, 0, cr
);
162 spl_fstrans_unmark(cookie
);
164 ASSERT3S(error
, <=, 0);
168 #endif /* HAVE_COMMIT_METADATA */
170 const struct export_operations zpl_export_operations
= {
171 .encode_fh
= zpl_encode_fh
,
172 .fh_to_dentry
= zpl_fh_to_dentry
,
173 .get_parent
= zpl_get_parent
,
174 #ifdef HAVE_COMMIT_METADATA
175 .commit_metadata
= zpl_commit_metadata
,
176 #endif /* HAVE_COMMIT_METADATA */