Whamcloud - gitweb
landing smfs.
[fs/lustre-release.git] / lustre / obdclass / simple.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2002, 2003 Cluster File Systems, Inc.
5  *  Author: Peter Braam <braam@clusterfs.com>
6  *  Aurhot: Andreas Dilger <adilger@clusterfs.com>
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #ifndef EXPORT_SYMTAB
25 # define EXPORT_SYMTAB
26 #endif
27
28 #include <linux/version.h>
29 #include <linux/fs.h>
30 #include <asm/unistd.h>
31
32 #define DEBUG_SUBSYSTEM S_FILTER
33
34 #include <linux/obd.h>
35 #include <linux/lustre_lib.h>
36 #include <linux/lustre_compat25.h>
37
38 /* Debugging check only needed during development */
39 #ifdef OBD_CTXT_DEBUG
40 # define ASSERT_CTXT_MAGIC(magic) LASSERT((magic) == OBD_RUN_CTXT_MAGIC)
41 # define ASSERT_NOT_KERNEL_CTXT(msg) LASSERT(!segment_eq(get_fs(), get_ds()))
42 # define ASSERT_KERNEL_CTXT(msg) LASSERT(segment_eq(get_fs(), get_ds()))
43 #else
44 # define ASSERT_CTXT_MAGIC(magic) do {} while(0)
45 # define ASSERT_NOT_KERNEL_CTXT(msg) do {} while(0)
46 # define ASSERT_KERNEL_CTXT(msg) do {} while(0)
47 #endif
48
49 /* push / pop to root of obd store */
50 void push_ctxt(struct lvfs_run_ctxt *save, struct lvfs_run_ctxt *new_ctx,
51                struct lvfs_ucred *uc)
52 {
53         //ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n");
54         ASSERT_CTXT_MAGIC(new_ctx->magic);
55         OBD_SET_CTXT_MAGIC(save);
56
57         /*
58         CDEBUG(D_INFO,
59                "= push %p->%p = cur fs %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
60                save, current, current->fs, current->fs->pwd,
61                atomic_read(&current->fs->pwd->d_count),
62                atomic_read(&current->fs->pwd->d_inode->i_count),
63                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
64                current->fs->pwdmnt,
65                atomic_read(&current->fs->pwdmnt->mnt_count));
66         */
67
68         save->fs = get_fs();
69         LASSERT(atomic_read(&current->fs->pwd->d_count));
70         LASSERT(atomic_read(&new_ctx->pwd->d_count));
71         save->pwd = dget(current->fs->pwd);
72         save->pwdmnt = mntget(current->fs->pwdmnt);
73         save->ngroups = current->ngroups;
74
75         LASSERT(save->pwd);
76         LASSERT(save->pwdmnt);
77         LASSERT(new_ctx->pwd);
78         LASSERT(new_ctx->pwdmnt);
79
80         if (uc) {
81                 save->luc.luc_fsuid = current->fsuid;
82                 save->luc.luc_fsgid = current->fsgid;
83                 save->luc.luc_cap = current->cap_effective;
84                 save->luc.luc_suppgid1 = current->groups[0];
85                 save->luc.luc_suppgid2 = current->groups[1];
86
87                 current->fsuid = uc->luc_fsuid;
88                 current->fsgid = uc->luc_fsgid;
89                 current->cap_effective = uc->luc_cap;
90                 current->ngroups = 0;
91
92                 if (uc->luc_suppgid1 != -1)
93                         current->groups[current->ngroups++] = uc->luc_suppgid1;
94                 if (uc->luc_suppgid2 != -1)
95                         current->groups[current->ngroups++] = uc->luc_suppgid2;
96         }
97         set_fs(new_ctx->fs);
98         set_fs_pwd(current->fs, new_ctx->pwdmnt, new_ctx->pwd);
99
100         /*
101         CDEBUG(D_INFO,
102                "= push %p->%p = cur fs %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
103                new_ctx, current, current->fs, current->fs->pwd,
104                atomic_read(&current->fs->pwd->d_count),
105                atomic_read(&current->fs->pwd->d_inode->i_count),
106                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
107                current->fs->pwdmnt,
108                atomic_read(&current->fs->pwdmnt->mnt_count));
109         */
110 }
111 EXPORT_SYMBOL(push_ctxt);
112
113 void pop_ctxt(struct lvfs_run_ctxt *saved, struct lvfs_run_ctxt *new_ctx,
114               struct lvfs_ucred *uc)
115 {
116         //printk("pc0");
117         ASSERT_CTXT_MAGIC(saved->magic);
118         //printk("pc1");
119         ASSERT_KERNEL_CTXT("popping non-kernel context!\n");
120
121         /*
122         CDEBUG(D_INFO,
123                " = pop  %p==%p = cur %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
124                new_ctx, current, current->fs, current->fs->pwd,
125                atomic_read(&current->fs->pwd->d_count),
126                atomic_read(&current->fs->pwd->d_inode->i_count),
127                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
128                current->fs->pwdmnt,
129                atomic_read(&current->fs->pwdmnt->mnt_count));
130         */
131
132         LASSERT(current->fs->pwd == new_ctx->pwd);
133         LASSERT(current->fs->pwdmnt == new_ctx->pwdmnt);
134
135         set_fs(saved->fs);
136         set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
137
138         dput(saved->pwd);
139         mntput(saved->pwdmnt);
140         if (uc) {
141                 current->fsuid = saved->luc.luc_fsuid;
142                 current->fsgid = saved->luc.luc_fsgid;
143                 current->cap_effective = saved->luc.luc_cap;
144                 current->ngroups = saved->ngroups;
145                 current->groups[0] = saved->luc.luc_suppgid1;
146                 current->groups[1] = saved->luc.luc_suppgid2;
147         }
148
149         /*
150         CDEBUG(D_INFO,
151                "= pop  %p->%p = cur fs %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
152                saved, current, current->fs, current->fs->pwd,
153                atomic_read(&current->fs->pwd->d_count),
154                atomic_read(&current->fs->pwd->d_inode->i_count),
155                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
156                current->fs->pwdmnt,
157                atomic_read(&current->fs->pwdmnt->mnt_count));
158         */
159 }
160 EXPORT_SYMBOL(pop_ctxt);
161
162 /* utility to make a file */
163 struct dentry *simple_mknod(struct dentry *dir, char *name, int mode)
164 {
165         struct dentry *dchild;
166         int err = 0;
167         ENTRY;
168
169         ASSERT_KERNEL_CTXT("kernel doing mknod outside kernel context\n");
170         CDEBUG(D_INODE, "creating file %*s\n", (int)strlen(name), name);
171
172         dchild = ll_lookup_one_len(name, dir, strlen(name));
173         if (IS_ERR(dchild))
174                 GOTO(out_up, dchild);
175
176         if (dchild->d_inode) {
177                 if (!S_ISREG(dchild->d_inode->i_mode))
178                         GOTO(out_err, err = -EEXIST);
179
180                 GOTO(out_up, dchild);
181         }
182
183         err = ll_vfs_create(dir->d_inode, dchild, (mode & ~S_IFMT) | S_IFREG, NULL);
184         if (err)
185                 GOTO(out_err, err);
186
187         RETURN(dchild);
188
189 out_err:
190         dput(dchild);
191         dchild = ERR_PTR(err);
192 out_up:
193         return dchild;
194 }
195 EXPORT_SYMBOL(simple_mknod);
196
197 /* utility to make a directory */
198 struct dentry *simple_mkdir(struct dentry *dir, char *name, int mode)
199 {
200         struct dentry *dchild;
201         int err = 0;
202         ENTRY;
203
204         ASSERT_KERNEL_CTXT("kernel doing mkdir outside kernel context\n");
205         CDEBUG(D_INODE, "creating directory %*s\n", (int)strlen(name), name);
206         dchild = ll_lookup_one_len(name, dir, strlen(name));
207         if (IS_ERR(dchild))
208                 GOTO(out_up, dchild);
209
210         if (dchild->d_inode) {
211                 if (!S_ISDIR(dchild->d_inode->i_mode))
212                         GOTO(out_err, err = -ENOTDIR);
213
214                 GOTO(out_up, dchild);
215         }
216
217         err = vfs_mkdir(dir->d_inode, dchild, mode);
218         if (err)
219                 GOTO(out_err, err);
220
221         RETURN(dchild);
222
223 out_err:
224         dput(dchild);
225         dchild = ERR_PTR(err);
226 out_up:
227         return dchild;
228 }
229 EXPORT_SYMBOL(simple_mkdir);
230
231 /*
232  * Read a file from within kernel context.  Prior to calling this
233  * function we should already have done a push_ctxt().
234  */
235 int lustre_fread(struct file *file, void *buf, int len, loff_t *off)
236 {
237         ASSERT_KERNEL_CTXT("kernel doing read outside kernel context\n");
238         if (!file || !file->f_op || !file->f_op->read || !off)
239                 RETURN(-ENOSYS);
240
241         return file->f_op->read(file, buf, len, off);
242 }
243 EXPORT_SYMBOL(lustre_fread);
244
245 /*
246  * Write a file from within kernel context.  Prior to calling this
247  * function we should already have done a push_ctxt().
248  */
249 int lustre_fwrite(struct file *file, const void *buf, int len, loff_t *off)
250 {
251         ENTRY;
252         ASSERT_KERNEL_CTXT("kernel doing write outside kernel context\n");
253         if (!file)
254                 RETURN(-ENOENT);
255         if (!file->f_op)
256                 RETURN(-ENOSYS);
257         if (!off)
258                 RETURN(-EINVAL);
259
260         if (!file->f_op->write)
261                 RETURN(-EROFS);
262
263         RETURN(file->f_op->write(file, buf, len, off));
264 }
265 EXPORT_SYMBOL(lustre_fwrite);
266