@@ -1088,3 +1088,239 @@ int nfs42_proc_clone(struct file *src_f, struct file *dst_f,
1088
1088
nfs_put_lock_context (src_lock );
1089
1089
return err ;
1090
1090
}
1091
+
1092
+ #define NFS4XATTR_MAXPAGES DIV_ROUND_UP(XATTR_SIZE_MAX, PAGE_SIZE)
1093
+
1094
+ static int _nfs42_proc_removexattr (struct inode * inode , const char * name )
1095
+ {
1096
+ struct nfs_server * server = NFS_SERVER (inode );
1097
+ struct nfs42_removexattrargs args = {
1098
+ .fh = NFS_FH (inode ),
1099
+ .xattr_name = name ,
1100
+ };
1101
+ struct nfs42_removexattrres res ;
1102
+ struct rpc_message msg = {
1103
+ .rpc_proc = & nfs4_procedures [NFSPROC4_CLNT_REMOVEXATTR ],
1104
+ .rpc_argp = & args ,
1105
+ .rpc_resp = & res ,
1106
+ };
1107
+ int ret ;
1108
+ unsigned long timestamp = jiffies ;
1109
+
1110
+ ret = nfs4_call_sync (server -> client , server , & msg , & args .seq_args ,
1111
+ & res .seq_res , 1 );
1112
+ if (!ret )
1113
+ nfs4_update_changeattr (inode , & res .cinfo , timestamp , 0 );
1114
+
1115
+ return ret ;
1116
+ }
1117
+
1118
+ static int _nfs42_proc_setxattr (struct inode * inode , const char * name ,
1119
+ const void * buf , size_t buflen , int flags )
1120
+ {
1121
+ struct nfs_server * server = NFS_SERVER (inode );
1122
+ struct page * pages [NFS4XATTR_MAXPAGES ];
1123
+ struct nfs42_setxattrargs arg = {
1124
+ .fh = NFS_FH (inode ),
1125
+ .xattr_pages = pages ,
1126
+ .xattr_len = buflen ,
1127
+ .xattr_name = name ,
1128
+ .xattr_flags = flags ,
1129
+ };
1130
+ struct nfs42_setxattrres res ;
1131
+ struct rpc_message msg = {
1132
+ .rpc_proc = & nfs4_procedures [NFSPROC4_CLNT_SETXATTR ],
1133
+ .rpc_argp = & arg ,
1134
+ .rpc_resp = & res ,
1135
+ };
1136
+ int ret , np ;
1137
+ unsigned long timestamp = jiffies ;
1138
+
1139
+ if (buflen > server -> sxasize )
1140
+ return - ERANGE ;
1141
+
1142
+ if (buflen > 0 ) {
1143
+ np = nfs4_buf_to_pages_noslab (buf , buflen , arg .xattr_pages );
1144
+ if (np < 0 )
1145
+ return np ;
1146
+ } else
1147
+ np = 0 ;
1148
+
1149
+ ret = nfs4_call_sync (server -> client , server , & msg , & arg .seq_args ,
1150
+ & res .seq_res , 1 );
1151
+
1152
+ for (; np > 0 ; np -- )
1153
+ put_page (pages [np - 1 ]);
1154
+
1155
+ if (!ret )
1156
+ nfs4_update_changeattr (inode , & res .cinfo , timestamp , 0 );
1157
+
1158
+ return ret ;
1159
+ }
1160
+
1161
+ static ssize_t _nfs42_proc_getxattr (struct inode * inode , const char * name ,
1162
+ void * buf , size_t buflen )
1163
+ {
1164
+ struct nfs_server * server = NFS_SERVER (inode );
1165
+ struct page * pages [NFS4XATTR_MAXPAGES ] = {};
1166
+ struct nfs42_getxattrargs arg = {
1167
+ .fh = NFS_FH (inode ),
1168
+ .xattr_pages = pages ,
1169
+ .xattr_len = buflen ,
1170
+ .xattr_name = name ,
1171
+ };
1172
+ struct nfs42_getxattrres res ;
1173
+ struct rpc_message msg = {
1174
+ .rpc_proc = & nfs4_procedures [NFSPROC4_CLNT_GETXATTR ],
1175
+ .rpc_argp = & arg ,
1176
+ .rpc_resp = & res ,
1177
+ };
1178
+ int ret , np ;
1179
+
1180
+ ret = nfs4_call_sync (server -> client , server , & msg , & arg .seq_args ,
1181
+ & res .seq_res , 0 );
1182
+ if (ret < 0 )
1183
+ return ret ;
1184
+
1185
+ if (buflen ) {
1186
+ if (res .xattr_len > buflen )
1187
+ return - ERANGE ;
1188
+ _copy_from_pages (buf , pages , 0 , res .xattr_len );
1189
+ }
1190
+
1191
+ np = DIV_ROUND_UP (res .xattr_len , PAGE_SIZE );
1192
+ while (-- np >= 0 )
1193
+ __free_page (pages [np ]);
1194
+
1195
+ return res .xattr_len ;
1196
+ }
1197
+
1198
+ static ssize_t _nfs42_proc_listxattrs (struct inode * inode , void * buf ,
1199
+ size_t buflen , u64 * cookiep , bool * eofp )
1200
+ {
1201
+ struct nfs_server * server = NFS_SERVER (inode );
1202
+ struct page * * pages ;
1203
+ struct nfs42_listxattrsargs arg = {
1204
+ .fh = NFS_FH (inode ),
1205
+ .cookie = * cookiep ,
1206
+ };
1207
+ struct nfs42_listxattrsres res = {
1208
+ .eof = false,
1209
+ .xattr_buf = buf ,
1210
+ .xattr_len = buflen ,
1211
+ };
1212
+ struct rpc_message msg = {
1213
+ .rpc_proc = & nfs4_procedures [NFSPROC4_CLNT_LISTXATTRS ],
1214
+ .rpc_argp = & arg ,
1215
+ .rpc_resp = & res ,
1216
+ };
1217
+ u32 xdrlen ;
1218
+ int ret , np ;
1219
+
1220
+
1221
+ res .scratch = alloc_page (GFP_KERNEL );
1222
+ if (!res .scratch )
1223
+ return - ENOMEM ;
1224
+
1225
+ xdrlen = nfs42_listxattr_xdrsize (buflen );
1226
+ if (xdrlen > server -> lxasize )
1227
+ xdrlen = server -> lxasize ;
1228
+ np = xdrlen / PAGE_SIZE + 1 ;
1229
+
1230
+ pages = kcalloc (np , sizeof (struct page * ), GFP_KERNEL );
1231
+ if (pages == NULL ) {
1232
+ __free_page (res .scratch );
1233
+ return - ENOMEM ;
1234
+ }
1235
+
1236
+ arg .xattr_pages = pages ;
1237
+ arg .count = xdrlen ;
1238
+
1239
+ ret = nfs4_call_sync (server -> client , server , & msg , & arg .seq_args ,
1240
+ & res .seq_res , 0 );
1241
+
1242
+ if (ret >= 0 ) {
1243
+ ret = res .copied ;
1244
+ * cookiep = res .cookie ;
1245
+ * eofp = res .eof ;
1246
+ }
1247
+
1248
+ while (-- np >= 0 ) {
1249
+ if (pages [np ])
1250
+ __free_page (pages [np ]);
1251
+ }
1252
+
1253
+ __free_page (res .scratch );
1254
+ kfree (pages );
1255
+
1256
+ return ret ;
1257
+
1258
+ }
1259
+
1260
+ ssize_t nfs42_proc_getxattr (struct inode * inode , const char * name ,
1261
+ void * buf , size_t buflen )
1262
+ {
1263
+ struct nfs4_exception exception = { };
1264
+ ssize_t err ;
1265
+
1266
+ do {
1267
+ err = _nfs42_proc_getxattr (inode , name , buf , buflen );
1268
+ if (err >= 0 )
1269
+ break ;
1270
+ err = nfs4_handle_exception (NFS_SERVER (inode ), err ,
1271
+ & exception );
1272
+ } while (exception .retry );
1273
+
1274
+ return err ;
1275
+ }
1276
+
1277
+ int nfs42_proc_setxattr (struct inode * inode , const char * name ,
1278
+ const void * buf , size_t buflen , int flags )
1279
+ {
1280
+ struct nfs4_exception exception = { };
1281
+ int err ;
1282
+
1283
+ do {
1284
+ err = _nfs42_proc_setxattr (inode , name , buf , buflen , flags );
1285
+ if (!err )
1286
+ break ;
1287
+ err = nfs4_handle_exception (NFS_SERVER (inode ), err ,
1288
+ & exception );
1289
+ } while (exception .retry );
1290
+
1291
+ return err ;
1292
+ }
1293
+
1294
+ ssize_t nfs42_proc_listxattrs (struct inode * inode , void * buf ,
1295
+ size_t buflen , u64 * cookiep , bool * eofp )
1296
+ {
1297
+ struct nfs4_exception exception = { };
1298
+ ssize_t err ;
1299
+
1300
+ do {
1301
+ err = _nfs42_proc_listxattrs (inode , buf , buflen ,
1302
+ cookiep , eofp );
1303
+ if (err >= 0 )
1304
+ break ;
1305
+ err = nfs4_handle_exception (NFS_SERVER (inode ), err ,
1306
+ & exception );
1307
+ } while (exception .retry );
1308
+
1309
+ return err ;
1310
+ }
1311
+
1312
+ int nfs42_proc_removexattr (struct inode * inode , const char * name )
1313
+ {
1314
+ struct nfs4_exception exception = { };
1315
+ int err ;
1316
+
1317
+ do {
1318
+ err = _nfs42_proc_removexattr (inode , name );
1319
+ if (!err )
1320
+ break ;
1321
+ err = nfs4_handle_exception (NFS_SERVER (inode ), err ,
1322
+ & exception );
1323
+ } while (exception .retry );
1324
+
1325
+ return err ;
1326
+ }
0 commit comments