1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * (C) 2001 Clemson University and The University of Chicago
4   *
5   * See COPYING in top-level directory.
6   */
7  
8  /*
9   *  Linux VFS namei operations.
10   */
11  
12  #include "protocol.h"
13  #include "orangefs-kernel.h"
14  
15  /*
16   * Get a newly allocated inode to go with a negative dentry.
17   */
orangefs_create(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode,bool exclusive)18  static int orangefs_create(struct mnt_idmap *idmap,
19  			struct inode *dir,
20  			struct dentry *dentry,
21  			umode_t mode,
22  			bool exclusive)
23  {
24  	struct orangefs_inode_s *parent = ORANGEFS_I(dir);
25  	struct orangefs_kernel_op_s *new_op;
26  	struct orangefs_object_kref ref;
27  	struct inode *inode;
28  	struct iattr iattr;
29  	int ret;
30  
31  	gossip_debug(GOSSIP_NAME_DEBUG, "%s: %pd\n",
32  		     __func__,
33  		     dentry);
34  
35  	new_op = op_alloc(ORANGEFS_VFS_OP_CREATE);
36  	if (!new_op)
37  		return -ENOMEM;
38  
39  	new_op->upcall.req.create.parent_refn = parent->refn;
40  
41  	fill_default_sys_attrs(new_op->upcall.req.create.attributes,
42  			       ORANGEFS_TYPE_METAFILE, mode);
43  
44  	strscpy(new_op->upcall.req.create.d_name, dentry->d_name.name);
45  
46  	ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
47  
48  	gossip_debug(GOSSIP_NAME_DEBUG,
49  		     "%s: %pd: handle:%pU: fsid:%d: new_op:%p: ret:%d:\n",
50  		     __func__,
51  		     dentry,
52  		     &new_op->downcall.resp.create.refn.khandle,
53  		     new_op->downcall.resp.create.refn.fs_id,
54  		     new_op,
55  		     ret);
56  
57  	if (ret < 0)
58  		goto out;
59  
60  	ref = new_op->downcall.resp.create.refn;
61  
62  	inode = orangefs_new_inode(dir->i_sb, dir, S_IFREG | mode, 0, &ref);
63  	if (IS_ERR(inode)) {
64  		gossip_err("%s: Failed to allocate inode for file :%pd:\n",
65  			   __func__,
66  			   dentry);
67  		ret = PTR_ERR(inode);
68  		goto out;
69  	}
70  
71  	gossip_debug(GOSSIP_NAME_DEBUG,
72  		     "%s: Assigned inode :%pU: for file :%pd:\n",
73  		     __func__,
74  		     get_khandle_from_ino(inode),
75  		     dentry);
76  
77  	d_instantiate_new(dentry, inode);
78  	orangefs_set_timeout(dentry);
79  
80  	gossip_debug(GOSSIP_NAME_DEBUG,
81  		     "%s: dentry instantiated for %pd\n",
82  		     __func__,
83  		     dentry);
84  
85  	memset(&iattr, 0, sizeof iattr);
86  	iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
87  	iattr.ia_mtime = iattr.ia_ctime = current_time(dir);
88  	__orangefs_setattr(dir, &iattr);
89  	ret = 0;
90  out:
91  	op_release(new_op);
92  	gossip_debug(GOSSIP_NAME_DEBUG,
93  		     "%s: %pd: returning %d\n",
94  		     __func__,
95  		     dentry,
96  		     ret);
97  	return ret;
98  }
99  
100  /*
101   * Attempt to resolve an object name (dentry->d_name), parent handle, and
102   * fsid into a handle for the object.
103   */
orangefs_lookup(struct inode * dir,struct dentry * dentry,unsigned int flags)104  static struct dentry *orangefs_lookup(struct inode *dir, struct dentry *dentry,
105  				   unsigned int flags)
106  {
107  	struct orangefs_inode_s *parent = ORANGEFS_I(dir);
108  	struct orangefs_kernel_op_s *new_op;
109  	struct inode *inode;
110  	int ret = -EINVAL;
111  
112  	/*
113  	 * in theory we could skip a lookup here (if the intent is to
114  	 * create) in order to avoid a potentially failed lookup, but
115  	 * leaving it in can skip a valid lookup and try to create a file
116  	 * that already exists (e.g. the vfs already handles checking for
117  	 * -EEXIST on O_EXCL opens, which is broken if we skip this lookup
118  	 * in the create path)
119  	 */
120  	gossip_debug(GOSSIP_NAME_DEBUG, "%s called on %pd\n",
121  		     __func__, dentry);
122  
123  	if (dentry->d_name.len > (ORANGEFS_NAME_MAX - 1))
124  		return ERR_PTR(-ENAMETOOLONG);
125  
126  	new_op = op_alloc(ORANGEFS_VFS_OP_LOOKUP);
127  	if (!new_op)
128  		return ERR_PTR(-ENOMEM);
129  
130  	new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW;
131  
132  	gossip_debug(GOSSIP_NAME_DEBUG, "%s:%s:%d using parent %pU\n",
133  		     __FILE__,
134  		     __func__,
135  		     __LINE__,
136  		     &parent->refn.khandle);
137  	new_op->upcall.req.lookup.parent_refn = parent->refn;
138  
139  	strscpy(new_op->upcall.req.lookup.d_name, dentry->d_name.name);
140  
141  	gossip_debug(GOSSIP_NAME_DEBUG,
142  		     "%s: doing lookup on %s under %pU,%d\n",
143  		     __func__,
144  		     new_op->upcall.req.lookup.d_name,
145  		     &new_op->upcall.req.lookup.parent_refn.khandle,
146  		     new_op->upcall.req.lookup.parent_refn.fs_id);
147  
148  	ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
149  
150  	gossip_debug(GOSSIP_NAME_DEBUG,
151  		     "Lookup Got %pU, fsid %d (ret=%d)\n",
152  		     &new_op->downcall.resp.lookup.refn.khandle,
153  		     new_op->downcall.resp.lookup.refn.fs_id,
154  		     ret);
155  
156  	if (ret == 0) {
157  		orangefs_set_timeout(dentry);
158  		inode = orangefs_iget(dir->i_sb, &new_op->downcall.resp.lookup.refn);
159  	} else if (ret == -ENOENT) {
160  		inode = NULL;
161  	} else {
162  		/* must be a non-recoverable error */
163  		inode = ERR_PTR(ret);
164  	}
165  
166  	op_release(new_op);
167  	return d_splice_alias(inode, dentry);
168  }
169  
170  /* return 0 on success; non-zero otherwise */
orangefs_unlink(struct inode * dir,struct dentry * dentry)171  static int orangefs_unlink(struct inode *dir, struct dentry *dentry)
172  {
173  	struct inode *inode = dentry->d_inode;
174  	struct orangefs_inode_s *parent = ORANGEFS_I(dir);
175  	struct orangefs_kernel_op_s *new_op;
176  	struct iattr iattr;
177  	int ret;
178  
179  	gossip_debug(GOSSIP_NAME_DEBUG,
180  		     "%s: called on %pd\n"
181  		     "  (inode %pU): Parent is %pU | fs_id %d\n",
182  		     __func__,
183  		     dentry,
184  		     get_khandle_from_ino(inode),
185  		     &parent->refn.khandle,
186  		     parent->refn.fs_id);
187  
188  	new_op = op_alloc(ORANGEFS_VFS_OP_REMOVE);
189  	if (!new_op)
190  		return -ENOMEM;
191  
192  	new_op->upcall.req.remove.parent_refn = parent->refn;
193  	strscpy(new_op->upcall.req.remove.d_name, dentry->d_name.name);
194  
195  	ret = service_operation(new_op, "orangefs_unlink",
196  				get_interruptible_flag(inode));
197  
198  	gossip_debug(GOSSIP_NAME_DEBUG,
199  		     "%s: service_operation returned:%d:\n",
200  		     __func__,
201  		     ret);
202  
203  	op_release(new_op);
204  
205  	if (!ret) {
206  		drop_nlink(inode);
207  
208  		memset(&iattr, 0, sizeof iattr);
209  		iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
210  		iattr.ia_mtime = iattr.ia_ctime = current_time(dir);
211  		__orangefs_setattr(dir, &iattr);
212  	}
213  	return ret;
214  }
215  
orangefs_symlink(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,const char * symname)216  static int orangefs_symlink(struct mnt_idmap *idmap,
217  		         struct inode *dir,
218  			 struct dentry *dentry,
219  			 const char *symname)
220  {
221  	struct orangefs_inode_s *parent = ORANGEFS_I(dir);
222  	struct orangefs_kernel_op_s *new_op;
223  	struct orangefs_object_kref ref;
224  	struct inode *inode;
225  	struct iattr iattr;
226  	int mode = 0755;
227  	int ret;
228  
229  	gossip_debug(GOSSIP_NAME_DEBUG, "%s: called\n", __func__);
230  
231  	if (!symname)
232  		return -EINVAL;
233  
234  	if (strlen(symname)+1 > ORANGEFS_NAME_MAX)
235  		return -ENAMETOOLONG;
236  
237  	new_op = op_alloc(ORANGEFS_VFS_OP_SYMLINK);
238  	if (!new_op)
239  		return -ENOMEM;
240  
241  	new_op->upcall.req.sym.parent_refn = parent->refn;
242  
243  	fill_default_sys_attrs(new_op->upcall.req.sym.attributes,
244  			       ORANGEFS_TYPE_SYMLINK,
245  			       mode);
246  
247  	strscpy(new_op->upcall.req.sym.entry_name, dentry->d_name.name);
248  	strscpy(new_op->upcall.req.sym.target, symname);
249  
250  	ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
251  
252  	gossip_debug(GOSSIP_NAME_DEBUG,
253  		     "Symlink Got ORANGEFS handle %pU on fsid %d (ret=%d)\n",
254  		     &new_op->downcall.resp.sym.refn.khandle,
255  		     new_op->downcall.resp.sym.refn.fs_id, ret);
256  
257  	if (ret < 0) {
258  		gossip_debug(GOSSIP_NAME_DEBUG,
259  			    "%s: failed with error code %d\n",
260  			    __func__, ret);
261  		goto out;
262  	}
263  
264  	ref = new_op->downcall.resp.sym.refn;
265  
266  	inode = orangefs_new_inode(dir->i_sb, dir, S_IFLNK | mode, 0, &ref);
267  	if (IS_ERR(inode)) {
268  		gossip_err
269  		    ("*** Failed to allocate orangefs symlink inode\n");
270  		ret = PTR_ERR(inode);
271  		goto out;
272  	}
273  	/*
274  	 * This is necessary because orangefs_inode_getattr will not
275  	 * re-read symlink size as it is impossible for it to change.
276  	 * Invalidating the cache does not help.  orangefs_new_inode
277  	 * does not set the correct size (it does not know symname).
278  	 */
279  	inode->i_size = strlen(symname);
280  
281  	gossip_debug(GOSSIP_NAME_DEBUG,
282  		     "Assigned symlink inode new number of %pU\n",
283  		     get_khandle_from_ino(inode));
284  
285  	d_instantiate_new(dentry, inode);
286  	orangefs_set_timeout(dentry);
287  
288  	gossip_debug(GOSSIP_NAME_DEBUG,
289  		     "Inode (Symlink) %pU -> %pd\n",
290  		     get_khandle_from_ino(inode),
291  		     dentry);
292  
293  	memset(&iattr, 0, sizeof iattr);
294  	iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
295  	iattr.ia_mtime = iattr.ia_ctime = current_time(dir);
296  	__orangefs_setattr(dir, &iattr);
297  	ret = 0;
298  out:
299  	op_release(new_op);
300  	return ret;
301  }
302  
orangefs_mkdir(struct mnt_idmap * idmap,struct inode * dir,struct dentry * dentry,umode_t mode)303  static int orangefs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
304  			  struct dentry *dentry, umode_t mode)
305  {
306  	struct orangefs_inode_s *parent = ORANGEFS_I(dir);
307  	struct orangefs_kernel_op_s *new_op;
308  	struct orangefs_object_kref ref;
309  	struct inode *inode;
310  	struct iattr iattr;
311  	int ret;
312  
313  	new_op = op_alloc(ORANGEFS_VFS_OP_MKDIR);
314  	if (!new_op)
315  		return -ENOMEM;
316  
317  	new_op->upcall.req.mkdir.parent_refn = parent->refn;
318  
319  	fill_default_sys_attrs(new_op->upcall.req.mkdir.attributes,
320  			      ORANGEFS_TYPE_DIRECTORY, mode);
321  
322  	strscpy(new_op->upcall.req.mkdir.d_name, dentry->d_name.name);
323  
324  	ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
325  
326  	gossip_debug(GOSSIP_NAME_DEBUG,
327  		     "Mkdir Got ORANGEFS handle %pU on fsid %d\n",
328  		     &new_op->downcall.resp.mkdir.refn.khandle,
329  		     new_op->downcall.resp.mkdir.refn.fs_id);
330  
331  	if (ret < 0) {
332  		gossip_debug(GOSSIP_NAME_DEBUG,
333  			     "%s: failed with error code %d\n",
334  			     __func__, ret);
335  		goto out;
336  	}
337  
338  	ref = new_op->downcall.resp.mkdir.refn;
339  
340  	inode = orangefs_new_inode(dir->i_sb, dir, S_IFDIR | mode, 0, &ref);
341  	if (IS_ERR(inode)) {
342  		gossip_err("*** Failed to allocate orangefs dir inode\n");
343  		ret = PTR_ERR(inode);
344  		goto out;
345  	}
346  
347  	gossip_debug(GOSSIP_NAME_DEBUG,
348  		     "Assigned dir inode new number of %pU\n",
349  		     get_khandle_from_ino(inode));
350  
351  	d_instantiate_new(dentry, inode);
352  	orangefs_set_timeout(dentry);
353  
354  	gossip_debug(GOSSIP_NAME_DEBUG,
355  		     "Inode (Directory) %pU -> %pd\n",
356  		     get_khandle_from_ino(inode),
357  		     dentry);
358  
359  	/*
360  	 * NOTE: we have no good way to keep nlink consistent for directories
361  	 * across clients; keep constant at 1.
362  	 */
363  	memset(&iattr, 0, sizeof iattr);
364  	iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
365  	iattr.ia_mtime = iattr.ia_ctime = current_time(dir);
366  	__orangefs_setattr(dir, &iattr);
367  out:
368  	op_release(new_op);
369  	return ret;
370  }
371  
orangefs_rename(struct mnt_idmap * idmap,struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,unsigned int flags)372  static int orangefs_rename(struct mnt_idmap *idmap,
373  			struct inode *old_dir,
374  			struct dentry *old_dentry,
375  			struct inode *new_dir,
376  			struct dentry *new_dentry,
377  			unsigned int flags)
378  {
379  	struct orangefs_kernel_op_s *new_op;
380  	struct iattr iattr;
381  	int ret;
382  
383  	if (flags)
384  		return -EINVAL;
385  
386  	gossip_debug(GOSSIP_NAME_DEBUG,
387  		     "orangefs_rename: called (%pd2 => %pd2) ct=%d\n",
388  		     old_dentry, new_dentry, d_count(new_dentry));
389  
390  	memset(&iattr, 0, sizeof iattr);
391  	iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
392  	iattr.ia_mtime = iattr.ia_ctime = current_time(new_dir);
393  	__orangefs_setattr(new_dir, &iattr);
394  
395  	new_op = op_alloc(ORANGEFS_VFS_OP_RENAME);
396  	if (!new_op)
397  		return -EINVAL;
398  
399  	new_op->upcall.req.rename.old_parent_refn = ORANGEFS_I(old_dir)->refn;
400  	new_op->upcall.req.rename.new_parent_refn = ORANGEFS_I(new_dir)->refn;
401  
402  	strscpy(new_op->upcall.req.rename.d_old_name, old_dentry->d_name.name);
403  	strscpy(new_op->upcall.req.rename.d_new_name, new_dentry->d_name.name);
404  
405  	ret = service_operation(new_op,
406  				"orangefs_rename",
407  				get_interruptible_flag(old_dentry->d_inode));
408  
409  	gossip_debug(GOSSIP_NAME_DEBUG,
410  		     "orangefs_rename: got downcall status %d\n",
411  		     ret);
412  
413  	if (new_dentry->d_inode)
414  		inode_set_ctime_current(d_inode(new_dentry));
415  
416  	op_release(new_op);
417  	return ret;
418  }
419  
420  /* ORANGEFS implementation of VFS inode operations for directories */
421  const struct inode_operations orangefs_dir_inode_operations = {
422  	.lookup = orangefs_lookup,
423  	.get_inode_acl = orangefs_get_acl,
424  	.set_acl = orangefs_set_acl,
425  	.create = orangefs_create,
426  	.unlink = orangefs_unlink,
427  	.symlink = orangefs_symlink,
428  	.mkdir = orangefs_mkdir,
429  	.rmdir = orangefs_unlink,
430  	.rename = orangefs_rename,
431  	.setattr = orangefs_setattr,
432  	.getattr = orangefs_getattr,
433  	.listxattr = orangefs_listxattr,
434  	.permission = orangefs_permission,
435  	.update_time = orangefs_update_time,
436  };
437