@@ -1144,6 +1144,208 @@ void nfsd4_shutdown_copy(struct nfs4_client *clp)
1144
1144
while ((copy = nfsd4_get_copy (clp )) != NULL )
1145
1145
nfsd4_stop_copy (copy );
1146
1146
}
1147
+ #ifdef CONFIG_NFSD_V4_2_INTER_SSC
1148
+
1149
+ extern struct file * nfs42_ssc_open (struct vfsmount * ss_mnt ,
1150
+ struct nfs_fh * src_fh ,
1151
+ nfs4_stateid * stateid );
1152
+ extern void nfs42_ssc_close (struct file * filep );
1153
+
1154
+ extern void nfs_sb_deactive (struct super_block * sb );
1155
+
1156
+ #define NFSD42_INTERSSC_MOUNTOPS "vers=4.2,addr=%s,sec=sys"
1157
+
1158
+ /**
1159
+ * Support one copy source server for now.
1160
+ */
1161
+ static __be32
1162
+ nfsd4_interssc_connect (struct nl4_server * nss , struct svc_rqst * rqstp ,
1163
+ struct vfsmount * * mount )
1164
+ {
1165
+ struct file_system_type * type ;
1166
+ struct vfsmount * ss_mnt ;
1167
+ struct nfs42_netaddr * naddr ;
1168
+ struct sockaddr_storage tmp_addr ;
1169
+ size_t tmp_addrlen , match_netid_len = 3 ;
1170
+ char * startsep = "" , * endsep = "" , * match_netid = "tcp" ;
1171
+ char * ipaddr , * dev_name , * raw_data ;
1172
+ int len , raw_len , status = - EINVAL ;
1173
+
1174
+ naddr = & nss -> u .nl4_addr ;
1175
+ tmp_addrlen = rpc_uaddr2sockaddr (SVC_NET (rqstp ), naddr -> addr ,
1176
+ naddr -> addr_len ,
1177
+ (struct sockaddr * )& tmp_addr ,
1178
+ sizeof (tmp_addr ));
1179
+ if (tmp_addrlen == 0 )
1180
+ goto out_err ;
1181
+
1182
+ if (tmp_addr .ss_family == AF_INET6 ) {
1183
+ startsep = "[" ;
1184
+ endsep = "]" ;
1185
+ match_netid = "tcp6" ;
1186
+ match_netid_len = 4 ;
1187
+ }
1188
+
1189
+ if (naddr -> netid_len != match_netid_len ||
1190
+ strncmp (naddr -> netid , match_netid , naddr -> netid_len ))
1191
+ goto out_err ;
1192
+
1193
+ /* Construct the raw data for the vfs_kern_mount call */
1194
+ len = RPC_MAX_ADDRBUFLEN + 1 ;
1195
+ ipaddr = kzalloc (len , GFP_KERNEL );
1196
+ if (!ipaddr )
1197
+ goto out_err ;
1198
+
1199
+ rpc_ntop ((struct sockaddr * )& tmp_addr , ipaddr , len );
1200
+
1201
+ /* 2 for ipv6 endsep and startsep. 3 for ":/" and trailing '/0'*/
1202
+
1203
+ raw_len = strlen (NFSD42_INTERSSC_MOUNTOPS ) + strlen (ipaddr );
1204
+ raw_data = kzalloc (raw_len , GFP_KERNEL );
1205
+ if (!raw_data )
1206
+ goto out_free_ipaddr ;
1207
+
1208
+ snprintf (raw_data , raw_len , NFSD42_INTERSSC_MOUNTOPS , ipaddr );
1209
+
1210
+ status = - ENODEV ;
1211
+ type = get_fs_type ("nfs" );
1212
+ if (!type )
1213
+ goto out_free_rawdata ;
1214
+
1215
+ /* Set the server:<export> for the vfs_kern_mount call */
1216
+ dev_name = kzalloc (len + 5 , GFP_KERNEL );
1217
+ if (!dev_name )
1218
+ goto out_free_rawdata ;
1219
+ snprintf (dev_name , len + 5 , "%s%s%s:/" , startsep , ipaddr , endsep );
1220
+
1221
+ /* Use an 'internal' mount: SB_KERNMOUNT -> MNT_INTERNAL */
1222
+ ss_mnt = vfs_kern_mount (type , SB_KERNMOUNT , dev_name , raw_data );
1223
+ module_put (type -> owner );
1224
+ if (IS_ERR (ss_mnt ))
1225
+ goto out_free_devname ;
1226
+
1227
+ status = 0 ;
1228
+ * mount = ss_mnt ;
1229
+
1230
+ out_free_devname :
1231
+ kfree (dev_name );
1232
+ out_free_rawdata :
1233
+ kfree (raw_data );
1234
+ out_free_ipaddr :
1235
+ kfree (ipaddr );
1236
+ out_err :
1237
+ return status ;
1238
+ }
1239
+
1240
+ static void
1241
+ nfsd4_interssc_disconnect (struct vfsmount * ss_mnt )
1242
+ {
1243
+ nfs_sb_deactive (ss_mnt -> mnt_sb );
1244
+ mntput (ss_mnt );
1245
+ }
1246
+
1247
+ /**
1248
+ * nfsd4_setup_inter_ssc
1249
+ *
1250
+ * Verify COPY destination stateid.
1251
+ * Connect to the source server with NFSv4.1.
1252
+ * Create the source struct file for nfsd_copy_range.
1253
+ * Called with COPY cstate:
1254
+ * SAVED_FH: source filehandle
1255
+ * CURRENT_FH: destination filehandle
1256
+ *
1257
+ * Returns errno (not nfserrxxx)
1258
+ */
1259
+ static __be32
1260
+ nfsd4_setup_inter_ssc (struct svc_rqst * rqstp ,
1261
+ struct nfsd4_compound_state * cstate ,
1262
+ struct nfsd4_copy * copy , struct vfsmount * * mount )
1263
+ {
1264
+ struct svc_fh * s_fh = NULL ;
1265
+ stateid_t * s_stid = & copy -> cp_src_stateid ;
1266
+ __be32 status = - EINVAL ;
1267
+
1268
+ /* Verify the destination stateid and set dst struct file*/
1269
+ status = nfs4_preprocess_stateid_op (rqstp , cstate , & cstate -> current_fh ,
1270
+ & copy -> cp_dst_stateid ,
1271
+ WR_STATE , & copy -> nf_dst , NULL );
1272
+ if (status )
1273
+ goto out ;
1274
+
1275
+ status = nfsd4_interssc_connect (& copy -> cp_src , rqstp , mount );
1276
+ if (status )
1277
+ goto out ;
1278
+
1279
+ s_fh = & cstate -> save_fh ;
1280
+
1281
+ copy -> c_fh .size = s_fh -> fh_handle .fh_size ;
1282
+ memcpy (copy -> c_fh .data , & s_fh -> fh_handle .fh_base , copy -> c_fh .size );
1283
+ copy -> stateid .seqid = s_stid -> si_generation ;
1284
+ memcpy (copy -> stateid .other , (void * )& s_stid -> si_opaque ,
1285
+ sizeof (stateid_opaque_t ));
1286
+
1287
+ status = 0 ;
1288
+ out :
1289
+ return status ;
1290
+ }
1291
+
1292
+ static void
1293
+ nfsd4_cleanup_inter_ssc (struct vfsmount * ss_mnt , struct nfsd_file * src ,
1294
+ struct nfsd_file * dst )
1295
+ {
1296
+ nfs42_ssc_close (src -> nf_file );
1297
+ nfsd_file_put (src );
1298
+ nfsd_file_put (dst );
1299
+ mntput (ss_mnt );
1300
+ }
1301
+
1302
+ #else /* CONFIG_NFSD_V4_2_INTER_SSC */
1303
+
1304
+ static __be32
1305
+ nfsd4_setup_inter_ssc (struct svc_rqst * rqstp ,
1306
+ struct nfsd4_compound_state * cstate ,
1307
+ struct nfsd4_copy * copy ,
1308
+ struct vfsmount * * mount )
1309
+ {
1310
+ * mount = NULL ;
1311
+ return - EINVAL ;
1312
+ }
1313
+
1314
+ static void
1315
+ nfsd4_cleanup_inter_ssc (struct vfsmount * ss_mnt , struct nfsd_file * src ,
1316
+ struct nfsd_file * dst )
1317
+ {
1318
+ }
1319
+
1320
+ static void
1321
+ nfsd4_interssc_disconnect (struct vfsmount * ss_mnt )
1322
+ {
1323
+ }
1324
+
1325
+ static struct file * nfs42_ssc_open (struct vfsmount * ss_mnt ,
1326
+ struct nfs_fh * src_fh ,
1327
+ nfs4_stateid * stateid )
1328
+ {
1329
+ return NULL ;
1330
+ }
1331
+ #endif /* CONFIG_NFSD_V4_2_INTER_SSC */
1332
+
1333
+ static __be32
1334
+ nfsd4_setup_intra_ssc (struct svc_rqst * rqstp ,
1335
+ struct nfsd4_compound_state * cstate ,
1336
+ struct nfsd4_copy * copy )
1337
+ {
1338
+ return nfsd4_verify_copy (rqstp , cstate , & copy -> cp_src_stateid ,
1339
+ & copy -> nf_src , & copy -> cp_dst_stateid ,
1340
+ & copy -> nf_dst );
1341
+ }
1342
+
1343
+ static void
1344
+ nfsd4_cleanup_intra_ssc (struct nfsd_file * src , struct nfsd_file * dst )
1345
+ {
1346
+ nfsd_file_put (src );
1347
+ nfsd_file_put (dst );
1348
+ }
1147
1349
1148
1350
static void nfsd4_cb_offload_release (struct nfsd4_callback * cb )
1149
1351
{
@@ -1209,12 +1411,16 @@ static __be32 nfsd4_do_copy(struct nfsd4_copy *copy, bool sync)
1209
1411
status = nfs_ok ;
1210
1412
}
1211
1413
1212
- nfsd_file_put (copy -> nf_src );
1213
- nfsd_file_put (copy -> nf_dst );
1414
+ if (!copy -> cp_intra ) /* Inter server SSC */
1415
+ nfsd4_cleanup_inter_ssc (copy -> ss_mnt , copy -> nf_src ,
1416
+ copy -> nf_dst );
1417
+ else
1418
+ nfsd4_cleanup_intra_ssc (copy -> nf_src , copy -> nf_dst );
1419
+
1214
1420
return status ;
1215
1421
}
1216
1422
1217
- static void dup_copy_fields (struct nfsd4_copy * src , struct nfsd4_copy * dst )
1423
+ static int dup_copy_fields (struct nfsd4_copy * src , struct nfsd4_copy * dst )
1218
1424
{
1219
1425
dst -> cp_src_pos = src -> cp_src_pos ;
1220
1426
dst -> cp_dst_pos = src -> cp_dst_pos ;
@@ -1224,8 +1430,17 @@ static void dup_copy_fields(struct nfsd4_copy *src, struct nfsd4_copy *dst)
1224
1430
memcpy (& dst -> fh , & src -> fh , sizeof (src -> fh ));
1225
1431
dst -> cp_clp = src -> cp_clp ;
1226
1432
dst -> nf_dst = nfsd_file_get (src -> nf_dst );
1227
- dst -> nf_src = nfsd_file_get (src -> nf_src );
1433
+ dst -> cp_intra = src -> cp_intra ;
1434
+ if (src -> cp_intra ) /* for inter, file_src doesn't exist yet */
1435
+ dst -> nf_src = nfsd_file_get (src -> nf_src );
1436
+
1228
1437
memcpy (& dst -> cp_stateid , & src -> cp_stateid , sizeof (src -> cp_stateid ));
1438
+ memcpy (& dst -> cp_src , & src -> cp_src , sizeof (struct nl4_server ));
1439
+ memcpy (& dst -> stateid , & src -> stateid , sizeof (src -> stateid ));
1440
+ memcpy (& dst -> c_fh , & src -> c_fh , sizeof (src -> c_fh ));
1441
+ dst -> ss_mnt = src -> ss_mnt ;
1442
+
1443
+ return 0 ;
1229
1444
}
1230
1445
1231
1446
static void cleanup_async_copy (struct nfsd4_copy * copy )
@@ -1244,7 +1459,25 @@ static int nfsd4_do_async_copy(void *data)
1244
1459
struct nfsd4_copy * copy = (struct nfsd4_copy * )data ;
1245
1460
struct nfsd4_copy * cb_copy ;
1246
1461
1462
+ if (!copy -> cp_intra ) { /* Inter server SSC */
1463
+ copy -> nf_src = kzalloc (sizeof (struct nfsd_file ), GFP_KERNEL );
1464
+ if (!copy -> nf_src ) {
1465
+ copy -> nfserr = nfserr_serverfault ;
1466
+ nfsd4_interssc_disconnect (copy -> ss_mnt );
1467
+ goto do_callback ;
1468
+ }
1469
+ copy -> nf_src -> nf_file = nfs42_ssc_open (copy -> ss_mnt , & copy -> c_fh ,
1470
+ & copy -> stateid );
1471
+ if (IS_ERR (copy -> nf_src -> nf_file )) {
1472
+ kfree (copy -> nf_src );
1473
+ copy -> nfserr = nfserr_offload_denied ;
1474
+ nfsd4_interssc_disconnect (copy -> ss_mnt );
1475
+ goto do_callback ;
1476
+ }
1477
+ }
1478
+
1247
1479
copy -> nfserr = nfsd4_do_copy (copy , 0 );
1480
+ do_callback :
1248
1481
cb_copy = kzalloc (sizeof (struct nfsd4_copy ), GFP_KERNEL );
1249
1482
if (!cb_copy )
1250
1483
goto out ;
@@ -1256,6 +1489,8 @@ static int nfsd4_do_async_copy(void *data)
1256
1489
& nfsd4_cb_offload_ops , NFSPROC4_CLNT_CB_OFFLOAD );
1257
1490
nfsd4_run_cb (& cb_copy -> cp_cb );
1258
1491
out :
1492
+ if (!copy -> cp_intra )
1493
+ kfree (copy -> nf_src );
1259
1494
cleanup_async_copy (copy );
1260
1495
return 0 ;
1261
1496
}
@@ -1268,11 +1503,20 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1268
1503
__be32 status ;
1269
1504
struct nfsd4_copy * async_copy = NULL ;
1270
1505
1271
- status = nfsd4_verify_copy (rqstp , cstate , & copy -> cp_src_stateid ,
1272
- & copy -> nf_src , & copy -> cp_dst_stateid ,
1273
- & copy -> nf_dst );
1274
- if (status )
1275
- goto out ;
1506
+ if (!copy -> cp_intra ) { /* Inter server SSC */
1507
+ if (!inter_copy_offload_enable || copy -> cp_synchronous ) {
1508
+ status = nfserr_notsupp ;
1509
+ goto out ;
1510
+ }
1511
+ status = nfsd4_setup_inter_ssc (rqstp , cstate , copy ,
1512
+ & copy -> ss_mnt );
1513
+ if (status )
1514
+ return nfserr_offload_denied ;
1515
+ } else {
1516
+ status = nfsd4_setup_intra_ssc (rqstp , cstate , copy );
1517
+ if (status )
1518
+ return status ;
1519
+ }
1276
1520
1277
1521
copy -> cp_clp = cstate -> clp ;
1278
1522
memcpy (& copy -> fh , & cstate -> current_fh .fh_handle ,
@@ -1283,15 +1527,15 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1283
1527
status = nfserrno (- ENOMEM );
1284
1528
async_copy = kzalloc (sizeof (struct nfsd4_copy ), GFP_KERNEL );
1285
1529
if (!async_copy )
1286
- goto out ;
1287
- if (!nfs4_init_copy_state (nn , copy )) {
1288
- kfree (async_copy );
1289
- goto out ;
1290
- }
1530
+ goto out_err ;
1531
+ if (!nfs4_init_copy_state (nn , copy ))
1532
+ goto out_err ;
1291
1533
refcount_set (& async_copy -> refcount , 1 );
1292
1534
memcpy (& copy -> cp_res .cb_stateid , & copy -> cp_stateid ,
1293
1535
sizeof (copy -> cp_stateid ));
1294
- dup_copy_fields (copy , async_copy );
1536
+ status = dup_copy_fields (copy , async_copy );
1537
+ if (status )
1538
+ goto out_err ;
1295
1539
async_copy -> copy_task = kthread_create (nfsd4_do_async_copy ,
1296
1540
async_copy , "%s" , "copy thread" );
1297
1541
if (IS_ERR (async_copy -> copy_task ))
@@ -1302,13 +1546,17 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1302
1546
spin_unlock (& async_copy -> cp_clp -> async_lock );
1303
1547
wake_up_process (async_copy -> copy_task );
1304
1548
status = nfs_ok ;
1305
- } else
1549
+ } else {
1306
1550
status = nfsd4_do_copy (copy , 1 );
1551
+ }
1307
1552
out :
1308
1553
return status ;
1309
1554
out_err :
1310
1555
if (async_copy )
1311
1556
cleanup_async_copy (async_copy );
1557
+ status = nfserrno (- ENOMEM );
1558
+ if (!copy -> cp_intra )
1559
+ nfsd4_interssc_disconnect (copy -> ss_mnt );
1312
1560
goto out ;
1313
1561
}
1314
1562
@@ -1319,7 +1567,7 @@ find_async_copy(struct nfs4_client *clp, stateid_t *stateid)
1319
1567
1320
1568
spin_lock (& clp -> async_lock );
1321
1569
list_for_each_entry (copy , & clp -> async_copies , copies ) {
1322
- if (memcmp (& copy -> cp_stateid , stateid , NFS4_STATEID_SIZE ))
1570
+ if (memcmp (& copy -> cp_stateid . stid , stateid , NFS4_STATEID_SIZE ))
1323
1571
continue ;
1324
1572
refcount_inc (& copy -> refcount );
1325
1573
spin_unlock (& clp -> async_lock );
@@ -1335,17 +1583,18 @@ nfsd4_offload_cancel(struct svc_rqst *rqstp,
1335
1583
union nfsd4_op_u * u )
1336
1584
{
1337
1585
struct nfsd4_offload_status * os = & u -> offload_status ;
1338
- __be32 status = 0 ;
1339
1586
struct nfsd4_copy * copy ;
1340
1587
struct nfs4_client * clp = cstate -> clp ;
1341
1588
1342
1589
copy = find_async_copy (clp , & os -> stateid );
1343
- if (copy )
1590
+ if (!copy ) {
1591
+ struct nfsd_net * nn = net_generic (SVC_NET (rqstp ), nfsd_net_id );
1592
+
1593
+ return manage_cpntf_state (nn , & os -> stateid , clp , NULL );
1594
+ } else
1344
1595
nfsd4_stop_copy (copy );
1345
- else
1346
- status = nfserr_bad_stateid ;
1347
1596
1348
- return status ;
1597
+ return nfs_ok ;
1349
1598
}
1350
1599
1351
1600
static __be32
0 commit comments