aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2013-04-03 01:11:18 -0400
committerBen Myers <bpm@sgi.com>2013-04-21 16:38:04 -0400
commit19de7351a8eb82dc99745e60e8f43474831d99c7 (patch)
tree2c0c1afc963c41e6766a08dfc631ccdfe913e574 /fs/xfs
parent93848a999cf9b9e4f4f77dba843a48c393f33c59 (diff)
xfs: split out symlink code into it's own file.
The symlink code is about to get more complicated when CRCs are added for remote symlink blocks. The symlink management code is mostly self contained, so move it to it's own files so that all the new code and the existing symlink code will not be intermingled with other unrelated code. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Ben Myers <bpm@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/Makefile5
-rw-r--r--fs/xfs/xfs_bmap.c21
-rw-r--r--fs/xfs/xfs_symlink.c529
-rw-r--r--fs/xfs/xfs_symlink.h38
-rw-r--r--fs/xfs/xfs_vnodeops.c478
5 files changed, 578 insertions, 493 deletions
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index d02201df855b..062f25cd6087 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -45,11 +45,11 @@ xfs-y += xfs_aops.o \
45 xfs_itable.o \ 45 xfs_itable.o \
46 xfs_message.o \ 46 xfs_message.o \
47 xfs_mru_cache.o \ 47 xfs_mru_cache.o \
48 xfs_super.o \
49 xfs_xattr.o \
50 xfs_rename.o \ 48 xfs_rename.o \
49 xfs_super.o \
51 xfs_utils.o \ 50 xfs_utils.o \
52 xfs_vnodeops.o \ 51 xfs_vnodeops.o \
52 xfs_xattr.o \
53 kmem.o \ 53 kmem.o \
54 uuid.o 54 uuid.o
55 55
@@ -73,6 +73,7 @@ xfs-y += xfs_alloc.o \
73 xfs_inode.o \ 73 xfs_inode.o \
74 xfs_log_recover.o \ 74 xfs_log_recover.o \
75 xfs_mount.o \ 75 xfs_mount.o \
76 xfs_symlink.o \
76 xfs_trans.o 77 xfs_trans.o
77 78
78# low-level transaction/log code 79# low-level transaction/log code
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 0531cd3927a9..0fcb7f48e91f 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -47,6 +47,7 @@
47#include "xfs_filestream.h" 47#include "xfs_filestream.h"
48#include "xfs_vnodeops.h" 48#include "xfs_vnodeops.h"
49#include "xfs_trace.h" 49#include "xfs_trace.h"
50#include "xfs_symlink.h"
50 51
51 52
52kmem_zone_t *xfs_bmap_free_item_zone; 53kmem_zone_t *xfs_bmap_free_item_zone;
@@ -1321,9 +1322,10 @@ xfs_bmap_add_attrfork_extents(
1321} 1322}
1322 1323
1323/* 1324/*
1324 * Block initialisation functions for local to extent format conversion. 1325 * Block initialisation function for local to extent format conversion.
1325 * As these get more complex, they will be moved to the relevant files, 1326 *
1326 * but for now they are too simple to worry about. 1327 * This shouldn't actually be called by anyone, so make sure debug kernels cause
1328 * a noticable failure.
1327 */ 1329 */
1328STATIC void 1330STATIC void
1329xfs_bmap_local_to_extents_init_fn( 1331xfs_bmap_local_to_extents_init_fn(
@@ -1332,23 +1334,12 @@ xfs_bmap_local_to_extents_init_fn(
1332 struct xfs_inode *ip, 1334 struct xfs_inode *ip,
1333 struct xfs_ifork *ifp) 1335 struct xfs_ifork *ifp)
1334{ 1336{
1337 ASSERT(0);
1335 bp->b_ops = &xfs_bmbt_buf_ops; 1338 bp->b_ops = &xfs_bmbt_buf_ops;
1336 memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes); 1339 memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
1337 xfs_trans_buf_set_type(tp, bp, XFS_BLF_BTREE_BUF); 1340 xfs_trans_buf_set_type(tp, bp, XFS_BLF_BTREE_BUF);
1338} 1341}
1339 1342
1340STATIC void
1341xfs_symlink_local_to_remote(
1342 struct xfs_trans *tp,
1343 struct xfs_buf *bp,
1344 struct xfs_inode *ip,
1345 struct xfs_ifork *ifp)
1346{
1347 /* remote symlink blocks are not verifiable until CRCs come along */
1348 bp->b_ops = NULL;
1349 memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
1350}
1351
1352/* 1343/*
1353 * Called from xfs_bmap_add_attrfork to handle local format files. Each 1344 * Called from xfs_bmap_add_attrfork to handle local format files. Each
1354 * different data fork content type needs a different callout to do the 1345 * different data fork content type needs a different callout to do the
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
new file mode 100644
index 000000000000..7512c96c7f29
--- /dev/null
+++ b/fs/xfs/xfs_symlink.c
@@ -0,0 +1,529 @@
1/*
2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * Copyright (c) 2012-2013 Red Hat, Inc.
4 * All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it would be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19#include "xfs.h"
20#include "xfs_fs.h"
21#include "xfs_types.h"
22#include "xfs_bit.h"
23#include "xfs_log.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h"
26#include "xfs_ag.h"
27#include "xfs_dir2.h"
28#include "xfs_mount.h"
29#include "xfs_da_btree.h"
30#include "xfs_bmap_btree.h"
31#include "xfs_ialloc_btree.h"
32#include "xfs_dinode.h"
33#include "xfs_inode.h"
34#include "xfs_inode_item.h"
35#include "xfs_itable.h"
36#include "xfs_ialloc.h"
37#include "xfs_alloc.h"
38#include "xfs_bmap.h"
39#include "xfs_error.h"
40#include "xfs_quota.h"
41#include "xfs_utils.h"
42#include "xfs_trans_space.h"
43#include "xfs_log_priv.h"
44#include "xfs_trace.h"
45#include "xfs_symlink.h"
46
47void
48xfs_symlink_local_to_remote(
49 struct xfs_trans *tp,
50 struct xfs_buf *bp,
51 struct xfs_inode *ip,
52 struct xfs_ifork *ifp)
53{
54 /* remote symlink blocks are not verifiable until CRCs come along */
55 bp->b_ops = NULL;
56 memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
57}
58
59/* ----- Kernel only functions below ----- */
60
61STATIC int
62xfs_readlink_bmap(
63 xfs_inode_t *ip,
64 char *link)
65{
66 xfs_mount_t *mp = ip->i_mount;
67 int pathlen = ip->i_d.di_size;
68 int nmaps = XFS_SYMLINK_MAPS;
69 xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS];
70 xfs_daddr_t d;
71 int byte_cnt;
72 int n;
73 xfs_buf_t *bp;
74 int error = 0;
75
76 error = xfs_bmapi_read(ip, 0, XFS_B_TO_FSB(mp, pathlen), mval, &nmaps,
77 0);
78 if (error)
79 goto out;
80
81 for (n = 0; n < nmaps; n++) {
82 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
83 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
84
85 bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0, NULL);
86 if (!bp)
87 return XFS_ERROR(ENOMEM);
88 error = bp->b_error;
89 if (error) {
90 xfs_buf_ioerror_alert(bp, __func__);
91 xfs_buf_relse(bp);
92 goto out;
93 }
94 if (pathlen < byte_cnt)
95 byte_cnt = pathlen;
96 pathlen -= byte_cnt;
97
98 memcpy(link, bp->b_addr, byte_cnt);
99 xfs_buf_relse(bp);
100 }
101
102 link[ip->i_d.di_size] = '\0';
103 error = 0;
104
105 out:
106 return error;
107}
108
109int
110xfs_readlink(
111 xfs_inode_t *ip,
112 char *link)
113{
114 xfs_mount_t *mp = ip->i_mount;
115 xfs_fsize_t pathlen;
116 int error = 0;
117
118 trace_xfs_readlink(ip);
119
120 if (XFS_FORCED_SHUTDOWN(mp))
121 return XFS_ERROR(EIO);
122
123 xfs_ilock(ip, XFS_ILOCK_SHARED);
124
125 pathlen = ip->i_d.di_size;
126 if (!pathlen)
127 goto out;
128
129 if (pathlen < 0 || pathlen > MAXPATHLEN) {
130 xfs_alert(mp, "%s: inode (%llu) bad symlink length (%lld)",
131 __func__, (unsigned long long) ip->i_ino,
132 (long long) pathlen);
133 ASSERT(0);
134 error = XFS_ERROR(EFSCORRUPTED);
135 goto out;
136 }
137
138
139 if (ip->i_df.if_flags & XFS_IFINLINE) {
140 memcpy(link, ip->i_df.if_u1.if_data, pathlen);
141 link[pathlen] = '\0';
142 } else {
143 error = xfs_readlink_bmap(ip, link);
144 }
145
146 out:
147 xfs_iunlock(ip, XFS_ILOCK_SHARED);
148 return error;
149}
150
151int
152xfs_symlink(
153 xfs_inode_t *dp,
154 struct xfs_name *link_name,
155 const char *target_path,
156 umode_t mode,
157 xfs_inode_t **ipp)
158{
159 xfs_mount_t *mp = dp->i_mount;
160 xfs_trans_t *tp;
161 xfs_inode_t *ip;
162 int error;
163 int pathlen;
164 xfs_bmap_free_t free_list;
165 xfs_fsblock_t first_block;
166 bool unlock_dp_on_error = false;
167 uint cancel_flags;
168 int committed;
169 xfs_fileoff_t first_fsb;
170 xfs_filblks_t fs_blocks;
171 int nmaps;
172 xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS];
173 xfs_daddr_t d;
174 const char *cur_chunk;
175 int byte_cnt;
176 int n;
177 xfs_buf_t *bp;
178 prid_t prid;
179 struct xfs_dquot *udqp, *gdqp;
180 uint resblks;
181
182 *ipp = NULL;
183 error = 0;
184 ip = NULL;
185 tp = NULL;
186
187 trace_xfs_symlink(dp, link_name);
188
189 if (XFS_FORCED_SHUTDOWN(mp))
190 return XFS_ERROR(EIO);
191
192 /*
193 * Check component lengths of the target path name.
194 */
195 pathlen = strlen(target_path);
196 if (pathlen >= MAXPATHLEN) /* total string too long */
197 return XFS_ERROR(ENAMETOOLONG);
198
199 udqp = gdqp = NULL;
200 if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
201 prid = xfs_get_projid(dp);
202 else
203 prid = XFS_PROJID_DEFAULT;
204
205 /*
206 * Make sure that we have allocated dquot(s) on disk.
207 */
208 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
209 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
210 if (error)
211 goto std_return;
212
213 tp = xfs_trans_alloc(mp, XFS_TRANS_SYMLINK);
214 cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
215 /*
216 * The symlink will fit into the inode data fork?
217 * There can't be any attributes so we get the whole variable part.
218 */
219 if (pathlen <= XFS_LITINO(mp, dp->i_d.di_version))
220 fs_blocks = 0;
221 else
222 fs_blocks = XFS_B_TO_FSB(mp, pathlen);
223 resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
224 error = xfs_trans_reserve(tp, resblks, XFS_SYMLINK_LOG_RES(mp), 0,
225 XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT);
226 if (error == ENOSPC && fs_blocks == 0) {
227 resblks = 0;
228 error = xfs_trans_reserve(tp, 0, XFS_SYMLINK_LOG_RES(mp), 0,
229 XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT);
230 }
231 if (error) {
232 cancel_flags = 0;
233 goto error_return;
234 }
235
236 xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
237 unlock_dp_on_error = true;
238
239 /*
240 * Check whether the directory allows new symlinks or not.
241 */
242 if (dp->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) {
243 error = XFS_ERROR(EPERM);
244 goto error_return;
245 }
246
247 /*
248 * Reserve disk quota : blocks and inode.
249 */
250 error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0);
251 if (error)
252 goto error_return;
253
254 /*
255 * Check for ability to enter directory entry, if no space reserved.
256 */
257 error = xfs_dir_canenter(tp, dp, link_name, resblks);
258 if (error)
259 goto error_return;
260 /*
261 * Initialize the bmap freelist prior to calling either
262 * bmapi or the directory create code.
263 */
264 xfs_bmap_init(&free_list, &first_block);
265
266 /*
267 * Allocate an inode for the symlink.
268 */
269 error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (mode & ~S_IFMT), 1, 0,
270 prid, resblks > 0, &ip, NULL);
271 if (error) {
272 if (error == ENOSPC)
273 goto error_return;
274 goto error1;
275 }
276
277 /*
278 * An error after we've joined dp to the transaction will result in the
279 * transaction cancel unlocking dp so don't do it explicitly in the
280 * error path.
281 */
282 xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
283 unlock_dp_on_error = false;
284
285 /*
286 * Also attach the dquot(s) to it, if applicable.
287 */
288 xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp);
289
290 if (resblks)
291 resblks -= XFS_IALLOC_SPACE_RES(mp);
292 /*
293 * If the symlink will fit into the inode, write it inline.
294 */
295 if (pathlen <= XFS_IFORK_DSIZE(ip)) {
296 xfs_idata_realloc(ip, pathlen, XFS_DATA_FORK);
297 memcpy(ip->i_df.if_u1.if_data, target_path, pathlen);
298 ip->i_d.di_size = pathlen;
299
300 /*
301 * The inode was initially created in extent format.
302 */
303 ip->i_df.if_flags &= ~(XFS_IFEXTENTS | XFS_IFBROOT);
304 ip->i_df.if_flags |= XFS_IFINLINE;
305
306 ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
307 xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
308
309 } else {
310 first_fsb = 0;
311 nmaps = XFS_SYMLINK_MAPS;
312
313 error = xfs_bmapi_write(tp, ip, first_fsb, fs_blocks,
314 XFS_BMAPI_METADATA, &first_block, resblks,
315 mval, &nmaps, &free_list);
316 if (error)
317 goto error2;
318
319 if (resblks)
320 resblks -= fs_blocks;
321 ip->i_d.di_size = pathlen;
322 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
323
324 cur_chunk = target_path;
325 for (n = 0; n < nmaps; n++) {
326 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
327 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
328 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
329 BTOBB(byte_cnt), 0);
330 if (!bp) {
331 error = ENOMEM;
332 goto error2;
333 }
334 if (pathlen < byte_cnt) {
335 byte_cnt = pathlen;
336 }
337 pathlen -= byte_cnt;
338
339 memcpy(bp->b_addr, cur_chunk, byte_cnt);
340 cur_chunk += byte_cnt;
341
342 xfs_trans_log_buf(tp, bp, 0, byte_cnt - 1);
343 }
344 }
345
346 /*
347 * Create the directory entry for the symlink.
348 */
349 error = xfs_dir_createname(tp, dp, link_name, ip->i_ino,
350 &first_block, &free_list, resblks);
351 if (error)
352 goto error2;
353 xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
354 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
355
356 /*
357 * If this is a synchronous mount, make sure that the
358 * symlink transaction goes to disk before returning to
359 * the user.
360 */
361 if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
362 xfs_trans_set_sync(tp);
363 }
364
365 error = xfs_bmap_finish(&tp, &free_list, &committed);
366 if (error) {
367 goto error2;
368 }
369 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
370 xfs_qm_dqrele(udqp);
371 xfs_qm_dqrele(gdqp);
372
373 *ipp = ip;
374 return 0;
375
376 error2:
377 IRELE(ip);
378 error1:
379 xfs_bmap_cancel(&free_list);
380 cancel_flags |= XFS_TRANS_ABORT;
381 error_return:
382 xfs_trans_cancel(tp, cancel_flags);
383 xfs_qm_dqrele(udqp);
384 xfs_qm_dqrele(gdqp);
385
386 if (unlock_dp_on_error)
387 xfs_iunlock(dp, XFS_ILOCK_EXCL);
388 std_return:
389 return error;
390}
391
392/*
393 * Free a symlink that has blocks associated with it.
394 */
395STATIC int
396xfs_inactive_symlink_rmt(
397 xfs_inode_t *ip,
398 xfs_trans_t **tpp)
399{
400 xfs_buf_t *bp;
401 int committed;
402 int done;
403 int error;
404 xfs_fsblock_t first_block;
405 xfs_bmap_free_t free_list;
406 int i;
407 xfs_mount_t *mp;
408 xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS];
409 int nmaps;
410 xfs_trans_t *ntp;
411 int size;
412 xfs_trans_t *tp;
413
414 tp = *tpp;
415 mp = ip->i_mount;
416 ASSERT(ip->i_d.di_size > XFS_IFORK_DSIZE(ip));
417 /*
418 * We're freeing a symlink that has some
419 * blocks allocated to it. Free the
420 * blocks here. We know that we've got
421 * either 1 or 2 extents and that we can
422 * free them all in one bunmapi call.
423 */
424 ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2);
425
426 /*
427 * Lock the inode, fix the size, and join it to the transaction.
428 * Hold it so in the normal path, we still have it locked for
429 * the second transaction. In the error paths we need it
430 * held so the cancel won't rele it, see below.
431 */
432 size = (int)ip->i_d.di_size;
433 ip->i_d.di_size = 0;
434 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
435 /*
436 * Find the block(s) so we can inval and unmap them.
437 */
438 done = 0;
439 xfs_bmap_init(&free_list, &first_block);
440 nmaps = ARRAY_SIZE(mval);
441 error = xfs_bmapi_read(ip, 0, XFS_B_TO_FSB(mp, size),
442 mval, &nmaps, 0);
443 if (error)
444 goto error0;
445 /*
446 * Invalidate the block(s).
447 */
448 for (i = 0; i < nmaps; i++) {
449 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp,
450 XFS_FSB_TO_DADDR(mp, mval[i].br_startblock),
451 XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0);
452 if (!bp) {
453 error = ENOMEM;
454 goto error1;
455 }
456 xfs_trans_binval(tp, bp);
457 }
458 /*
459 * Unmap the dead block(s) to the free_list.
460 */
461 if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps,
462 &first_block, &free_list, &done)))
463 goto error1;
464 ASSERT(done);
465 /*
466 * Commit the first transaction. This logs the EFI and the inode.
467 */
468 if ((error = xfs_bmap_finish(&tp, &free_list, &committed)))
469 goto error1;
470 /*
471 * The transaction must have been committed, since there were
472 * actually extents freed by xfs_bunmapi. See xfs_bmap_finish.
473 * The new tp has the extent freeing and EFDs.
474 */
475 ASSERT(committed);
476 /*
477 * The first xact was committed, so add the inode to the new one.
478 * Mark it dirty so it will be logged and moved forward in the log as
479 * part of every commit.
480 */
481 xfs_trans_ijoin(tp, ip, 0);
482 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
483 /*
484 * Get a new, empty transaction to return to our caller.
485 */
486 ntp = xfs_trans_dup(tp);
487 /*
488 * Commit the transaction containing extent freeing and EFDs.
489 * If we get an error on the commit here or on the reserve below,
490 * we need to unlock the inode since the new transaction doesn't
491 * have the inode attached.
492 */
493 error = xfs_trans_commit(tp, 0);
494 tp = ntp;
495 if (error) {
496 ASSERT(XFS_FORCED_SHUTDOWN(mp));
497 goto error0;
498 }
499 /*
500 * transaction commit worked ok so we can drop the extra ticket
501 * reference that we gained in xfs_trans_dup()
502 */
503 xfs_log_ticket_put(tp->t_ticket);
504
505 /*
506 * Remove the memory for extent descriptions (just bookkeeping).
507 */
508 if (ip->i_df.if_bytes)
509 xfs_idata_realloc(ip, -ip->i_df.if_bytes, XFS_DATA_FORK);
510 ASSERT(ip->i_df.if_bytes == 0);
511 /*
512 * Put an itruncate log reservation in the new transaction
513 * for our caller.
514 */
515 if ((error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
516 XFS_TRANS_PERM_LOG_RES, XFS_ITRUNCATE_LOG_COUNT))) {
517 ASSERT(XFS_FORCED_SHUTDOWN(mp));
518 goto error0;
519 }
520
521 xfs_trans_ijoin(tp, ip, 0);
522 *tpp = tp;
523 return 0;
524
525 error1:
526 xfs_bmap_cancel(&free_list);
527 error0:
528 return error;
529}
diff --git a/fs/xfs/xfs_symlink.h b/fs/xfs/xfs_symlink.h
new file mode 100644
index 000000000000..07bdabcc4158
--- /dev/null
+++ b/fs/xfs/xfs_symlink.h
@@ -0,0 +1,38 @@
1/*
2 * Copyright (c) 2012 Red Hat, Inc. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write the Free Software Foundation,
15 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17#ifndef __XFS_SYMLINK_H
18#define __XFS_SYMLINK_H 1
19
20/*
21 * The maximum pathlen is 1024 bytes. Since the minimum file system
22 * blocksize is 512 bytes, we can get a max of 2 extents back from
23 * bmapi.
24 */
25#define XFS_SYMLINK_MAPS 2
26
27void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp,
28 struct xfs_inode *ip, struct xfs_ifork *ifp);
29
30#ifdef __KERNEL__
31
32int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,
33 const char *target_path, umode_t mode, struct xfs_inode **ipp);
34int xfs_readlink(struct xfs_inode *ip, char *link);
35int xfs_inactive_symlink_rmt(struct xfs_inode *ip, struct xfs_trans **tpp);
36
37#endif /* __KERNEL__ */
38#endif /* __XFS_SYMLINK_H */
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index aa0c06692e18..1501f4fa51a6 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2000-2006 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * Copyright (c) 2012 Red Hat, Inc.
3 * All Rights Reserved. 4 * All Rights Reserved.
4 * 5 *
5 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -48,103 +49,8 @@
48#include "xfs_vnodeops.h" 49#include "xfs_vnodeops.h"
49#include "xfs_trace.h" 50#include "xfs_trace.h"
50#include "xfs_icache.h" 51#include "xfs_icache.h"
52#include "xfs_symlink.h"
51 53
52/*
53 * The maximum pathlen is 1024 bytes. Since the minimum file system
54 * blocksize is 512 bytes, we can get a max of 2 extents back from
55 * bmapi.
56 */
57#define SYMLINK_MAPS 2
58
59STATIC int
60xfs_readlink_bmap(
61 xfs_inode_t *ip,
62 char *link)
63{
64 xfs_mount_t *mp = ip->i_mount;
65 int pathlen = ip->i_d.di_size;
66 int nmaps = SYMLINK_MAPS;
67 xfs_bmbt_irec_t mval[SYMLINK_MAPS];
68 xfs_daddr_t d;
69 int byte_cnt;
70 int n;
71 xfs_buf_t *bp;
72 int error = 0;
73
74 error = xfs_bmapi_read(ip, 0, XFS_B_TO_FSB(mp, pathlen), mval, &nmaps,
75 0);
76 if (error)
77 goto out;
78
79 for (n = 0; n < nmaps; n++) {
80 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
81 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
82
83 bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0, NULL);
84 if (!bp)
85 return XFS_ERROR(ENOMEM);
86 error = bp->b_error;
87 if (error) {
88 xfs_buf_ioerror_alert(bp, __func__);
89 xfs_buf_relse(bp);
90 goto out;
91 }
92 if (pathlen < byte_cnt)
93 byte_cnt = pathlen;
94 pathlen -= byte_cnt;
95
96 memcpy(link, bp->b_addr, byte_cnt);
97 xfs_buf_relse(bp);
98 }
99
100 link[ip->i_d.di_size] = '\0';
101 error = 0;
102
103 out:
104 return error;
105}
106
107int
108xfs_readlink(
109 xfs_inode_t *ip,
110 char *link)
111{
112 xfs_mount_t *mp = ip->i_mount;
113 xfs_fsize_t pathlen;
114 int error = 0;
115
116 trace_xfs_readlink(ip);
117
118 if (XFS_FORCED_SHUTDOWN(mp))
119 return XFS_ERROR(EIO);
120
121 xfs_ilock(ip, XFS_ILOCK_SHARED);
122
123 pathlen = ip->i_d.di_size;
124 if (!pathlen)
125 goto out;
126
127 if (pathlen < 0 || pathlen > MAXPATHLEN) {
128 xfs_alert(mp, "%s: inode (%llu) bad symlink length (%lld)",
129 __func__, (unsigned long long) ip->i_ino,
130 (long long) pathlen);
131 ASSERT(0);
132 error = XFS_ERROR(EFSCORRUPTED);
133 goto out;
134 }
135
136
137 if (ip->i_df.if_flags & XFS_IFINLINE) {
138 memcpy(link, ip->i_df.if_u1.if_data, pathlen);
139 link[pathlen] = '\0';
140 } else {
141 error = xfs_readlink_bmap(ip, link);
142 }
143
144 out:
145 xfs_iunlock(ip, XFS_ILOCK_SHARED);
146 return error;
147}
148 54
149/* 55/*
150 * This is called by xfs_inactive to free any blocks beyond eof 56 * This is called by xfs_inactive to free any blocks beyond eof
@@ -249,145 +155,6 @@ xfs_free_eofblocks(
249 return error; 155 return error;
250} 156}
251 157
252/*
253 * Free a symlink that has blocks associated with it.
254 */
255STATIC int
256xfs_inactive_symlink_rmt(
257 xfs_inode_t *ip,
258 xfs_trans_t **tpp)
259{
260 xfs_buf_t *bp;
261 int committed;
262 int done;
263 int error;
264 xfs_fsblock_t first_block;
265 xfs_bmap_free_t free_list;
266 int i;
267 xfs_mount_t *mp;
268 xfs_bmbt_irec_t mval[SYMLINK_MAPS];
269 int nmaps;
270 xfs_trans_t *ntp;
271 int size;
272 xfs_trans_t *tp;
273
274 tp = *tpp;
275 mp = ip->i_mount;
276 ASSERT(ip->i_d.di_size > XFS_IFORK_DSIZE(ip));
277 /*
278 * We're freeing a symlink that has some
279 * blocks allocated to it. Free the
280 * blocks here. We know that we've got
281 * either 1 or 2 extents and that we can
282 * free them all in one bunmapi call.
283 */
284 ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2);
285
286 /*
287 * Lock the inode, fix the size, and join it to the transaction.
288 * Hold it so in the normal path, we still have it locked for
289 * the second transaction. In the error paths we need it
290 * held so the cancel won't rele it, see below.
291 */
292 size = (int)ip->i_d.di_size;
293 ip->i_d.di_size = 0;
294 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
295 /*
296 * Find the block(s) so we can inval and unmap them.
297 */
298 done = 0;
299 xfs_bmap_init(&free_list, &first_block);
300 nmaps = ARRAY_SIZE(mval);
301 error = xfs_bmapi_read(ip, 0, XFS_B_TO_FSB(mp, size),
302 mval, &nmaps, 0);
303 if (error)
304 goto error0;
305 /*
306 * Invalidate the block(s).
307 */
308 for (i = 0; i < nmaps; i++) {
309 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp,
310 XFS_FSB_TO_DADDR(mp, mval[i].br_startblock),
311 XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0);
312 if (!bp) {
313 error = ENOMEM;
314 goto error1;
315 }
316 xfs_trans_binval(tp, bp);
317 }
318 /*
319 * Unmap the dead block(s) to the free_list.
320 */
321 if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps,
322 &first_block, &free_list, &done)))
323 goto error1;
324 ASSERT(done);
325 /*
326 * Commit the first transaction. This logs the EFI and the inode.
327 */
328 if ((error = xfs_bmap_finish(&tp, &free_list, &committed)))
329 goto error1;
330 /*
331 * The transaction must have been committed, since there were
332 * actually extents freed by xfs_bunmapi. See xfs_bmap_finish.
333 * The new tp has the extent freeing and EFDs.
334 */
335 ASSERT(committed);
336 /*
337 * The first xact was committed, so add the inode to the new one.
338 * Mark it dirty so it will be logged and moved forward in the log as
339 * part of every commit.
340 */
341 xfs_trans_ijoin(tp, ip, 0);
342 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
343 /*
344 * Get a new, empty transaction to return to our caller.
345 */
346 ntp = xfs_trans_dup(tp);
347 /*
348 * Commit the transaction containing extent freeing and EFDs.
349 * If we get an error on the commit here or on the reserve below,
350 * we need to unlock the inode since the new transaction doesn't
351 * have the inode attached.
352 */
353 error = xfs_trans_commit(tp, 0);
354 tp = ntp;
355 if (error) {
356 ASSERT(XFS_FORCED_SHUTDOWN(mp));
357 goto error0;
358 }
359 /*
360 * transaction commit worked ok so we can drop the extra ticket
361 * reference that we gained in xfs_trans_dup()
362 */
363 xfs_log_ticket_put(tp->t_ticket);
364
365 /*
366 * Remove the memory for extent descriptions (just bookkeeping).
367 */
368 if (ip->i_df.if_bytes)
369 xfs_idata_realloc(ip, -ip->i_df.if_bytes, XFS_DATA_FORK);
370 ASSERT(ip->i_df.if_bytes == 0);
371 /*
372 * Put an itruncate log reservation in the new transaction
373 * for our caller.
374 */
375 if ((error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
376 XFS_TRANS_PERM_LOG_RES, XFS_ITRUNCATE_LOG_COUNT))) {
377 ASSERT(XFS_FORCED_SHUTDOWN(mp));
378 goto error0;
379 }
380
381 xfs_trans_ijoin(tp, ip, 0);
382 *tpp = tp;
383 return 0;
384
385 error1:
386 xfs_bmap_cancel(&free_list);
387 error0:
388 return error;
389}
390
391int 158int
392xfs_release( 159xfs_release(
393 xfs_inode_t *ip) 160 xfs_inode_t *ip)
@@ -1353,247 +1120,6 @@ xfs_link(
1353} 1120}
1354 1121
1355int 1122int
1356xfs_symlink(
1357 xfs_inode_t *dp,
1358 struct xfs_name *link_name,
1359 const char *target_path,
1360 umode_t mode,
1361 xfs_inode_t **ipp)
1362{
1363 xfs_mount_t *mp = dp->i_mount;
1364 xfs_trans_t *tp;
1365 xfs_inode_t *ip;
1366 int error;
1367 int pathlen;
1368 xfs_bmap_free_t free_list;
1369 xfs_fsblock_t first_block;
1370 bool unlock_dp_on_error = false;
1371 uint cancel_flags;
1372 int committed;
1373 xfs_fileoff_t first_fsb;
1374 xfs_filblks_t fs_blocks;
1375 int nmaps;
1376 xfs_bmbt_irec_t mval[SYMLINK_MAPS];
1377 xfs_daddr_t d;
1378 const char *cur_chunk;
1379 int byte_cnt;
1380 int n;
1381 xfs_buf_t *bp;
1382 prid_t prid;
1383 struct xfs_dquot *udqp, *gdqp;
1384 uint resblks;
1385
1386 *ipp = NULL;
1387 error = 0;
1388 ip = NULL;
1389 tp = NULL;
1390
1391 trace_xfs_symlink(dp, link_name);
1392
1393 if (XFS_FORCED_SHUTDOWN(mp))
1394 return XFS_ERROR(EIO);
1395
1396 /*
1397 * Check component lengths of the target path name.
1398 */
1399 pathlen = strlen(target_path);
1400 if (pathlen >= MAXPATHLEN) /* total string too long */
1401 return XFS_ERROR(ENAMETOOLONG);
1402
1403 udqp = gdqp = NULL;
1404 if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
1405 prid = xfs_get_projid(dp);
1406 else
1407 prid = XFS_PROJID_DEFAULT;
1408
1409 /*
1410 * Make sure that we have allocated dquot(s) on disk.
1411 */
1412 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
1413 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
1414 if (error)
1415 goto std_return;
1416
1417 tp = xfs_trans_alloc(mp, XFS_TRANS_SYMLINK);
1418 cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
1419 /*
1420 * The symlink will fit into the inode data fork?
1421 * There can't be any attributes so we get the whole variable part.
1422 */
1423 if (pathlen <= XFS_LITINO(mp, dp->i_d.di_version))
1424 fs_blocks = 0;
1425 else
1426 fs_blocks = XFS_B_TO_FSB(mp, pathlen);
1427 resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
1428 error = xfs_trans_reserve(tp, resblks, XFS_SYMLINK_LOG_RES(mp), 0,
1429 XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT);
1430 if (error == ENOSPC && fs_blocks == 0) {
1431 resblks = 0;
1432 error = xfs_trans_reserve(tp, 0, XFS_SYMLINK_LOG_RES(mp), 0,
1433 XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT);
1434 }
1435 if (error) {
1436 cancel_flags = 0;
1437 goto error_return;
1438 }
1439
1440 xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
1441 unlock_dp_on_error = true;
1442
1443 /*
1444 * Check whether the directory allows new symlinks or not.
1445 */
1446 if (dp->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) {
1447 error = XFS_ERROR(EPERM);
1448 goto error_return;
1449 }
1450
1451 /*
1452 * Reserve disk quota : blocks and inode.
1453 */
1454 error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0);
1455 if (error)
1456 goto error_return;
1457
1458 /*
1459 * Check for ability to enter directory entry, if no space reserved.
1460 */
1461 error = xfs_dir_canenter(tp, dp, link_name, resblks);
1462 if (error)
1463 goto error_return;
1464 /*
1465 * Initialize the bmap freelist prior to calling either
1466 * bmapi or the directory create code.
1467 */
1468 xfs_bmap_init(&free_list, &first_block);
1469
1470 /*
1471 * Allocate an inode for the symlink.
1472 */
1473 error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (mode & ~S_IFMT), 1, 0,
1474 prid, resblks > 0, &ip, NULL);
1475 if (error) {
1476 if (error == ENOSPC)
1477 goto error_return;
1478 goto error1;
1479 }
1480
1481 /*
1482 * An error after we've joined dp to the transaction will result in the
1483 * transaction cancel unlocking dp so don't do it explicitly in the
1484 * error path.
1485 */
1486 xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
1487 unlock_dp_on_error = false;
1488
1489 /*
1490 * Also attach the dquot(s) to it, if applicable.
1491 */
1492 xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp);
1493
1494 if (resblks)
1495 resblks -= XFS_IALLOC_SPACE_RES(mp);
1496 /*
1497 * If the symlink will fit into the inode, write it inline.
1498 */
1499 if (pathlen <= XFS_IFORK_DSIZE(ip)) {
1500 xfs_idata_realloc(ip, pathlen, XFS_DATA_FORK);
1501 memcpy(ip->i_df.if_u1.if_data, target_path, pathlen);
1502 ip->i_d.di_size = pathlen;
1503
1504 /*
1505 * The inode was initially created in extent format.
1506 */
1507 ip->i_df.if_flags &= ~(XFS_IFEXTENTS | XFS_IFBROOT);
1508 ip->i_df.if_flags |= XFS_IFINLINE;
1509
1510 ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
1511 xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
1512
1513 } else {
1514 first_fsb = 0;
1515 nmaps = SYMLINK_MAPS;
1516
1517 error = xfs_bmapi_write(tp, ip, first_fsb, fs_blocks,
1518 XFS_BMAPI_METADATA, &first_block, resblks,
1519 mval, &nmaps, &free_list);
1520 if (error)
1521 goto error2;
1522
1523 if (resblks)
1524 resblks -= fs_blocks;
1525 ip->i_d.di_size = pathlen;
1526 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1527
1528 cur_chunk = target_path;
1529 for (n = 0; n < nmaps; n++) {
1530 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
1531 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
1532 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
1533 BTOBB(byte_cnt), 0);
1534 if (!bp) {
1535 error = ENOMEM;
1536 goto error2;
1537 }
1538 if (pathlen < byte_cnt) {
1539 byte_cnt = pathlen;
1540 }
1541 pathlen -= byte_cnt;
1542
1543 memcpy(bp->b_addr, cur_chunk, byte_cnt);
1544 cur_chunk += byte_cnt;
1545
1546 xfs_trans_log_buf(tp, bp, 0, byte_cnt - 1);
1547 }
1548 }
1549
1550 /*
1551 * Create the directory entry for the symlink.
1552 */
1553 error = xfs_dir_createname(tp, dp, link_name, ip->i_ino,
1554 &first_block, &free_list, resblks);
1555 if (error)
1556 goto error2;
1557 xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
1558 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
1559
1560 /*
1561 * If this is a synchronous mount, make sure that the
1562 * symlink transaction goes to disk before returning to
1563 * the user.
1564 */
1565 if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
1566 xfs_trans_set_sync(tp);
1567 }
1568
1569 error = xfs_bmap_finish(&tp, &free_list, &committed);
1570 if (error) {
1571 goto error2;
1572 }
1573 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
1574 xfs_qm_dqrele(udqp);
1575 xfs_qm_dqrele(gdqp);
1576
1577 *ipp = ip;
1578 return 0;
1579
1580 error2:
1581 IRELE(ip);
1582 error1:
1583 xfs_bmap_cancel(&free_list);
1584 cancel_flags |= XFS_TRANS_ABORT;
1585 error_return:
1586 xfs_trans_cancel(tp, cancel_flags);
1587 xfs_qm_dqrele(udqp);
1588 xfs_qm_dqrele(gdqp);
1589
1590 if (unlock_dp_on_error)
1591 xfs_iunlock(dp, XFS_ILOCK_EXCL);
1592 std_return:
1593 return error;
1594}
1595
1596int
1597xfs_set_dmattrs( 1123xfs_set_dmattrs(
1598 xfs_inode_t *ip, 1124 xfs_inode_t *ip,
1599 u_int evmask, 1125 u_int evmask,