Commit | Line | Data |
---|---|---|
d7e09d03 PT |
1 | /* |
2 | * GPL HEADER START | |
3 | * | |
4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 only, | |
8 | * as published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * General Public License version 2 for more details (a copy is included | |
14 | * in the LICENSE file that accompanied this code). | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * version 2 along with this program; If not, see | |
18 | * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf | |
19 | * | |
20 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
21 | * CA 95054 USA or visit www.sun.com if you need additional information or | |
22 | * have any questions. | |
23 | * | |
24 | * GPL HEADER END | |
25 | */ | |
26 | /* | |
27 | * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | |
28 | * Use is subject to license terms. | |
29 | * | |
30 | * Copyright (c) 2011, 2012, Intel Corporation. | |
31 | */ | |
32 | /* | |
33 | * This file is part of Lustre, http://www.lustre.org/ | |
34 | * Lustre is a trademark of Sun Microsystems, Inc. | |
35 | * | |
36 | * lustre/lvfs/lvfs_linux.c | |
37 | * | |
38 | * Author: Andreas Dilger <adilger@clusterfs.com> | |
39 | */ | |
40 | ||
41 | #define DEBUG_SUBSYSTEM S_FILTER | |
42 | ||
d7e09d03 PT |
43 | #include <linux/fs.h> |
44 | #include <asm/unistd.h> | |
45 | #include <linux/slab.h> | |
46 | #include <linux/pagemap.h> | |
47 | #include <linux/quotaops.h> | |
d7e09d03 | 48 | #include <linux/libcfs/libcfs.h> |
d7e09d03 | 49 | #include <linux/module.h> |
d7e09d03 PT |
50 | #include <linux/lustre_compat25.h> |
51 | #include <lvfs.h> | |
52 | ||
53 | #include <obd.h> | |
54 | #include <lustre_lib.h> | |
55 | ||
56 | struct lprocfs_stats *obd_memory = NULL; | |
57 | EXPORT_SYMBOL(obd_memory); | |
58 | /* refine later and change to seqlock or simlar from libcfs */ | |
59 | ||
60 | /* Debugging check only needed during development */ | |
61 | #ifdef OBD_CTXT_DEBUG | |
62 | # define ASSERT_CTXT_MAGIC(magic) LASSERT((magic) == OBD_RUN_CTXT_MAGIC) | |
63 | # define ASSERT_NOT_KERNEL_CTXT(msg) LASSERTF(!segment_eq(get_fs(), get_ds()),\ | |
64 | msg) | |
65 | # define ASSERT_KERNEL_CTXT(msg) LASSERTF(segment_eq(get_fs(), get_ds()), msg) | |
66 | #else | |
90131cc9 NH |
67 | # define ASSERT_CTXT_MAGIC(magic) do {} while (0) |
68 | # define ASSERT_NOT_KERNEL_CTXT(msg) do {} while (0) | |
69 | # define ASSERT_KERNEL_CTXT(msg) do {} while (0) | |
d7e09d03 PT |
70 | #endif |
71 | ||
72 | static void push_group_info(struct lvfs_run_ctxt *save, | |
73 | struct group_info *ginfo) | |
74 | { | |
75 | if (!ginfo) { | |
76 | save->ngroups = current_ngroups; | |
77 | current_ngroups = 0; | |
78 | } else { | |
79 | struct cred *cred; | |
80 | task_lock(current); | |
81 | save->group_info = current_cred()->group_info; | |
8afd983c JB |
82 | cred = prepare_creds(); |
83 | if (cred) { | |
d7e09d03 PT |
84 | cred->group_info = ginfo; |
85 | commit_creds(cred); | |
86 | } | |
87 | task_unlock(current); | |
88 | } | |
89 | } | |
90 | ||
91 | static void pop_group_info(struct lvfs_run_ctxt *save, | |
92 | struct group_info *ginfo) | |
93 | { | |
94 | if (!ginfo) { | |
95 | current_ngroups = save->ngroups; | |
96 | } else { | |
97 | struct cred *cred; | |
98 | task_lock(current); | |
8afd983c JB |
99 | cred = prepare_creds(); |
100 | if (cred) { | |
d7e09d03 PT |
101 | cred->group_info = save->group_info; |
102 | commit_creds(cred); | |
103 | } | |
104 | task_unlock(current); | |
105 | } | |
106 | } | |
107 | ||
108 | /* push / pop to root of obd store */ | |
109 | void push_ctxt(struct lvfs_run_ctxt *save, struct lvfs_run_ctxt *new_ctx, | |
110 | struct lvfs_ucred *uc) | |
111 | { | |
112 | /* if there is underlaying dt_device then push_ctxt is not needed */ | |
113 | if (new_ctx->dt != NULL) | |
114 | return; | |
115 | ||
13a7e2cf | 116 | /* ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n"); */ |
d7e09d03 PT |
117 | ASSERT_CTXT_MAGIC(new_ctx->magic); |
118 | OBD_SET_CTXT_MAGIC(save); | |
119 | ||
120 | save->fs = get_fs(); | |
193deee1 AV |
121 | LASSERT(d_count(cfs_fs_pwd(current->fs))); |
122 | LASSERT(d_count(new_ctx->pwd)); | |
d7e09d03 PT |
123 | save->pwd = dget(cfs_fs_pwd(current->fs)); |
124 | save->pwdmnt = mntget(cfs_fs_mnt(current->fs)); | |
125 | save->luc.luc_umask = current_umask(); | |
126 | save->ngroups = current_cred()->group_info->ngroups; | |
127 | ||
128 | LASSERT(save->pwd); | |
129 | LASSERT(save->pwdmnt); | |
130 | LASSERT(new_ctx->pwd); | |
131 | LASSERT(new_ctx->pwdmnt); | |
132 | ||
133 | if (uc) { | |
134 | struct cred *cred; | |
135 | save->luc.luc_uid = current_uid(); | |
136 | save->luc.luc_gid = current_gid(); | |
137 | save->luc.luc_fsuid = current_fsuid(); | |
138 | save->luc.luc_fsgid = current_fsgid(); | |
139 | save->luc.luc_cap = current_cap(); | |
140 | ||
8afd983c JB |
141 | cred = prepare_creds(); |
142 | if (cred) { | |
d7e09d03 PT |
143 | cred->uid = uc->luc_uid; |
144 | cred->gid = uc->luc_gid; | |
145 | cred->fsuid = uc->luc_fsuid; | |
146 | cred->fsgid = uc->luc_fsgid; | |
147 | cred->cap_effective = uc->luc_cap; | |
148 | commit_creds(cred); | |
149 | } | |
150 | ||
151 | push_group_info(save, | |
152 | uc->luc_ginfo ?: | |
153 | uc->luc_identity ? uc->luc_identity->mi_ginfo : | |
154 | NULL); | |
155 | } | |
156 | current->fs->umask = 0; /* umask already applied on client */ | |
157 | set_fs(new_ctx->fs); | |
158 | ll_set_fs_pwd(current->fs, new_ctx->pwdmnt, new_ctx->pwd); | |
159 | } | |
160 | EXPORT_SYMBOL(push_ctxt); | |
161 | ||
162 | void pop_ctxt(struct lvfs_run_ctxt *saved, struct lvfs_run_ctxt *new_ctx, | |
163 | struct lvfs_ucred *uc) | |
164 | { | |
165 | /* if there is underlaying dt_device then pop_ctxt is not needed */ | |
166 | if (new_ctx->dt != NULL) | |
167 | return; | |
168 | ||
169 | ASSERT_CTXT_MAGIC(saved->magic); | |
170 | ASSERT_KERNEL_CTXT("popping non-kernel context!\n"); | |
171 | ||
172 | LASSERTF(cfs_fs_pwd(current->fs) == new_ctx->pwd, "%p != %p\n", | |
173 | cfs_fs_pwd(current->fs), new_ctx->pwd); | |
174 | LASSERTF(cfs_fs_mnt(current->fs) == new_ctx->pwdmnt, "%p != %p\n", | |
175 | cfs_fs_mnt(current->fs), new_ctx->pwdmnt); | |
176 | ||
177 | set_fs(saved->fs); | |
178 | ll_set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd); | |
179 | ||
180 | dput(saved->pwd); | |
181 | mntput(saved->pwdmnt); | |
182 | current->fs->umask = saved->luc.luc_umask; | |
183 | if (uc) { | |
184 | struct cred *cred; | |
8afd983c JB |
185 | cred = prepare_creds(); |
186 | if (cred) { | |
d7e09d03 PT |
187 | cred->uid = saved->luc.luc_uid; |
188 | cred->gid = saved->luc.luc_gid; | |
189 | cred->fsuid = saved->luc.luc_fsuid; | |
190 | cred->fsgid = saved->luc.luc_fsgid; | |
191 | cred->cap_effective = saved->luc.luc_cap; | |
192 | commit_creds(cred); | |
193 | } | |
194 | ||
195 | pop_group_info(saved, | |
196 | uc->luc_ginfo ?: | |
197 | uc->luc_identity ? uc->luc_identity->mi_ginfo : | |
198 | NULL); | |
199 | } | |
200 | } | |
201 | EXPORT_SYMBOL(pop_ctxt); | |
202 | ||
203 | /* utility to rename a file */ | |
204 | int lustre_rename(struct dentry *dir, struct vfsmount *mnt, | |
205 | char *oldname, char *newname) | |
206 | { | |
207 | struct dentry *dchild_old, *dchild_new; | |
208 | int err = 0; | |
d7e09d03 PT |
209 | |
210 | ASSERT_KERNEL_CTXT("kernel doing rename outside kernel context\n"); | |
211 | CDEBUG(D_INODE, "renaming file %.*s to %.*s\n", | |
212 | (int)strlen(oldname), oldname, (int)strlen(newname), newname); | |
213 | ||
214 | dchild_old = ll_lookup_one_len(oldname, dir, strlen(oldname)); | |
215 | if (IS_ERR(dchild_old)) | |
0a3bdb00 | 216 | return PTR_ERR(dchild_old); |
d7e09d03 PT |
217 | |
218 | if (!dchild_old->d_inode) | |
219 | GOTO(put_old, err = -ENOENT); | |
220 | ||
221 | dchild_new = ll_lookup_one_len(newname, dir, strlen(newname)); | |
222 | if (IS_ERR(dchild_new)) | |
223 | GOTO(put_old, err = PTR_ERR(dchild_new)); | |
224 | ||
225 | err = ll_vfs_rename(dir->d_inode, dchild_old, mnt, | |
8e6d782c | 226 | dir->d_inode, dchild_new, mnt, NULL); |
d7e09d03 PT |
227 | |
228 | dput(dchild_new); | |
229 | put_old: | |
230 | dput(dchild_old); | |
0a3bdb00 | 231 | return err; |
d7e09d03 PT |
232 | } |
233 | EXPORT_SYMBOL(lustre_rename); | |
234 | ||
235 | /* Note: dput(dchild) will *not* be called if there is an error */ | |
236 | struct l_file *l_dentry_open(struct lvfs_run_ctxt *ctxt, struct l_dentry *de, | |
237 | int flags) | |
238 | { | |
239 | struct path path = { | |
240 | .dentry = de, | |
241 | .mnt = ctxt->pwdmnt, | |
242 | }; | |
dd4c3a48 | 243 | return dentry_open(&path, flags, current_cred()); |
d7e09d03 PT |
244 | } |
245 | EXPORT_SYMBOL(l_dentry_open); | |
246 | ||
247 | #ifdef LPROCFS | |
248 | __s64 lprocfs_read_helper(struct lprocfs_counter *lc, | |
249 | struct lprocfs_counter_header *header, | |
250 | enum lprocfs_stats_flags flags, | |
251 | enum lprocfs_fields_flags field) | |
252 | { | |
253 | __s64 ret = 0; | |
254 | ||
255 | if (lc == NULL || header == NULL) | |
0a3bdb00 | 256 | return 0; |
d7e09d03 PT |
257 | |
258 | switch (field) { | |
ec40a9af JB |
259 | case LPROCFS_FIELDS_FLAGS_CONFIG: |
260 | ret = header->lc_config; | |
261 | break; | |
262 | case LPROCFS_FIELDS_FLAGS_SUM: | |
263 | ret = lc->lc_sum; | |
264 | if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) | |
265 | ret += lc->lc_sum_irq; | |
266 | break; | |
267 | case LPROCFS_FIELDS_FLAGS_MIN: | |
268 | ret = lc->lc_min; | |
269 | break; | |
270 | case LPROCFS_FIELDS_FLAGS_MAX: | |
271 | ret = lc->lc_max; | |
272 | break; | |
273 | case LPROCFS_FIELDS_FLAGS_AVG: | |
274 | ret = (lc->lc_max - lc->lc_min) / 2; | |
275 | break; | |
276 | case LPROCFS_FIELDS_FLAGS_SUMSQUARE: | |
277 | ret = lc->lc_sumsquare; | |
278 | break; | |
279 | case LPROCFS_FIELDS_FLAGS_COUNT: | |
280 | ret = lc->lc_count; | |
281 | break; | |
282 | default: | |
283 | break; | |
a22526e4 | 284 | } |
d7e09d03 | 285 | |
0a3bdb00 | 286 | return ret; |
d7e09d03 PT |
287 | } |
288 | EXPORT_SYMBOL(lprocfs_read_helper); | |
289 | #endif /* LPROCFS */ | |
290 | ||
291 | MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); | |
292 | MODULE_DESCRIPTION("Lustre VFS Filesystem Helper v0.1"); | |
293 | MODULE_LICENSE("GPL"); |