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