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