| .. | .. |
|---|
| 22 | 22 | 3) object removal. Locking rules: caller locks parent, finds victim, |
|---|
| 23 | 23 | locks victim and calls the method. Locks are exclusive. |
|---|
| 24 | 24 | |
|---|
| 25 | | -4) rename() that is _not_ cross-directory. Locking rules: caller locks |
|---|
| 26 | | -the parent and finds source and target. In case of exchange (with |
|---|
| 27 | | -RENAME_EXCHANGE in flags argument) lock both. In any case, |
|---|
| 28 | | -if the target already exists, lock it. If the source is a non-directory, |
|---|
| 29 | | -lock it. If we need to lock both, lock them in inode pointer order. |
|---|
| 30 | | -Then call the method. All locks are exclusive. |
|---|
| 25 | +4) rename() that is _not_ cross-directory. Locking rules: caller locks the |
|---|
| 26 | +parent and finds source and target. We lock both (provided they exist). If we |
|---|
| 27 | +need to lock two inodes of different type (dir vs non-dir), we lock directory |
|---|
| 28 | +first. If we need to lock two inodes of the same type, lock them in inode |
|---|
| 29 | +pointer order. Then call the method. All locks are exclusive. |
|---|
| 31 | 30 | NB: we might get away with locking the source (and target in exchange |
|---|
| 32 | 31 | case) shared. |
|---|
| 33 | 32 | |
|---|
| .. | .. |
|---|
| 44 | 43 | rules: |
|---|
| 45 | 44 | |
|---|
| 46 | 45 | * lock the filesystem |
|---|
| 47 | | - * lock parents in "ancestors first" order. |
|---|
| 46 | + * lock parents in "ancestors first" order. If one is not ancestor of |
|---|
| 47 | + the other, lock them in inode pointer order. |
|---|
| 48 | 48 | * find source and target. |
|---|
| 49 | 49 | * if old parent is equal to or is a descendent of target |
|---|
| 50 | 50 | fail with -ENOTEMPTY |
|---|
| 51 | 51 | * if new parent is equal to or is a descendent of source |
|---|
| 52 | 52 | fail with -ELOOP |
|---|
| 53 | | - * If it's an exchange, lock both the source and the target. |
|---|
| 54 | | - * If the target exists, lock it. If the source is a non-directory, |
|---|
| 55 | | - lock it. If we need to lock both, do so in inode pointer order. |
|---|
| 53 | + * Lock both the source and the target provided they exist. If we |
|---|
| 54 | + need to lock two inodes of different type (dir vs non-dir), we lock |
|---|
| 55 | + the directory first. If we need to lock two inodes of the same type, |
|---|
| 56 | + lock them in inode pointer order. |
|---|
| 56 | 57 | * call the method. |
|---|
| 57 | 58 | |
|---|
| 58 | 59 | All ->i_rwsem are taken exclusive. Again, we might get away with locking |
|---|
| .. | .. |
|---|
| 66 | 67 | |
|---|
| 67 | 68 | Proof: |
|---|
| 68 | 69 | |
|---|
| 69 | | - First of all, at any moment we have a partial ordering of the |
|---|
| 70 | | - objects - A < B iff A is an ancestor of B. |
|---|
| 70 | + First of all, at any moment we have a linear ordering of the |
|---|
| 71 | + objects - A < B iff (A is an ancestor of B) or (B is not an ancestor |
|---|
| 72 | + of A and ptr(A) < ptr(B)). |
|---|
| 71 | 73 | |
|---|
| 72 | 74 | That ordering can change. However, the following is true: |
|---|
| 73 | 75 | |
|---|