Skip to content

Commit 668f455

Browse files
committed
Merge branch 'pnfs'
2 parents 3627452 + 01d7b29 commit 668f455

File tree

6 files changed

+218
-136
lines changed

6 files changed

+218
-136
lines changed

fs/nfs/blocklayout/dev.c

Lines changed: 75 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ nfs4_block_decode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b)
6565
if (!p)
6666
return -EIO;
6767
b->simple.nr_sigs = be32_to_cpup(p++);
68-
if (!b->simple.nr_sigs) {
69-
dprintk("no signature\n");
68+
if (!b->simple.nr_sigs || b->simple.nr_sigs > PNFS_BLOCK_MAX_UUIDS) {
69+
dprintk("Bad signature count: %d\n", b->simple.nr_sigs);
7070
return -EIO;
7171
}
7272

@@ -89,7 +89,8 @@ nfs4_block_decode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b)
8989
memcpy(&b->simple.sigs[i].sig, p,
9090
b->simple.sigs[i].sig_len);
9191

92-
b->simple.len += 8 + 4 + b->simple.sigs[i].sig_len;
92+
b->simple.len += 8 + 4 + \
93+
(XDR_QUADLEN(b->simple.sigs[i].sig_len) << 2);
9394
}
9495
break;
9596
case PNFS_BLOCK_VOLUME_SLICE:
@@ -104,7 +105,12 @@ nfs4_block_decode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b)
104105
p = xdr_inline_decode(xdr, 4);
105106
if (!p)
106107
return -EIO;
108+
107109
b->concat.volumes_count = be32_to_cpup(p++);
110+
if (b->concat.volumes_count > PNFS_BLOCK_MAX_DEVICES) {
111+
dprintk("Too many volumes: %d\n", b->concat.volumes_count);
112+
return -EIO;
113+
}
108114

109115
p = xdr_inline_decode(xdr, b->concat.volumes_count * 4);
110116
if (!p)
@@ -116,8 +122,13 @@ nfs4_block_decode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b)
116122
p = xdr_inline_decode(xdr, 8 + 4);
117123
if (!p)
118124
return -EIO;
125+
119126
p = xdr_decode_hyper(p, &b->stripe.chunk_size);
120127
b->stripe.volumes_count = be32_to_cpup(p++);
128+
if (b->stripe.volumes_count > PNFS_BLOCK_MAX_DEVICES) {
129+
dprintk("Too many volumes: %d\n", b->stripe.volumes_count);
130+
return -EIO;
131+
}
121132

122133
p = xdr_inline_decode(xdr, b->stripe.volumes_count * 4);
123134
if (!p)
@@ -224,18 +235,20 @@ bl_parse_simple(struct nfs_server *server, struct pnfs_block_dev *d,
224235
struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask)
225236
{
226237
struct pnfs_block_volume *v = &volumes[idx];
238+
struct block_device *bdev;
227239
dev_t dev;
228240

229241
dev = bl_resolve_deviceid(server, v, gfp_mask);
230242
if (!dev)
231243
return -EIO;
232244

233-
d->bdev = blkdev_get_by_dev(dev, FMODE_READ | FMODE_WRITE, NULL);
234-
if (IS_ERR(d->bdev)) {
245+
bdev = blkdev_get_by_dev(dev, FMODE_READ | FMODE_WRITE, NULL);
246+
if (IS_ERR(bdev)) {
235247
printk(KERN_WARNING "pNFS: failed to open device %d:%d (%ld)\n",
236-
MAJOR(dev), MINOR(dev), PTR_ERR(d->bdev));
237-
return PTR_ERR(d->bdev);
248+
MAJOR(dev), MINOR(dev), PTR_ERR(bdev));
249+
return PTR_ERR(bdev);
238250
}
251+
d->bdev = bdev;
239252

240253

241254
d->len = i_size_read(d->bdev->bd_inode);
@@ -287,44 +300,71 @@ bl_validate_designator(struct pnfs_block_volume *v)
287300
}
288301
}
289302

303+
/*
304+
* Try to open the udev path for the WWN. At least on Debian the udev
305+
* by-id path will always point to the dm-multipath device if one exists.
306+
*/
307+
static struct block_device *
308+
bl_open_udev_path(struct pnfs_block_volume *v)
309+
{
310+
struct block_device *bdev;
311+
const char *devname;
312+
313+
devname = kasprintf(GFP_KERNEL, "/dev/disk/by-id/wwn-0x%*phN",
314+
v->scsi.designator_len, v->scsi.designator);
315+
if (!devname)
316+
return ERR_PTR(-ENOMEM);
317+
318+
bdev = blkdev_get_by_path(devname, FMODE_READ | FMODE_WRITE, NULL);
319+
if (IS_ERR(bdev)) {
320+
pr_warn("pNFS: failed to open device %s (%ld)\n",
321+
devname, PTR_ERR(bdev));
322+
}
323+
324+
kfree(devname);
325+
return bdev;
326+
}
327+
328+
/*
329+
* Try to open the RH/Fedora specific dm-mpath udev path for this WWN, as the
330+
* wwn- links will only point to the first discovered SCSI device there.
331+
*/
332+
static struct block_device *
333+
bl_open_dm_mpath_udev_path(struct pnfs_block_volume *v)
334+
{
335+
struct block_device *bdev;
336+
const char *devname;
337+
338+
devname = kasprintf(GFP_KERNEL,
339+
"/dev/disk/by-id/dm-uuid-mpath-%d%*phN",
340+
v->scsi.designator_type,
341+
v->scsi.designator_len, v->scsi.designator);
342+
if (!devname)
343+
return ERR_PTR(-ENOMEM);
344+
345+
bdev = blkdev_get_by_path(devname, FMODE_READ | FMODE_WRITE, NULL);
346+
kfree(devname);
347+
return bdev;
348+
}
349+
290350
static int
291351
bl_parse_scsi(struct nfs_server *server, struct pnfs_block_dev *d,
292352
struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask)
293353
{
294354
struct pnfs_block_volume *v = &volumes[idx];
355+
struct block_device *bdev;
295356
const struct pr_ops *ops;
296-
const char *devname;
297357
int error;
298358

299359
if (!bl_validate_designator(v))
300360
return -EINVAL;
301361

302-
switch (v->scsi.designator_len) {
303-
case 8:
304-
devname = kasprintf(GFP_KERNEL, "/dev/disk/by-id/wwn-0x%8phN",
305-
v->scsi.designator);
306-
break;
307-
case 12:
308-
devname = kasprintf(GFP_KERNEL, "/dev/disk/by-id/wwn-0x%12phN",
309-
v->scsi.designator);
310-
break;
311-
case 16:
312-
devname = kasprintf(GFP_KERNEL, "/dev/disk/by-id/wwn-0x%16phN",
313-
v->scsi.designator);
314-
break;
315-
default:
316-
return -EINVAL;
317-
}
318-
319-
d->bdev = blkdev_get_by_path(devname, FMODE_READ, NULL);
320-
if (IS_ERR(d->bdev)) {
321-
pr_warn("pNFS: failed to open device %s (%ld)\n",
322-
devname, PTR_ERR(d->bdev));
323-
kfree(devname);
324-
return PTR_ERR(d->bdev);
325-
}
326-
327-
kfree(devname);
362+
bdev = bl_open_dm_mpath_udev_path(v);
363+
if (IS_ERR(bdev))
364+
bdev = bl_open_udev_path(v);
365+
if (IS_ERR(bdev))
366+
return PTR_ERR(bdev);
367+
d->bdev = bdev;
328368

329369
d->len = i_size_read(d->bdev->bd_inode);
330370
d->map = bl_map_simple;
@@ -352,7 +392,7 @@ bl_parse_scsi(struct nfs_server *server, struct pnfs_block_dev *d,
352392
return 0;
353393

354394
out_blkdev_put:
355-
blkdev_put(d->bdev, FMODE_READ);
395+
blkdev_put(d->bdev, FMODE_READ | FMODE_WRITE);
356396
return error;
357397
}
358398

fs/nfs/callback_proc.c

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -119,27 +119,30 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
119119
* hashed by filehandle.
120120
*/
121121
static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp,
122-
struct nfs_fh *fh, nfs4_stateid *stateid)
122+
struct nfs_fh *fh)
123123
{
124124
struct nfs_server *server;
125+
struct nfs_inode *nfsi;
125126
struct inode *ino;
126127
struct pnfs_layout_hdr *lo;
127128

129+
restart:
128130
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
129131
list_for_each_entry(lo, &server->layouts, plh_layouts) {
130-
if (!nfs4_stateid_match_other(&lo->plh_stateid, stateid))
132+
nfsi = NFS_I(lo->plh_inode);
133+
if (nfs_compare_fh(fh, &nfsi->fh))
131134
continue;
132-
if (nfs_compare_fh(fh, &NFS_I(lo->plh_inode)->fh))
135+
if (nfsi->layout != lo)
133136
continue;
134137
ino = igrab(lo->plh_inode);
135138
if (!ino)
136139
break;
137140
spin_lock(&ino->i_lock);
138141
/* Is this layout in the process of being freed? */
139-
if (NFS_I(ino)->layout != lo) {
142+
if (nfsi->layout != lo) {
140143
spin_unlock(&ino->i_lock);
141144
iput(ino);
142-
break;
145+
goto restart;
143146
}
144147
pnfs_get_layout_hdr(lo);
145148
spin_unlock(&ino->i_lock);
@@ -151,13 +154,13 @@ static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp,
151154
}
152155

153156
static struct pnfs_layout_hdr * get_layout_by_fh(struct nfs_client *clp,
154-
struct nfs_fh *fh, nfs4_stateid *stateid)
157+
struct nfs_fh *fh)
155158
{
156159
struct pnfs_layout_hdr *lo;
157160

158161
spin_lock(&clp->cl_lock);
159162
rcu_read_lock();
160-
lo = get_layout_by_fh_locked(clp, fh, stateid);
163+
lo = get_layout_by_fh_locked(clp, fh);
161164
rcu_read_unlock();
162165
spin_unlock(&clp->cl_lock);
163166

@@ -167,17 +170,39 @@ static struct pnfs_layout_hdr * get_layout_by_fh(struct nfs_client *clp,
167170
/*
168171
* Enforce RFC5661 section 12.5.5.2.1. (Layout Recall and Return Sequencing)
169172
*/
170-
static bool pnfs_check_stateid_sequence(struct pnfs_layout_hdr *lo,
173+
static u32 pnfs_check_callback_stateid(struct pnfs_layout_hdr *lo,
171174
const nfs4_stateid *new)
172175
{
173176
u32 oldseq, newseq;
174177

175-
oldseq = be32_to_cpu(lo->plh_stateid.seqid);
178+
/* Is the stateid still not initialised? */
179+
if (!pnfs_layout_is_valid(lo))
180+
return NFS4ERR_DELAY;
181+
182+
/* Mismatched stateid? */
183+
if (!nfs4_stateid_match_other(&lo->plh_stateid, new))
184+
return NFS4ERR_BAD_STATEID;
185+
176186
newseq = be32_to_cpu(new->seqid);
187+
/* Are we already in a layout recall situation? */
188+
if (test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags) &&
189+
lo->plh_return_seq != 0) {
190+
if (newseq < lo->plh_return_seq)
191+
return NFS4ERR_OLD_STATEID;
192+
if (newseq > lo->plh_return_seq)
193+
return NFS4ERR_DELAY;
194+
goto out;
195+
}
177196

197+
/* Check that the stateid matches what we think it should be. */
198+
oldseq = be32_to_cpu(lo->plh_stateid.seqid);
178199
if (newseq > oldseq + 1)
179-
return false;
180-
return true;
200+
return NFS4ERR_DELAY;
201+
/* Crazy server! */
202+
if (newseq <= oldseq)
203+
return NFS4ERR_OLD_STATEID;
204+
out:
205+
return NFS_OK;
181206
}
182207

183208
static u32 initiate_file_draining(struct nfs_client *clp,
@@ -188,26 +213,23 @@ static u32 initiate_file_draining(struct nfs_client *clp,
188213
u32 rv = NFS4ERR_NOMATCHING_LAYOUT;
189214
LIST_HEAD(free_me_list);
190215

191-
lo = get_layout_by_fh(clp, &args->cbl_fh, &args->cbl_stateid);
216+
lo = get_layout_by_fh(clp, &args->cbl_fh);
192217
if (!lo) {
193218
trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, NULL,
194219
&args->cbl_stateid, -rv);
195220
goto out;
196221
}
197222

198223
ino = lo->plh_inode;
224+
pnfs_layoutcommit_inode(ino, false);
225+
199226

200227
spin_lock(&ino->i_lock);
201-
if (!pnfs_check_stateid_sequence(lo, &args->cbl_stateid)) {
202-
rv = NFS4ERR_DELAY;
228+
rv = pnfs_check_callback_stateid(lo, &args->cbl_stateid);
229+
if (rv != NFS_OK)
203230
goto unlock;
204-
}
205231
pnfs_set_layout_stateid(lo, &args->cbl_stateid, true);
206-
spin_unlock(&ino->i_lock);
207-
208-
pnfs_layoutcommit_inode(ino, false);
209232

210-
spin_lock(&ino->i_lock);
211233
/*
212234
* Enforce RFC5661 Section 12.5.5.2.1.5 (Bulk Recall and Return)
213235
*/
@@ -223,11 +245,13 @@ static u32 initiate_file_draining(struct nfs_client *clp,
223245
goto unlock;
224246
}
225247

248+
/* Embrace your forgetfulness! */
249+
rv = NFS4ERR_NOMATCHING_LAYOUT;
250+
226251
if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) {
227252
NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo,
228253
&args->cbl_range);
229254
}
230-
pnfs_mark_layout_returned_if_empty(lo);
231255
unlock:
232256
spin_unlock(&ino->i_lock);
233257
pnfs_free_lseg_list(&free_me_list);

fs/nfs/nfs42proc.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,7 @@ nfs42_layoutstat_done(struct rpc_task *task, void *calldata)
351351
* Mark the bad layout state as invalid, then retry
352352
* with the current stateid.
353353
*/
354-
set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
355-
pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0);
354+
pnfs_mark_layout_stateid_invalid(lo, &head);
356355
spin_unlock(&inode->i_lock);
357356
pnfs_free_lseg_list(&head);
358357
} else

fs/nfs/nfs4proc.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7944,8 +7944,7 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
79447944
/*
79457945
* Mark the bad layout state as invalid, then retry
79467946
*/
7947-
set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
7948-
pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0);
7947+
pnfs_mark_layout_stateid_invalid(lo, &head);
79497948
spin_unlock(&inode->i_lock);
79507949
pnfs_free_lseg_list(&head);
79517950
status = -EAGAIN;
@@ -8144,8 +8143,7 @@ static void nfs4_layoutreturn_release(void *calldata)
81448143
spin_lock(&lo->plh_inode->i_lock);
81458144
pnfs_mark_matching_lsegs_invalid(lo, &freeme, &lrp->args.range,
81468145
be32_to_cpu(lrp->args.stateid.seqid));
8147-
pnfs_mark_layout_returned_if_empty(lo);
8148-
if (lrp->res.lrs_present)
8146+
if (lrp->res.lrs_present && pnfs_layout_is_valid(lo))
81498147
pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
81508148
pnfs_clear_layoutreturn_waitbit(lo);
81518149
spin_unlock(&lo->plh_inode->i_lock);

0 commit comments

Comments
 (0)