diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 271 |
1 files changed, 186 insertions, 85 deletions
diff --git a/fs/namei.c b/fs/namei.c index 6dbbd42d8b95..4acdac043b6b 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -28,7 +28,10 @@ | |||
28 | #include <linux/syscalls.h> | 28 | #include <linux/syscalls.h> |
29 | #include <linux/mount.h> | 29 | #include <linux/mount.h> |
30 | #include <linux/audit.h> | 30 | #include <linux/audit.h> |
31 | #include <linux/capability.h> | ||
31 | #include <linux/file.h> | 32 | #include <linux/file.h> |
33 | #include <linux/fcntl.h> | ||
34 | #include <linux/namei.h> | ||
32 | #include <asm/namei.h> | 35 | #include <asm/namei.h> |
33 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
34 | 37 | ||
@@ -112,7 +115,7 @@ | |||
112 | * POSIX.1 2.4: an empty pathname is invalid (ENOENT). | 115 | * POSIX.1 2.4: an empty pathname is invalid (ENOENT). |
113 | * PATH_MAX includes the nul terminator --RR. | 116 | * PATH_MAX includes the nul terminator --RR. |
114 | */ | 117 | */ |
115 | static inline int do_getname(const char __user *filename, char *page) | 118 | static int do_getname(const char __user *filename, char *page) |
116 | { | 119 | { |
117 | int retval; | 120 | int retval; |
118 | unsigned long len = PATH_MAX; | 121 | unsigned long len = PATH_MAX; |
@@ -395,7 +398,7 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, | |||
395 | * short-cut DAC fails, then call permission() to do more | 398 | * short-cut DAC fails, then call permission() to do more |
396 | * complete permission check. | 399 | * complete permission check. |
397 | */ | 400 | */ |
398 | static inline int exec_permission_lite(struct inode *inode, | 401 | static int exec_permission_lite(struct inode *inode, |
399 | struct nameidata *nd) | 402 | struct nameidata *nd) |
400 | { | 403 | { |
401 | umode_t mode = inode->i_mode; | 404 | umode_t mode = inode->i_mode; |
@@ -438,7 +441,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s | |||
438 | struct dentry * result; | 441 | struct dentry * result; |
439 | struct inode *dir = parent->d_inode; | 442 | struct inode *dir = parent->d_inode; |
440 | 443 | ||
441 | down(&dir->i_sem); | 444 | mutex_lock(&dir->i_mutex); |
442 | /* | 445 | /* |
443 | * First re-do the cached lookup just in case it was created | 446 | * First re-do the cached lookup just in case it was created |
444 | * while we waited for the directory semaphore.. | 447 | * while we waited for the directory semaphore.. |
@@ -464,7 +467,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s | |||
464 | else | 467 | else |
465 | result = dentry; | 468 | result = dentry; |
466 | } | 469 | } |
467 | up(&dir->i_sem); | 470 | mutex_unlock(&dir->i_mutex); |
468 | return result; | 471 | return result; |
469 | } | 472 | } |
470 | 473 | ||
@@ -472,7 +475,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s | |||
472 | * Uhhuh! Nasty case: the cache was re-populated while | 475 | * Uhhuh! Nasty case: the cache was re-populated while |
473 | * we waited on the semaphore. Need to revalidate. | 476 | * we waited on the semaphore. Need to revalidate. |
474 | */ | 477 | */ |
475 | up(&dir->i_sem); | 478 | mutex_unlock(&dir->i_mutex); |
476 | if (result->d_op && result->d_op->d_revalidate) { | 479 | if (result->d_op && result->d_op->d_revalidate) { |
477 | if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) { | 480 | if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) { |
478 | dput(result); | 481 | dput(result); |
@@ -485,7 +488,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s | |||
485 | static int __emul_lookup_dentry(const char *, struct nameidata *); | 488 | static int __emul_lookup_dentry(const char *, struct nameidata *); |
486 | 489 | ||
487 | /* SMP-safe */ | 490 | /* SMP-safe */ |
488 | static inline int | 491 | static __always_inline int |
489 | walk_init_root(const char *name, struct nameidata *nd) | 492 | walk_init_root(const char *name, struct nameidata *nd) |
490 | { | 493 | { |
491 | read_lock(¤t->fs->lock); | 494 | read_lock(¤t->fs->lock); |
@@ -503,7 +506,7 @@ walk_init_root(const char *name, struct nameidata *nd) | |||
503 | return 1; | 506 | return 1; |
504 | } | 507 | } |
505 | 508 | ||
506 | static inline int __vfs_follow_link(struct nameidata *nd, const char *link) | 509 | static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link) |
507 | { | 510 | { |
508 | int res = 0; | 511 | int res = 0; |
509 | char *name; | 512 | char *name; |
@@ -543,7 +546,7 @@ struct path { | |||
543 | struct dentry *dentry; | 546 | struct dentry *dentry; |
544 | }; | 547 | }; |
545 | 548 | ||
546 | static inline int __do_follow_link(struct path *path, struct nameidata *nd) | 549 | static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) |
547 | { | 550 | { |
548 | int error; | 551 | int error; |
549 | void *cookie; | 552 | void *cookie; |
@@ -689,7 +692,7 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry) | |||
689 | return 0; | 692 | return 0; |
690 | } | 693 | } |
691 | 694 | ||
692 | static inline void follow_dotdot(struct nameidata *nd) | 695 | static __always_inline void follow_dotdot(struct nameidata *nd) |
693 | { | 696 | { |
694 | while(1) { | 697 | while(1) { |
695 | struct vfsmount *parent; | 698 | struct vfsmount *parent; |
@@ -1062,7 +1065,8 @@ set_it: | |||
1062 | } | 1065 | } |
1063 | 1066 | ||
1064 | /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ | 1067 | /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ |
1065 | int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd) | 1068 | static int fastcall do_path_lookup(int dfd, const char *name, |
1069 | unsigned int flags, struct nameidata *nd) | ||
1066 | { | 1070 | { |
1067 | int retval = 0; | 1071 | int retval = 0; |
1068 | 1072 | ||
@@ -1082,9 +1086,38 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata | |||
1082 | } | 1086 | } |
1083 | nd->mnt = mntget(current->fs->rootmnt); | 1087 | nd->mnt = mntget(current->fs->rootmnt); |
1084 | nd->dentry = dget(current->fs->root); | 1088 | nd->dentry = dget(current->fs->root); |
1085 | } else { | 1089 | } else if (dfd == AT_FDCWD) { |
1086 | nd->mnt = mntget(current->fs->pwdmnt); | 1090 | nd->mnt = mntget(current->fs->pwdmnt); |
1087 | nd->dentry = dget(current->fs->pwd); | 1091 | nd->dentry = dget(current->fs->pwd); |
1092 | } else { | ||
1093 | struct file *file; | ||
1094 | int fput_needed; | ||
1095 | struct dentry *dentry; | ||
1096 | |||
1097 | file = fget_light(dfd, &fput_needed); | ||
1098 | if (!file) { | ||
1099 | retval = -EBADF; | ||
1100 | goto out_fail; | ||
1101 | } | ||
1102 | |||
1103 | dentry = file->f_dentry; | ||
1104 | |||
1105 | if (!S_ISDIR(dentry->d_inode->i_mode)) { | ||
1106 | retval = -ENOTDIR; | ||
1107 | fput_light(file, fput_needed); | ||
1108 | goto out_fail; | ||
1109 | } | ||
1110 | |||
1111 | retval = file_permission(file, MAY_EXEC); | ||
1112 | if (retval) { | ||
1113 | fput_light(file, fput_needed); | ||
1114 | goto out_fail; | ||
1115 | } | ||
1116 | |||
1117 | nd->mnt = mntget(file->f_vfsmnt); | ||
1118 | nd->dentry = dget(dentry); | ||
1119 | |||
1120 | fput_light(file, fput_needed); | ||
1088 | } | 1121 | } |
1089 | read_unlock(¤t->fs->lock); | 1122 | read_unlock(¤t->fs->lock); |
1090 | current->total_link_count = 0; | 1123 | current->total_link_count = 0; |
@@ -1093,11 +1126,19 @@ out: | |||
1093 | if (unlikely(current->audit_context | 1126 | if (unlikely(current->audit_context |
1094 | && nd && nd->dentry && nd->dentry->d_inode)) | 1127 | && nd && nd->dentry && nd->dentry->d_inode)) |
1095 | audit_inode(name, nd->dentry->d_inode, flags); | 1128 | audit_inode(name, nd->dentry->d_inode, flags); |
1129 | out_fail: | ||
1096 | return retval; | 1130 | return retval; |
1097 | } | 1131 | } |
1098 | 1132 | ||
1099 | static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags, | 1133 | int fastcall path_lookup(const char *name, unsigned int flags, |
1100 | struct nameidata *nd, int open_flags, int create_mode) | 1134 | struct nameidata *nd) |
1135 | { | ||
1136 | return do_path_lookup(AT_FDCWD, name, flags, nd); | ||
1137 | } | ||
1138 | |||
1139 | static int __path_lookup_intent_open(int dfd, const char *name, | ||
1140 | unsigned int lookup_flags, struct nameidata *nd, | ||
1141 | int open_flags, int create_mode) | ||
1101 | { | 1142 | { |
1102 | struct file *filp = get_empty_filp(); | 1143 | struct file *filp = get_empty_filp(); |
1103 | int err; | 1144 | int err; |
@@ -1107,7 +1148,7 @@ static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags | |||
1107 | nd->intent.open.file = filp; | 1148 | nd->intent.open.file = filp; |
1108 | nd->intent.open.flags = open_flags; | 1149 | nd->intent.open.flags = open_flags; |
1109 | nd->intent.open.create_mode = create_mode; | 1150 | nd->intent.open.create_mode = create_mode; |
1110 | err = path_lookup(name, lookup_flags|LOOKUP_OPEN, nd); | 1151 | err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd); |
1111 | if (IS_ERR(nd->intent.open.file)) { | 1152 | if (IS_ERR(nd->intent.open.file)) { |
1112 | if (err == 0) { | 1153 | if (err == 0) { |
1113 | err = PTR_ERR(nd->intent.open.file); | 1154 | err = PTR_ERR(nd->intent.open.file); |
@@ -1125,10 +1166,10 @@ static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags | |||
1125 | * @nd: pointer to nameidata | 1166 | * @nd: pointer to nameidata |
1126 | * @open_flags: open intent flags | 1167 | * @open_flags: open intent flags |
1127 | */ | 1168 | */ |
1128 | int path_lookup_open(const char *name, unsigned int lookup_flags, | 1169 | int path_lookup_open(int dfd, const char *name, unsigned int lookup_flags, |
1129 | struct nameidata *nd, int open_flags) | 1170 | struct nameidata *nd, int open_flags) |
1130 | { | 1171 | { |
1131 | return __path_lookup_intent_open(name, lookup_flags, nd, | 1172 | return __path_lookup_intent_open(dfd, name, lookup_flags, nd, |
1132 | open_flags, 0); | 1173 | open_flags, 0); |
1133 | } | 1174 | } |
1134 | 1175 | ||
@@ -1140,12 +1181,12 @@ int path_lookup_open(const char *name, unsigned int lookup_flags, | |||
1140 | * @open_flags: open intent flags | 1181 | * @open_flags: open intent flags |
1141 | * @create_mode: create intent flags | 1182 | * @create_mode: create intent flags |
1142 | */ | 1183 | */ |
1143 | static int path_lookup_create(const char *name, unsigned int lookup_flags, | 1184 | static int path_lookup_create(int dfd, const char *name, |
1144 | struct nameidata *nd, int open_flags, | 1185 | unsigned int lookup_flags, struct nameidata *nd, |
1145 | int create_mode) | 1186 | int open_flags, int create_mode) |
1146 | { | 1187 | { |
1147 | return __path_lookup_intent_open(name, lookup_flags|LOOKUP_CREATE, nd, | 1188 | return __path_lookup_intent_open(dfd, name, lookup_flags|LOOKUP_CREATE, |
1148 | open_flags, create_mode); | 1189 | nd, open_flags, create_mode); |
1149 | } | 1190 | } |
1150 | 1191 | ||
1151 | int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags, | 1192 | int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags, |
@@ -1155,7 +1196,7 @@ int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags, | |||
1155 | int err = PTR_ERR(tmp); | 1196 | int err = PTR_ERR(tmp); |
1156 | 1197 | ||
1157 | if (!IS_ERR(tmp)) { | 1198 | if (!IS_ERR(tmp)) { |
1158 | err = __path_lookup_intent_open(tmp, lookup_flags, nd, open_flags, 0); | 1199 | err = __path_lookup_intent_open(AT_FDCWD, tmp, lookup_flags, nd, open_flags, 0); |
1159 | putname(tmp); | 1200 | putname(tmp); |
1160 | } | 1201 | } |
1161 | return err; | 1202 | return err; |
@@ -1247,18 +1288,24 @@ access: | |||
1247 | * that namei follows links, while lnamei does not. | 1288 | * that namei follows links, while lnamei does not. |
1248 | * SMP-safe | 1289 | * SMP-safe |
1249 | */ | 1290 | */ |
1250 | int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd) | 1291 | int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags, |
1292 | struct nameidata *nd) | ||
1251 | { | 1293 | { |
1252 | char *tmp = getname(name); | 1294 | char *tmp = getname(name); |
1253 | int err = PTR_ERR(tmp); | 1295 | int err = PTR_ERR(tmp); |
1254 | 1296 | ||
1255 | if (!IS_ERR(tmp)) { | 1297 | if (!IS_ERR(tmp)) { |
1256 | err = path_lookup(tmp, flags, nd); | 1298 | err = do_path_lookup(dfd, tmp, flags, nd); |
1257 | putname(tmp); | 1299 | putname(tmp); |
1258 | } | 1300 | } |
1259 | return err; | 1301 | return err; |
1260 | } | 1302 | } |
1261 | 1303 | ||
1304 | int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd) | ||
1305 | { | ||
1306 | return __user_walk_fd(AT_FDCWD, name, flags, nd); | ||
1307 | } | ||
1308 | |||
1262 | /* | 1309 | /* |
1263 | * It's inline, so penalty for filesystems that don't use sticky bit is | 1310 | * It's inline, so penalty for filesystems that don't use sticky bit is |
1264 | * minimal. | 1311 | * minimal. |
@@ -1293,7 +1340,7 @@ static inline int check_sticky(struct inode *dir, struct inode *inode) | |||
1293 | * 10. We don't allow removal of NFS sillyrenamed files; it's handled by | 1340 | * 10. We don't allow removal of NFS sillyrenamed files; it's handled by |
1294 | * nfs_async_unlink(). | 1341 | * nfs_async_unlink(). |
1295 | */ | 1342 | */ |
1296 | static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir) | 1343 | static int may_delete(struct inode *dir,struct dentry *victim,int isdir) |
1297 | { | 1344 | { |
1298 | int error; | 1345 | int error; |
1299 | 1346 | ||
@@ -1366,7 +1413,7 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) | |||
1366 | struct dentry *p; | 1413 | struct dentry *p; |
1367 | 1414 | ||
1368 | if (p1 == p2) { | 1415 | if (p1 == p2) { |
1369 | down(&p1->d_inode->i_sem); | 1416 | mutex_lock(&p1->d_inode->i_mutex); |
1370 | return NULL; | 1417 | return NULL; |
1371 | } | 1418 | } |
1372 | 1419 | ||
@@ -1374,30 +1421,30 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) | |||
1374 | 1421 | ||
1375 | for (p = p1; p->d_parent != p; p = p->d_parent) { | 1422 | for (p = p1; p->d_parent != p; p = p->d_parent) { |
1376 | if (p->d_parent == p2) { | 1423 | if (p->d_parent == p2) { |
1377 | down(&p2->d_inode->i_sem); | 1424 | mutex_lock(&p2->d_inode->i_mutex); |
1378 | down(&p1->d_inode->i_sem); | 1425 | mutex_lock(&p1->d_inode->i_mutex); |
1379 | return p; | 1426 | return p; |
1380 | } | 1427 | } |
1381 | } | 1428 | } |
1382 | 1429 | ||
1383 | for (p = p2; p->d_parent != p; p = p->d_parent) { | 1430 | for (p = p2; p->d_parent != p; p = p->d_parent) { |
1384 | if (p->d_parent == p1) { | 1431 | if (p->d_parent == p1) { |
1385 | down(&p1->d_inode->i_sem); | 1432 | mutex_lock(&p1->d_inode->i_mutex); |
1386 | down(&p2->d_inode->i_sem); | 1433 | mutex_lock(&p2->d_inode->i_mutex); |
1387 | return p; | 1434 | return p; |
1388 | } | 1435 | } |
1389 | } | 1436 | } |
1390 | 1437 | ||
1391 | down(&p1->d_inode->i_sem); | 1438 | mutex_lock(&p1->d_inode->i_mutex); |
1392 | down(&p2->d_inode->i_sem); | 1439 | mutex_lock(&p2->d_inode->i_mutex); |
1393 | return NULL; | 1440 | return NULL; |
1394 | } | 1441 | } |
1395 | 1442 | ||
1396 | void unlock_rename(struct dentry *p1, struct dentry *p2) | 1443 | void unlock_rename(struct dentry *p1, struct dentry *p2) |
1397 | { | 1444 | { |
1398 | up(&p1->d_inode->i_sem); | 1445 | mutex_unlock(&p1->d_inode->i_mutex); |
1399 | if (p1 != p2) { | 1446 | if (p1 != p2) { |
1400 | up(&p2->d_inode->i_sem); | 1447 | mutex_unlock(&p2->d_inode->i_mutex); |
1401 | up(&p1->d_inode->i_sb->s_vfs_rename_sem); | 1448 | up(&p1->d_inode->i_sb->s_vfs_rename_sem); |
1402 | } | 1449 | } |
1403 | } | 1450 | } |
@@ -1491,7 +1538,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1491 | if (!error) { | 1538 | if (!error) { |
1492 | DQUOT_INIT(inode); | 1539 | DQUOT_INIT(inode); |
1493 | 1540 | ||
1494 | error = do_truncate(dentry, 0, NULL); | 1541 | error = do_truncate(dentry, 0, ATTR_MTIME|ATTR_CTIME, NULL); |
1495 | } | 1542 | } |
1496 | put_write_access(inode); | 1543 | put_write_access(inode); |
1497 | if (error) | 1544 | if (error) |
@@ -1517,7 +1564,8 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1517 | * for symlinks (where the permissions are checked later). | 1564 | * for symlinks (where the permissions are checked later). |
1518 | * SMP-safe | 1565 | * SMP-safe |
1519 | */ | 1566 | */ |
1520 | int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) | 1567 | int open_namei(int dfd, const char *pathname, int flag, |
1568 | int mode, struct nameidata *nd) | ||
1521 | { | 1569 | { |
1522 | int acc_mode, error; | 1570 | int acc_mode, error; |
1523 | struct path path; | 1571 | struct path path; |
@@ -1539,7 +1587,8 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) | |||
1539 | * The simplest case - just a plain lookup. | 1587 | * The simplest case - just a plain lookup. |
1540 | */ | 1588 | */ |
1541 | if (!(flag & O_CREAT)) { | 1589 | if (!(flag & O_CREAT)) { |
1542 | error = path_lookup_open(pathname, lookup_flags(flag), nd, flag); | 1590 | error = path_lookup_open(dfd, pathname, lookup_flags(flag), |
1591 | nd, flag); | ||
1543 | if (error) | 1592 | if (error) |
1544 | return error; | 1593 | return error; |
1545 | goto ok; | 1594 | goto ok; |
@@ -1548,7 +1597,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) | |||
1548 | /* | 1597 | /* |
1549 | * Create - we need to know the parent. | 1598 | * Create - we need to know the parent. |
1550 | */ | 1599 | */ |
1551 | error = path_lookup_create(pathname, LOOKUP_PARENT, nd, flag, mode); | 1600 | error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode); |
1552 | if (error) | 1601 | if (error) |
1553 | return error; | 1602 | return error; |
1554 | 1603 | ||
@@ -1563,14 +1612,14 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) | |||
1563 | 1612 | ||
1564 | dir = nd->dentry; | 1613 | dir = nd->dentry; |
1565 | nd->flags &= ~LOOKUP_PARENT; | 1614 | nd->flags &= ~LOOKUP_PARENT; |
1566 | down(&dir->d_inode->i_sem); | 1615 | mutex_lock(&dir->d_inode->i_mutex); |
1567 | path.dentry = lookup_hash(nd); | 1616 | path.dentry = lookup_hash(nd); |
1568 | path.mnt = nd->mnt; | 1617 | path.mnt = nd->mnt; |
1569 | 1618 | ||
1570 | do_last: | 1619 | do_last: |
1571 | error = PTR_ERR(path.dentry); | 1620 | error = PTR_ERR(path.dentry); |
1572 | if (IS_ERR(path.dentry)) { | 1621 | if (IS_ERR(path.dentry)) { |
1573 | up(&dir->d_inode->i_sem); | 1622 | mutex_unlock(&dir->d_inode->i_mutex); |
1574 | goto exit; | 1623 | goto exit; |
1575 | } | 1624 | } |
1576 | 1625 | ||
@@ -1579,7 +1628,7 @@ do_last: | |||
1579 | if (!IS_POSIXACL(dir->d_inode)) | 1628 | if (!IS_POSIXACL(dir->d_inode)) |
1580 | mode &= ~current->fs->umask; | 1629 | mode &= ~current->fs->umask; |
1581 | error = vfs_create(dir->d_inode, path.dentry, mode, nd); | 1630 | error = vfs_create(dir->d_inode, path.dentry, mode, nd); |
1582 | up(&dir->d_inode->i_sem); | 1631 | mutex_unlock(&dir->d_inode->i_mutex); |
1583 | dput(nd->dentry); | 1632 | dput(nd->dentry); |
1584 | nd->dentry = path.dentry; | 1633 | nd->dentry = path.dentry; |
1585 | if (error) | 1634 | if (error) |
@@ -1593,7 +1642,7 @@ do_last: | |||
1593 | /* | 1642 | /* |
1594 | * It already exists. | 1643 | * It already exists. |
1595 | */ | 1644 | */ |
1596 | up(&dir->d_inode->i_sem); | 1645 | mutex_unlock(&dir->d_inode->i_mutex); |
1597 | 1646 | ||
1598 | error = -EEXIST; | 1647 | error = -EEXIST; |
1599 | if (flag & O_EXCL) | 1648 | if (flag & O_EXCL) |
@@ -1665,7 +1714,7 @@ do_link: | |||
1665 | goto exit; | 1714 | goto exit; |
1666 | } | 1715 | } |
1667 | dir = nd->dentry; | 1716 | dir = nd->dentry; |
1668 | down(&dir->d_inode->i_sem); | 1717 | mutex_lock(&dir->d_inode->i_mutex); |
1669 | path.dentry = lookup_hash(nd); | 1718 | path.dentry = lookup_hash(nd); |
1670 | path.mnt = nd->mnt; | 1719 | path.mnt = nd->mnt; |
1671 | __putname(nd->last.name); | 1720 | __putname(nd->last.name); |
@@ -1680,13 +1729,13 @@ do_link: | |||
1680 | * Simple function to lookup and return a dentry and create it | 1729 | * Simple function to lookup and return a dentry and create it |
1681 | * if it doesn't exist. Is SMP-safe. | 1730 | * if it doesn't exist. Is SMP-safe. |
1682 | * | 1731 | * |
1683 | * Returns with nd->dentry->d_inode->i_sem locked. | 1732 | * Returns with nd->dentry->d_inode->i_mutex locked. |
1684 | */ | 1733 | */ |
1685 | struct dentry *lookup_create(struct nameidata *nd, int is_dir) | 1734 | struct dentry *lookup_create(struct nameidata *nd, int is_dir) |
1686 | { | 1735 | { |
1687 | struct dentry *dentry = ERR_PTR(-EEXIST); | 1736 | struct dentry *dentry = ERR_PTR(-EEXIST); |
1688 | 1737 | ||
1689 | down(&nd->dentry->d_inode->i_sem); | 1738 | mutex_lock(&nd->dentry->d_inode->i_mutex); |
1690 | /* | 1739 | /* |
1691 | * Yucky last component or no last component at all? | 1740 | * Yucky last component or no last component at all? |
1692 | * (foo/., foo/.., /////) | 1741 | * (foo/., foo/.., /////) |
@@ -1743,7 +1792,8 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | |||
1743 | return error; | 1792 | return error; |
1744 | } | 1793 | } |
1745 | 1794 | ||
1746 | asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev) | 1795 | asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, |
1796 | unsigned dev) | ||
1747 | { | 1797 | { |
1748 | int error = 0; | 1798 | int error = 0; |
1749 | char * tmp; | 1799 | char * tmp; |
@@ -1756,7 +1806,7 @@ asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev) | |||
1756 | if (IS_ERR(tmp)) | 1806 | if (IS_ERR(tmp)) |
1757 | return PTR_ERR(tmp); | 1807 | return PTR_ERR(tmp); |
1758 | 1808 | ||
1759 | error = path_lookup(tmp, LOOKUP_PARENT, &nd); | 1809 | error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd); |
1760 | if (error) | 1810 | if (error) |
1761 | goto out; | 1811 | goto out; |
1762 | dentry = lookup_create(&nd, 0); | 1812 | dentry = lookup_create(&nd, 0); |
@@ -1784,7 +1834,7 @@ asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev) | |||
1784 | } | 1834 | } |
1785 | dput(dentry); | 1835 | dput(dentry); |
1786 | } | 1836 | } |
1787 | up(&nd.dentry->d_inode->i_sem); | 1837 | mutex_unlock(&nd.dentry->d_inode->i_mutex); |
1788 | path_release(&nd); | 1838 | path_release(&nd); |
1789 | out: | 1839 | out: |
1790 | putname(tmp); | 1840 | putname(tmp); |
@@ -1792,6 +1842,11 @@ out: | |||
1792 | return error; | 1842 | return error; |
1793 | } | 1843 | } |
1794 | 1844 | ||
1845 | asmlinkage long sys_mknod(const char __user *filename, int mode, unsigned dev) | ||
1846 | { | ||
1847 | return sys_mknodat(AT_FDCWD, filename, mode, dev); | ||
1848 | } | ||
1849 | |||
1795 | int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | 1850 | int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) |
1796 | { | 1851 | { |
1797 | int error = may_create(dir, dentry, NULL); | 1852 | int error = may_create(dir, dentry, NULL); |
@@ -1814,7 +1869,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
1814 | return error; | 1869 | return error; |
1815 | } | 1870 | } |
1816 | 1871 | ||
1817 | asmlinkage long sys_mkdir(const char __user * pathname, int mode) | 1872 | asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) |
1818 | { | 1873 | { |
1819 | int error = 0; | 1874 | int error = 0; |
1820 | char * tmp; | 1875 | char * tmp; |
@@ -1825,7 +1880,7 @@ asmlinkage long sys_mkdir(const char __user * pathname, int mode) | |||
1825 | struct dentry *dentry; | 1880 | struct dentry *dentry; |
1826 | struct nameidata nd; | 1881 | struct nameidata nd; |
1827 | 1882 | ||
1828 | error = path_lookup(tmp, LOOKUP_PARENT, &nd); | 1883 | error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd); |
1829 | if (error) | 1884 | if (error) |
1830 | goto out; | 1885 | goto out; |
1831 | dentry = lookup_create(&nd, 1); | 1886 | dentry = lookup_create(&nd, 1); |
@@ -1836,7 +1891,7 @@ asmlinkage long sys_mkdir(const char __user * pathname, int mode) | |||
1836 | error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); | 1891 | error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); |
1837 | dput(dentry); | 1892 | dput(dentry); |
1838 | } | 1893 | } |
1839 | up(&nd.dentry->d_inode->i_sem); | 1894 | mutex_unlock(&nd.dentry->d_inode->i_mutex); |
1840 | path_release(&nd); | 1895 | path_release(&nd); |
1841 | out: | 1896 | out: |
1842 | putname(tmp); | 1897 | putname(tmp); |
@@ -1845,6 +1900,11 @@ out: | |||
1845 | return error; | 1900 | return error; |
1846 | } | 1901 | } |
1847 | 1902 | ||
1903 | asmlinkage long sys_mkdir(const char __user *pathname, int mode) | ||
1904 | { | ||
1905 | return sys_mkdirat(AT_FDCWD, pathname, mode); | ||
1906 | } | ||
1907 | |||
1848 | /* | 1908 | /* |
1849 | * We try to drop the dentry early: we should have | 1909 | * We try to drop the dentry early: we should have |
1850 | * a usage count of 2 if we're the only user of this | 1910 | * a usage count of 2 if we're the only user of this |
@@ -1885,7 +1945,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1885 | 1945 | ||
1886 | DQUOT_INIT(dir); | 1946 | DQUOT_INIT(dir); |
1887 | 1947 | ||
1888 | down(&dentry->d_inode->i_sem); | 1948 | mutex_lock(&dentry->d_inode->i_mutex); |
1889 | dentry_unhash(dentry); | 1949 | dentry_unhash(dentry); |
1890 | if (d_mountpoint(dentry)) | 1950 | if (d_mountpoint(dentry)) |
1891 | error = -EBUSY; | 1951 | error = -EBUSY; |
@@ -1897,7 +1957,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1897 | dentry->d_inode->i_flags |= S_DEAD; | 1957 | dentry->d_inode->i_flags |= S_DEAD; |
1898 | } | 1958 | } |
1899 | } | 1959 | } |
1900 | up(&dentry->d_inode->i_sem); | 1960 | mutex_unlock(&dentry->d_inode->i_mutex); |
1901 | if (!error) { | 1961 | if (!error) { |
1902 | d_delete(dentry); | 1962 | d_delete(dentry); |
1903 | } | 1963 | } |
@@ -1906,7 +1966,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1906 | return error; | 1966 | return error; |
1907 | } | 1967 | } |
1908 | 1968 | ||
1909 | asmlinkage long sys_rmdir(const char __user * pathname) | 1969 | static long do_rmdir(int dfd, const char __user *pathname) |
1910 | { | 1970 | { |
1911 | int error = 0; | 1971 | int error = 0; |
1912 | char * name; | 1972 | char * name; |
@@ -1917,7 +1977,7 @@ asmlinkage long sys_rmdir(const char __user * pathname) | |||
1917 | if(IS_ERR(name)) | 1977 | if(IS_ERR(name)) |
1918 | return PTR_ERR(name); | 1978 | return PTR_ERR(name); |
1919 | 1979 | ||
1920 | error = path_lookup(name, LOOKUP_PARENT, &nd); | 1980 | error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd); |
1921 | if (error) | 1981 | if (error) |
1922 | goto exit; | 1982 | goto exit; |
1923 | 1983 | ||
@@ -1932,14 +1992,14 @@ asmlinkage long sys_rmdir(const char __user * pathname) | |||
1932 | error = -EBUSY; | 1992 | error = -EBUSY; |
1933 | goto exit1; | 1993 | goto exit1; |
1934 | } | 1994 | } |
1935 | down(&nd.dentry->d_inode->i_sem); | 1995 | mutex_lock(&nd.dentry->d_inode->i_mutex); |
1936 | dentry = lookup_hash(&nd); | 1996 | dentry = lookup_hash(&nd); |
1937 | error = PTR_ERR(dentry); | 1997 | error = PTR_ERR(dentry); |
1938 | if (!IS_ERR(dentry)) { | 1998 | if (!IS_ERR(dentry)) { |
1939 | error = vfs_rmdir(nd.dentry->d_inode, dentry); | 1999 | error = vfs_rmdir(nd.dentry->d_inode, dentry); |
1940 | dput(dentry); | 2000 | dput(dentry); |
1941 | } | 2001 | } |
1942 | up(&nd.dentry->d_inode->i_sem); | 2002 | mutex_unlock(&nd.dentry->d_inode->i_mutex); |
1943 | exit1: | 2003 | exit1: |
1944 | path_release(&nd); | 2004 | path_release(&nd); |
1945 | exit: | 2005 | exit: |
@@ -1947,6 +2007,11 @@ exit: | |||
1947 | return error; | 2007 | return error; |
1948 | } | 2008 | } |
1949 | 2009 | ||
2010 | asmlinkage long sys_rmdir(const char __user *pathname) | ||
2011 | { | ||
2012 | return do_rmdir(AT_FDCWD, pathname); | ||
2013 | } | ||
2014 | |||
1950 | int vfs_unlink(struct inode *dir, struct dentry *dentry) | 2015 | int vfs_unlink(struct inode *dir, struct dentry *dentry) |
1951 | { | 2016 | { |
1952 | int error = may_delete(dir, dentry, 0); | 2017 | int error = may_delete(dir, dentry, 0); |
@@ -1959,7 +2024,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1959 | 2024 | ||
1960 | DQUOT_INIT(dir); | 2025 | DQUOT_INIT(dir); |
1961 | 2026 | ||
1962 | down(&dentry->d_inode->i_sem); | 2027 | mutex_lock(&dentry->d_inode->i_mutex); |
1963 | if (d_mountpoint(dentry)) | 2028 | if (d_mountpoint(dentry)) |
1964 | error = -EBUSY; | 2029 | error = -EBUSY; |
1965 | else { | 2030 | else { |
@@ -1967,7 +2032,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1967 | if (!error) | 2032 | if (!error) |
1968 | error = dir->i_op->unlink(dir, dentry); | 2033 | error = dir->i_op->unlink(dir, dentry); |
1969 | } | 2034 | } |
1970 | up(&dentry->d_inode->i_sem); | 2035 | mutex_unlock(&dentry->d_inode->i_mutex); |
1971 | 2036 | ||
1972 | /* We don't d_delete() NFS sillyrenamed files--they still exist. */ | 2037 | /* We don't d_delete() NFS sillyrenamed files--they still exist. */ |
1973 | if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { | 2038 | if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { |
@@ -1979,11 +2044,11 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1979 | 2044 | ||
1980 | /* | 2045 | /* |
1981 | * Make sure that the actual truncation of the file will occur outside its | 2046 | * Make sure that the actual truncation of the file will occur outside its |
1982 | * directory's i_sem. Truncate can take a long time if there is a lot of | 2047 | * directory's i_mutex. Truncate can take a long time if there is a lot of |
1983 | * writeout happening, and we don't want to prevent access to the directory | 2048 | * writeout happening, and we don't want to prevent access to the directory |
1984 | * while waiting on the I/O. | 2049 | * while waiting on the I/O. |
1985 | */ | 2050 | */ |
1986 | asmlinkage long sys_unlink(const char __user * pathname) | 2051 | static long do_unlinkat(int dfd, const char __user *pathname) |
1987 | { | 2052 | { |
1988 | int error = 0; | 2053 | int error = 0; |
1989 | char * name; | 2054 | char * name; |
@@ -1995,13 +2060,13 @@ asmlinkage long sys_unlink(const char __user * pathname) | |||
1995 | if(IS_ERR(name)) | 2060 | if(IS_ERR(name)) |
1996 | return PTR_ERR(name); | 2061 | return PTR_ERR(name); |
1997 | 2062 | ||
1998 | error = path_lookup(name, LOOKUP_PARENT, &nd); | 2063 | error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd); |
1999 | if (error) | 2064 | if (error) |
2000 | goto exit; | 2065 | goto exit; |
2001 | error = -EISDIR; | 2066 | error = -EISDIR; |
2002 | if (nd.last_type != LAST_NORM) | 2067 | if (nd.last_type != LAST_NORM) |
2003 | goto exit1; | 2068 | goto exit1; |
2004 | down(&nd.dentry->d_inode->i_sem); | 2069 | mutex_lock(&nd.dentry->d_inode->i_mutex); |
2005 | dentry = lookup_hash(&nd); | 2070 | dentry = lookup_hash(&nd); |
2006 | error = PTR_ERR(dentry); | 2071 | error = PTR_ERR(dentry); |
2007 | if (!IS_ERR(dentry)) { | 2072 | if (!IS_ERR(dentry)) { |
@@ -2015,7 +2080,7 @@ asmlinkage long sys_unlink(const char __user * pathname) | |||
2015 | exit2: | 2080 | exit2: |
2016 | dput(dentry); | 2081 | dput(dentry); |
2017 | } | 2082 | } |
2018 | up(&nd.dentry->d_inode->i_sem); | 2083 | mutex_unlock(&nd.dentry->d_inode->i_mutex); |
2019 | if (inode) | 2084 | if (inode) |
2020 | iput(inode); /* truncate the inode here */ | 2085 | iput(inode); /* truncate the inode here */ |
2021 | exit1: | 2086 | exit1: |
@@ -2030,6 +2095,22 @@ slashes: | |||
2030 | goto exit2; | 2095 | goto exit2; |
2031 | } | 2096 | } |
2032 | 2097 | ||
2098 | asmlinkage long sys_unlinkat(int dfd, const char __user *pathname, int flag) | ||
2099 | { | ||
2100 | if ((flag & ~AT_REMOVEDIR) != 0) | ||
2101 | return -EINVAL; | ||
2102 | |||
2103 | if (flag & AT_REMOVEDIR) | ||
2104 | return do_rmdir(dfd, pathname); | ||
2105 | |||
2106 | return do_unlinkat(dfd, pathname); | ||
2107 | } | ||
2108 | |||
2109 | asmlinkage long sys_unlink(const char __user *pathname) | ||
2110 | { | ||
2111 | return do_unlinkat(AT_FDCWD, pathname); | ||
2112 | } | ||
2113 | |||
2033 | int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode) | 2114 | int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode) |
2034 | { | 2115 | { |
2035 | int error = may_create(dir, dentry, NULL); | 2116 | int error = may_create(dir, dentry, NULL); |
@@ -2051,7 +2132,8 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, i | |||
2051 | return error; | 2132 | return error; |
2052 | } | 2133 | } |
2053 | 2134 | ||
2054 | asmlinkage long sys_symlink(const char __user * oldname, const char __user * newname) | 2135 | asmlinkage long sys_symlinkat(const char __user *oldname, |
2136 | int newdfd, const char __user *newname) | ||
2055 | { | 2137 | { |
2056 | int error = 0; | 2138 | int error = 0; |
2057 | char * from; | 2139 | char * from; |
@@ -2066,7 +2148,7 @@ asmlinkage long sys_symlink(const char __user * oldname, const char __user * new | |||
2066 | struct dentry *dentry; | 2148 | struct dentry *dentry; |
2067 | struct nameidata nd; | 2149 | struct nameidata nd; |
2068 | 2150 | ||
2069 | error = path_lookup(to, LOOKUP_PARENT, &nd); | 2151 | error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd); |
2070 | if (error) | 2152 | if (error) |
2071 | goto out; | 2153 | goto out; |
2072 | dentry = lookup_create(&nd, 0); | 2154 | dentry = lookup_create(&nd, 0); |
@@ -2075,7 +2157,7 @@ asmlinkage long sys_symlink(const char __user * oldname, const char __user * new | |||
2075 | error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO); | 2157 | error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO); |
2076 | dput(dentry); | 2158 | dput(dentry); |
2077 | } | 2159 | } |
2078 | up(&nd.dentry->d_inode->i_sem); | 2160 | mutex_unlock(&nd.dentry->d_inode->i_mutex); |
2079 | path_release(&nd); | 2161 | path_release(&nd); |
2080 | out: | 2162 | out: |
2081 | putname(to); | 2163 | putname(to); |
@@ -2084,6 +2166,11 @@ out: | |||
2084 | return error; | 2166 | return error; |
2085 | } | 2167 | } |
2086 | 2168 | ||
2169 | asmlinkage long sys_symlink(const char __user *oldname, const char __user *newname) | ||
2170 | { | ||
2171 | return sys_symlinkat(oldname, AT_FDCWD, newname); | ||
2172 | } | ||
2173 | |||
2087 | int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) | 2174 | int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) |
2088 | { | 2175 | { |
2089 | struct inode *inode = old_dentry->d_inode; | 2176 | struct inode *inode = old_dentry->d_inode; |
@@ -2113,10 +2200,10 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de | |||
2113 | if (error) | 2200 | if (error) |
2114 | return error; | 2201 | return error; |
2115 | 2202 | ||
2116 | down(&old_dentry->d_inode->i_sem); | 2203 | mutex_lock(&old_dentry->d_inode->i_mutex); |
2117 | DQUOT_INIT(dir); | 2204 | DQUOT_INIT(dir); |
2118 | error = dir->i_op->link(old_dentry, dir, new_dentry); | 2205 | error = dir->i_op->link(old_dentry, dir, new_dentry); |
2119 | up(&old_dentry->d_inode->i_sem); | 2206 | mutex_unlock(&old_dentry->d_inode->i_mutex); |
2120 | if (!error) | 2207 | if (!error) |
2121 | fsnotify_create(dir, new_dentry->d_name.name); | 2208 | fsnotify_create(dir, new_dentry->d_name.name); |
2122 | return error; | 2209 | return error; |
@@ -2131,7 +2218,8 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de | |||
2131 | * with linux 2.0, and to avoid hard-linking to directories | 2218 | * with linux 2.0, and to avoid hard-linking to directories |
2132 | * and other special files. --ADM | 2219 | * and other special files. --ADM |
2133 | */ | 2220 | */ |
2134 | asmlinkage long sys_link(const char __user * oldname, const char __user * newname) | 2221 | asmlinkage long sys_linkat(int olddfd, const char __user *oldname, |
2222 | int newdfd, const char __user *newname) | ||
2135 | { | 2223 | { |
2136 | struct dentry *new_dentry; | 2224 | struct dentry *new_dentry; |
2137 | struct nameidata nd, old_nd; | 2225 | struct nameidata nd, old_nd; |
@@ -2142,10 +2230,10 @@ asmlinkage long sys_link(const char __user * oldname, const char __user * newnam | |||
2142 | if (IS_ERR(to)) | 2230 | if (IS_ERR(to)) |
2143 | return PTR_ERR(to); | 2231 | return PTR_ERR(to); |
2144 | 2232 | ||
2145 | error = __user_walk(oldname, 0, &old_nd); | 2233 | error = __user_walk_fd(olddfd, oldname, 0, &old_nd); |
2146 | if (error) | 2234 | if (error) |
2147 | goto exit; | 2235 | goto exit; |
2148 | error = path_lookup(to, LOOKUP_PARENT, &nd); | 2236 | error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd); |
2149 | if (error) | 2237 | if (error) |
2150 | goto out; | 2238 | goto out; |
2151 | error = -EXDEV; | 2239 | error = -EXDEV; |
@@ -2157,7 +2245,7 @@ asmlinkage long sys_link(const char __user * oldname, const char __user * newnam | |||
2157 | error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); | 2245 | error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); |
2158 | dput(new_dentry); | 2246 | dput(new_dentry); |
2159 | } | 2247 | } |
2160 | up(&nd.dentry->d_inode->i_sem); | 2248 | mutex_unlock(&nd.dentry->d_inode->i_mutex); |
2161 | out_release: | 2249 | out_release: |
2162 | path_release(&nd); | 2250 | path_release(&nd); |
2163 | out: | 2251 | out: |
@@ -2168,6 +2256,11 @@ exit: | |||
2168 | return error; | 2256 | return error; |
2169 | } | 2257 | } |
2170 | 2258 | ||
2259 | asmlinkage long sys_link(const char __user *oldname, const char __user *newname) | ||
2260 | { | ||
2261 | return sys_linkat(AT_FDCWD, oldname, AT_FDCWD, newname); | ||
2262 | } | ||
2263 | |||
2171 | /* | 2264 | /* |
2172 | * The worst of all namespace operations - renaming directory. "Perverted" | 2265 | * The worst of all namespace operations - renaming directory. "Perverted" |
2173 | * doesn't even start to describe it. Somebody in UCB had a heck of a trip... | 2266 | * doesn't even start to describe it. Somebody in UCB had a heck of a trip... |
@@ -2178,7 +2271,7 @@ exit: | |||
2178 | * sb->s_vfs_rename_sem. We might be more accurate, but that's another | 2271 | * sb->s_vfs_rename_sem. We might be more accurate, but that's another |
2179 | * story. | 2272 | * story. |
2180 | * c) we have to lock _three_ objects - parents and victim (if it exists). | 2273 | * c) we have to lock _three_ objects - parents and victim (if it exists). |
2181 | * And that - after we got ->i_sem on parents (until then we don't know | 2274 | * And that - after we got ->i_mutex on parents (until then we don't know |
2182 | * whether the target exists). Solution: try to be smart with locking | 2275 | * whether the target exists). Solution: try to be smart with locking |
2183 | * order for inodes. We rely on the fact that tree topology may change | 2276 | * order for inodes. We rely on the fact that tree topology may change |
2184 | * only under ->s_vfs_rename_sem _and_ that parent of the object we | 2277 | * only under ->s_vfs_rename_sem _and_ that parent of the object we |
@@ -2195,9 +2288,9 @@ exit: | |||
2195 | * stuff into VFS), but the former is not going away. Solution: the same | 2288 | * stuff into VFS), but the former is not going away. Solution: the same |
2196 | * trick as in rmdir(). | 2289 | * trick as in rmdir(). |
2197 | * e) conversion from fhandle to dentry may come in the wrong moment - when | 2290 | * e) conversion from fhandle to dentry may come in the wrong moment - when |
2198 | * we are removing the target. Solution: we will have to grab ->i_sem | 2291 | * we are removing the target. Solution: we will have to grab ->i_mutex |
2199 | * in the fhandle_to_dentry code. [FIXME - current nfsfh.c relies on | 2292 | * in the fhandle_to_dentry code. [FIXME - current nfsfh.c relies on |
2200 | * ->i_sem on parents, which works but leads to some truely excessive | 2293 | * ->i_mutex on parents, which works but leads to some truely excessive |
2201 | * locking]. | 2294 | * locking]. |
2202 | */ | 2295 | */ |
2203 | static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, | 2296 | static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, |
@@ -2222,7 +2315,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, | |||
2222 | 2315 | ||
2223 | target = new_dentry->d_inode; | 2316 | target = new_dentry->d_inode; |
2224 | if (target) { | 2317 | if (target) { |
2225 | down(&target->i_sem); | 2318 | mutex_lock(&target->i_mutex); |
2226 | dentry_unhash(new_dentry); | 2319 | dentry_unhash(new_dentry); |
2227 | } | 2320 | } |
2228 | if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) | 2321 | if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) |
@@ -2232,7 +2325,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, | |||
2232 | if (target) { | 2325 | if (target) { |
2233 | if (!error) | 2326 | if (!error) |
2234 | target->i_flags |= S_DEAD; | 2327 | target->i_flags |= S_DEAD; |
2235 | up(&target->i_sem); | 2328 | mutex_unlock(&target->i_mutex); |
2236 | if (d_unhashed(new_dentry)) | 2329 | if (d_unhashed(new_dentry)) |
2237 | d_rehash(new_dentry); | 2330 | d_rehash(new_dentry); |
2238 | dput(new_dentry); | 2331 | dput(new_dentry); |
@@ -2255,7 +2348,7 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, | |||
2255 | dget(new_dentry); | 2348 | dget(new_dentry); |
2256 | target = new_dentry->d_inode; | 2349 | target = new_dentry->d_inode; |
2257 | if (target) | 2350 | if (target) |
2258 | down(&target->i_sem); | 2351 | mutex_lock(&target->i_mutex); |
2259 | if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) | 2352 | if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) |
2260 | error = -EBUSY; | 2353 | error = -EBUSY; |
2261 | else | 2354 | else |
@@ -2266,7 +2359,7 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, | |||
2266 | d_move(old_dentry, new_dentry); | 2359 | d_move(old_dentry, new_dentry); |
2267 | } | 2360 | } |
2268 | if (target) | 2361 | if (target) |
2269 | up(&target->i_sem); | 2362 | mutex_unlock(&target->i_mutex); |
2270 | dput(new_dentry); | 2363 | dput(new_dentry); |
2271 | return error; | 2364 | return error; |
2272 | } | 2365 | } |
@@ -2314,7 +2407,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2314 | return error; | 2407 | return error; |
2315 | } | 2408 | } |
2316 | 2409 | ||
2317 | static inline int do_rename(const char * oldname, const char * newname) | 2410 | static int do_rename(int olddfd, const char *oldname, |
2411 | int newdfd, const char *newname) | ||
2318 | { | 2412 | { |
2319 | int error = 0; | 2413 | int error = 0; |
2320 | struct dentry * old_dir, * new_dir; | 2414 | struct dentry * old_dir, * new_dir; |
@@ -2322,11 +2416,11 @@ static inline int do_rename(const char * oldname, const char * newname) | |||
2322 | struct dentry * trap; | 2416 | struct dentry * trap; |
2323 | struct nameidata oldnd, newnd; | 2417 | struct nameidata oldnd, newnd; |
2324 | 2418 | ||
2325 | error = path_lookup(oldname, LOOKUP_PARENT, &oldnd); | 2419 | error = do_path_lookup(olddfd, oldname, LOOKUP_PARENT, &oldnd); |
2326 | if (error) | 2420 | if (error) |
2327 | goto exit; | 2421 | goto exit; |
2328 | 2422 | ||
2329 | error = path_lookup(newname, LOOKUP_PARENT, &newnd); | 2423 | error = do_path_lookup(newdfd, newname, LOOKUP_PARENT, &newnd); |
2330 | if (error) | 2424 | if (error) |
2331 | goto exit1; | 2425 | goto exit1; |
2332 | 2426 | ||
@@ -2390,7 +2484,8 @@ exit: | |||
2390 | return error; | 2484 | return error; |
2391 | } | 2485 | } |
2392 | 2486 | ||
2393 | asmlinkage long sys_rename(const char __user * oldname, const char __user * newname) | 2487 | asmlinkage long sys_renameat(int olddfd, const char __user *oldname, |
2488 | int newdfd, const char __user *newname) | ||
2394 | { | 2489 | { |
2395 | int error; | 2490 | int error; |
2396 | char * from; | 2491 | char * from; |
@@ -2402,13 +2497,18 @@ asmlinkage long sys_rename(const char __user * oldname, const char __user * newn | |||
2402 | to = getname(newname); | 2497 | to = getname(newname); |
2403 | error = PTR_ERR(to); | 2498 | error = PTR_ERR(to); |
2404 | if (!IS_ERR(to)) { | 2499 | if (!IS_ERR(to)) { |
2405 | error = do_rename(from,to); | 2500 | error = do_rename(olddfd, from, newdfd, to); |
2406 | putname(to); | 2501 | putname(to); |
2407 | } | 2502 | } |
2408 | putname(from); | 2503 | putname(from); |
2409 | return error; | 2504 | return error; |
2410 | } | 2505 | } |
2411 | 2506 | ||
2507 | asmlinkage long sys_rename(const char __user *oldname, const char __user *newname) | ||
2508 | { | ||
2509 | return sys_renameat(AT_FDCWD, oldname, AT_FDCWD, newname); | ||
2510 | } | ||
2511 | |||
2412 | int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link) | 2512 | int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link) |
2413 | { | 2513 | { |
2414 | int len; | 2514 | int len; |
@@ -2552,6 +2652,7 @@ struct inode_operations page_symlink_inode_operations = { | |||
2552 | }; | 2652 | }; |
2553 | 2653 | ||
2554 | EXPORT_SYMBOL(__user_walk); | 2654 | EXPORT_SYMBOL(__user_walk); |
2655 | EXPORT_SYMBOL(__user_walk_fd); | ||
2555 | EXPORT_SYMBOL(follow_down); | 2656 | EXPORT_SYMBOL(follow_down); |
2556 | EXPORT_SYMBOL(follow_up); | 2657 | EXPORT_SYMBOL(follow_up); |
2557 | EXPORT_SYMBOL(get_write_access); /* binfmt_aout */ | 2658 | EXPORT_SYMBOL(get_write_access); /* binfmt_aout */ |