[PATCH] new (local) helper: user_path_parent()

Preparation to untangling intents mess: reduce the number of do_path_lookup()
callers.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro 2ad94ae6 2d8f3038

+57 -80
+57 -80
fs/namei.c
··· 1352 1352 return err; 1353 1353 } 1354 1354 1355 + static int user_path_parent(int dfd, const char __user *path, 1356 + struct nameidata *nd, char **name) 1357 + { 1358 + char *s = getname(path); 1359 + int error; 1360 + 1361 + if (IS_ERR(s)) 1362 + return PTR_ERR(s); 1363 + 1364 + error = do_path_lookup(dfd, s, LOOKUP_PARENT, nd); 1365 + if (error) 1366 + putname(s); 1367 + else 1368 + *name = s; 1369 + 1370 + return error; 1371 + } 1372 + 1355 1373 /* 1356 1374 * It's inline, so penalty for filesystems that don't use sticky bit is 1357 1375 * minimal. ··· 2007 1989 asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, 2008 1990 unsigned dev) 2009 1991 { 2010 - int error = 0; 2011 - char * tmp; 2012 - struct dentry * dentry; 1992 + int error; 1993 + char *tmp; 1994 + struct dentry *dentry; 2013 1995 struct nameidata nd; 2014 1996 2015 1997 if (S_ISDIR(mode)) 2016 1998 return -EPERM; 2017 - tmp = getname(filename); 2018 - if (IS_ERR(tmp)) 2019 - return PTR_ERR(tmp); 2020 1999 2021 - error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd); 2000 + error = user_path_parent(dfd, filename, &nd, &tmp); 2022 2001 if (error) 2023 - goto out; 2002 + return error; 2003 + 2024 2004 dentry = lookup_create(&nd, 0); 2025 2005 if (IS_ERR(dentry)) { 2026 2006 error = PTR_ERR(dentry); ··· 2050 2034 out_unlock: 2051 2035 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2052 2036 path_put(&nd.path); 2053 - out: 2054 2037 putname(tmp); 2055 2038 2056 2039 return error; ··· 2089 2074 struct dentry *dentry; 2090 2075 struct nameidata nd; 2091 2076 2092 - tmp = getname(pathname); 2093 - error = PTR_ERR(tmp); 2094 - if (IS_ERR(tmp)) 2077 + error = user_path_parent(dfd, pathname, &nd, &tmp); 2078 + if (error) 2095 2079 goto out_err; 2096 2080 2097 - error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd); 2098 - if (error) 2099 - goto out; 2100 2081 dentry = lookup_create(&nd, 1); 2101 2082 error = PTR_ERR(dentry); 2102 2083 if (IS_ERR(dentry)) ··· 2110 2099 out_unlock: 2111 2100 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2112 2101 path_put(&nd.path); 2113 - out: 2114 2102 putname(tmp); 2115 2103 out_err: 2116 2104 return error; ··· 2187 2177 struct dentry *dentry; 2188 2178 struct nameidata nd; 2189 2179 2190 - name = getname(pathname); 2191 - if(IS_ERR(name)) 2192 - return PTR_ERR(name); 2193 - 2194 - error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd); 2180 + error = user_path_parent(dfd, pathname, &nd, &name); 2195 2181 if (error) 2196 - goto exit; 2182 + return error; 2197 2183 2198 2184 switch(nd.last_type) { 2199 2185 case LAST_DOTDOT: ··· 2218 2212 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2219 2213 exit1: 2220 2214 path_put(&nd.path); 2221 - exit: 2222 2215 putname(name); 2223 2216 return error; 2224 2217 } ··· 2266 2261 */ 2267 2262 static long do_unlinkat(int dfd, const char __user *pathname) 2268 2263 { 2269 - int error = 0; 2270 - char * name; 2264 + int error; 2265 + char *name; 2271 2266 struct dentry *dentry; 2272 2267 struct nameidata nd; 2273 2268 struct inode *inode = NULL; 2274 2269 2275 - name = getname(pathname); 2276 - if(IS_ERR(name)) 2277 - return PTR_ERR(name); 2278 - 2279 - error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd); 2270 + error = user_path_parent(dfd, pathname, &nd, &name); 2280 2271 if (error) 2281 - goto exit; 2272 + return error; 2273 + 2282 2274 error = -EISDIR; 2283 2275 if (nd.last_type != LAST_NORM) 2284 2276 goto exit1; ··· 2302 2300 iput(inode); /* truncate the inode here */ 2303 2301 exit1: 2304 2302 path_put(&nd.path); 2305 - exit: 2306 2303 putname(name); 2307 2304 return error; 2308 2305 ··· 2351 2350 asmlinkage long sys_symlinkat(const char __user *oldname, 2352 2351 int newdfd, const char __user *newname) 2353 2352 { 2354 - int error = 0; 2355 - char * from; 2356 - char * to; 2353 + int error; 2354 + char *from; 2355 + char *to; 2357 2356 struct dentry *dentry; 2358 2357 struct nameidata nd; 2359 2358 2360 2359 from = getname(oldname); 2361 - if(IS_ERR(from)) 2360 + if (IS_ERR(from)) 2362 2361 return PTR_ERR(from); 2363 - to = getname(newname); 2364 - error = PTR_ERR(to); 2365 - if (IS_ERR(to)) 2362 + 2363 + error = user_path_parent(newdfd, newname, &nd, &to); 2364 + if (error) 2366 2365 goto out_putname; 2367 2366 2368 - error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd); 2369 - if (error) 2370 - goto out; 2371 2367 dentry = lookup_create(&nd, 0); 2372 2368 error = PTR_ERR(dentry); 2373 2369 if (IS_ERR(dentry)) ··· 2380 2382 out_unlock: 2381 2383 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2382 2384 path_put(&nd.path); 2383 - out: 2384 2385 putname(to); 2385 2386 out_putname: 2386 2387 putname(from); ··· 2446 2449 struct nameidata nd; 2447 2450 struct path old_path; 2448 2451 int error; 2449 - char * to; 2452 + char *to; 2450 2453 2451 2454 if ((flags & ~AT_SYMLINK_FOLLOW) != 0) 2452 2455 return -EINVAL; 2453 - 2454 - to = getname(newname); 2455 - if (IS_ERR(to)) 2456 - return PTR_ERR(to); 2457 2456 2458 2457 error = user_path_at(olddfd, oldname, 2459 2458 flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0, 2460 2459 &old_path); 2461 2460 if (error) 2462 - goto exit; 2463 - error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd); 2461 + return error; 2462 + 2463 + error = user_path_parent(newdfd, newname, &nd, &to); 2464 2464 if (error) 2465 2465 goto out; 2466 2466 error = -EXDEV; ··· 2478 2484 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2479 2485 out_release: 2480 2486 path_put(&nd.path); 2487 + putname(to); 2481 2488 out: 2482 2489 path_put(&old_path); 2483 - exit: 2484 - putname(to); 2485 2490 2486 2491 return error; 2487 2492 } ··· 2636 2643 return error; 2637 2644 } 2638 2645 2639 - static int do_rename(int olddfd, const char *oldname, 2640 - int newdfd, const char *newname) 2646 + asmlinkage long sys_renameat(int olddfd, const char __user *oldname, 2647 + int newdfd, const char __user *newname) 2641 2648 { 2642 - int error = 0; 2643 - struct dentry * old_dir, * new_dir; 2644 - struct dentry * old_dentry, *new_dentry; 2645 - struct dentry * trap; 2649 + struct dentry *old_dir, *new_dir; 2650 + struct dentry *old_dentry, *new_dentry; 2651 + struct dentry *trap; 2646 2652 struct nameidata oldnd, newnd; 2653 + char *from; 2654 + char *to; 2655 + int error; 2647 2656 2648 - error = do_path_lookup(olddfd, oldname, LOOKUP_PARENT, &oldnd); 2657 + error = user_path_parent(olddfd, oldname, &oldnd, &from); 2649 2658 if (error) 2650 2659 goto exit; 2651 2660 2652 - error = do_path_lookup(newdfd, newname, LOOKUP_PARENT, &newnd); 2661 + error = user_path_parent(newdfd, newname, &newnd, &to); 2653 2662 if (error) 2654 2663 goto exit1; 2655 2664 ··· 2713 2718 unlock_rename(new_dir, old_dir); 2714 2719 exit2: 2715 2720 path_put(&newnd.path); 2721 + putname(to); 2716 2722 exit1: 2717 2723 path_put(&oldnd.path); 2718 - exit: 2719 - return error; 2720 - } 2721 - 2722 - asmlinkage long sys_renameat(int olddfd, const char __user *oldname, 2723 - int newdfd, const char __user *newname) 2724 - { 2725 - int error; 2726 - char * from; 2727 - char * to; 2728 - 2729 - from = getname(oldname); 2730 - if(IS_ERR(from)) 2731 - return PTR_ERR(from); 2732 - to = getname(newname); 2733 - error = PTR_ERR(to); 2734 - if (!IS_ERR(to)) { 2735 - error = do_rename(olddfd, from, newdfd, to); 2736 - putname(to); 2737 - } 2738 2724 putname(from); 2725 + exit: 2739 2726 return error; 2740 2727 } 2741 2728