History

open-style analog of vfs_path_lookup()

new function: file_open_root(dentry, mnt, name, flags) opens the file vfs_path_lookup would arrive to. Note that name can be empty; in that case the usual requirement that dentry should be a directory is lifted. open-coded equivalents switched to it, may_open() got down exactly one caller and became static.

Al Viro committed 15 years ago

Commit 73d049a1 parent 5b6ca027 files · +77 −84Browse files

Unified · Split

7 files
  1. arch/um/drivers/mconsole_kern.c +2 −19
  2. fs/internal.h +2 −0
  3. fs/namei.c +52 −28
  4. fs/nfsctl.c +4 −17
  5. fs/open.c +14 −0
  6. include/linux/fs.h +2 −2
  7. kernel/sysctl_binary.c +1 −18
arch/um/drivers/mconsole_kern.c+2−19
@@ -124,35 +124,18 @@ void mconsole_log(struct mc_request *req) · 123 unmodified lines
124#if 0124#if 0
125void mconsole_proc(struct mc_request *req)125void mconsole_proc(struct mc_request *req)
126{126{
127 struct nameidata nd;
128 struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt;127 struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt;
129 struct file *file;128 struct file *file;
130 int n, err;129 int n;
131 char *ptr = req->request.data, *buf;130 char *ptr = req->request.data, *buf;
132 mm_segment_t old_fs = get_fs();131 mm_segment_t old_fs = get_fs();
133 132
134 ptr += strlen("proc");133 ptr += strlen("proc");
135 ptr = skip_spaces(ptr);134 ptr = skip_spaces(ptr);
136 135
137 err = vfs_path_lookup(mnt->mnt_root, mnt, ptr, LOOKUP_FOLLOW, &nd);136 file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY);
138 if (err) {
139 mconsole_reply(req, "Failed to look up file", 1, 0);
140 goto out;
141 }
142
143 err = may_open(&nd.path, MAY_READ, O_RDONLY);
144 if (result) {
145 mconsole_reply(req, "Failed to open file", 1, 0);
146 path_put(&nd.path);
147 goto out;
148 }
149
150 file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY,
151 current_cred());
152 err = PTR_ERR(file);
153 if (IS_ERR(file)) {137 if (IS_ERR(file)) {
154 mconsole_reply(req, "Failed to open file", 1, 0);138 mconsole_reply(req, "Failed to open file", 1, 0);
155 path_put(&nd.path);
156 goto out;139 goto out;
157 }140 }
158 141
fs/internal.h+2−0
@@ -114,6 +114,8 @@ struct open_flags { · 113 unmodified lines
114};114};
115extern struct file *do_filp_open(int dfd, const char *pathname,115extern struct file *do_filp_open(int dfd, const char *pathname,
116 const struct open_flags *op, int lookup_flags);116 const struct open_flags *op, int lookup_flags);
117extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
118 const char *, const struct open_flags *, int lookup_flags);
117 119
118/*120/*
119 * inode.c121 * inode.c
fs/namei.c+52−28
@@ -1487,11 +1487,13 @@ static int path_init(int dfd, const char *name, unsigned int flags, · 1486 unmodified lines
1487 nd->depth = 0;1487 nd->depth = 0;
1488 if (flags & LOOKUP_ROOT) {1488 if (flags & LOOKUP_ROOT) {
1489 struct inode *inode = nd->root.dentry->d_inode;1489 struct inode *inode = nd->root.dentry->d_inode;
1490 if (!inode->i_op->lookup)1490 if (*name) {
1491 return -ENOTDIR;1491 if (!inode->i_op->lookup)
1492 retval = inode_permission(inode, MAY_EXEC);1492 return -ENOTDIR;
1493 if (retval)1493 retval = inode_permission(inode, MAY_EXEC);
1494 return retval;1494 if (retval)
1495 return retval;
1496 }
1495 nd->path = nd->root;1497 nd->path = nd->root;
1496 nd->inode = inode;1498 nd->inode = inode;
1497 if (flags & LOOKUP_RCU) {1499 if (flags & LOOKUP_RCU) {
@@ -1937,7 +1939,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode, · 439 unmodified lines
1937 return error;1939 return error;
1938}1940}
1939 1941
1940int may_open(struct path *path, int acc_mode, int flag)1942static int may_open(struct path *path, int acc_mode, int flag)
1941{1943{
1942 struct dentry *dentry = path->dentry;1944 struct dentry *dentry = path->dentry;
1943 struct inode *inode = dentry->d_inode;1945 struct inode *inode = dentry->d_inode;
@@ -2250,11 +2252,10 @@ exit: · 306 unmodified lines
2250}2252}
2251 2253
2252static struct file *path_openat(int dfd, const char *pathname,2254static struct file *path_openat(int dfd, const char *pathname,
2253 const struct open_flags *op, int flags)2255 struct nameidata *nd, const struct open_flags *op, int flags)
2254{2256{
2255 struct file *base = NULL;2257 struct file *base = NULL;
2256 struct file *filp;2258 struct file *filp;
2257 struct nameidata nd;
2258 struct path path;2259 struct path path;
2259 int count = 0;2260 int count = 0;
2260 int error;2261 int error;
@@ -2264,27 +2265,27 @@ static struct file *path_openat(int dfd, const char *pathname, · 3 unmodified lines
2264 return ERR_PTR(-ENFILE);2265 return ERR_PTR(-ENFILE);
2265 2266
2266 filp->f_flags = op->open_flag;2267 filp->f_flags = op->open_flag;
2267 nd.intent.open.file = filp;2268 nd->intent.open.file = filp;
2268 nd.intent.open.flags = open_to_namei_flags(op->open_flag);2269 nd->intent.open.flags = open_to_namei_flags(op->open_flag);
2269 nd.intent.open.create_mode = op->mode;2270 nd->intent.open.create_mode = op->mode;
2270 2271
2271 error = path_init(dfd, pathname, flags | LOOKUP_PARENT, &nd, &base);2272 error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
2272 if (unlikely(error))2273 if (unlikely(error))
2273 goto out_filp;2274 goto out_filp;
2274 2275
2275 current->total_link_count = 0;2276 current->total_link_count = 0;
2276 error = link_path_walk(pathname, &nd);2277 error = link_path_walk(pathname, nd);
2277 if (unlikely(error))2278 if (unlikely(error))
2278 goto out_filp;2279 goto out_filp;
2279 2280
2280 filp = do_last(&nd, &path, op, pathname);2281 filp = do_last(nd, &path, op, pathname);
2281 while (unlikely(!filp)) { /* trailing symlink */2282 while (unlikely(!filp)) { /* trailing symlink */
2282 struct path link = path;2283 struct path link = path;
2283 struct inode *linki = link.dentry->d_inode;2284 struct inode *linki = link.dentry->d_inode;
2284 void *cookie;2285 void *cookie;
2285 if (!(nd.flags & LOOKUP_FOLLOW) || count++ == 32) {2286 if (!(nd->flags & LOOKUP_FOLLOW) || count++ == 32) {
2286 path_put_conditional(&path, &nd);2287 path_put_conditional(&path, nd);
2287 path_put(&nd.path);2288 path_put(&nd->path);
2288 filp = ERR_PTR(-ELOOP);2289 filp = ERR_PTR(-ELOOP);
2289 break;2290 break;
2290 }2291 }
@@ -2299,23 +2300,23 @@ static struct file *path_openat(int dfd, const char *pathname, · 8 unmodified lines
2299 * have to putname() it when we are done. Procfs-like symlinks2300 * have to putname() it when we are done. Procfs-like symlinks
2300 * just set LAST_BIND.2301 * just set LAST_BIND.
2301 */2302 */
2302 nd.flags |= LOOKUP_PARENT;2303 nd->flags |= LOOKUP_PARENT;
2303 nd.flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);2304 nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
2304 error = __do_follow_link(&link, &nd, &cookie);2305 error = __do_follow_link(&link, nd, &cookie);
2305 if (unlikely(error))2306 if (unlikely(error))
2306 filp = ERR_PTR(error);2307 filp = ERR_PTR(error);
2307 else2308 else
2308 filp = do_last(&nd, &path, op, pathname);2309 filp = do_last(nd, &path, op, pathname);
2309 if (!IS_ERR(cookie) && linki->i_op->put_link)2310 if (!IS_ERR(cookie) && linki->i_op->put_link)
2310 linki->i_op->put_link(link.dentry, &nd, cookie);2311 linki->i_op->put_link(link.dentry, nd, cookie);
2311 path_put(&link);2312 path_put(&link);
2312 }2313 }
2313out:2314out:
2314 if (nd.root.mnt && !(nd.flags & LOOKUP_ROOT))2315 if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT))
2315 path_put(&nd.root);2316 path_put(&nd->root);
2316 if (base)2317 if (base)
2317 fput(base);2318 fput(base);
2318 release_open_intent(&nd);2319 release_open_intent(nd);
2319 return filp;2320 return filp;
2320 2321
2321out_filp:2322out_filp:
@@ -2326,16 +2327,39 @@ out_filp: · 4 unmodified lines
2326struct file *do_filp_open(int dfd, const char *pathname,2327struct file *do_filp_open(int dfd, const char *pathname,
2327 const struct open_flags *op, int flags)2328 const struct open_flags *op, int flags)
2328{2329{
2330 struct nameidata nd;
2329 struct file *filp;2331 struct file *filp;
2330 2332
2331 filp = path_openat(dfd, pathname, op, flags | LOOKUP_RCU);2333 filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU);
2332 if (unlikely(filp == ERR_PTR(-ECHILD)))2334 if (unlikely(filp == ERR_PTR(-ECHILD)))
2333 filp = path_openat(dfd, pathname, op, flags);2335 filp = path_openat(dfd, pathname, &nd, op, flags);
2334 if (unlikely(filp == ERR_PTR(-ESTALE)))2336 if (unlikely(filp == ERR_PTR(-ESTALE)))
2335 filp = path_openat(dfd, pathname, op, flags | LOOKUP_REVAL);2337 filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_REVAL);
2336 return filp;2338 return filp;
2337}2339}
2338 2340
2341struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
2342 const char *name, const struct open_flags *op, int flags)
2343{
2344 struct nameidata nd;
2345 struct file *file;
2346
2347 nd.root.mnt = mnt;
2348 nd.root.dentry = dentry;
2349
2350 flags |= LOOKUP_ROOT;
2351
2352 if (dentry->d_inode->i_op->follow_link)
2353 return ERR_PTR(-ELOOP);
2354
2355 file = path_openat(-1, name, &nd, op, flags | LOOKUP_RCU);
2356 if (unlikely(file == ERR_PTR(-ECHILD)))
2357 file = path_openat(-1, name, &nd, op, flags);
2358 if (unlikely(file == ERR_PTR(-ESTALE)))
2359 file = path_openat(-1, name, &nd, op, flags | LOOKUP_REVAL);
2360 return file;
2361}
2362
2339/**2363/**
2340 * lookup_create - lookup a dentry, creating it if it doesn't exist2364 * lookup_create - lookup a dentry, creating it if it doesn't exist
2341 * @nd: nameidata info2365 * @nd: nameidata info
fs/nfsctl.c+4−17
@@ -22,30 +22,17 @@ · 21 unmodified lines
22 22
23static struct file *do_open(char *name, int flags)23static struct file *do_open(char *name, int flags)
24{24{
25 struct nameidata nd;
26 struct vfsmount *mnt;25 struct vfsmount *mnt;
27 int error;26 struct file *file;
28 27
29 mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);28 mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
30 if (IS_ERR(mnt))29 if (IS_ERR(mnt))
31 return (struct file *)mnt;30 return (struct file *)mnt;
32 31
33 error = vfs_path_lookup(mnt->mnt_root, mnt, name, 0, &nd);32 file = file_open_root(mnt->mnt_root, mnt, name, flags);
34 mntput(mnt); /* drop do_kern_mount reference */
35 if (error)
36 return ERR_PTR(error);
37
38 if (flags == O_RDWR)
39 error = may_open(&nd.path, MAY_READ|MAY_WRITE, flags);
40 else
41 error = may_open(&nd.path, MAY_WRITE, flags);
42 33
43 if (!error)34 mntput(mnt); /* drop do_kern_mount reference */
44 return dentry_open(nd.path.dentry, nd.path.mnt, flags,35 return file;
45 current_cred());
46
47 path_put(&nd.path);
48 return ERR_PTR(error);
49}36}
50 37
51static struct {38static struct {
fs/open.c+14−0
@@ -959,6 +959,20 @@ struct file *filp_open(const char *filename, int flags, int mode) · 958 unmodified lines
959}959}
960EXPORT_SYMBOL(filp_open);960EXPORT_SYMBOL(filp_open);
961 961
962struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
963 const char *filename, int flags)
964{
965 struct open_flags op;
966 int lookup = build_open_flags(flags, 0, &op);
967 if (flags & O_CREAT)
968 return ERR_PTR(-EINVAL);
969 if (!filename && (flags & O_DIRECTORY))
970 if (!dentry->d_inode->i_op->lookup)
971 return ERR_PTR(-ENOTDIR);
972 return do_file_open_root(dentry, mnt, filename, &op, lookup);
973}
974EXPORT_SYMBOL(file_open_root);
975
962long do_sys_open(int dfd, const char __user *filename, int flags, int mode)976long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
963{977{
964 struct open_flags op;978 struct open_flags op;
include/linux/fs.h+2−2
@@ -1990,6 +1990,8 @@ extern int do_fallocate(struct file *file, int mode, loff_t offset, · 1989 unmodified lines
1990extern long do_sys_open(int dfd, const char __user *filename, int flags,1990extern long do_sys_open(int dfd, const char __user *filename, int flags,
1991 int mode);1991 int mode);
1992extern struct file *filp_open(const char *, int, int);1992extern struct file *filp_open(const char *, int, int);
1993extern struct file *file_open_root(struct dentry *, struct vfsmount *,
1994 const char *, int);
1993extern struct file * dentry_open(struct dentry *, struct vfsmount *, int,1995extern struct file * dentry_open(struct dentry *, struct vfsmount *, int,
1994 const struct cred *);1996 const struct cred *);
1995extern int filp_close(struct file *, fl_owner_t id);1997extern int filp_close(struct file *, fl_owner_t id);
@@ -2205,8 +2207,6 @@ extern struct file *create_read_pipe(struct file *f, int flags); · 209 unmodified lines
2205extern struct file *create_write_pipe(int flags);2207extern struct file *create_write_pipe(int flags);
2206extern void free_write_pipe(struct file *);2208extern void free_write_pipe(struct file *);
2207 2209
2208extern int may_open(struct path *, int, int);
2209
2210extern int kernel_read(struct file *, loff_t, char *, unsigned long);2210extern int kernel_read(struct file *, loff_t, char *, unsigned long);
2211extern struct file * open_exec(const char *);2211extern struct file * open_exec(const char *);
2212 2212
kernel/sysctl_binary.c+1−18
@@ -1321,13 +1321,11 @@ static ssize_t binary_sysctl(const int *name, int nlen, · 1320 unmodified lines
1321 void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)1321 void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
1322{1322{
1323 const struct bin_table *table = NULL;1323 const struct bin_table *table = NULL;
1324 struct nameidata nd;
1325 struct vfsmount *mnt;1324 struct vfsmount *mnt;
1326 struct file *file;1325 struct file *file;
1327 ssize_t result;1326 ssize_t result;
1328 char *pathname;1327 char *pathname;
1329 int flags;1328 int flags;
1330 int acc_mode;
1331 1329
1332 pathname = sysctl_getname(name, nlen, &table);1330 pathname = sysctl_getname(name, nlen, &table);
1333 result = PTR_ERR(pathname);1331 result = PTR_ERR(pathname);
@@ -1337,28 +1335,17 @@ static ssize_t binary_sysctl(const int *name, int nlen, · 3 unmodified lines
1337 /* How should the sysctl be accessed? */1335 /* How should the sysctl be accessed? */
1338 if (oldval && oldlen && newval && newlen) {1336 if (oldval && oldlen && newval && newlen) {
1339 flags = O_RDWR;1337 flags = O_RDWR;
1340 acc_mode = MAY_READ | MAY_WRITE;
1341 } else if (newval && newlen) {1338 } else if (newval && newlen) {
1342 flags = O_WRONLY;1339 flags = O_WRONLY;
1343 acc_mode = MAY_WRITE;
1344 } else if (oldval && oldlen) {1340 } else if (oldval && oldlen) {
1345 flags = O_RDONLY;1341 flags = O_RDONLY;
1346 acc_mode = MAY_READ;
1347 } else {1342 } else {
1348 result = 0;1343 result = 0;
1349 goto out_putname;1344 goto out_putname;
1350 }1345 }
1351 1346
1352 mnt = current->nsproxy->pid_ns->proc_mnt;1347 mnt = current->nsproxy->pid_ns->proc_mnt;
1353 result = vfs_path_lookup(mnt->mnt_root, mnt, pathname, 0, &nd);1348 file = file_open_root(mnt->mnt_root, mnt, pathname, flags);
1354 if (result)
1355 goto out_putname;
1356
1357 result = may_open(&nd.path, acc_mode, flags);
1358 if (result)
1359 goto out_putpath;
1360
1361 file = dentry_open(nd.path.dentry, nd.path.mnt, flags, current_cred());
1362 result = PTR_ERR(file);1349 result = PTR_ERR(file);
1363 if (IS_ERR(file))1350 if (IS_ERR(file))
1364 goto out_putname;1351 goto out_putname;
@@ -1370,10 +1357,6 @@ out_putname: · 5 unmodified lines
1370 putname(pathname);1357 putname(pathname);
1371out:1358out:
1372 return result;1359 return result;
1373
1374out_putpath:
1375 path_put(&nd.path);
1376 goto out_putname;
1377}1360}
1378 1361
1379 1362

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t