xfs_symlink.c (9cb5f15d88d4cbda3bac22769d9e4808bd6cf248) xfs_symlink.c (5d31a85dcc1fa4c5d4a925c6da67751653a700ba)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
4 * Copyright (c) 2012-2013 Red Hat, Inc.
5 * All rights reserved.
6 */
7#include "xfs.h"
8#include "xfs_shared.h"

--- 11 unchanged lines hidden (view full) ---

20#include "xfs_symlink.h"
21#include "xfs_trans_space.h"
22#include "xfs_trace.h"
23#include "xfs_trans.h"
24#include "xfs_ialloc.h"
25#include "xfs_error.h"
26#include "xfs_health.h"
27#include "xfs_symlink_remote.h"
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
4 * Copyright (c) 2012-2013 Red Hat, Inc.
5 * All rights reserved.
6 */
7#include "xfs.h"
8#include "xfs_shared.h"

--- 11 unchanged lines hidden (view full) ---

20#include "xfs_symlink.h"
21#include "xfs_trans_space.h"
22#include "xfs_trace.h"
23#include "xfs_trans.h"
24#include "xfs_ialloc.h"
25#include "xfs_error.h"
26#include "xfs_health.h"
27#include "xfs_symlink_remote.h"
28#include "xfs_parent.h"
29#include "xfs_defer.h"
28
29int
30xfs_readlink(
31 struct xfs_inode *ip,
32 char *link)
33{
34 struct xfs_mount *mp = ip->i_mount;
35 xfs_fsize_t pathlen;

--- 59 unchanged lines hidden (view full) ---

95 bool unlock_dp_on_error = false;
96 xfs_filblks_t fs_blocks;
97 prid_t prid;
98 struct xfs_dquot *udqp = NULL;
99 struct xfs_dquot *gdqp = NULL;
100 struct xfs_dquot *pdqp = NULL;
101 uint resblks;
102 xfs_ino_t ino;
30
31int
32xfs_readlink(
33 struct xfs_inode *ip,
34 char *link)
35{
36 struct xfs_mount *mp = ip->i_mount;
37 xfs_fsize_t pathlen;

--- 59 unchanged lines hidden (view full) ---

97 bool unlock_dp_on_error = false;
98 xfs_filblks_t fs_blocks;
99 prid_t prid;
100 struct xfs_dquot *udqp = NULL;
101 struct xfs_dquot *gdqp = NULL;
102 struct xfs_dquot *pdqp = NULL;
103 uint resblks;
104 xfs_ino_t ino;
105 struct xfs_parent_args *ppargs;
103
104 *ipp = NULL;
105
106 trace_xfs_symlink(dp, link_name);
107
108 if (xfs_is_shutdown(mp))
109 return -EIO;
110

--- 14 unchanged lines hidden (view full) ---

125 mapped_fsgid(idmap, &init_user_ns), prid,
126 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
127 &udqp, &gdqp, &pdqp);
128 if (error)
129 return error;
130
131 /*
132 * The symlink will fit into the inode data fork?
106
107 *ipp = NULL;
108
109 trace_xfs_symlink(dp, link_name);
110
111 if (xfs_is_shutdown(mp))
112 return -EIO;
113

--- 14 unchanged lines hidden (view full) ---

128 mapped_fsgid(idmap, &init_user_ns), prid,
129 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
130 &udqp, &gdqp, &pdqp);
131 if (error)
132 return error;
133
134 /*
135 * The symlink will fit into the inode data fork?
133 * There can't be any attributes so we get the whole variable part.
136 * If there are no parent pointers, then there wont't be any attributes.
137 * So we get the whole variable part, and do not need to reserve extra
138 * blocks. Otherwise, we need to reserve the blocks.
134 */
139 */
135 if (pathlen <= XFS_LITINO(mp))
140 if (pathlen <= XFS_LITINO(mp) && !xfs_has_parent(mp))
136 fs_blocks = 0;
137 else
138 fs_blocks = xfs_symlink_blocks(mp, pathlen);
141 fs_blocks = 0;
142 else
143 fs_blocks = xfs_symlink_blocks(mp, pathlen);
139 resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
144 resblks = xfs_symlink_space_res(mp, link_name->len, fs_blocks);
140
145
146 error = xfs_parent_start(mp, &ppargs);
147 if (error)
148 goto out_release_dquots;
149
141 error = xfs_trans_alloc_icreate(mp, &M_RES(mp)->tr_symlink, udqp, gdqp,
142 pdqp, resblks, &tp);
143 if (error)
150 error = xfs_trans_alloc_icreate(mp, &M_RES(mp)->tr_symlink, udqp, gdqp,
151 pdqp, resblks, &tp);
152 if (error)
144 goto out_release_dquots;
153 goto out_parent;
145
146 xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
147 unlock_dp_on_error = true;
148
149 /*
150 * Check whether the directory allows new symlinks or not.
151 */
152 if (dp->i_diflags & XFS_DIFLAG_NOSYMLINKS) {
153 error = -EPERM;
154 goto out_trans_cancel;
155 }
156
157 /*
158 * Allocate an inode for the symlink.
159 */
160 error = xfs_dialloc(&tp, dp->i_ino, S_IFLNK, &ino);
161 if (!error)
162 error = xfs_init_new_inode(idmap, tp, dp, ino,
163 S_IFLNK | (mode & ~S_IFMT), 1, 0, prid,
154
155 xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
156 unlock_dp_on_error = true;
157
158 /*
159 * Check whether the directory allows new symlinks or not.
160 */
161 if (dp->i_diflags & XFS_DIFLAG_NOSYMLINKS) {
162 error = -EPERM;
163 goto out_trans_cancel;
164 }
165
166 /*
167 * Allocate an inode for the symlink.
168 */
169 error = xfs_dialloc(&tp, dp->i_ino, S_IFLNK, &ino);
170 if (!error)
171 error = xfs_init_new_inode(idmap, tp, dp, ino,
172 S_IFLNK | (mode & ~S_IFMT), 1, 0, prid,
164 false, &ip);
173 xfs_has_parent(mp), &ip);
165 if (error)
166 goto out_trans_cancel;
167
168 /*
169 * Now we join the directory inode to the transaction. We do not do it
170 * earlier because xfs_dir_ialloc might commit the previous transaction
171 * (and release all the locks). An error from here on will result in
172 * the transaction cancel unlocking dp so don't do it explicitly in the

--- 17 unchanged lines hidden (view full) ---

190 /*
191 * Create the directory entry for the symlink.
192 */
193 error = xfs_dir_createname(tp, dp, link_name, ip->i_ino, resblks);
194 if (error)
195 goto out_trans_cancel;
196 xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
197 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
174 if (error)
175 goto out_trans_cancel;
176
177 /*
178 * Now we join the directory inode to the transaction. We do not do it
179 * earlier because xfs_dir_ialloc might commit the previous transaction
180 * (and release all the locks). An error from here on will result in
181 * the transaction cancel unlocking dp so don't do it explicitly in the

--- 17 unchanged lines hidden (view full) ---

199 /*
200 * Create the directory entry for the symlink.
201 */
202 error = xfs_dir_createname(tp, dp, link_name, ip->i_ino, resblks);
203 if (error)
204 goto out_trans_cancel;
205 xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
206 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
207
208 /* Add parent pointer for the new symlink. */
209 if (ppargs) {
210 error = xfs_parent_addname(tp, ppargs, dp, link_name, ip);
211 if (error)
212 goto out_trans_cancel;
213 }
214
198 xfs_dir_update_hook(dp, ip, 1, link_name);
199
200 /*
201 * If this is a synchronous mount, make sure that the
202 * symlink transaction goes to disk before returning to
203 * the user.
204 */
205 if (xfs_has_wsync(mp) || xfs_has_dirsync(mp))

--- 5 unchanged lines hidden (view full) ---

211
212 xfs_qm_dqrele(udqp);
213 xfs_qm_dqrele(gdqp);
214 xfs_qm_dqrele(pdqp);
215
216 *ipp = ip;
217 xfs_iunlock(ip, XFS_ILOCK_EXCL);
218 xfs_iunlock(dp, XFS_ILOCK_EXCL);
215 xfs_dir_update_hook(dp, ip, 1, link_name);
216
217 /*
218 * If this is a synchronous mount, make sure that the
219 * symlink transaction goes to disk before returning to
220 * the user.
221 */
222 if (xfs_has_wsync(mp) || xfs_has_dirsync(mp))

--- 5 unchanged lines hidden (view full) ---

228
229 xfs_qm_dqrele(udqp);
230 xfs_qm_dqrele(gdqp);
231 xfs_qm_dqrele(pdqp);
232
233 *ipp = ip;
234 xfs_iunlock(ip, XFS_ILOCK_EXCL);
235 xfs_iunlock(dp, XFS_ILOCK_EXCL);
236 xfs_parent_finish(mp, ppargs);
219 return 0;
220
221out_trans_cancel:
222 xfs_trans_cancel(tp);
223out_release_inode:
224 /*
225 * Wait until after the current transaction is aborted to finish the
226 * setup of the inode and release the inode. This prevents recursive
227 * transactions and deadlocks from xfs_inactive.
228 */
229 if (ip) {
230 xfs_iunlock(ip, XFS_ILOCK_EXCL);
231 xfs_finish_inode_setup(ip);
232 xfs_irele(ip);
233 }
237 return 0;
238
239out_trans_cancel:
240 xfs_trans_cancel(tp);
241out_release_inode:
242 /*
243 * Wait until after the current transaction is aborted to finish the
244 * setup of the inode and release the inode. This prevents recursive
245 * transactions and deadlocks from xfs_inactive.
246 */
247 if (ip) {
248 xfs_iunlock(ip, XFS_ILOCK_EXCL);
249 xfs_finish_inode_setup(ip);
250 xfs_irele(ip);
251 }
252out_parent:
253 xfs_parent_finish(mp, ppargs);
234out_release_dquots:
235 xfs_qm_dqrele(udqp);
236 xfs_qm_dqrele(gdqp);
237 xfs_qm_dqrele(pdqp);
238
239 if (unlock_dp_on_error)
240 xfs_iunlock(dp, XFS_ILOCK_EXCL);
241 return error;

--- 115 unchanged lines hidden ---
254out_release_dquots:
255 xfs_qm_dqrele(udqp);
256 xfs_qm_dqrele(gdqp);
257 xfs_qm_dqrele(pdqp);
258
259 if (unlock_dp_on_error)
260 xfs_iunlock(dp, XFS_ILOCK_EXCL);
261 return error;

--- 115 unchanged lines hidden ---