xref: /openbmc/linux/fs/orangefs/namei.c (revision 274dcf55bd4ab12af1cc1d3b77416285bef8ebf4)
1*274dcf55SMike Marshall /*
2*274dcf55SMike Marshall  * (C) 2001 Clemson University and The University of Chicago
3*274dcf55SMike Marshall  *
4*274dcf55SMike Marshall  * See COPYING in top-level directory.
5*274dcf55SMike Marshall  */
6*274dcf55SMike Marshall 
7*274dcf55SMike Marshall /*
8*274dcf55SMike Marshall  *  Linux VFS namei operations.
9*274dcf55SMike Marshall  */
10*274dcf55SMike Marshall 
11*274dcf55SMike Marshall #include "protocol.h"
12*274dcf55SMike Marshall #include "pvfs2-kernel.h"
13*274dcf55SMike Marshall 
14*274dcf55SMike Marshall /*
15*274dcf55SMike Marshall  * Get a newly allocated inode to go with a negative dentry.
16*274dcf55SMike Marshall  */
17*274dcf55SMike Marshall static int pvfs2_create(struct inode *dir,
18*274dcf55SMike Marshall 			struct dentry *dentry,
19*274dcf55SMike Marshall 			umode_t mode,
20*274dcf55SMike Marshall 			bool exclusive)
21*274dcf55SMike Marshall {
22*274dcf55SMike Marshall 	struct pvfs2_inode_s *parent = PVFS2_I(dir);
23*274dcf55SMike Marshall 	struct pvfs2_kernel_op_s *new_op;
24*274dcf55SMike Marshall 	struct inode *inode;
25*274dcf55SMike Marshall 	int ret;
26*274dcf55SMike Marshall 
27*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG, "%s: called\n", __func__);
28*274dcf55SMike Marshall 
29*274dcf55SMike Marshall 	new_op = op_alloc(PVFS2_VFS_OP_CREATE);
30*274dcf55SMike Marshall 	if (!new_op)
31*274dcf55SMike Marshall 		return -ENOMEM;
32*274dcf55SMike Marshall 
33*274dcf55SMike Marshall 	new_op->upcall.req.create.parent_refn = parent->refn;
34*274dcf55SMike Marshall 
35*274dcf55SMike Marshall 	fill_default_sys_attrs(new_op->upcall.req.create.attributes,
36*274dcf55SMike Marshall 			       PVFS_TYPE_METAFILE, mode);
37*274dcf55SMike Marshall 
38*274dcf55SMike Marshall 	strncpy(new_op->upcall.req.create.d_name,
39*274dcf55SMike Marshall 		dentry->d_name.name, PVFS2_NAME_LEN);
40*274dcf55SMike Marshall 
41*274dcf55SMike Marshall 	ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
42*274dcf55SMike Marshall 
43*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
44*274dcf55SMike Marshall 		     "Create Got PVFS2 handle %pU on fsid %d (ret=%d)\n",
45*274dcf55SMike Marshall 		     &new_op->downcall.resp.create.refn.khandle,
46*274dcf55SMike Marshall 		     new_op->downcall.resp.create.refn.fs_id, ret);
47*274dcf55SMike Marshall 
48*274dcf55SMike Marshall 	if (ret < 0) {
49*274dcf55SMike Marshall 		gossip_debug(GOSSIP_NAME_DEBUG,
50*274dcf55SMike Marshall 			     "%s: failed with error code %d\n",
51*274dcf55SMike Marshall 			     __func__, ret);
52*274dcf55SMike Marshall 		goto out;
53*274dcf55SMike Marshall 	}
54*274dcf55SMike Marshall 
55*274dcf55SMike Marshall 	inode = pvfs2_new_inode(dir->i_sb, dir, S_IFREG | mode, 0,
56*274dcf55SMike Marshall 				&new_op->downcall.resp.create.refn);
57*274dcf55SMike Marshall 	if (IS_ERR(inode)) {
58*274dcf55SMike Marshall 		gossip_err("*** Failed to allocate pvfs2 file inode\n");
59*274dcf55SMike Marshall 		ret = PTR_ERR(inode);
60*274dcf55SMike Marshall 		goto out;
61*274dcf55SMike Marshall 	}
62*274dcf55SMike Marshall 
63*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
64*274dcf55SMike Marshall 		     "Assigned file inode new number of %pU\n",
65*274dcf55SMike Marshall 		     get_khandle_from_ino(inode));
66*274dcf55SMike Marshall 
67*274dcf55SMike Marshall 	d_instantiate(dentry, inode);
68*274dcf55SMike Marshall 	unlock_new_inode(inode);
69*274dcf55SMike Marshall 
70*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
71*274dcf55SMike Marshall 		     "Inode (Regular File) %pU -> %s\n",
72*274dcf55SMike Marshall 		     get_khandle_from_ino(inode),
73*274dcf55SMike Marshall 		     dentry->d_name.name);
74*274dcf55SMike Marshall 
75*274dcf55SMike Marshall 	SetMtimeFlag(parent);
76*274dcf55SMike Marshall 	dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
77*274dcf55SMike Marshall 	mark_inode_dirty_sync(dir);
78*274dcf55SMike Marshall 	ret = 0;
79*274dcf55SMike Marshall out:
80*274dcf55SMike Marshall 	op_release(new_op);
81*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG, "%s: returning %d\n", __func__, ret);
82*274dcf55SMike Marshall 	return ret;
83*274dcf55SMike Marshall }
84*274dcf55SMike Marshall 
85*274dcf55SMike Marshall /*
86*274dcf55SMike Marshall  * Attempt to resolve an object name (dentry->d_name), parent handle, and
87*274dcf55SMike Marshall  * fsid into a handle for the object.
88*274dcf55SMike Marshall  */
89*274dcf55SMike Marshall static struct dentry *pvfs2_lookup(struct inode *dir, struct dentry *dentry,
90*274dcf55SMike Marshall 				   unsigned int flags)
91*274dcf55SMike Marshall {
92*274dcf55SMike Marshall 	struct pvfs2_inode_s *parent = PVFS2_I(dir);
93*274dcf55SMike Marshall 	struct pvfs2_kernel_op_s *new_op;
94*274dcf55SMike Marshall 	struct inode *inode;
95*274dcf55SMike Marshall 	struct dentry *res;
96*274dcf55SMike Marshall 	int ret = -EINVAL;
97*274dcf55SMike Marshall 
98*274dcf55SMike Marshall 	/*
99*274dcf55SMike Marshall 	 * in theory we could skip a lookup here (if the intent is to
100*274dcf55SMike Marshall 	 * create) in order to avoid a potentially failed lookup, but
101*274dcf55SMike Marshall 	 * leaving it in can skip a valid lookup and try to create a file
102*274dcf55SMike Marshall 	 * that already exists (e.g. the vfs already handles checking for
103*274dcf55SMike Marshall 	 * -EEXIST on O_EXCL opens, which is broken if we skip this lookup
104*274dcf55SMike Marshall 	 * in the create path)
105*274dcf55SMike Marshall 	 */
106*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG, "%s called on %s\n",
107*274dcf55SMike Marshall 		     __func__, dentry->d_name.name);
108*274dcf55SMike Marshall 
109*274dcf55SMike Marshall 	if (dentry->d_name.len > (PVFS2_NAME_LEN - 1))
110*274dcf55SMike Marshall 		return ERR_PTR(-ENAMETOOLONG);
111*274dcf55SMike Marshall 
112*274dcf55SMike Marshall 	new_op = op_alloc(PVFS2_VFS_OP_LOOKUP);
113*274dcf55SMike Marshall 	if (!new_op)
114*274dcf55SMike Marshall 		return ERR_PTR(-ENOMEM);
115*274dcf55SMike Marshall 
116*274dcf55SMike Marshall 	new_op->upcall.req.lookup.sym_follow = flags & LOOKUP_FOLLOW;
117*274dcf55SMike Marshall 
118*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG, "%s:%s:%d using parent %pU\n",
119*274dcf55SMike Marshall 		     __FILE__,
120*274dcf55SMike Marshall 		     __func__,
121*274dcf55SMike Marshall 		     __LINE__,
122*274dcf55SMike Marshall 		     &parent->refn.khandle);
123*274dcf55SMike Marshall 	new_op->upcall.req.lookup.parent_refn = parent->refn;
124*274dcf55SMike Marshall 
125*274dcf55SMike Marshall 	strncpy(new_op->upcall.req.lookup.d_name, dentry->d_name.name,
126*274dcf55SMike Marshall 		PVFS2_NAME_LEN);
127*274dcf55SMike Marshall 
128*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
129*274dcf55SMike Marshall 		     "%s: doing lookup on %s under %pU,%d (follow=%s)\n",
130*274dcf55SMike Marshall 		     __func__,
131*274dcf55SMike Marshall 		     new_op->upcall.req.lookup.d_name,
132*274dcf55SMike Marshall 		     &new_op->upcall.req.lookup.parent_refn.khandle,
133*274dcf55SMike Marshall 		     new_op->upcall.req.lookup.parent_refn.fs_id,
134*274dcf55SMike Marshall 		     ((new_op->upcall.req.lookup.sym_follow ==
135*274dcf55SMike Marshall 		       PVFS2_LOOKUP_LINK_FOLLOW) ? "yes" : "no"));
136*274dcf55SMike Marshall 
137*274dcf55SMike Marshall 	ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
138*274dcf55SMike Marshall 
139*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
140*274dcf55SMike Marshall 		     "Lookup Got %pU, fsid %d (ret=%d)\n",
141*274dcf55SMike Marshall 		     &new_op->downcall.resp.lookup.refn.khandle,
142*274dcf55SMike Marshall 		     new_op->downcall.resp.lookup.refn.fs_id,
143*274dcf55SMike Marshall 		     ret);
144*274dcf55SMike Marshall 
145*274dcf55SMike Marshall 	if (ret < 0) {
146*274dcf55SMike Marshall 		if (ret == -ENOENT) {
147*274dcf55SMike Marshall 			/*
148*274dcf55SMike Marshall 			 * if no inode was found, add a negative dentry to
149*274dcf55SMike Marshall 			 * dcache anyway; if we don't, we don't hold expected
150*274dcf55SMike Marshall 			 * lookup semantics and we most noticeably break
151*274dcf55SMike Marshall 			 * during directory renames.
152*274dcf55SMike Marshall 			 *
153*274dcf55SMike Marshall 			 * however, if the operation failed or exited, do not
154*274dcf55SMike Marshall 			 * add the dentry (e.g. in the case that a touch is
155*274dcf55SMike Marshall 			 * issued on a file that already exists that was
156*274dcf55SMike Marshall 			 * interrupted during this lookup -- no need to add
157*274dcf55SMike Marshall 			 * another negative dentry for an existing file)
158*274dcf55SMike Marshall 			 */
159*274dcf55SMike Marshall 
160*274dcf55SMike Marshall 			gossip_debug(GOSSIP_NAME_DEBUG,
161*274dcf55SMike Marshall 				     "pvfs2_lookup: Adding *negative* dentry "
162*274dcf55SMike Marshall 				     "%p for %s\n",
163*274dcf55SMike Marshall 				     dentry,
164*274dcf55SMike Marshall 				     dentry->d_name.name);
165*274dcf55SMike Marshall 
166*274dcf55SMike Marshall 			d_add(dentry, NULL);
167*274dcf55SMike Marshall 			res = NULL;
168*274dcf55SMike Marshall 			goto out;
169*274dcf55SMike Marshall 		}
170*274dcf55SMike Marshall 
171*274dcf55SMike Marshall 		/* must be a non-recoverable error */
172*274dcf55SMike Marshall 		res = ERR_PTR(ret);
173*274dcf55SMike Marshall 		goto out;
174*274dcf55SMike Marshall 	}
175*274dcf55SMike Marshall 
176*274dcf55SMike Marshall 	inode = pvfs2_iget(dir->i_sb, &new_op->downcall.resp.lookup.refn);
177*274dcf55SMike Marshall 	if (IS_ERR(inode)) {
178*274dcf55SMike Marshall 		gossip_debug(GOSSIP_NAME_DEBUG,
179*274dcf55SMike Marshall 			"error %ld from iget\n", PTR_ERR(inode));
180*274dcf55SMike Marshall 		res = ERR_CAST(inode);
181*274dcf55SMike Marshall 		goto out;
182*274dcf55SMike Marshall 	}
183*274dcf55SMike Marshall 
184*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
185*274dcf55SMike Marshall 		     "%s:%s:%d "
186*274dcf55SMike Marshall 		     "Found good inode [%lu] with count [%d]\n",
187*274dcf55SMike Marshall 		     __FILE__,
188*274dcf55SMike Marshall 		     __func__,
189*274dcf55SMike Marshall 		     __LINE__,
190*274dcf55SMike Marshall 		     inode->i_ino,
191*274dcf55SMike Marshall 		     (int)atomic_read(&inode->i_count));
192*274dcf55SMike Marshall 
193*274dcf55SMike Marshall 	/* update dentry/inode pair into dcache */
194*274dcf55SMike Marshall 	res = d_splice_alias(inode, dentry);
195*274dcf55SMike Marshall 
196*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
197*274dcf55SMike Marshall 		     "Lookup success (inode ct = %d)\n",
198*274dcf55SMike Marshall 		     (int)atomic_read(&inode->i_count));
199*274dcf55SMike Marshall out:
200*274dcf55SMike Marshall 	op_release(new_op);
201*274dcf55SMike Marshall 	return res;
202*274dcf55SMike Marshall }
203*274dcf55SMike Marshall 
204*274dcf55SMike Marshall /* return 0 on success; non-zero otherwise */
205*274dcf55SMike Marshall static int pvfs2_unlink(struct inode *dir, struct dentry *dentry)
206*274dcf55SMike Marshall {
207*274dcf55SMike Marshall 	struct inode *inode = dentry->d_inode;
208*274dcf55SMike Marshall 	struct pvfs2_inode_s *parent = PVFS2_I(dir);
209*274dcf55SMike Marshall 	struct pvfs2_kernel_op_s *new_op;
210*274dcf55SMike Marshall 	int ret;
211*274dcf55SMike Marshall 
212*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
213*274dcf55SMike Marshall 		     "%s: called on %s\n"
214*274dcf55SMike Marshall 		     "  (inode %pU): Parent is %pU | fs_id %d\n",
215*274dcf55SMike Marshall 		     __func__,
216*274dcf55SMike Marshall 		     dentry->d_name.name,
217*274dcf55SMike Marshall 		     get_khandle_from_ino(inode),
218*274dcf55SMike Marshall 		     &parent->refn.khandle,
219*274dcf55SMike Marshall 		     parent->refn.fs_id);
220*274dcf55SMike Marshall 
221*274dcf55SMike Marshall 	new_op = op_alloc(PVFS2_VFS_OP_REMOVE);
222*274dcf55SMike Marshall 	if (!new_op)
223*274dcf55SMike Marshall 		return -ENOMEM;
224*274dcf55SMike Marshall 
225*274dcf55SMike Marshall 	new_op->upcall.req.remove.parent_refn = parent->refn;
226*274dcf55SMike Marshall 	strncpy(new_op->upcall.req.remove.d_name, dentry->d_name.name,
227*274dcf55SMike Marshall 		PVFS2_NAME_LEN);
228*274dcf55SMike Marshall 
229*274dcf55SMike Marshall 	ret = service_operation(new_op, "pvfs2_unlink",
230*274dcf55SMike Marshall 				get_interruptible_flag(inode));
231*274dcf55SMike Marshall 
232*274dcf55SMike Marshall 	/* when request is serviced properly, free req op struct */
233*274dcf55SMike Marshall 	op_release(new_op);
234*274dcf55SMike Marshall 
235*274dcf55SMike Marshall 	if (!ret) {
236*274dcf55SMike Marshall 		drop_nlink(inode);
237*274dcf55SMike Marshall 
238*274dcf55SMike Marshall 		SetMtimeFlag(parent);
239*274dcf55SMike Marshall 		dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
240*274dcf55SMike Marshall 		mark_inode_dirty_sync(dir);
241*274dcf55SMike Marshall 	}
242*274dcf55SMike Marshall 	return ret;
243*274dcf55SMike Marshall }
244*274dcf55SMike Marshall 
245*274dcf55SMike Marshall /*
246*274dcf55SMike Marshall  * pvfs2_link() is only implemented here to make sure that we return a
247*274dcf55SMike Marshall  * reasonable error code (the kernel will return a misleading EPERM
248*274dcf55SMike Marshall  * otherwise).  PVFS2 does not support hard links.
249*274dcf55SMike Marshall  */
250*274dcf55SMike Marshall static int pvfs2_link(struct dentry *old_dentry,
251*274dcf55SMike Marshall 		      struct inode *dir,
252*274dcf55SMike Marshall 		      struct dentry *dentry)
253*274dcf55SMike Marshall {
254*274dcf55SMike Marshall 	return -EOPNOTSUPP;
255*274dcf55SMike Marshall }
256*274dcf55SMike Marshall 
257*274dcf55SMike Marshall /*
258*274dcf55SMike Marshall  * pvfs2_mknod() is only implemented here to make sure that we return a
259*274dcf55SMike Marshall  * reasonable error code (the kernel will return a misleading EPERM
260*274dcf55SMike Marshall  * otherwise).  PVFS2 does not support special files such as fifos or devices.
261*274dcf55SMike Marshall  */
262*274dcf55SMike Marshall static int pvfs2_mknod(struct inode *dir,
263*274dcf55SMike Marshall 		       struct dentry *dentry,
264*274dcf55SMike Marshall 		       umode_t mode,
265*274dcf55SMike Marshall 		       dev_t rdev)
266*274dcf55SMike Marshall {
267*274dcf55SMike Marshall 	return -EOPNOTSUPP;
268*274dcf55SMike Marshall }
269*274dcf55SMike Marshall 
270*274dcf55SMike Marshall static int pvfs2_symlink(struct inode *dir,
271*274dcf55SMike Marshall 			 struct dentry *dentry,
272*274dcf55SMike Marshall 			 const char *symname)
273*274dcf55SMike Marshall {
274*274dcf55SMike Marshall 	struct pvfs2_inode_s *parent = PVFS2_I(dir);
275*274dcf55SMike Marshall 	struct pvfs2_kernel_op_s *new_op;
276*274dcf55SMike Marshall 	struct inode *inode;
277*274dcf55SMike Marshall 	int mode = 755;
278*274dcf55SMike Marshall 	int ret;
279*274dcf55SMike Marshall 
280*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG, "%s: called\n", __func__);
281*274dcf55SMike Marshall 
282*274dcf55SMike Marshall 	if (!symname)
283*274dcf55SMike Marshall 		return -EINVAL;
284*274dcf55SMike Marshall 
285*274dcf55SMike Marshall 	new_op = op_alloc(PVFS2_VFS_OP_SYMLINK);
286*274dcf55SMike Marshall 	if (!new_op)
287*274dcf55SMike Marshall 		return -ENOMEM;
288*274dcf55SMike Marshall 
289*274dcf55SMike Marshall 	new_op->upcall.req.sym.parent_refn = parent->refn;
290*274dcf55SMike Marshall 
291*274dcf55SMike Marshall 	fill_default_sys_attrs(new_op->upcall.req.sym.attributes,
292*274dcf55SMike Marshall 			       PVFS_TYPE_SYMLINK,
293*274dcf55SMike Marshall 			       mode);
294*274dcf55SMike Marshall 
295*274dcf55SMike Marshall 	strncpy(new_op->upcall.req.sym.entry_name,
296*274dcf55SMike Marshall 		dentry->d_name.name,
297*274dcf55SMike Marshall 		PVFS2_NAME_LEN);
298*274dcf55SMike Marshall 	strncpy(new_op->upcall.req.sym.target, symname, PVFS2_NAME_LEN);
299*274dcf55SMike Marshall 
300*274dcf55SMike Marshall 	ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
301*274dcf55SMike Marshall 
302*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
303*274dcf55SMike Marshall 		     "Symlink Got PVFS2 handle %pU on fsid %d (ret=%d)\n",
304*274dcf55SMike Marshall 		     &new_op->downcall.resp.sym.refn.khandle,
305*274dcf55SMike Marshall 		     new_op->downcall.resp.sym.refn.fs_id, ret);
306*274dcf55SMike Marshall 
307*274dcf55SMike Marshall 	if (ret < 0) {
308*274dcf55SMike Marshall 		gossip_debug(GOSSIP_NAME_DEBUG,
309*274dcf55SMike Marshall 			    "%s: failed with error code %d\n",
310*274dcf55SMike Marshall 			    __func__, ret);
311*274dcf55SMike Marshall 		goto out;
312*274dcf55SMike Marshall 	}
313*274dcf55SMike Marshall 
314*274dcf55SMike Marshall 	inode = pvfs2_new_inode(dir->i_sb, dir, S_IFLNK | mode, 0,
315*274dcf55SMike Marshall 				&new_op->downcall.resp.sym.refn);
316*274dcf55SMike Marshall 	if (IS_ERR(inode)) {
317*274dcf55SMike Marshall 		gossip_err
318*274dcf55SMike Marshall 		    ("*** Failed to allocate pvfs2 symlink inode\n");
319*274dcf55SMike Marshall 		ret = PTR_ERR(inode);
320*274dcf55SMike Marshall 		goto out;
321*274dcf55SMike Marshall 	}
322*274dcf55SMike Marshall 
323*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
324*274dcf55SMike Marshall 		     "Assigned symlink inode new number of %pU\n",
325*274dcf55SMike Marshall 		     get_khandle_from_ino(inode));
326*274dcf55SMike Marshall 
327*274dcf55SMike Marshall 	d_instantiate(dentry, inode);
328*274dcf55SMike Marshall 	unlock_new_inode(inode);
329*274dcf55SMike Marshall 
330*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
331*274dcf55SMike Marshall 		     "Inode (Symlink) %pU -> %s\n",
332*274dcf55SMike Marshall 		     get_khandle_from_ino(inode),
333*274dcf55SMike Marshall 		     dentry->d_name.name);
334*274dcf55SMike Marshall 
335*274dcf55SMike Marshall 	SetMtimeFlag(parent);
336*274dcf55SMike Marshall 	dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
337*274dcf55SMike Marshall 	mark_inode_dirty_sync(dir);
338*274dcf55SMike Marshall 	ret = 0;
339*274dcf55SMike Marshall out:
340*274dcf55SMike Marshall 	op_release(new_op);
341*274dcf55SMike Marshall 	return ret;
342*274dcf55SMike Marshall }
343*274dcf55SMike Marshall 
344*274dcf55SMike Marshall static int pvfs2_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
345*274dcf55SMike Marshall {
346*274dcf55SMike Marshall 	struct pvfs2_inode_s *parent = PVFS2_I(dir);
347*274dcf55SMike Marshall 	struct pvfs2_kernel_op_s *new_op;
348*274dcf55SMike Marshall 	struct inode *inode;
349*274dcf55SMike Marshall 	int ret;
350*274dcf55SMike Marshall 
351*274dcf55SMike Marshall 	new_op = op_alloc(PVFS2_VFS_OP_MKDIR);
352*274dcf55SMike Marshall 	if (!new_op)
353*274dcf55SMike Marshall 		return -ENOMEM;
354*274dcf55SMike Marshall 
355*274dcf55SMike Marshall 	new_op->upcall.req.mkdir.parent_refn = parent->refn;
356*274dcf55SMike Marshall 
357*274dcf55SMike Marshall 	fill_default_sys_attrs(new_op->upcall.req.mkdir.attributes,
358*274dcf55SMike Marshall 			       PVFS_TYPE_DIRECTORY, mode);
359*274dcf55SMike Marshall 
360*274dcf55SMike Marshall 	strncpy(new_op->upcall.req.mkdir.d_name,
361*274dcf55SMike Marshall 		dentry->d_name.name, PVFS2_NAME_LEN);
362*274dcf55SMike Marshall 
363*274dcf55SMike Marshall 	ret = service_operation(new_op, __func__, get_interruptible_flag(dir));
364*274dcf55SMike Marshall 
365*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
366*274dcf55SMike Marshall 		     "Mkdir Got PVFS2 handle %pU on fsid %d\n",
367*274dcf55SMike Marshall 		     &new_op->downcall.resp.mkdir.refn.khandle,
368*274dcf55SMike Marshall 		     new_op->downcall.resp.mkdir.refn.fs_id);
369*274dcf55SMike Marshall 
370*274dcf55SMike Marshall 	if (ret < 0) {
371*274dcf55SMike Marshall 		gossip_debug(GOSSIP_NAME_DEBUG,
372*274dcf55SMike Marshall 			     "%s: failed with error code %d\n",
373*274dcf55SMike Marshall 			     __func__, ret);
374*274dcf55SMike Marshall 		goto out;
375*274dcf55SMike Marshall 	}
376*274dcf55SMike Marshall 
377*274dcf55SMike Marshall 	inode = pvfs2_new_inode(dir->i_sb, dir, S_IFDIR | mode, 0,
378*274dcf55SMike Marshall 				&new_op->downcall.resp.mkdir.refn);
379*274dcf55SMike Marshall 	if (IS_ERR(inode)) {
380*274dcf55SMike Marshall 		gossip_err("*** Failed to allocate pvfs2 dir inode\n");
381*274dcf55SMike Marshall 		ret = PTR_ERR(inode);
382*274dcf55SMike Marshall 		goto out;
383*274dcf55SMike Marshall 	}
384*274dcf55SMike Marshall 
385*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
386*274dcf55SMike Marshall 		     "Assigned dir inode new number of %pU\n",
387*274dcf55SMike Marshall 		     get_khandle_from_ino(inode));
388*274dcf55SMike Marshall 
389*274dcf55SMike Marshall 	d_instantiate(dentry, inode);
390*274dcf55SMike Marshall 	unlock_new_inode(inode);
391*274dcf55SMike Marshall 
392*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
393*274dcf55SMike Marshall 		     "Inode (Directory) %pU -> %s\n",
394*274dcf55SMike Marshall 		     get_khandle_from_ino(inode),
395*274dcf55SMike Marshall 		     dentry->d_name.name);
396*274dcf55SMike Marshall 
397*274dcf55SMike Marshall 	/*
398*274dcf55SMike Marshall 	 * NOTE: we have no good way to keep nlink consistent for directories
399*274dcf55SMike Marshall 	 * across clients; keep constant at 1.
400*274dcf55SMike Marshall 	 */
401*274dcf55SMike Marshall 	SetMtimeFlag(parent);
402*274dcf55SMike Marshall 	dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
403*274dcf55SMike Marshall 	mark_inode_dirty_sync(dir);
404*274dcf55SMike Marshall out:
405*274dcf55SMike Marshall 	op_release(new_op);
406*274dcf55SMike Marshall 	return ret;
407*274dcf55SMike Marshall }
408*274dcf55SMike Marshall 
409*274dcf55SMike Marshall static int pvfs2_rename(struct inode *old_dir,
410*274dcf55SMike Marshall 			struct dentry *old_dentry,
411*274dcf55SMike Marshall 			struct inode *new_dir,
412*274dcf55SMike Marshall 			struct dentry *new_dentry)
413*274dcf55SMike Marshall {
414*274dcf55SMike Marshall 	struct pvfs2_kernel_op_s *new_op;
415*274dcf55SMike Marshall 	int ret;
416*274dcf55SMike Marshall 
417*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
418*274dcf55SMike Marshall 		     "pvfs2_rename: called (%s/%s => %s/%s) ct=%d\n",
419*274dcf55SMike Marshall 		     old_dentry->d_parent->d_name.name,
420*274dcf55SMike Marshall 		     old_dentry->d_name.name,
421*274dcf55SMike Marshall 		     new_dentry->d_parent->d_name.name,
422*274dcf55SMike Marshall 		     new_dentry->d_name.name,
423*274dcf55SMike Marshall 		     d_count(new_dentry));
424*274dcf55SMike Marshall 
425*274dcf55SMike Marshall 	new_op = op_alloc(PVFS2_VFS_OP_RENAME);
426*274dcf55SMike Marshall 	if (!new_op)
427*274dcf55SMike Marshall 		return -EINVAL;
428*274dcf55SMike Marshall 
429*274dcf55SMike Marshall 	new_op->upcall.req.rename.old_parent_refn = PVFS2_I(old_dir)->refn;
430*274dcf55SMike Marshall 	new_op->upcall.req.rename.new_parent_refn = PVFS2_I(new_dir)->refn;
431*274dcf55SMike Marshall 
432*274dcf55SMike Marshall 	strncpy(new_op->upcall.req.rename.d_old_name,
433*274dcf55SMike Marshall 		old_dentry->d_name.name,
434*274dcf55SMike Marshall 		PVFS2_NAME_LEN);
435*274dcf55SMike Marshall 	strncpy(new_op->upcall.req.rename.d_new_name,
436*274dcf55SMike Marshall 		new_dentry->d_name.name,
437*274dcf55SMike Marshall 		PVFS2_NAME_LEN);
438*274dcf55SMike Marshall 
439*274dcf55SMike Marshall 	ret = service_operation(new_op,
440*274dcf55SMike Marshall 				"pvfs2_rename",
441*274dcf55SMike Marshall 				get_interruptible_flag(old_dentry->d_inode));
442*274dcf55SMike Marshall 
443*274dcf55SMike Marshall 	gossip_debug(GOSSIP_NAME_DEBUG,
444*274dcf55SMike Marshall 		     "pvfs2_rename: got downcall status %d\n",
445*274dcf55SMike Marshall 		     ret);
446*274dcf55SMike Marshall 
447*274dcf55SMike Marshall 	if (new_dentry->d_inode)
448*274dcf55SMike Marshall 		new_dentry->d_inode->i_ctime = CURRENT_TIME;
449*274dcf55SMike Marshall 
450*274dcf55SMike Marshall 	op_release(new_op);
451*274dcf55SMike Marshall 	return ret;
452*274dcf55SMike Marshall }
453*274dcf55SMike Marshall 
454*274dcf55SMike Marshall /* PVFS2 implementation of VFS inode operations for directories */
455*274dcf55SMike Marshall struct inode_operations pvfs2_dir_inode_operations = {
456*274dcf55SMike Marshall 	.lookup = pvfs2_lookup,
457*274dcf55SMike Marshall 	.get_acl = pvfs2_get_acl,
458*274dcf55SMike Marshall 	.set_acl = pvfs2_set_acl,
459*274dcf55SMike Marshall 	.create = pvfs2_create,
460*274dcf55SMike Marshall 	.link = pvfs2_link,
461*274dcf55SMike Marshall 	.unlink = pvfs2_unlink,
462*274dcf55SMike Marshall 	.symlink = pvfs2_symlink,
463*274dcf55SMike Marshall 	.mkdir = pvfs2_mkdir,
464*274dcf55SMike Marshall 	.rmdir = pvfs2_unlink,
465*274dcf55SMike Marshall 	.mknod = pvfs2_mknod,
466*274dcf55SMike Marshall 	.rename = pvfs2_rename,
467*274dcf55SMike Marshall 	.setattr = pvfs2_setattr,
468*274dcf55SMike Marshall 	.getattr = pvfs2_getattr,
469*274dcf55SMike Marshall 	.setxattr = generic_setxattr,
470*274dcf55SMike Marshall 	.getxattr = generic_getxattr,
471*274dcf55SMike Marshall 	.removexattr = generic_removexattr,
472*274dcf55SMike Marshall 	.listxattr = pvfs2_listxattr,
473*274dcf55SMike Marshall };
474