1111#include "cifsproto.h"
1212#include "cifs_unicode.h"
1313#include "cifs_debug.h"
14+ #include "fs_context.h"
1415#include "reparse.h"
1516
1617int smb2_create_reparse_symlink (const unsigned int xid , struct inode * inode ,
@@ -68,7 +69,7 @@ int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
6869 iov .iov_base = buf ;
6970 iov .iov_len = len ;
7071 new = smb2_get_reparse_inode (& data , inode -> i_sb , xid ,
71- tcon , full_path , & iov );
72+ tcon , full_path , & iov , NULL );
7273 if (!IS_ERR (new ))
7374 d_instantiate (dentry , new );
7475 else
@@ -114,9 +115,9 @@ static int nfs_set_reparse_buf(struct reparse_posix_data *buf,
114115 return 0 ;
115116}
116117
117- int smb2_make_nfs_node (unsigned int xid , struct inode * inode ,
118- struct dentry * dentry , struct cifs_tcon * tcon ,
119- const char * full_path , umode_t mode , dev_t dev )
118+ static int mknod_nfs (unsigned int xid , struct inode * inode ,
119+ struct dentry * dentry , struct cifs_tcon * tcon ,
120+ const char * full_path , umode_t mode , dev_t dev )
120121{
121122 struct cifs_open_info_data data ;
122123 struct reparse_posix_data * p ;
@@ -136,12 +137,171 @@ int smb2_make_nfs_node(unsigned int xid, struct inode *inode,
136137 };
137138
138139 new = smb2_get_reparse_inode (& data , inode -> i_sb , xid ,
139- tcon , full_path , & iov );
140+ tcon , full_path , & iov , NULL );
141+ if (!IS_ERR (new ))
142+ d_instantiate (dentry , new );
143+ else
144+ rc = PTR_ERR (new );
145+ cifs_free_open_info (& data );
146+ return rc ;
147+ }
148+
149+ static int wsl_set_reparse_buf (struct reparse_data_buffer * buf ,
150+ mode_t mode , struct kvec * iov )
151+ {
152+ u32 tag ;
153+
154+ switch ((tag = reparse_mode_wsl_tag (mode ))) {
155+ case IO_REPARSE_TAG_LX_BLK :
156+ case IO_REPARSE_TAG_LX_CHR :
157+ case IO_REPARSE_TAG_LX_FIFO :
158+ case IO_REPARSE_TAG_AF_UNIX :
159+ break ;
160+ default :
161+ return - EOPNOTSUPP ;
162+ }
163+
164+ buf -> ReparseTag = cpu_to_le32 (tag );
165+ buf -> Reserved = 0 ;
166+ buf -> ReparseDataLength = 0 ;
167+ iov -> iov_base = buf ;
168+ iov -> iov_len = sizeof (* buf );
169+ return 0 ;
170+ }
171+
172+ static struct smb2_create_ea_ctx * ea_create_context (u32 dlen , size_t * cc_len )
173+ {
174+ struct smb2_create_ea_ctx * cc ;
175+
176+ * cc_len = round_up (sizeof (* cc ) + dlen , 8 );
177+ cc = kzalloc (* cc_len , GFP_KERNEL );
178+ if (!cc )
179+ return ERR_PTR (- ENOMEM );
180+
181+ cc -> ctx .NameOffset = cpu_to_le16 (offsetof(struct smb2_create_ea_ctx ,
182+ name ));
183+ cc -> ctx .NameLength = cpu_to_le16 (4 );
184+ memcpy (cc -> name , SMB2_CREATE_EA_BUFFER , strlen (SMB2_CREATE_EA_BUFFER ));
185+ cc -> ctx .DataOffset = cpu_to_le16 (offsetof(struct smb2_create_ea_ctx , ea ));
186+ cc -> ctx .DataLength = cpu_to_le32 (dlen );
187+ return cc ;
188+ }
189+
190+ struct wsl_xattr {
191+ const char * name ;
192+ __le64 value ;
193+ u16 size ;
194+ u32 next ;
195+ };
196+
197+ static int wsl_set_xattrs (struct inode * inode , umode_t _mode ,
198+ dev_t _dev , struct kvec * iov )
199+ {
200+ struct smb2_file_full_ea_info * ea ;
201+ struct smb2_create_ea_ctx * cc ;
202+ struct smb3_fs_context * ctx = CIFS_SB (inode -> i_sb )-> ctx ;
203+ __le64 uid = cpu_to_le64 (from_kuid (current_user_ns (), ctx -> linux_uid ));
204+ __le64 gid = cpu_to_le64 (from_kgid (current_user_ns (), ctx -> linux_gid ));
205+ __le64 dev = cpu_to_le64 (((u64 )MINOR (_dev ) << 32 ) | MAJOR (_dev ));
206+ __le64 mode = cpu_to_le64 (_mode );
207+ struct wsl_xattr xattrs [] = {
208+ { .name = "$LXUID" , .value = uid , .size = 4 , },
209+ { .name = "$LXGID" , .value = gid , .size = 4 , },
210+ { .name = "$LXMOD" , .value = mode , .size = 4 , },
211+ { .name = "$LXDEV" , .value = dev , .size = 8 , },
212+ };
213+ size_t cc_len ;
214+ u32 dlen = 0 , next = 0 ;
215+ int i , num_xattrs ;
216+ u8 name_size = strlen (xattrs [0 ].name ) + 1 ;
217+
218+ memset (iov , 0 , sizeof (* iov ));
219+
220+ /* Exclude $LXDEV xattr for sockets and fifos */
221+ if (S_ISSOCK (_mode ) || S_ISFIFO (_mode ))
222+ num_xattrs = ARRAY_SIZE (xattrs ) - 1 ;
223+ else
224+ num_xattrs = ARRAY_SIZE (xattrs );
225+
226+ for (i = 0 ; i < num_xattrs ; i ++ ) {
227+ xattrs [i ].next = ALIGN (sizeof (* ea ) + name_size +
228+ xattrs [i ].size , 4 );
229+ dlen += xattrs [i ].next ;
230+ }
231+
232+ cc = ea_create_context (dlen , & cc_len );
233+ if (!cc )
234+ return PTR_ERR (cc );
235+
236+ ea = & cc -> ea ;
237+ for (i = 0 ; i < num_xattrs ; i ++ ) {
238+ ea = (void * )((u8 * )ea + next );
239+ next = xattrs [i ].next ;
240+ ea -> next_entry_offset = cpu_to_le32 (next );
241+
242+ ea -> ea_name_length = name_size - 1 ;
243+ ea -> ea_value_length = cpu_to_le16 (xattrs [i ].size );
244+ memcpy (ea -> ea_data , xattrs [i ].name , name_size );
245+ memcpy (& ea -> ea_data [name_size ],
246+ & xattrs [i ].value , xattrs [i ].size );
247+ }
248+ ea -> next_entry_offset = 0 ;
249+
250+ iov -> iov_base = cc ;
251+ iov -> iov_len = cc_len ;
252+ return 0 ;
253+ }
254+
255+ static int mknod_wsl (unsigned int xid , struct inode * inode ,
256+ struct dentry * dentry , struct cifs_tcon * tcon ,
257+ const char * full_path , umode_t mode , dev_t dev )
258+ {
259+ struct cifs_open_info_data data ;
260+ struct reparse_data_buffer buf ;
261+ struct inode * new ;
262+ struct kvec reparse_iov , xattr_iov ;
263+ int rc ;
264+
265+ rc = wsl_set_reparse_buf (& buf , mode , & reparse_iov );
266+ if (rc )
267+ return rc ;
268+
269+ rc = wsl_set_xattrs (inode , mode , dev , & xattr_iov );
270+ if (rc )
271+ return rc ;
272+
273+ data = (struct cifs_open_info_data ) {
274+ .reparse_point = true,
275+ .reparse = { .tag = le32_to_cpu (buf .ReparseTag ), .buf = & buf , },
276+ };
277+
278+ new = smb2_get_reparse_inode (& data , inode -> i_sb ,
279+ xid , tcon , full_path ,
280+ & reparse_iov , & xattr_iov );
140281 if (!IS_ERR (new ))
141282 d_instantiate (dentry , new );
142283 else
143284 rc = PTR_ERR (new );
144285 cifs_free_open_info (& data );
286+ kfree (xattr_iov .iov_base );
287+ return rc ;
288+ }
289+
290+ int smb2_mknod_reparse (unsigned int xid , struct inode * inode ,
291+ struct dentry * dentry , struct cifs_tcon * tcon ,
292+ const char * full_path , umode_t mode , dev_t dev )
293+ {
294+ struct smb3_fs_context * ctx = CIFS_SB (inode -> i_sb )-> ctx ;
295+ int rc = - EOPNOTSUPP ;
296+
297+ switch (ctx -> reparse_type ) {
298+ case CIFS_REPARSE_TYPE_NFS :
299+ rc = mknod_nfs (xid , inode , dentry , tcon , full_path , mode , dev );
300+ break ;
301+ case CIFS_REPARSE_TYPE_WSL :
302+ rc = mknod_wsl (xid , inode , dentry , tcon , full_path , mode , dev );
303+ break ;
304+ }
145305 return rc ;
146306}
147307
0 commit comments