Whamcloud - gitweb
- merge 0.7rc1 from b_devel to HEAD (20030612 merge point)
[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 #define EXPORT_SYMTAB
25
26 #include <linux/version.h>
27 #include <linux/fs.h>
28 #include <asm/unistd.h>
29
30 #define DEBUG_SUBSYSTEM S_FILTER
31
32 #include <linux/obd.h>
33 #include <linux/lustre_lib.h>
34
35 /* Debugging check only needed during development */
36 #ifdef OBD_CTXT_DEBUG
37 # define ASSERT_CTXT_MAGIC(magic) LASSERT((magic) == OBD_RUN_CTXT_MAGIC)
38 # define ASSERT_NOT_KERNEL_CTXT(msg) LASSERT(!segment_eq(get_fs(), get_ds()))
39 # define ASSERT_KERNEL_CTXT(msg) LASSERT(segment_eq(get_fs(), get_ds()))
40 #else
41 # define ASSERT_CTXT_MAGIC(magic) do {} while(0)
42 # define ASSERT_NOT_KERNEL_CTXT(msg) do {} while(0)
43 # define ASSERT_KERNEL_CTXT(msg) do {} while(0)
44 #endif
45
46 /* push / pop to root of obd store */
47 void push_ctxt(struct obd_run_ctxt *save, struct obd_run_ctxt *new_ctx,
48                struct obd_ucred *uc)
49 {
50         //ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n");
51         ASSERT_CTXT_MAGIC(new_ctx->magic);
52         OBD_SET_CTXT_MAGIC(save);
53
54         /*
55         CDEBUG(D_INFO,
56                "= push %p->%p = cur fs %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
57                save, current, current->fs, current->fs->pwd,
58                atomic_read(&current->fs->pwd->d_count),
59                atomic_read(&current->fs->pwd->d_inode->i_count),
60                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
61                current->fs->pwdmnt,
62                atomic_read(&current->fs->pwdmnt->mnt_count));
63         */
64
65         save->fs = get_fs();
66         LASSERT(atomic_read(&current->fs->pwd->d_count));
67         LASSERT(atomic_read(&new_ctx->pwd->d_count));
68         save->pwd = dget(current->fs->pwd);
69         save->pwdmnt = mntget(current->fs->pwdmnt);
70         save->ngroups = current->ngroups;
71
72         LASSERT(save->pwd);
73         LASSERT(save->pwdmnt);
74         LASSERT(new_ctx->pwd);
75         LASSERT(new_ctx->pwdmnt);
76
77         if (uc) {
78                 save->ouc.ouc_fsuid = current->fsuid;
79                 save->ouc.ouc_fsgid = current->fsgid;
80                 save->ouc.ouc_cap = current->cap_effective;
81                 save->ouc.ouc_suppgid1 = current->groups[0];
82                 save->ouc.ouc_suppgid2 = current->groups[1];
83
84                 current->fsuid = uc->ouc_fsuid;
85                 current->fsgid = uc->ouc_fsgid;
86                 current->cap_effective = uc->ouc_cap;
87                 current->ngroups = 0;
88
89                 if (uc->ouc_suppgid1 != -1)
90                         current->groups[current->ngroups++] = uc->ouc_suppgid1;
91                 if (uc->ouc_suppgid2 != -1)
92                         current->groups[current->ngroups++] = uc->ouc_suppgid2;
93         }
94         set_fs(new_ctx->fs);
95         set_fs_pwd(current->fs, new_ctx->pwdmnt, new_ctx->pwd);
96
97         /*
98         CDEBUG(D_INFO,
99                "= push %p->%p = cur fs %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
100                new_ctx, current, current->fs, current->fs->pwd,
101                atomic_read(&current->fs->pwd->d_count),
102                atomic_read(&current->fs->pwd->d_inode->i_count),
103                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
104                current->fs->pwdmnt,
105                atomic_read(&current->fs->pwdmnt->mnt_count));
106         */
107 }
108 EXPORT_SYMBOL(push_ctxt);
109
110 void pop_ctxt(struct obd_run_ctxt *saved, struct obd_run_ctxt *new_ctx,
111               struct obd_ucred *uc)
112 {
113         //printk("pc0");
114         ASSERT_CTXT_MAGIC(saved->magic);
115         //printk("pc1");
116         ASSERT_KERNEL_CTXT("popping non-kernel context!\n");
117
118         /*
119         CDEBUG(D_INFO,
120                " = pop  %p==%p = cur %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
121                new_ctx, current, current->fs, current->fs->pwd,
122                atomic_read(&current->fs->pwd->d_count),
123                atomic_read(&current->fs->pwd->d_inode->i_count),
124                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
125                current->fs->pwdmnt,
126                atomic_read(&current->fs->pwdmnt->mnt_count));
127         */
128
129         LASSERT(current->fs->pwd == new_ctx->pwd);
130         LASSERT(current->fs->pwdmnt == new_ctx->pwdmnt);
131
132         set_fs(saved->fs);
133         set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
134
135         dput(saved->pwd);
136         mntput(saved->pwdmnt);
137         if (uc) {
138                 current->fsuid = saved->ouc.ouc_fsuid;
139                 current->fsgid = saved->ouc.ouc_fsgid;
140                 current->cap_effective = saved->ouc.ouc_cap;
141                 current->ngroups = saved->ngroups;
142
143                 current->groups[0] = saved->ouc.ouc_suppgid1;
144                 current->groups[1] = saved->ouc.ouc_suppgid2;
145         }
146
147         /*
148         CDEBUG(D_INFO,
149                "= pop  %p->%p = cur fs %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
150                saved, current, current->fs, current->fs->pwd,
151                atomic_read(&current->fs->pwd->d_count),
152                atomic_read(&current->fs->pwd->d_inode->i_count),
153                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
154                current->fs->pwdmnt,
155                atomic_read(&current->fs->pwdmnt->mnt_count));
156         */
157 }
158 EXPORT_SYMBOL(pop_ctxt);
159
160 /* utility to make a file */
161 struct dentry *simple_mknod(struct dentry *dir, char *name, int mode)
162 {
163         struct dentry *dchild;
164         int err = 0;
165         ENTRY;
166
167         ASSERT_KERNEL_CTXT("kernel doing mknod outside kernel context\n");
168         CDEBUG(D_INODE, "creating file %*s\n", (int)strlen(name), name);
169
170         dchild = lookup_one_len(name, dir, strlen(name));
171         if (IS_ERR(dchild))
172                 GOTO(out_up, dchild);
173
174         if (dchild->d_inode) {
175                 if (!S_ISREG(dchild->d_inode->i_mode))
176                         GOTO(out_err, err = -EEXIST);
177
178                 GOTO(out_up, dchild);
179         }
180
181         err = vfs_create(dir->d_inode, dchild, (mode & ~S_IFMT) | S_IFREG);
182         if (err)
183                 GOTO(out_err, err);
184
185         RETURN(dchild);
186
187 out_err:
188         dput(dchild);
189         dchild = ERR_PTR(err);
190 out_up:
191         return dchild;
192 }
193 EXPORT_SYMBOL(simple_mknod);
194
195 /* utility to make a directory */
196 struct dentry *simple_mkdir(struct dentry *dir, char *name, int mode)
197 {
198         struct dentry *dchild;
199         int err = 0;
200         ENTRY;
201
202         ASSERT_KERNEL_CTXT("kernel doing mkdir outside kernel context\n");
203         CDEBUG(D_INODE, "creating directory %*s\n", (int)strlen(name), name);
204         dchild = lookup_one_len(name, dir, strlen(name));
205         if (IS_ERR(dchild))
206                 GOTO(out_up, dchild);
207
208         if (dchild->d_inode) {
209                 if (!S_ISDIR(dchild->d_inode->i_mode))
210                         GOTO(out_err, err = -ENOTDIR);
211
212                 GOTO(out_up, dchild);
213         }
214
215         err = vfs_mkdir(dir->d_inode, dchild, mode);
216         if (err)
217                 GOTO(out_err, err);
218
219         RETURN(dchild);
220
221 out_err:
222         dput(dchild);
223         dchild = ERR_PTR(err);
224 out_up:
225         return dchild;
226 }
227 EXPORT_SYMBOL(simple_mkdir);
228
229 /*
230  * Read a file from within kernel context.  Prior to calling this
231  * function we should already have done a push_ctxt().
232  */
233 int lustre_fread(struct file *file, void *buf, int len, loff_t *off)
234 {
235         ASSERT_KERNEL_CTXT("kernel doing read outside kernel context\n");
236         if (!file || !file->f_op || !file->f_op->read || !off)
237                 RETURN(-ENOSYS);
238
239         return file->f_op->read(file, buf, len, off);
240 }
241 EXPORT_SYMBOL(lustre_fread);
242
243 /*
244  * Write a file from within kernel context.  Prior to calling this
245  * function we should already have done a push_ctxt().
246  */
247 int lustre_fwrite(struct file *file, const void *buf, int len, loff_t *off)
248 {
249         ENTRY;
250         ASSERT_KERNEL_CTXT("kernel doing write outside kernel context\n");
251         if (!file)
252                 RETURN(-ENOENT);
253         if (!file->f_op)
254                 RETURN(-ENOSYS);
255         if (!off)
256                 RETURN(-EINVAL);
257
258         if (!file->f_op->write)
259                 RETURN(-EROFS);
260
261         RETURN(file->f_op->write(file, buf, len, off));
262 }
263 EXPORT_SYMBOL(lustre_fwrite);
264
265 /*
266  * Sync a file from within kernel context.  Prior to calling this
267  * function we should already have done a push_ctxt().
268  */
269 int lustre_fsync(struct file *file)
270 {
271         ENTRY;
272         ASSERT_KERNEL_CTXT("kernel doing sync outside kernel context\n");
273         if (!file || !file->f_op || !file->f_op->fsync)
274                 RETURN(-ENOSYS);
275
276         RETURN(file->f_op->fsync(file, file->f_dentry, 0));
277 }
278 EXPORT_SYMBOL(lustre_fsync);