2 * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved.
4 * Portions based on Adam Richter's smalldevfs and thus
5 * Copyright 2002-2003 Yggdrasil Computing, Inc.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it would be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write the Free Software Foundation, Inc., 59
24 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
26 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
27 * Mountain View, CA 94043, or:
31 * For further information regarding this notice, see:
33 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
36 #include <linux/module.h>
37 #include <linux/kernel.h>
39 #include <linux/mount.h>
40 #include <linux/namei.h>
41 #include <linux/string.h>
42 #include <linux/slab.h>
43 #include <asm/sn/hwgfs.h>
46 extern struct vfsmount *hwgfs_vfsmount;
48 /* TODO: Move this to some .h file or, more likely, use a slightly
49 different interface from lookup_create. */
50 extern struct dentry *lookup_create(struct nameidata *nd, int is_dir);
59 char buf[strlen(*path)+1];
62 while ((slash = strchr(*path, '/')) != NULL) {
63 int len = slash - *path;
64 memcpy(buf, *path, len);
67 error = link_path_walk(buf, nd);
71 nd->dentry = lookup_create(nd, is_dir);
72 if (unlikely(IS_ERR(nd->dentry)))
73 return PTR_ERR(nd->dentry);
75 if (!nd->dentry->d_inode)
76 error = vfs_mkdir(nd->dentry->d_parent->d_inode,
79 up(&nd->dentry->d_parent->d_inode->i_sem);
89 /* On success, returns with parent_inode->i_sem taken. */
95 struct inode **parent_inode,
96 struct dentry **dentry)
102 dir = hwgfs_vfsmount->mnt_sb->s_root;
104 memset(&nd, 0, sizeof(nd));
105 nd.flags = LOOKUP_PARENT;
106 nd.mnt = mntget(hwgfs_vfsmount);
107 nd.dentry = dget(dir);
109 error = walk_parents_mkdir(&name, &nd, is_dir);
113 error = link_path_walk(name, &nd);
117 *dentry = lookup_create(&nd, is_dir);
119 if (unlikely(IS_ERR(*dentry)))
120 return PTR_ERR(*dentry);
121 *parent_inode = (*dentry)->d_parent->d_inode;
133 len += de->d_name.len + 1; /* count the '/' */
136 return len; /* -1 because we omit the leading '/',
137 +1 because we include trailing '\0' */
146 struct dentry *hwgfs_root;
148 char *path_orig = path;
150 if (unlikely(de == NULL))
153 hwgfs_root = hwgfs_vfsmount->mnt_sb->s_root;
154 if (unlikely(de == hwgfs_root))
157 spin_lock(&dcache_lock);
158 len = path_len(de, hwgfs_root);
160 spin_unlock(&dcache_lock);
161 return -ENAMETOOLONG;
168 path -= de->d_name.len;
169 memcpy(path, de->d_name.name, de->d_name.len);
171 if (de == hwgfs_root)
176 spin_unlock(&dcache_lock);
177 BUG_ON(path != path_orig);
192 dev_t devnum = MKDEV(major, minor);
193 struct inode *parent_inode;
194 struct dentry *dentry;
197 error = hwgfs_decode(dir, name, 0, &parent_inode, &dentry);
198 if (likely(!error)) {
199 error = vfs_mknod(parent_inode, dentry, mode, devnum);
200 if (likely(!error)) {
202 * Do this inside parents i_sem to avoid racing
206 dentry->d_inode->i_fop = ops;
207 dentry->d_fsdata = info;
208 up(&parent_inode->i_sem);
210 up(&parent_inode->i_sem);
225 hwgfs_handle_t *handle,
228 struct inode *parent_inode;
229 struct dentry *dentry;
232 error = hwgfs_decode(dir, name, 0, &parent_inode, &dentry);
233 if (likely(!error)) {
234 error = vfs_symlink(parent_inode, dentry, link);
235 dentry->d_fsdata = info;
238 up(&parent_inode->i_sem);
250 struct inode *parent_inode;
251 struct dentry *dentry;
254 error = hwgfs_decode(dir, name, 1, &parent_inode, &dentry);
255 if (likely(!error)) {
256 error = vfs_mkdir(parent_inode, dentry, 0755);
257 up(&parent_inode->i_sem);
259 if (unlikely(error)) {
263 dentry->d_fsdata = info;
273 struct inode *parent_inode = de->d_parent->d_inode;
275 if (S_ISDIR(de->d_inode->i_mode))
276 vfs_rmdir(parent_inode, de);
278 vfs_unlink(parent_inode, de);
281 /* XXX: this function is utterly bogus. Every use of it is racy and the
282 prototype is stupid. You have been warned. --hch. */
287 unsigned int major, /* IGNORED */
288 unsigned int minor, /* IGNORED */
289 char type, /* IGNORED */
290 int traverse_symlinks)
292 struct dentry *dentry = NULL;
298 memset(&nd, 0, sizeof(nd));
300 nd.mnt = mntget(hwgfs_vfsmount);
301 nd.dentry = dget(base ? base : hwgfs_vfsmount->mnt_sb->s_root);
302 if (traverse_symlinks)
303 nd.flags = LOOKUP_FOLLOW;
305 error = link_path_walk(name, &nd);
306 if (likely(!error)) {
308 path_release(&nd); /* stale data from here! */
318 struct dentry *parent;
320 spin_lock(&de->d_lock);
321 parent = de->d_parent;
322 spin_unlock(&de->d_lock);
332 if (unlikely(de == NULL))
345 EXPORT_SYMBOL(hwgfs_generate_path);
346 EXPORT_SYMBOL(hwgfs_register);
347 EXPORT_SYMBOL(hwgfs_unregister);
348 EXPORT_SYMBOL(hwgfs_mk_symlink);
349 EXPORT_SYMBOL(hwgfs_mk_dir);
350 EXPORT_SYMBOL(hwgfs_find_handle);
351 EXPORT_SYMBOL(hwgfs_get_parent);
352 EXPORT_SYMBOL(hwgfs_set_info);
353 EXPORT_SYMBOL(hwgfs_get_info);