Whamcloud - gitweb
Fix comments, add declaration for simple_mknod().
[fs/lustre-release.git] / lustre / lib / simple.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lib/simple.c
5  *
6  * Copyright (C) 2002  Cluster File Systems, Inc.
7  *
8  * This code is issued under the GNU General Public License.
9  * See the file COPYING in this distribution
10  *
11  * by Peter Braam <braam@clusterfs.com>
12  * and Andreas Dilger <adilger@clusterfs.com>
13  */
14
15 #define EXPORT_SYMTAB
16
17 #include <linux/version.h>
18 #include <linux/fs.h>
19 #include <asm/unistd.h>
20
21 #define DEBUG_SUBSYSTEM S_FILTER
22
23 #include <linux/obd_support.h>
24 #include <linux/obd.h>
25 #include <linux/lustre_mds.h>
26 #include <linux/lustre_lib.h>
27 #include <linux/lustre_net.h>
28
29 #ifdef OBD_CTXT_DEBUG
30 /* Debugging check only needed during development */
31 #define ASSERT_CTXT_MAGIC(magic) do { if ((magic) != OBD_RUN_CTXT_MAGIC) { \
32                                 CERROR("bad ctxt magic\n"); LBUG(); } } while(0)
33 #define ASSERT_NOT_KERNEL_CTXT(msg) do { if (segment_eq(get_fs(), get_ds())) { \
34                                         CERROR(msg); LBUG(); } } while(0)
35 #define ASSERT_KERNEL_CTXT(msg) do { if (!segment_eq(get_fs(), get_ds())) { \
36                                         CERROR(msg); LBUG(); } } while(0)
37 #else
38 #define ASSERT_CTXT_MAGIC(magic) do {} while(0)
39 #define ASSERT_NOT_KERNEL_CTXT(msg) do {} while(0)
40 #define ASSERT_KERNEL_CTXT(msg) do {} while(0)
41 #endif
42
43 /* push / pop to root of obd store */
44 void push_ctxt(struct obd_run_ctxt *save, struct obd_run_ctxt *new)
45 {
46         //ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n");
47         ASSERT_CTXT_MAGIC(new->magic);
48         OBD_SET_CTXT_MAGIC(save);
49         save->fs = get_fs();
50         save->pwd = dget(current->fs->pwd);
51         save->pwdmnt = mntget(current->fs->pwdmnt);
52
53         LASSERT(save->pwd);
54         LASSERT(save->pwdmnt);
55         LASSERT(new->pwd);
56         LASSERT(new->pwdmnt);
57
58         set_fs(new->fs);
59         set_fs_pwd(current->fs, new->pwdmnt, new->pwd);
60 }
61
62 void pop_ctxt(struct obd_run_ctxt *saved)
63 {
64         //printk("pc0");
65         ASSERT_CTXT_MAGIC(saved->magic);
66         //printk("pc1");
67         ASSERT_KERNEL_CTXT("popping non-kernel context!\n");
68         //printk("pc2");
69         set_fs(saved->fs);
70         //printk("pc3\n");
71         set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
72         //printk("pc4");
73
74         dput(saved->pwd);
75         //printk("pc5");
76         mntput(saved->pwdmnt);
77         //printk("pc6\n");
78 }
79
80 /* utility to make a file */
81 struct dentry *simple_mknod(struct dentry *dir, char *name, int mode)
82 {
83         struct dentry *dchild;
84         int err = 0;
85         ENTRY;
86
87         ASSERT_KERNEL_CTXT("kernel doing mknod outside kernel context\n");
88         CDEBUG(D_INODE, "creating file %*s\n", (int)strlen(name), name);
89         down(&dir->d_inode->i_sem);
90         dchild = lookup_one_len(name, dir, strlen(name));
91         if (IS_ERR(dchild))
92                 GOTO(out, PTR_ERR(dchild));
93
94         if (dchild->d_inode) {
95                 if (!S_ISDIR(dchild->d_inode->i_mode))
96                         GOTO(out, err = -ENOTDIR);
97
98                 GOTO(out, dchild);
99         }
100
101         err = vfs_create(dir->d_inode, dchild, S_IFREG | mode);
102         EXIT;
103 out:
104         up(&dir->d_inode->i_sem);
105         if (err) {
106                 dput(dchild);
107                 RETURN(ERR_PTR(err));
108         }
109
110         RETURN(dchild);
111 }
112
113 /* utility to make a directory */
114 struct dentry *simple_mkdir(struct dentry *dir, char *name, int mode)
115 {
116         struct dentry *dchild;
117         int err = 0;
118         ENTRY;
119
120         ASSERT_KERNEL_CTXT("kernel doing mkdir outside kernel context\n");
121         CDEBUG(D_INODE, "creating directory %*s\n", (int)strlen(name), name);
122         down(&dir->d_inode->i_sem);
123         dchild = lookup_one_len(name, dir, strlen(name));
124         if (IS_ERR(dchild))
125                 GOTO(out, PTR_ERR(dchild));
126
127         if (dchild->d_inode) {
128                 if (!S_ISDIR(dchild->d_inode->i_mode))
129                         GOTO(out, err = -ENOTDIR);
130
131                 GOTO(out, dchild);
132         }
133
134         err = vfs_mkdir(dir->d_inode, dchild, mode);
135         EXIT;
136 out:
137         up(&dir->d_inode->i_sem);
138         if (err) {
139                 dput(dchild);
140                 RETURN(ERR_PTR(err));
141         }
142
143         RETURN(dchild);
144 }
145
146 /*
147  * Read a file from within kernel context.  Prior to calling this
148  * function we should already have done a push_ctxt().
149  */
150 int lustre_fread(struct file *file, char *str, int len, loff_t *off)
151 {
152         ASSERT_KERNEL_CTXT("kernel doing read outside kernel context\n");
153         if (!file || !file->f_op || !file->f_op->read || !off)
154                 RETURN(-ENOSYS);
155
156         return file->f_op->read(file, str, len, off);
157 }
158
159 /*
160  * Write a file from within kernel context.  Prior to calling this
161  * function we should already have done a push_ctxt().
162  */
163 int lustre_fwrite(struct file *file, const char *str, int len, loff_t *off)
164 {
165         ASSERT_KERNEL_CTXT("kernel doing write outside kernel context\n");
166         if (!file || !file->f_op || !off)
167                 RETURN(-ENOSYS);
168
169         if (!file->f_op->write)
170                 RETURN(-EROFS);
171
172         return file->f_op->write(file, str, len, off);
173 }
174
175 /*
176  * Sync a file from within kernel context.  Prior to calling this
177  * function we should already have done a push_ctxt().
178  */
179 int lustre_fsync(struct file *file)
180 {
181         ASSERT_KERNEL_CTXT("kernel doing sync outside kernel context\n");
182         if (!file || !file->f_op || !file->f_op->fsync)
183                 RETURN(-ENOSYS);
184
185         return file->f_op->fsync(file, file->f_dentry, 0);
186 }