Whamcloud - gitweb
land b_md onto HEAD. the highlights:
[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_ctx,
45                struct obd_ucred *uc)
46 {
47         //ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n");
48         ASSERT_CTXT_MAGIC(new_ctx->magic);
49         OBD_SET_CTXT_MAGIC(save);
50
51         /*
52         CDEBUG(D_INFO, "== push %p->%p == cur fs %p pwd %p (%*s), pwdmnt %p\n",
53                save, current, current->fs, current->fs->pwd,
54                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
55                current->fs->pwdmnt);
56         */
57
58         save->fs = get_fs();
59         save->pwd = dget(current->fs->pwd);
60         save->pwdmnt = mntget(current->fs->pwdmnt);
61
62         LASSERT(save->pwd);
63         LASSERT(save->pwdmnt);
64         LASSERT(new_ctx->pwd);
65         LASSERT(new_ctx->pwdmnt);
66
67         if (uc) {
68                 save->fsuid = current->fsuid;
69                 save->fsgid = current->fsgid;
70                 save->cap = current->cap_effective;
71
72                 current->fsuid = uc->ouc_fsuid;
73                 current->fsgid = uc->ouc_fsgid;
74                 current->cap_effective = uc->ouc_cap;
75         }
76         set_fs(new_ctx->fs);
77         set_fs_pwd(current->fs, new_ctx->pwdmnt, new_ctx->pwd);
78
79         /*
80         CDEBUG(D_INFO, "== push %p==%p == cur fs %p pwd %p (%*s), pwdmnt %p\n",
81                new_ctx, current, current->fs, current->fs->pwd,
82                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
83                current->fs->pwdmnt);
84         */
85 }
86
87 void pop_ctxt(struct obd_run_ctxt *saved, struct obd_run_ctxt *new_ctx,
88               struct obd_ucred *uc)
89 {
90         //printk("pc0");
91         ASSERT_CTXT_MAGIC(saved->magic);
92         //printk("pc1");
93         ASSERT_KERNEL_CTXT("popping non-kernel context!\n");
94
95         /*
96         CDEBUG(D_INFO, " == pop  %p==%p == cur %p pwd %p (%*s), pwdmnt %p\n",
97                new_ctx, current, current->fs, current->fs->pwd,
98                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
99                current->fs->pwdmnt);
100         */
101
102         LASSERT(current->fs->pwd == new_ctx->pwd);
103         LASSERT(current->fs->pwdmnt == new_ctx->pwdmnt);
104
105         //printk("pc2");
106         set_fs(saved->fs);
107         //printk("pc3\n");
108         set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
109         //printk("pc4");
110
111         dput(saved->pwd);
112         //printk("pc5");
113         mntput(saved->pwdmnt);
114         //printk("pc6\n");
115         if (uc) {
116                 current->fsuid = saved->fsuid;
117                 current->fsgid = saved->fsgid;
118                 current->cap_effective = saved->cap;
119         }
120
121         /*
122         CDEBUG(D_INFO, "== pop  %p->%p == cur fs %p pwd %p (%*s), pwdmnt %p\n",
123                saved, current, current->fs, current->fs->pwd,
124                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
125                current->fs->pwdmnt);
126         */
127 }
128
129 /* utility to make a file */
130 struct dentry *simple_mknod(struct dentry *dir, char *name, int mode)
131 {
132         struct dentry *dchild;
133         int err = 0;
134         ENTRY;
135
136         ASSERT_KERNEL_CTXT("kernel doing mknod outside kernel context\n");
137         CDEBUG(D_INODE, "creating file %*s\n", (int)strlen(name), name);
138
139         down(&dir->d_inode->i_sem);
140         dchild = lookup_one_len(name, dir, strlen(name));
141         if (IS_ERR(dchild))
142                 GOTO(out_up, dchild);
143
144         if (dchild->d_inode) {
145                 if ((dchild->d_inode->i_mode & S_IFMT) != S_IFREG)
146                         GOTO(out_err, err = -EEXIST);
147
148                 GOTO(out_up, dchild);
149         }
150
151         err = vfs_create(dir->d_inode, dchild, (mode & ~S_IFMT) | S_IFREG);
152         if (err)
153                 GOTO(out_err, err);
154
155         up(&dir->d_inode->i_sem);
156         RETURN(dchild);
157
158 out_err:
159         dput(dchild);
160         dchild = ERR_PTR(err);
161 out_up:
162         up(&dir->d_inode->i_sem);
163         return dchild;
164 }
165
166 /* utility to make a directory */
167 struct dentry *simple_mkdir(struct dentry *dir, char *name, int mode)
168 {
169         struct dentry *dchild;
170         int err = 0;
171         ENTRY;
172
173         ASSERT_KERNEL_CTXT("kernel doing mkdir outside kernel context\n");
174         CDEBUG(D_INODE, "creating directory %*s\n", (int)strlen(name), name);
175         down(&dir->d_inode->i_sem);
176         dchild = lookup_one_len(name, dir, strlen(name));
177         if (IS_ERR(dchild))
178                 GOTO(out_up, dchild);
179
180         if (dchild->d_inode) {
181                 if (!S_ISDIR(dchild->d_inode->i_mode))
182                         GOTO(out_err, err = -ENOTDIR);
183
184                 GOTO(out_up, dchild);
185         }
186
187         err = vfs_mkdir(dir->d_inode, dchild, mode);
188         if (err)
189                 GOTO(out_err, err);
190
191         up(&dir->d_inode->i_sem);
192         RETURN(dchild);
193
194 out_err:
195         dput(dchild);
196         dchild = ERR_PTR(err);
197 out_up:
198         up(&dir->d_inode->i_sem);
199         return dchild;
200 }
201
202 /*
203  * Read a file from within kernel context.  Prior to calling this
204  * function we should already have done a push_ctxt().
205  */
206 int lustre_fread(struct file *file, char *str, int len, loff_t *off)
207 {
208         ASSERT_KERNEL_CTXT("kernel doing read outside kernel context\n");
209         if (!file || !file->f_op || !file->f_op->read || !off)
210                 RETURN(-ENOSYS);
211
212         return file->f_op->read(file, str, len, off);
213 }
214
215 /*
216  * Write a file from within kernel context.  Prior to calling this
217  * function we should already have done a push_ctxt().
218  */
219 int lustre_fwrite(struct file *file, const char *str, int len, loff_t *off)
220 {
221         ASSERT_KERNEL_CTXT("kernel doing write outside kernel context\n");
222         if (!file || !file->f_op || !off)
223                 RETURN(-ENOSYS);
224
225         if (!file->f_op->write)
226                 RETURN(-EROFS);
227
228         return file->f_op->write(file, str, len, off);
229 }
230
231 /*
232  * Sync a file from within kernel context.  Prior to calling this
233  * function we should already have done a push_ctxt().
234  */
235 int lustre_fsync(struct file *file)
236 {
237         ASSERT_KERNEL_CTXT("kernel doing sync outside kernel context\n");
238         if (!file || !file->f_op || !file->f_op->fsync)
239                 RETURN(-ENOSYS);
240
241         return file->f_op->fsync(file, file->f_dentry, 0);
242 }