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
)
40 struct inode
*ip
= dentry
->d_inode
;
41 #endif /* HAVE_ENCODE_FH_WITH_INODE */
42 fstrans_cookie_t cookie
;
43 fid_t
*fid
= (fid_t
*)fh
;
46 len_bytes
= *max_len
* sizeof (__u32
);
48 if (len_bytes
< offsetof(fid_t
, fid_data
))
51 fid
->fid_len
= len_bytes
- offsetof(fid_t
, fid_data
);
52 cookie
= spl_fstrans_mark();
54 if (zfsctl_is_node(ip
))
55 rc
= zfsctl_fid(ip
, fid
);
57 rc
= zfs_fid(ip
, fid
);
59 spl_fstrans_unmark(cookie
);
60 len_bytes
= offsetof(fid_t
, fid_data
) + fid
->fid_len
;
61 *max_len
= roundup(len_bytes
, sizeof (__u32
)) / sizeof (__u32
);
63 return (rc
== 0 ? FILEID_INO32_GEN
: 255);
66 static struct dentry
*
67 zpl_dentry_obtain_alias(struct inode
*ip
)
69 struct dentry
*result
;
71 #ifdef HAVE_D_OBTAIN_ALIAS
72 result
= d_obtain_alias(ip
);
74 result
= d_alloc_anon(ip
);
78 result
= ERR_PTR(-ENOMEM
);
80 #endif /* HAVE_D_OBTAIN_ALIAS */
85 static struct dentry
*
86 zpl_fh_to_dentry(struct super_block
*sb
, struct fid
*fh
,
87 int fh_len
, int fh_type
)
89 fid_t
*fid
= (fid_t
*)fh
;
90 fstrans_cookie_t cookie
;
94 len_bytes
= fh_len
* sizeof (__u32
);
96 if (fh_type
!= FILEID_INO32_GEN
||
97 len_bytes
< offsetof(fid_t
, fid_data
) ||
98 len_bytes
< offsetof(fid_t
, fid_data
) + fid
->fid_len
)
99 return (ERR_PTR(-EINVAL
));
101 cookie
= spl_fstrans_mark();
102 rc
= zfs_vget(sb
, &ip
, fid
);
103 spl_fstrans_unmark(cookie
);
107 * If we see ENOENT it might mean that an NFSv4 * client
108 * is using a cached inode value in a file handle and
109 * that the sought after file has had its inode changed
110 * by a third party. So change the error to ESTALE
111 * which will trigger a full lookup by the client and
112 * will find the new filename/inode pair if it still
118 return (ERR_PTR(-rc
));
121 ASSERT((ip
!= NULL
) && !IS_ERR(ip
));
123 return (zpl_dentry_obtain_alias(ip
));
126 static struct dentry
*
127 zpl_get_parent(struct dentry
*child
)
130 fstrans_cookie_t cookie
;
135 cookie
= spl_fstrans_mark();
136 error
= -zfs_lookup(child
->d_inode
, "..", &ip
, 0, cr
, NULL
, NULL
);
137 spl_fstrans_unmark(cookie
);
139 ASSERT3S(error
, <=, 0);
142 return (ERR_PTR(error
));
144 return (zpl_dentry_obtain_alias(ip
));
147 #ifdef HAVE_COMMIT_METADATA
149 zpl_commit_metadata(struct inode
*inode
)
152 fstrans_cookie_t cookie
;
155 if (zfsctl_is_node(inode
))
159 cookie
= spl_fstrans_mark();
160 error
= -zfs_fsync(inode
, 0, cr
);
161 spl_fstrans_unmark(cookie
);
163 ASSERT3S(error
, <=, 0);
167 #endif /* HAVE_COMMIT_METADATA */
169 const struct export_operations zpl_export_operations
= {
170 .encode_fh
= zpl_encode_fh
,
171 .fh_to_dentry
= zpl_fh_to_dentry
,
172 .get_parent
= zpl_get_parent
,
173 #ifdef HAVE_COMMIT_METADATA
174 .commit_metadata
= zpl_commit_metadata
,
175 #endif /* HAVE_COMMIT_METADATA */