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