diff options
Diffstat (limited to 'fs/ocfs2/namei.c')
-rw-r--r-- | fs/ocfs2/namei.c | 305 |
1 files changed, 234 insertions, 71 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index f171b51a74f7..e7bde21149ae 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -171,7 +171,8 @@ bail_add: | |||
171 | ret = ERR_PTR(status); | 171 | ret = ERR_PTR(status); |
172 | goto bail_unlock; | 172 | goto bail_unlock; |
173 | } | 173 | } |
174 | } | 174 | } else |
175 | ocfs2_dentry_attach_gen(dentry); | ||
175 | 176 | ||
176 | bail_unlock: | 177 | bail_unlock: |
177 | /* Don't drop the cluster lock until *after* the d_add -- | 178 | /* Don't drop the cluster lock until *after* the d_add -- |
@@ -472,32 +473,23 @@ leave: | |||
472 | return status; | 473 | return status; |
473 | } | 474 | } |
474 | 475 | ||
475 | static int ocfs2_mknod_locked(struct ocfs2_super *osb, | 476 | static int __ocfs2_mknod_locked(struct inode *dir, |
476 | struct inode *dir, | 477 | struct inode *inode, |
477 | struct inode *inode, | 478 | dev_t dev, |
478 | dev_t dev, | 479 | struct buffer_head **new_fe_bh, |
479 | struct buffer_head **new_fe_bh, | 480 | struct buffer_head *parent_fe_bh, |
480 | struct buffer_head *parent_fe_bh, | 481 | handle_t *handle, |
481 | handle_t *handle, | 482 | struct ocfs2_alloc_context *inode_ac, |
482 | struct ocfs2_alloc_context *inode_ac) | 483 | u64 fe_blkno, u64 suballoc_loc, u16 suballoc_bit) |
483 | { | 484 | { |
484 | int status = 0; | 485 | int status = 0; |
486 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | ||
485 | struct ocfs2_dinode *fe = NULL; | 487 | struct ocfs2_dinode *fe = NULL; |
486 | struct ocfs2_extent_list *fel; | 488 | struct ocfs2_extent_list *fel; |
487 | u64 suballoc_loc, fe_blkno = 0; | ||
488 | u16 suballoc_bit; | ||
489 | u16 feat; | 489 | u16 feat; |
490 | 490 | ||
491 | *new_fe_bh = NULL; | 491 | *new_fe_bh = NULL; |
492 | 492 | ||
493 | status = ocfs2_claim_new_inode(handle, dir, parent_fe_bh, | ||
494 | inode_ac, &suballoc_loc, | ||
495 | &suballoc_bit, &fe_blkno); | ||
496 | if (status < 0) { | ||
497 | mlog_errno(status); | ||
498 | goto leave; | ||
499 | } | ||
500 | |||
501 | /* populate as many fields early on as possible - many of | 493 | /* populate as many fields early on as possible - many of |
502 | * these are used by the support functions here and in | 494 | * these are used by the support functions here and in |
503 | * callers. */ | 495 | * callers. */ |
@@ -591,6 +583,34 @@ leave: | |||
591 | return status; | 583 | return status; |
592 | } | 584 | } |
593 | 585 | ||
586 | static int ocfs2_mknod_locked(struct ocfs2_super *osb, | ||
587 | struct inode *dir, | ||
588 | struct inode *inode, | ||
589 | dev_t dev, | ||
590 | struct buffer_head **new_fe_bh, | ||
591 | struct buffer_head *parent_fe_bh, | ||
592 | handle_t *handle, | ||
593 | struct ocfs2_alloc_context *inode_ac) | ||
594 | { | ||
595 | int status = 0; | ||
596 | u64 suballoc_loc, fe_blkno = 0; | ||
597 | u16 suballoc_bit; | ||
598 | |||
599 | *new_fe_bh = NULL; | ||
600 | |||
601 | status = ocfs2_claim_new_inode(handle, dir, parent_fe_bh, | ||
602 | inode_ac, &suballoc_loc, | ||
603 | &suballoc_bit, &fe_blkno); | ||
604 | if (status < 0) { | ||
605 | mlog_errno(status); | ||
606 | return status; | ||
607 | } | ||
608 | |||
609 | return __ocfs2_mknod_locked(dir, inode, dev, new_fe_bh, | ||
610 | parent_fe_bh, handle, inode_ac, | ||
611 | fe_blkno, suballoc_loc, suballoc_bit); | ||
612 | } | ||
613 | |||
594 | static int ocfs2_mkdir(struct inode *dir, | 614 | static int ocfs2_mkdir(struct inode *dir, |
595 | struct dentry *dentry, | 615 | struct dentry *dentry, |
596 | int mode) | 616 | int mode) |
@@ -1852,61 +1872,117 @@ bail: | |||
1852 | return status; | 1872 | return status; |
1853 | } | 1873 | } |
1854 | 1874 | ||
1855 | static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, | 1875 | static int ocfs2_lookup_lock_orphan_dir(struct ocfs2_super *osb, |
1856 | struct inode **ret_orphan_dir, | 1876 | struct inode **ret_orphan_dir, |
1857 | u64 blkno, | 1877 | struct buffer_head **ret_orphan_dir_bh) |
1858 | char *name, | ||
1859 | struct ocfs2_dir_lookup_result *lookup) | ||
1860 | { | 1878 | { |
1861 | struct inode *orphan_dir_inode; | 1879 | struct inode *orphan_dir_inode; |
1862 | struct buffer_head *orphan_dir_bh = NULL; | 1880 | struct buffer_head *orphan_dir_bh = NULL; |
1863 | int status = 0; | 1881 | int ret = 0; |
1864 | |||
1865 | status = ocfs2_blkno_stringify(blkno, name); | ||
1866 | if (status < 0) { | ||
1867 | mlog_errno(status); | ||
1868 | return status; | ||
1869 | } | ||
1870 | 1882 | ||
1871 | orphan_dir_inode = ocfs2_get_system_file_inode(osb, | 1883 | orphan_dir_inode = ocfs2_get_system_file_inode(osb, |
1872 | ORPHAN_DIR_SYSTEM_INODE, | 1884 | ORPHAN_DIR_SYSTEM_INODE, |
1873 | osb->slot_num); | 1885 | osb->slot_num); |
1874 | if (!orphan_dir_inode) { | 1886 | if (!orphan_dir_inode) { |
1875 | status = -ENOENT; | 1887 | ret = -ENOENT; |
1876 | mlog_errno(status); | 1888 | mlog_errno(ret); |
1877 | return status; | 1889 | return ret; |
1878 | } | 1890 | } |
1879 | 1891 | ||
1880 | mutex_lock(&orphan_dir_inode->i_mutex); | 1892 | mutex_lock(&orphan_dir_inode->i_mutex); |
1881 | 1893 | ||
1882 | status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1); | 1894 | ret = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1); |
1883 | if (status < 0) { | 1895 | if (ret < 0) { |
1884 | mlog_errno(status); | 1896 | mutex_unlock(&orphan_dir_inode->i_mutex); |
1885 | goto leave; | 1897 | iput(orphan_dir_inode); |
1898 | |||
1899 | mlog_errno(ret); | ||
1900 | return ret; | ||
1886 | } | 1901 | } |
1887 | 1902 | ||
1888 | status = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode, | 1903 | *ret_orphan_dir = orphan_dir_inode; |
1889 | orphan_dir_bh, name, | 1904 | *ret_orphan_dir_bh = orphan_dir_bh; |
1890 | OCFS2_ORPHAN_NAMELEN, lookup); | ||
1891 | if (status < 0) { | ||
1892 | ocfs2_inode_unlock(orphan_dir_inode, 1); | ||
1893 | 1905 | ||
1894 | mlog_errno(status); | 1906 | return 0; |
1895 | goto leave; | 1907 | } |
1908 | |||
1909 | static int __ocfs2_prepare_orphan_dir(struct inode *orphan_dir_inode, | ||
1910 | struct buffer_head *orphan_dir_bh, | ||
1911 | u64 blkno, | ||
1912 | char *name, | ||
1913 | struct ocfs2_dir_lookup_result *lookup) | ||
1914 | { | ||
1915 | int ret; | ||
1916 | struct ocfs2_super *osb = OCFS2_SB(orphan_dir_inode->i_sb); | ||
1917 | |||
1918 | ret = ocfs2_blkno_stringify(blkno, name); | ||
1919 | if (ret < 0) { | ||
1920 | mlog_errno(ret); | ||
1921 | return ret; | ||
1922 | } | ||
1923 | |||
1924 | ret = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode, | ||
1925 | orphan_dir_bh, name, | ||
1926 | OCFS2_ORPHAN_NAMELEN, lookup); | ||
1927 | if (ret < 0) { | ||
1928 | mlog_errno(ret); | ||
1929 | return ret; | ||
1930 | } | ||
1931 | |||
1932 | return 0; | ||
1933 | } | ||
1934 | |||
1935 | /** | ||
1936 | * ocfs2_prepare_orphan_dir() - Prepare an orphan directory for | ||
1937 | * insertion of an orphan. | ||
1938 | * @osb: ocfs2 file system | ||
1939 | * @ret_orphan_dir: Orphan dir inode - returned locked! | ||
1940 | * @blkno: Actual block number of the inode to be inserted into orphan dir. | ||
1941 | * @lookup: dir lookup result, to be passed back into functions like | ||
1942 | * ocfs2_orphan_add | ||
1943 | * | ||
1944 | * Returns zero on success and the ret_orphan_dir, name and lookup | ||
1945 | * fields will be populated. | ||
1946 | * | ||
1947 | * Returns non-zero on failure. | ||
1948 | */ | ||
1949 | static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, | ||
1950 | struct inode **ret_orphan_dir, | ||
1951 | u64 blkno, | ||
1952 | char *name, | ||
1953 | struct ocfs2_dir_lookup_result *lookup) | ||
1954 | { | ||
1955 | struct inode *orphan_dir_inode = NULL; | ||
1956 | struct buffer_head *orphan_dir_bh = NULL; | ||
1957 | int ret = 0; | ||
1958 | |||
1959 | ret = ocfs2_lookup_lock_orphan_dir(osb, &orphan_dir_inode, | ||
1960 | &orphan_dir_bh); | ||
1961 | if (ret < 0) { | ||
1962 | mlog_errno(ret); | ||
1963 | return ret; | ||
1964 | } | ||
1965 | |||
1966 | ret = __ocfs2_prepare_orphan_dir(orphan_dir_inode, orphan_dir_bh, | ||
1967 | blkno, name, lookup); | ||
1968 | if (ret < 0) { | ||
1969 | mlog_errno(ret); | ||
1970 | goto out; | ||
1896 | } | 1971 | } |
1897 | 1972 | ||
1898 | *ret_orphan_dir = orphan_dir_inode; | 1973 | *ret_orphan_dir = orphan_dir_inode; |
1899 | 1974 | ||
1900 | leave: | 1975 | out: |
1901 | if (status) { | 1976 | brelse(orphan_dir_bh); |
1977 | |||
1978 | if (ret) { | ||
1979 | ocfs2_inode_unlock(orphan_dir_inode, 1); | ||
1902 | mutex_unlock(&orphan_dir_inode->i_mutex); | 1980 | mutex_unlock(&orphan_dir_inode->i_mutex); |
1903 | iput(orphan_dir_inode); | 1981 | iput(orphan_dir_inode); |
1904 | } | 1982 | } |
1905 | 1983 | ||
1906 | brelse(orphan_dir_bh); | 1984 | mlog_exit(ret); |
1907 | 1985 | return ret; | |
1908 | mlog_exit(status); | ||
1909 | return status; | ||
1910 | } | 1986 | } |
1911 | 1987 | ||
1912 | static int ocfs2_orphan_add(struct ocfs2_super *osb, | 1988 | static int ocfs2_orphan_add(struct ocfs2_super *osb, |
@@ -2053,6 +2129,99 @@ leave: | |||
2053 | return status; | 2129 | return status; |
2054 | } | 2130 | } |
2055 | 2131 | ||
2132 | /** | ||
2133 | * ocfs2_prep_new_orphaned_file() - Prepare the orphan dir to recieve a newly | ||
2134 | * allocated file. This is different from the typical 'add to orphan dir' | ||
2135 | * operation in that the inode does not yet exist. This is a problem because | ||
2136 | * the orphan dir stringifies the inode block number to come up with it's | ||
2137 | * dirent. Obviously if the inode does not yet exist we have a chicken and egg | ||
2138 | * problem. This function works around it by calling deeper into the orphan | ||
2139 | * and suballoc code than other callers. Use this only by necessity. | ||
2140 | * @dir: The directory which this inode will ultimately wind up under - not the | ||
2141 | * orphan dir! | ||
2142 | * @dir_bh: buffer_head the @dir inode block | ||
2143 | * @orphan_name: string of length (CFS2_ORPHAN_NAMELEN + 1). Will be filled | ||
2144 | * with the string to be used for orphan dirent. Pass back to the orphan dir | ||
2145 | * code. | ||
2146 | * @ret_orphan_dir: orphan dir inode returned to be passed back into orphan | ||
2147 | * dir code. | ||
2148 | * @ret_di_blkno: block number where the new inode will be allocated. | ||
2149 | * @orphan_insert: Dir insert context to be passed back into orphan dir code. | ||
2150 | * @ret_inode_ac: Inode alloc context to be passed back to the allocator. | ||
2151 | * | ||
2152 | * Returns zero on success and the ret_orphan_dir, name and lookup | ||
2153 | * fields will be populated. | ||
2154 | * | ||
2155 | * Returns non-zero on failure. | ||
2156 | */ | ||
2157 | static int ocfs2_prep_new_orphaned_file(struct inode *dir, | ||
2158 | struct buffer_head *dir_bh, | ||
2159 | char *orphan_name, | ||
2160 | struct inode **ret_orphan_dir, | ||
2161 | u64 *ret_di_blkno, | ||
2162 | struct ocfs2_dir_lookup_result *orphan_insert, | ||
2163 | struct ocfs2_alloc_context **ret_inode_ac) | ||
2164 | { | ||
2165 | int ret; | ||
2166 | u64 di_blkno; | ||
2167 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | ||
2168 | struct inode *orphan_dir = NULL; | ||
2169 | struct buffer_head *orphan_dir_bh = NULL; | ||
2170 | struct ocfs2_alloc_context *inode_ac = NULL; | ||
2171 | |||
2172 | ret = ocfs2_lookup_lock_orphan_dir(osb, &orphan_dir, &orphan_dir_bh); | ||
2173 | if (ret < 0) { | ||
2174 | mlog_errno(ret); | ||
2175 | return ret; | ||
2176 | } | ||
2177 | |||
2178 | /* reserve an inode spot */ | ||
2179 | ret = ocfs2_reserve_new_inode(osb, &inode_ac); | ||
2180 | if (ret < 0) { | ||
2181 | if (ret != -ENOSPC) | ||
2182 | mlog_errno(ret); | ||
2183 | goto out; | ||
2184 | } | ||
2185 | |||
2186 | ret = ocfs2_find_new_inode_loc(dir, dir_bh, inode_ac, | ||
2187 | &di_blkno); | ||
2188 | if (ret) { | ||
2189 | mlog_errno(ret); | ||
2190 | goto out; | ||
2191 | } | ||
2192 | |||
2193 | ret = __ocfs2_prepare_orphan_dir(orphan_dir, orphan_dir_bh, | ||
2194 | di_blkno, orphan_name, orphan_insert); | ||
2195 | if (ret < 0) { | ||
2196 | mlog_errno(ret); | ||
2197 | goto out; | ||
2198 | } | ||
2199 | |||
2200 | out: | ||
2201 | if (ret == 0) { | ||
2202 | *ret_orphan_dir = orphan_dir; | ||
2203 | *ret_di_blkno = di_blkno; | ||
2204 | *ret_inode_ac = inode_ac; | ||
2205 | /* | ||
2206 | * orphan_name and orphan_insert are already up to | ||
2207 | * date via prepare_orphan_dir | ||
2208 | */ | ||
2209 | } else { | ||
2210 | /* Unroll reserve_new_inode* */ | ||
2211 | if (inode_ac) | ||
2212 | ocfs2_free_alloc_context(inode_ac); | ||
2213 | |||
2214 | /* Unroll orphan dir locking */ | ||
2215 | mutex_unlock(&orphan_dir->i_mutex); | ||
2216 | ocfs2_inode_unlock(orphan_dir, 1); | ||
2217 | iput(orphan_dir); | ||
2218 | } | ||
2219 | |||
2220 | brelse(orphan_dir_bh); | ||
2221 | |||
2222 | return 0; | ||
2223 | } | ||
2224 | |||
2056 | int ocfs2_create_inode_in_orphan(struct inode *dir, | 2225 | int ocfs2_create_inode_in_orphan(struct inode *dir, |
2057 | int mode, | 2226 | int mode, |
2058 | struct inode **new_inode) | 2227 | struct inode **new_inode) |
@@ -2068,6 +2237,8 @@ int ocfs2_create_inode_in_orphan(struct inode *dir, | |||
2068 | struct buffer_head *new_di_bh = NULL; | 2237 | struct buffer_head *new_di_bh = NULL; |
2069 | struct ocfs2_alloc_context *inode_ac = NULL; | 2238 | struct ocfs2_alloc_context *inode_ac = NULL; |
2070 | struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; | 2239 | struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; |
2240 | u64 uninitialized_var(di_blkno), suballoc_loc; | ||
2241 | u16 suballoc_bit; | ||
2071 | 2242 | ||
2072 | status = ocfs2_inode_lock(dir, &parent_di_bh, 1); | 2243 | status = ocfs2_inode_lock(dir, &parent_di_bh, 1); |
2073 | if (status < 0) { | 2244 | if (status < 0) { |
@@ -2076,20 +2247,9 @@ int ocfs2_create_inode_in_orphan(struct inode *dir, | |||
2076 | return status; | 2247 | return status; |
2077 | } | 2248 | } |
2078 | 2249 | ||
2079 | /* | 2250 | status = ocfs2_prep_new_orphaned_file(dir, parent_di_bh, |
2080 | * We give the orphan dir the root blkno to fake an orphan name, | 2251 | orphan_name, &orphan_dir, |
2081 | * and allocate enough space for our insertion. | 2252 | &di_blkno, &orphan_insert, &inode_ac); |
2082 | */ | ||
2083 | status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, | ||
2084 | osb->root_blkno, | ||
2085 | orphan_name, &orphan_insert); | ||
2086 | if (status < 0) { | ||
2087 | mlog_errno(status); | ||
2088 | goto leave; | ||
2089 | } | ||
2090 | |||
2091 | /* reserve an inode spot */ | ||
2092 | status = ocfs2_reserve_new_inode(osb, &inode_ac); | ||
2093 | if (status < 0) { | 2253 | if (status < 0) { |
2094 | if (status != -ENOSPC) | 2254 | if (status != -ENOSPC) |
2095 | mlog_errno(status); | 2255 | mlog_errno(status); |
@@ -2116,17 +2276,20 @@ int ocfs2_create_inode_in_orphan(struct inode *dir, | |||
2116 | goto leave; | 2276 | goto leave; |
2117 | did_quota_inode = 1; | 2277 | did_quota_inode = 1; |
2118 | 2278 | ||
2119 | inode->i_nlink = 0; | 2279 | status = ocfs2_claim_new_inode_at_loc(handle, dir, inode_ac, |
2120 | /* do the real work now. */ | 2280 | &suballoc_loc, |
2121 | status = ocfs2_mknod_locked(osb, dir, inode, | 2281 | &suballoc_bit, di_blkno); |
2122 | 0, &new_di_bh, parent_di_bh, handle, | ||
2123 | inode_ac); | ||
2124 | if (status < 0) { | 2282 | if (status < 0) { |
2125 | mlog_errno(status); | 2283 | mlog_errno(status); |
2126 | goto leave; | 2284 | goto leave; |
2127 | } | 2285 | } |
2128 | 2286 | ||
2129 | status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, orphan_name); | 2287 | inode->i_nlink = 0; |
2288 | /* do the real work now. */ | ||
2289 | status = __ocfs2_mknod_locked(dir, inode, | ||
2290 | 0, &new_di_bh, parent_di_bh, handle, | ||
2291 | inode_ac, di_blkno, suballoc_loc, | ||
2292 | suballoc_bit); | ||
2130 | if (status < 0) { | 2293 | if (status < 0) { |
2131 | mlog_errno(status); | 2294 | mlog_errno(status); |
2132 | goto leave; | 2295 | goto leave; |